release.sh: fix two minor nitpicks
[xorg-util-modular.git] / release.sh
blob74e339dfbf047484e2a8dbdd9a8d828fc7a8e8cc
1 #!/bin/bash
3 # Creates and upload a git module tarball
5 # Note on portability:
6 # This script is intended to run on any platform supported by X.Org.
7 # Basically, it should be able to run in a Bourne shell.
11 export LC_ALL=en_US.UTF-8
14 #------------------------------------------------------------------------------
15 # Function: check_local_changes
16 #------------------------------------------------------------------------------
18 check_local_changes() {
19 git diff --quiet HEAD > /dev/null 2>&1
20 if [ $? -ne 0 ]; then
21 echo ""
22 echo "Uncommitted changes found. Did you forget to commit? Aborting."
23 echo ""
24 echo "You can perform a 'git stash' to save your local changes and"
25 echo "a 'git stash apply' to recover them after the tarball release."
26 echo "Make sure to rebuild and run 'make distcheck' again."
27 echo ""
28 echo "Alternatively, you can clone the module in another directory"
29 echo "and run ./configure. No need to build if testing was finished."
30 echo ""
31 return 1
33 return 0
36 #------------------------------------------------------------------------------
37 # Function: check_option_args
38 #------------------------------------------------------------------------------
40 # perform sanity checks on cmdline args which require arguments
41 # arguments:
42 # $1 - the option being examined
43 # $2 - the argument to the option
44 # returns:
45 # if it returns, everything is good
46 # otherwise it exit's
47 check_option_args() {
48 option=$1
49 arg=$2
51 # check for an argument
52 if [ x"$arg" = x ]; then
53 echo ""
54 echo "Error: the '$option' option is missing its required argument."
55 echo ""
56 usage
57 exit 1
60 # does the argument look like an option?
61 echo $arg | $GREP "^-" > /dev/null
62 if [ $? -eq 0 ]; then
63 echo ""
64 echo "Error: the argument '$arg' of option '$option' looks like an option itself."
65 echo ""
66 usage
67 exit 1
71 #------------------------------------------------------------------------------
72 # Function: check_gpgkey
73 #------------------------------------------------------------------------------
75 # check if the gpg key provided is known/available
76 # arguments:
77 # $1 - the gpg key
78 # returns:
79 # if it returns, everything is good
80 # otherwise it exit's
81 check_gpgkey() {
82 arg=$1
84 $GPG --list-keys "$arg" &>/dev/null
85 if [ $? -ne 0 ]; then
86 echo ""
87 echo "Error: the argument '$arg' is not a known gpg key."
88 echo ""
89 usage
90 exit 1
94 #------------------------------------------------------------------------------
95 # Function: check_modules_specification
96 #------------------------------------------------------------------------------
98 check_modules_specification() {
100 if [ x"$MODFILE" = x ]; then
101 if [ x"${INPUT_MODULES}" = x ]; then
102 echo ""
103 echo "Error: no modules specified (blank command line)."
104 usage
105 exit 1
111 #------------------------------------------------------------------------------
112 # Function: generate_announce
113 #------------------------------------------------------------------------------
115 generate_announce()
117 cat <<RELEASE
118 Subject: [ANNOUNCE] $pkg_name $pkg_version
119 To: $list_to
120 Cc: $list_cc
122 `git log --no-merges "$tag_range" | git shortlog`
124 git tag: $tag_name
126 RELEASE
128 for tarball in $tarbz2 $targz $tarxz; do
129 tarball=`basename $tarball`
130 cat <<RELEASE
131 https://$host_current/$section_path/$tarball
132 MD5: `$MD5SUM $tarball`
133 SHA1: `$SHA1SUM $tarball`
134 SHA256: `$SHA256SUM $tarball`
135 SHA512: `$SHA512SUM $tarball`
136 PGP: https://${host_current}/${section_path}/${tarball}.sig
138 RELEASE
139 done
142 #------------------------------------------------------------------------------
143 # Function: read_modfile
144 #------------------------------------------------------------------------------
146 # Read the module names from the file and set a variable to hold them
147 # This will be the same interface as cmd line supplied modules
149 read_modfile() {
151 if [ x"$MODFILE" != x ]; then
152 # Make sure the file is sane
153 if [ ! -r "$MODFILE" ]; then
154 echo "Error: module file '$MODFILE' is not readable or does not exist."
155 exit 1
157 # read from input file, skipping blank and comment lines
158 while read line; do
159 # skip blank lines
160 if [ x"$line" = x ]; then
161 continue
163 # skip comment lines
164 if echo "$line" | $GREP -q "^#" ; then
165 continue;
167 INPUT_MODULES="$INPUT_MODULES $line"
168 done <"$MODFILE"
170 return 0
173 #------------------------------------------------------------------------------
174 # Function: print_epilog
175 #------------------------------------------------------------------------------
177 print_epilog() {
179 epilog="======== Successful Completion"
180 if [ x"$NO_QUIT" != x ]; then
181 if [ x"$failed_modules" != x ]; then
182 epilog="======== Partial Completion"
184 elif [ x"$failed_modules" != x ]; then
185 epilog="======== Stopped on Error"
188 echo ""
189 echo "$epilog `date`"
191 # Report about modules that failed for one reason or another
192 if [ x"$failed_modules" != x ]; then
193 echo " List of failed modules:"
194 for mod in $failed_modules; do
195 echo " $mod"
196 done
197 echo "========"
198 echo ""
202 #------------------------------------------------------------------------------
203 # Function: process_modules
204 #------------------------------------------------------------------------------
206 # Loop through each module to release
207 # Exit on error if --no-quit was not specified
209 process_modules() {
210 for MODULE_RPATH in ${INPUT_MODULES}; do
211 if ! process_module ; then
212 echo "Error: processing module \"$MODULE_RPATH\" failed."
213 failed_modules="$failed_modules $MODULE_RPATH"
214 if [ x"$NO_QUIT" = x ]; then
215 print_epilog
216 exit 1
219 done
222 #------------------------------------------------------------------------------
223 # Function: get_section
224 #------------------------------------------------------------------------------
225 # Code 'return 0' on success
226 # Code 'return 1' on error
227 # Sets global variable $section
228 get_section() {
229 local module_url
230 local full_module_url
232 # Obtain the git url in order to find the section to which this module belongs
233 full_module_url=`git config --get remote.$remote_name.url | sed 's:\.git$::'`
234 if [ $? -ne 0 ]; then
235 echo "Error: unable to obtain git url for remote \"$remote_name\"."
236 return 1
239 # The last part of the git url will tell us the section. Look for xorg first
240 module_url=`echo "$full_module_url" | $GREP -o "xorg/.*"`
241 if [ $? -eq 0 ]; then
242 module_url=`echo $module_url | rev | cut -d'/' -f1,2 | rev`
243 else
244 # The look for mesa, xcb, etc...
245 module_url=`echo "$full_module_url" | $GREP -o -e "mesa/.*" -e "/xcb/.*" -e "/xkeyboard-config" -e "/nouveau/xf86-video-nouveau" -e "/libevdev" -e "/wayland/.*" -e "/evemu" -e "/libinput"`
246 if [ $? -eq 0 ]; then
247 module_url=`echo $module_url | cut -d'/' -f2,3`
248 else
249 echo "Error: unable to locate a valid project url from \"$full_module_url\"."
250 echo "Cannot establish url as one of xorg, mesa, xcb, xf86-video-nouveau, xkeyboard-config or wayland"
251 cd $top_src
252 return 1
256 # Find the section (subdirs) where the tarballs are to be uploaded
257 # The module relative path can be app/xfs, xserver, or mesa/drm for example
258 section=`echo $module_url | cut -d'/' -f1`
259 if [ $? -ne 0 ]; then
260 echo "Error: unable to extract section from $module_url first field."
261 return 1
264 if [ x"$section" = xmesa ]; then
265 section=`echo $module_url | cut -d'/' -f2`
266 if [ $? -ne 0 ]; then
267 echo "Error: unable to extract section from $module_url second field."
268 return 1
269 elif [ x"$section" != xdrm ] &&
270 [ x"$section" != xmesa ] &&
271 [ x"$section" != xglu ] &&
272 [ x"$section" != xdemos ]; then
273 echo "Error: section $section is not supported, only libdrm, mesa, glu and demos are."
274 return 1
278 if [ x"$section" = xwayland -o x"$section" = xxorg ]; then
279 section=`echo $module_url | cut -d'/' -f2`
280 if [ $? -ne 0 ]; then
281 echo "Error: unable to extract section from $module_url second field."
282 return 1
286 return 0
289 # Function: sign_or_fail
290 #------------------------------------------------------------------------------
292 # Sign the given file, if any
293 # Output the name of the signature generated to stdout (all other output to
294 # stderr)
295 # Return 0 on success, 1 on fail
297 sign_or_fail() {
298 if [ -n "$1" ]; then
299 sig=$1.sig
300 rm -f $sig
301 $GPG -b $GPGKEY $1 1>&2
302 if [ $? -ne 0 ]; then
303 echo "Error: failed to sign $1." >&2
304 return 1
306 echo $sig
308 return 0
311 #------------------------------------------------------------------------------
312 # Function: process_module
313 #------------------------------------------------------------------------------
314 # Code 'return 0' on success to process the next module
315 # Code 'return 1' on error to process next module if invoked with --no-quit
317 process_module() {
319 local use_autogen=0
320 local use_meson=0
322 top_src=`pwd`
323 echo ""
324 echo "======== Processing \"$top_src/$MODULE_RPATH\""
326 # This is the location where the script has been invoked
327 if [ ! -d $MODULE_RPATH ] ; then
328 echo "Error: $MODULE_RPATH cannot be found under $top_src."
329 return 1
332 # Change directory to be in the git module
333 cd $MODULE_RPATH
334 if [ $? -ne 0 ]; then
335 echo "Error: failed to cd to $MODULE_RPATH."
336 return 1
339 # ----- Now in the git module *root* directory ----- #
341 # Check that this is indeed a git module
342 # Don't assume that $(top_srcdir)/.git is a directory. It may be
343 # a gitlink file if $(top_srcdir) is a submodule checkout or a linked
344 # worktree.
345 if [ ! -e .git ]; then
346 echo "Error: there is no git module here: `pwd`"
347 return 1
350 # Determine what is the current branch and the remote name
351 current_branch=`git branch | $GREP "\*" | sed -e "s/\* //"`
352 remote_name=`git config --get branch.$current_branch.remote`
353 remote_branch=`git config --get branch.$current_branch.merge | cut -d'/' -f3,4`
354 echo "Info: working off the \"$current_branch\" branch tracking the remote \"$remote_name/$remote_branch\"."
356 # Obtain the section
357 get_section
358 if [ $? -ne 0 ]; then
359 cd $top_src
360 return 1
363 # Check for uncommitted/queued changes.
364 check_local_changes
365 if [ $? -ne 0 ]; then
366 return 1
369 if [ -f autogen.sh ]; then
370 use_autogen=1
371 elif [ -f meson.build ]; then
372 use_meson=1
373 which jq >& /dev/null
374 if [ $? -ne 0 ]; then
375 echo "Cannot find required jq(1) to parse project metadata"
376 return 1
378 else
379 echo "Cannot find autogen.sh or meson.build"
380 return 1
383 if [ $use_autogen != 0 ]; then
384 # If AC_CONFIG_AUX_DIR isn't set, libtool will search down to ../.. for
385 # install-sh and then just guesses that's the aux dir, dumping
386 # config.sub and other files into that directory. make distclean then
387 # complains about leftover files. So let's put our real module dir out
388 # of reach of libtool.
390 # We use release/$section/$build_dir because git worktree will pick the
391 # last part as branch identifier, so it needs to be random to avoid
392 # conflicts.
393 build_dir="release/$section"
394 mkdir -p "$build_dir"
396 # Create tmpdir for the release
397 build_dir=`mktemp -d -p "$build_dir" build.XXXXXXXXXX`
398 if [ $? -ne 0 ]; then
399 echo "Error: could not create a temporary directory for the release"
400 echo "Do you have coreutils' mktemp ?"
401 return 1
404 # Worktree removal is intentionally left to the user, due to:
405 # - currently we cannot select only one worktree to prune
406 # - requires to removal of $build_dir which might contradict with the
407 # user decision to keep some artefacts like tarballs or other
408 echo "Info: creating new git worktree."
409 git worktree add $build_dir
410 if [ $? -ne 0 ]; then
411 echo "Error: failed to create a git worktree."
412 cd $top_src
413 return 1
416 cd $build_dir
417 if [ $? -ne 0 ]; then
418 echo "Error: failed to cd to $MODULE_RPATH/$build_dir."
419 cd $top_src
420 return 1
423 echo "Info: running autogen.sh"
424 ./autogen.sh >/dev/null
426 if [ $? -ne 0 ]; then
427 echo "Error: failed to configure module."
428 cd $top_src
429 return 1
432 # Run 'make dist/distcheck' to ensure the tarball matches the git module content
433 # Important to run make dist/distcheck before looking in Makefile, may need to reconfigure
434 echo "Info: running \"make $MAKE_DIST_CMD\" to create tarballs:"
435 ${MAKE} $MAKEFLAGS $MAKE_DIST_CMD > /dev/null
436 if [ $? -ne 0 ]; then
437 echo "Error: \"$MAKE $MAKEFLAGS $MAKE_DIST_CMD\" failed."
438 cd $top_src
439 return 1
442 # Find out the tarname from the makefile
443 pkg_name=`$GREP '^PACKAGE = ' Makefile | sed 's|PACKAGE = ||'`
444 pkg_version=`$GREP '^VERSION = ' Makefile | sed 's|VERSION = ||'`
445 tar_root="."
446 announce_dir=$tar_root
447 else
448 # meson sets up ninja dist so we don't have to do worktrees and it
449 # has the builddir enabled by default
450 build_dir="builddir"
451 meson $build_dir
452 if [ $? -ne 0 ]; then
453 echo "Error: failed to configure module."
454 cd $top_src
455 return 1
458 echo "Info: running \"ninja dist\" to create tarball:"
459 ninja -C $build_dir dist
460 if [ $? -ne 0 ]; then
461 echo "Error: ninja dist failed"
462 cd $top_src
463 return 1
466 # Find out the package name from the meson.build file
467 pkg_name=$(meson introspect $build_dir --projectinfo | jq -r .descriptive_name)
468 pkg_version=$(meson introspect $build_dir --projectinfo | jq -r .version)
469 tar_root="$build_dir/meson-dist"
470 announce_dir=$tar_root
473 tar_name="$pkg_name-$pkg_version"
474 targz="$tar_root/$tar_name.tar.gz"
475 tarbz2="$tar_root/$tar_name.tar.bz2"
476 tarxz="$tar_root/$tar_name.tar.xz"
478 [ -e $targz ] && ls -l $targz || unset targz
479 [ -e $tarbz2 ] && ls -l $tarbz2 || unset tarbz2
480 [ -e $tarxz ] && ls -l $tarxz || unset tarxz
482 if [ -z "$targz" -a -z "$tarbz2" -a -z "$tarxz" ]; then
483 echo "Error: no compatible tarballs found."
484 cd $top_src
485 return 1
488 # wayland/weston/libinput tag with the version number only
489 tag_name="$tar_name"
490 if [ x"$section" = xwayland ] ||
491 [ x"$section" = xweston ] ||
492 [ x"$section" = xlibinput ]; then
493 tag_name="$pkg_version"
496 # evemu tag with the version number prefixed by 'v'
497 if [ x"$section" = xevemu ]; then
498 tag_name="v$pkg_version"
501 gpgsignerr=0
502 siggz="$(sign_or_fail ${targz})"
503 gpgsignerr=$((${gpgsignerr} + $?))
504 sigbz2="$(sign_or_fail ${tarbz2})"
505 gpgsignerr=$((${gpgsignerr} + $?))
506 sigxz="$(sign_or_fail ${tarxz})"
507 gpgsignerr=$((${gpgsignerr} + $?))
508 if [ ${gpgsignerr} -ne 0 ]; then
509 echo "Error: unable to sign at least one of the tarballs."
510 cd $top_src
511 return 1
514 # Obtain the top commit SHA which should be the version bump
515 # It should not have been tagged yet (the script will do it later)
516 local_top_commit_sha=`git rev-list --max-count=1 HEAD`
517 if [ $? -ne 0 ]; then
518 echo "Error: unable to obtain the local top commit id."
519 cd $top_src
520 return 1
523 # Check that the top commit looks like a version bump
524 git diff --unified=0 HEAD^ | $GREP -F $pkg_version >/dev/null 2>&1
525 if [ $? -ne 0 ]; then
526 # Wayland repos use m4_define([wayland_major_version], [0])
527 git diff --unified=0 HEAD^ | $GREP -E "(major|minor|micro)_version" >/dev/null 2>&1
528 if [ $? -ne 0 ]; then
529 echo "Error: the local top commit does not look like a version bump."
530 echo " the diff does not contain the string \"$pkg_version\"."
531 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
532 echo " the local top commit is: \"$local_top_commit_descr\""
533 cd $top_src
534 return 1
538 # Check that the top commit has been pushed to remote
539 remote_top_commit_sha=`git rev-list --max-count=1 $remote_name/$remote_branch`
540 if [ $? -ne 0 ]; then
541 echo "Error: unable to obtain top commit from the remote repository."
542 cd $top_src
543 return 1
545 if [ x"$remote_top_commit_sha" != x"$local_top_commit_sha" ]; then
546 echo "Error: the local top commit has not been pushed to the remote."
547 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
548 echo " the local top commit is: \"$local_top_commit_descr\""
549 cd $top_src
550 return 1
553 # If a tag exists with the tar name, ensure it is tagging the top commit
554 # It may happen if the version set in configure.ac has been previously released
555 tagged_commit_sha=`git rev-list --max-count=1 $tag_name 2>/dev/null`
556 if [ $? -eq 0 ]; then
557 # Check if the tag is pointing to the top commit
558 if [ x"$tagged_commit_sha" != x"$remote_top_commit_sha" ]; then
559 echo "Error: the \"$tag_name\" already exists."
560 echo " this tag is not tagging the top commit."
561 remote_top_commit_descr=`git log --oneline --max-count=1 $remote_top_commit_sha`
562 echo " the top commit is: \"$remote_top_commit_descr\""
563 local_tag_commit_descr=`git log --oneline --max-count=1 $tagged_commit_sha`
564 echo " tag \"$tag_name\" is tagging some other commit: \"$local_tag_commit_descr\""
565 cd $top_src
566 return 1
567 else
568 echo "Info: module already tagged with \"$tag_name\"."
570 else
571 # Tag the top commit with the tar name
572 if [ x"$DRY_RUN" = x ]; then
573 git tag $GPGKEY -s -m $tag_name $tag_name
574 if [ $? -ne 0 ]; then
575 echo "Error: unable to tag module with \"$tag_name\"."
576 cd $top_src
577 return 1
578 else
579 echo "Info: module tagged with \"$tag_name\"."
581 else
582 echo "Info: skipping the commit tagging in dry-run mode."
586 # --------- Now the tarballs are ready to upload ----------
588 # The hostname which is used to connect to the development resources
589 hostname="annarchy.freedesktop.org"
591 # Some hostnames are also used as /srv subdirs
592 host_fdo="www.freedesktop.org"
593 host_xorg="xorg.freedesktop.org"
594 host_dri="dri.freedesktop.org"
595 host_mesa="mesa.freedesktop.org"
596 host_wayland="wayland.freedesktop.org"
598 # Mailing lists where to post the all [Announce] e-mails
599 list_to="xorg-announce@lists.x.org"
601 # Mailing lists to be CC according to the project (xorg|dri|xkb)
602 list_xorg_user="xorg@lists.x.org"
603 list_dri_devel="dri-devel@lists.freedesktop.org"
604 list_mesa_announce="mesa-announce@lists.freedesktop.org"
605 list_mesa_devel="mesa-dev@lists.freedesktop.org"
607 list_xkb="xkb@listserv.bat.ru"
608 list_xcb="xcb@lists.freedesktop.org"
609 list_nouveau="nouveau@lists.freedesktop.org"
610 list_wayland="wayland-devel@lists.freedesktop.org"
611 list_input="input-tools@lists.freedesktop.org"
613 host_current=$host_xorg
614 section_path=archive/individual/$section
615 srv_path="/srv/$host_current/$section_path"
616 list_cc=$list_xorg_user
618 # Handle special cases such as non xorg projects or migrated xorg projects
619 # Nouveau has its own list and section, but goes with the other drivers
620 if [ x"$section" = xnouveau ]; then
621 section_path=archive/individual/driver
622 srv_path="/srv/$host_current/$section_path"
623 list_cc=$list_nouveau
626 # Xcb has a separate mailing list
627 if [ x"$section" = xxcb ]; then
628 list_cc=$list_xcb
631 # Module mesa/drm goes in the dri "libdrm" section
632 if [ x"$section" = xdrm ]; then
633 host_current=$host_dri
634 section_path=libdrm
635 srv_path="/srv/$host_current/www/$section_path"
636 list_cc=$list_dri_devel
637 elif [ x"$section" = xmesa ]; then
638 host_current=$host_mesa
639 section_path=archive
640 srv_path="/srv/$host_current/www/$section_path"
641 list_to=$list_mesa_announce
642 list_cc=$list_mesa_devel
643 elif [ x"$section" = xdemos ] || [ x"$section" = xglu ]; then
644 host_current=$host_mesa
645 section_path=archive/$section
646 srv_path="/srv/$host_current/www/$section_path"
647 list_to=$list_mesa_announce
648 list_cc=$list_mesa_devel
651 # Module xkeyboard-config goes in a subdir of the xorg "data" section
652 if [ x"$section" = xxkeyboard-config ]; then
653 host_current=$host_xorg
654 section_path=archive/individual/data/$section
655 srv_path="/srv/$host_current/$section_path"
656 list_cc=$list_xkb
659 if [ x"$section" = xlibevdev ]; then
660 host_current=$host_fdo
661 section_path="software/$section"
662 srv_path="/srv/$host_current/www/$section_path"
663 list_to=$list_input
664 unset list_cc
667 if [ x"$section" = xwayland ] ||
668 [ x"$section" = xweston ]; then
669 host_current=$host_wayland
670 section_path="releases"
671 srv_path="/srv/$host_current/www/$section_path"
672 list_to=$list_wayland
673 unset list_cc
674 elif [ x"$section" = xlibinput ]; then
675 host_current=$host_fdo
676 section_path="software/libinput"
677 srv_path="/srv/$host_current/www/$section_path"
678 list_to=$list_wayland
679 unset list_cc
680 elif [ x"$section" = xevemu ]; then
681 host_current=$host_fdo
682 section_path="software/evemu"
683 srv_path="/srv/$host_current/www/$section_path"
684 list_to=$list_input
685 unset list_cc
688 # Use personal web space on the host for unit testing (leave commented out)
689 # srv_path="~/public_html$srv_path"
691 # Check that the server path actually does exist
692 echo "Info: checking if path exists on web server:"
693 ssh $USER_NAME$hostname ls $srv_path >/dev/null 2>&1
694 if [ $? -ne 0 ]; then
695 echo "Error: the path \"$srv_path\" on the web server does not exist."
696 cd $top_src
697 return 1
700 # Check for already existing tarballs
701 for tarball in $targz $tarbz2 $tarxz; do
702 echo "Info: checking if tarball $tarball already exists on web server:"
703 ssh $USER_NAME$hostname ls $srv_path/$tarball >/dev/null 2>&1
704 if [ $? -eq 0 ]; then
705 if [ "x$FORCE" = "xyes" ]; then
706 echo "Warning: overwriting released tarballs due to --force option."
707 else
708 echo "Error: tarball $tar_name already exists. Use --force to overwrite."
709 cd $top_src
710 return 1
713 done
715 # Upload to host using the 'scp' remote file copy program
716 if [ x"$DRY_RUN" = x ]; then
717 echo "Info: uploading tarballs to web server:"
718 scp $targz $tarbz2 $tarxz $siggz $sigbz2 $sigxz $USER_NAME$hostname:$srv_path
719 if [ $? -ne 0 ]; then
720 echo "Error: the tarballs uploading failed."
721 cd $top_src
722 return 1
724 else
725 echo "Info: skipping tarballs uploading in dry-run mode."
726 echo " \"$srv_path\"."
729 # Pushing the top commit tag to the remote repository
730 if [ x$DRY_RUN = x ]; then
731 echo "Info: pushing tag \"$tag_name\" to remote \"$remote_name\":"
732 git push $remote_name $tag_name
733 if [ $? -ne 0 ]; then
734 echo "Error: unable to push tag \"$tag_name\" to the remote repository."
735 echo " it is recommended you fix this manually and not run the script again"
736 cd $top_src
737 return 1
739 else
740 echo "Info: skipped pushing tag \"$tag_name\" to the remote repository in dry-run mode."
743 MD5SUM=`which md5sum || which gmd5sum`
744 SHA1SUM=`which sha1sum || which gsha1sum`
745 SHA256SUM=`which sha256sum || which gsha256sum`
746 SHA512SUM=`which sha512sum || which gsha512sum`
748 # --------- Generate the announce e-mail ------------------
749 # Failing to generate the announce is not considered a fatal error
751 # Git-describe returns only "the most recent tag", it may not be the expected one
752 # However, we only use it for the commit history which will be the same anyway.
753 tag_previous=`git describe --abbrev=0 HEAD^ 2>/dev/null`
754 # Git fails with rc=128 if no tags can be found prior to HEAD^
755 if [ $? -ne 0 ]; then
756 if [ $? -ne 0 ]; then
757 echo "Warning: unable to find a previous tag."
758 echo " perhaps a first release on this branch."
759 echo " Please check the commit history in the announce."
762 if [ x"$tag_previous" != x ]; then
763 # The top commit may not have been tagged in dry-run mode. Use commit.
764 tag_range=$tag_previous..$local_top_commit_sha
765 else
766 tag_range=$tag_name
768 pushd "$tar_root"
769 generate_announce > "$tar_name.announce"
770 popd
772 echo "Info: [ANNOUNCE] template generated in \"$announce_dir/$tar_name.announce\" file."
773 echo " Please pgp sign and send it."
775 # --------- Update the JH Build moduleset -----------------
776 # Failing to update the jh moduleset is not considered a fatal error
777 if [ x"$JH_MODULESET" != x ]; then
778 for tarball in $targz $tarbz2 $tarxz; do
779 if [ x$DRY_RUN = x ]; then
780 sha1sum=`$SHA1SUM $tarball | cut -d' ' -f1`
781 $top_src/util/modular/update-moduleset.sh $JH_MODULESET $sha1sum $tarball
782 echo "Info: updated jh moduleset: \"$JH_MODULESET\""
783 else
784 echo "Info: skipping jh moduleset \"$JH_MODULESET\" update in dry-run mode."
787 # $tar* may be unset, so simply loop through all of them and the
788 # first one that is set updates the module file
789 break
790 done
794 # --------- Successful completion --------------------------
795 cd $top_src
796 return 0
800 #------------------------------------------------------------------------------
801 # Function: usage
802 #------------------------------------------------------------------------------
803 # Displays the script usage and exits successfully
805 usage() {
806 basename="`expr "//$0" : '.*/\([^/]*\)'`"
807 cat <<HELP
809 Usage: $basename [options] path...
811 Where "path" is a relative path to a git module, including '.'.
813 Options:
814 --dist make 'dist' instead of 'distcheck'; use with caution
815 --distcheck Default, ignored for compatibility
816 --dry-run Does everything except tagging and uploading tarballs
817 --force Force overwriting an existing release
818 --gpgkey <key> Specify the key used to sign the git tag/release tarballs
819 --help Display this help and exit successfully
820 --modfile <file> Release the git modules specified in <file>
821 --moduleset <file> The jhbuild moduleset full pathname to be updated
822 --no-quit Do not quit after error; just print error message
823 --user <name>@ Username of your fdo account if not configured in ssh
825 Environment variables defined by the "make" program and used by release.sh:
826 MAKE The name of the make command [make]
827 MAKEFLAGS: Options to pass to all \$(MAKE) invocations
829 HELP
832 #------------------------------------------------------------------------------
833 # Script main line
834 #------------------------------------------------------------------------------
837 # Choose which make program to use (could be gmake)
838 MAKE=${MAKE:="make"}
840 # Choose which grep program to use (on Solaris, must be gnu grep)
841 if [ "x$GREP" = "x" ] ; then
842 if [ -x /usr/gnu/bin/grep ] ; then
843 GREP=/usr/gnu/bin/grep
844 else
845 GREP=grep
849 # Find path for GnuPG v2
850 if [ "x$GPG" = "x" ] ; then
851 if [ -x /usr/bin/gpg2 ] ; then
852 GPG=/usr/bin/gpg2
853 else
854 GPG=gpg
858 # Avoid problems if GPGKEY is already set in the environment
859 unset GPGKEY
861 # Set the default make tarball creation command
862 MAKE_DIST_CMD=distcheck
864 # Process command line args
865 while [ $# != 0 ]
867 case $1 in
868 # Use 'dist' rather than 'distcheck' to create tarballs
869 # You really only want to do this if you're releasing a module you can't
870 # possibly build-test. Please consider carefully the wisdom of doing so.
871 --dist)
872 MAKE_DIST_CMD=dist
874 # Use 'distcheck' to create tarballs
875 --distcheck)
876 MAKE_DIST_CMD=distcheck
878 # Does everything except uploading tarball
879 --dry-run)
880 DRY_RUN=yes
882 # Force overwriting an existing release
883 # Use only if nothing changed in the git repo
884 --force)
885 FORCE=yes
887 # Allow user specified GPG key
888 --gpgkey)
889 check_option_args $1 $2
890 shift
891 check_gpgkey $1
892 GPGKEY="-u $1"
894 # Display this help and exit successfully
895 --help)
896 usage
897 exit 0
899 # Release the git modules specified in <file>
900 --modfile)
901 check_option_args $1 $2
902 shift
903 MODFILE=$1
905 # The jhbuild moduleset to update with relase info
906 --moduleset)
907 check_option_args $1 $2
908 shift
909 JH_MODULESET=$1
911 # Do not quit after error; just print error message
912 --no-quit)
913 NO_QUIT=yes
915 # Username of your fdo account if not configured in ssh
916 --user)
917 check_option_args $1 $2
918 shift
919 USER_NAME=$1
921 --*)
922 echo ""
923 echo "Error: unknown option: $1"
924 echo ""
925 usage
926 exit 1
929 echo ""
930 echo "Error: unknown option: $1"
931 echo ""
932 usage
933 exit 1
936 if [ x"${MODFILE}" != x ]; then
937 echo ""
938 echo "Error: specifying both modules and --modfile is not permitted"
939 echo ""
940 usage
941 exit 1
943 INPUT_MODULES="${INPUT_MODULES} $1"
945 esac
947 shift
948 done
950 # If no modules specified (blank cmd line) display help
951 check_modules_specification
953 # Read the module file and normalize input in INPUT_MODULES
954 read_modfile
956 # Loop through each module to release
957 # Exit on error if --no-quit no specified
958 process_modules
960 # Print the epilog with final status
961 print_epilog