release.sh: correct the link to the .announce file
[xorg-util-modular.git] / release.sh
blob826c11440e093d6099f52f0b7b7a7308d4ba483b
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 else
374 echo "Cannot find autogen.sh or meson.build"
375 return 1
378 if [ $use_autogen != 0 ]; then
379 # If AC_CONFIG_AUX_DIR isn't set, libtool will search down to ../.. for
380 # install-sh and then just guesses that's the aux dir, dumping
381 # config.sub and other files into that directory. make distclean then
382 # complains about leftover files. So let's put our real module dir out
383 # of reach of libtool.
385 # We use release/$section/$build_dir because git worktree will pick the
386 # last part as branch identifier, so it needs to be random to avoid
387 # conflicts.
388 build_dir="release/$section"
389 mkdir -p "$build_dir"
391 # Create tmpdir for the release
392 build_dir=`mktemp -d -p "$build_dir" build.XXXXXXXXXX`
393 if [ $? -ne 0 ]; then
394 echo "Error: could not create a temporary directory for the release"
395 echo "Do you have coreutils' mktemp ?"
396 return 1
399 # Worktree removal is intentionally left to the user, due to:
400 # - currently we cannot select only one worktree to prune
401 # - requires to removal of $build_dir which might contradict with the
402 # user decision to keep some artefacts like tarballs or other
403 echo "Info: creating new git worktree."
404 git worktree add $build_dir
405 if [ $? -ne 0 ]; then
406 echo "Error: failed to create a git worktree."
407 cd $top_src
408 return 1
411 cd $build_dir
412 if [ $? -ne 0 ]; then
413 echo "Error: failed to cd to $MODULE_RPATH/$build_dir."
414 cd $top_src
415 return 1
418 echo "Info: running autogen.sh"
419 ./autogen.sh >/dev/null
421 if [ $? -ne 0 ]; then
422 echo "Error: failed to configure module."
423 cd $top_src
424 return 1
427 # Run 'make dist/distcheck' to ensure the tarball matches the git module content
428 # Important to run make dist/distcheck before looking in Makefile, may need to reconfigure
429 echo "Info: running \"make $MAKE_DIST_CMD\" to create tarballs:"
430 ${MAKE} $MAKEFLAGS $MAKE_DIST_CMD > /dev/null
431 if [ $? -ne 0 ]; then
432 echo "Error: \"$MAKE $MAKEFLAGS $MAKE_DIST_CMD\" failed."
433 cd $top_src
434 return 1
437 # Find out the tarname from the makefile
438 pkg_name=`$GREP '^PACKAGE = ' Makefile | sed 's|PACKAGE = ||'`
439 pkg_version=`$GREP '^VERSION = ' Makefile | sed 's|VERSION = ||'`
440 tar_root="."
441 announce_dir=$tar_root
442 else
443 # meson sets up ninja dist so we don't have to do worktrees and it
444 # has the builddir enabled by default
445 build_dir="builddir"
446 meson $build_dir
447 if [ $? -ne 0 ]; then
448 echo "Error: failed to configure module."
449 cd $top_src
450 return 1
453 echo "Info: running \"ninja dist\" to create tarballs:"
454 ninja -C $build_dir dist
455 if [ $? -ne 0 ]; then
456 echo "Error: ninja dist failed"
457 cd $top_src
458 return 1
461 # Find out the package name from the meson.build file
462 pkg_name=`$GREP '^project(' meson.build | sed "s|project([\'\"]\([^\'\"]\+\)[\'\"].*|\1|"`
463 pkg_version=`git describe`
464 tar_root="$build_dir/meson-dist"
465 announce_dir=$tar_root
468 tar_name="$pkg_name-$pkg_version"
469 targz="$tar_root/$tar_name.tar.gz"
470 tarbz2="$tar_root/$tar_name.tar.bz2"
471 tarxz="$tar_root/$tar_name.tar.xz"
473 [ -e $targz ] && ls -l $targz || unset targz
474 [ -e $tarbz2 ] && ls -l $tarbz2 || unset tarbz2
475 [ -e $tarxz ] && ls -l $tarxz || unset tarxz
477 if [ -z "$targz" -a -z "$tarbz2" -a -z "$tarxz" ]; then
478 echo "Error: no compatible tarballs found."
479 cd $top_src
480 return 1
483 # wayland/weston/libinput tag with the version number only
484 tag_name="$tar_name"
485 if [ x"$section" = xwayland ] ||
486 [ x"$section" = xweston ] ||
487 [ x"$section" = xlibinput ]; then
488 tag_name="$pkg_version"
491 # evemu tag with the version number prefixed by 'v'
492 if [ x"$section" = xevemu ]; then
493 tag_name="v$pkg_version"
496 gpgsignerr=0
497 siggz="$(sign_or_fail ${targz})"
498 gpgsignerr=$((${gpgsignerr} + $?))
499 sigbz2="$(sign_or_fail ${tarbz2})"
500 gpgsignerr=$((${gpgsignerr} + $?))
501 sigxz="$(sign_or_fail ${tarxz})"
502 gpgsignerr=$((${gpgsignerr} + $?))
503 if [ ${gpgsignerr} -ne 0 ]; then
504 echo "Error: unable to sign at least one of the tarballs."
505 cd $top_src
506 return 1
509 # Obtain the top commit SHA which should be the version bump
510 # It should not have been tagged yet (the script will do it later)
511 local_top_commit_sha=`git rev-list --max-count=1 HEAD`
512 if [ $? -ne 0 ]; then
513 echo "Error: unable to obtain the local top commit id."
514 cd $top_src
515 return 1
518 # Check that the top commit looks like a version bump
519 git diff --unified=0 HEAD^ | $GREP -F $pkg_version >/dev/null 2>&1
520 if [ $? -ne 0 ]; then
521 # Wayland repos use m4_define([wayland_major_version], [0])
522 git diff --unified=0 HEAD^ | $GREP -E "(major|minor|micro)_version" >/dev/null 2>&1
523 if [ $? -ne 0 ]; then
524 echo "Error: the local top commit does not look like a version bump."
525 echo " the diff does not contain the string \"$pkg_version\"."
526 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
527 echo " the local top commit is: \"$local_top_commit_descr\""
528 cd $top_src
529 return 1
533 # Check that the top commit has been pushed to remote
534 remote_top_commit_sha=`git rev-list --max-count=1 $remote_name/$remote_branch`
535 if [ $? -ne 0 ]; then
536 echo "Error: unable to obtain top commit from the remote repository."
537 cd $top_src
538 return 1
540 if [ x"$remote_top_commit_sha" != x"$local_top_commit_sha" ]; then
541 echo "Error: the local top commit has not been pushed to the remote."
542 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
543 echo " the local top commit is: \"$local_top_commit_descr\""
544 cd $top_src
545 return 1
548 # If a tag exists with the tar name, ensure it is tagging the top commit
549 # It may happen if the version set in configure.ac has been previously released
550 tagged_commit_sha=`git rev-list --max-count=1 $tag_name 2>/dev/null`
551 if [ $? -eq 0 ]; then
552 # Check if the tag is pointing to the top commit
553 if [ x"$tagged_commit_sha" != x"$remote_top_commit_sha" ]; then
554 echo "Error: the \"$tag_name\" already exists."
555 echo " this tag is not tagging the top commit."
556 remote_top_commit_descr=`git log --oneline --max-count=1 $remote_top_commit_sha`
557 echo " the top commit is: \"$remote_top_commit_descr\""
558 local_tag_commit_descr=`git log --oneline --max-count=1 $tagged_commit_sha`
559 echo " tag \"$tag_name\" is tagging some other commit: \"$local_tag_commit_descr\""
560 cd $top_src
561 return 1
562 else
563 echo "Info: module already tagged with \"$tag_name\"."
565 else
566 # Tag the top commit with the tar name
567 if [ x"$DRY_RUN" = x ]; then
568 git tag $GPGKEY -s -m $tag_name $tag_name
569 if [ $? -ne 0 ]; then
570 echo "Error: unable to tag module with \"$tag_name\"."
571 cd $top_src
572 return 1
573 else
574 echo "Info: module tagged with \"$tag_name\"."
576 else
577 echo "Info: skipping the commit tagging in dry-run mode."
581 # --------- Now the tarballs are ready to upload ----------
583 # The hostname which is used to connect to the development resources
584 hostname="annarchy.freedesktop.org"
586 # Some hostnames are also used as /srv subdirs
587 host_fdo="www.freedesktop.org"
588 host_xorg="xorg.freedesktop.org"
589 host_dri="dri.freedesktop.org"
590 host_mesa="mesa.freedesktop.org"
591 host_wayland="wayland.freedesktop.org"
593 # Mailing lists where to post the all [Announce] e-mails
594 list_to="xorg-announce@lists.x.org"
596 # Mailing lists to be CC according to the project (xorg|dri|xkb)
597 list_xorg_user="xorg@lists.x.org"
598 list_dri_devel="dri-devel@lists.freedesktop.org"
599 list_mesa_announce="mesa-announce@lists.freedesktop.org"
600 list_mesa_devel="mesa-dev@lists.freedesktop.org"
602 list_xkb="xkb@listserv.bat.ru"
603 list_xcb="xcb@lists.freedesktop.org"
604 list_nouveau="nouveau@lists.freedesktop.org"
605 list_wayland="wayland-devel@lists.freedesktop.org"
606 list_input="input-tools@lists.freedesktop.org"
608 host_current=$host_xorg
609 section_path=archive/individual/$section
610 srv_path="/srv/$host_current/$section_path"
611 list_cc=$list_xorg_user
613 # Handle special cases such as non xorg projects or migrated xorg projects
614 # Nouveau has its own list and section, but goes with the other drivers
615 if [ x"$section" = xnouveau ]; then
616 section_path=archive/individual/driver
617 srv_path="/srv/$host_current/$section_path"
618 list_cc=$list_nouveau
621 # Xcb has a separate mailing list
622 if [ x"$section" = xxcb ]; then
623 list_cc=$list_xcb
626 # Module mesa/drm goes in the dri "libdrm" section
627 if [ x"$section" = xdrm ]; then
628 host_current=$host_dri
629 section_path=libdrm
630 srv_path="/srv/$host_current/www/$section_path"
631 list_cc=$list_dri_devel
632 elif [ x"$section" = xmesa ]; then
633 host_current=$host_mesa
634 section_path=archive
635 srv_path="/srv/$host_current/www/$section_path"
636 list_to=$list_mesa_announce
637 list_cc=$list_mesa_devel
638 elif [ x"$section" = xdemos ] || [ x"$section" = xglu ]; then
639 host_current=$host_mesa
640 section_path=archive/$section
641 srv_path="/srv/$host_current/www/$section_path"
642 list_to=$list_mesa_announce
643 list_cc=$list_mesa_devel
646 # Module xkeyboard-config goes in a subdir of the xorg "data" section
647 if [ x"$section" = xxkeyboard-config ]; then
648 host_current=$host_xorg
649 section_path=archive/individual/data/$section
650 srv_path="/srv/$host_current/$section_path"
651 list_cc=$list_xkb
654 if [ x"$section" = xlibevdev ]; then
655 host_current=$host_fdo
656 section_path="software/$section"
657 srv_path="/srv/$host_current/www/$section_path"
658 list_to=$list_input
659 unset list_cc
662 if [ x"$section" = xwayland ] ||
663 [ x"$section" = xweston ]; then
664 host_current=$host_wayland
665 section_path="releases"
666 srv_path="/srv/$host_current/www/$section_path"
667 list_to=$list_wayland
668 unset list_cc
669 elif [ x"$section" = xlibinput ]; then
670 host_current=$host_fdo
671 section_path="software/libinput"
672 srv_path="/srv/$host_current/www/$section_path"
673 list_to=$list_wayland
674 unset list_cc
675 elif [ x"$section" = xevemu ]; then
676 host_current=$host_fdo
677 section_path="software/evemu"
678 srv_path="/srv/$host_current/www/$section_path"
679 list_to=$list_input
680 unset list_cc
683 # Use personal web space on the host for unit testing (leave commented out)
684 # srv_path="~/public_html$srv_path"
686 # Check that the server path actually does exist
687 echo "Info: checking if path exists on web server:"
688 ssh $USER_NAME$hostname ls $srv_path >/dev/null 2>&1
689 if [ $? -ne 0 ]; then
690 echo "Error: the path \"$srv_path\" on the web server does not exist."
691 cd $top_src
692 return 1
695 # Check for already existing tarballs
696 for tarball in $targz $tarbz2 $tarxz; do
697 echo "Info: checking if tarball $tarball already exists on web server:"
698 ssh $USER_NAME$hostname ls $srv_path/$tarball >/dev/null 2>&1
699 if [ $? -eq 0 ]; then
700 if [ "x$FORCE" = "xyes" ]; then
701 echo "Warning: overwriting released tarballs due to --force option."
702 else
703 echo "Error: tarball $tar_name already exists. Use --force to overwrite."
704 cd $top_src
705 return 1
708 done
710 # Upload to host using the 'scp' remote file copy program
711 if [ x"$DRY_RUN" = x ]; then
712 echo "Info: uploading tarballs to web server:"
713 scp $targz $tarbz2 $tarxz $siggz $sigbz2 $sigxz $USER_NAME$hostname:$srv_path
714 if [ $? -ne 0 ]; then
715 echo "Error: the tarballs uploading failed."
716 cd $top_src
717 return 1
719 else
720 echo "Info: skipping tarballs uploading in dry-run mode."
721 echo " \"$srv_path\"."
724 # Pushing the top commit tag to the remote repository
725 if [ x$DRY_RUN = x ]; then
726 echo "Info: pushing tag \"$tag_name\" to remote \"$remote_name\":"
727 git push $remote_name $tag_name
728 if [ $? -ne 0 ]; then
729 echo "Error: unable to push tag \"$tag_name\" to the remote repository."
730 echo " it is recommended you fix this manually and not run the script again"
731 cd $top_src
732 return 1
734 else
735 echo "Info: skipped pushing tag \"$tag_name\" to the remote repository in dry-run mode."
738 MD5SUM=`which md5sum || which gmd5sum`
739 SHA1SUM=`which sha1sum || which gsha1sum`
740 SHA256SUM=`which sha256sum || which gsha256sum`
741 SHA512SUM=`which sha512sum || which gsha512sum`
743 # --------- Generate the announce e-mail ------------------
744 # Failing to generate the announce is not considered a fatal error
746 # Git-describe returns only "the most recent tag", it may not be the expected one
747 # However, we only use it for the commit history which will be the same anyway.
748 tag_previous=`git describe --abbrev=0 HEAD^ 2>/dev/null`
749 # Git fails with rc=128 if no tags can be found prior to HEAD^
750 if [ $? -ne 0 ]; then
751 if [ $? -ne 0 ]; then
752 echo "Warning: unable to find a previous tag."
753 echo " perhaps a first release on this branch."
754 echo " Please check the commit history in the announce."
757 if [ x"$tag_previous" != x ]; then
758 # The top commit may not have been tagged in dry-run mode. Use commit.
759 tag_range=$tag_previous..$local_top_commit_sha
760 else
761 tag_range=$tag_name
763 pushd "$tar_root"
764 generate_announce > "$tar_name.announce"
765 popd
767 echo "Info: [ANNOUNCE] template generated in \"$announce_dir/$tar_name.announce\" file."
768 echo " Please pgp sign and send it."
770 # --------- Update the JH Build moduleset -----------------
771 # Failing to update the jh moduleset is not considered a fatal error
772 if [ x"$JH_MODULESET" != x ]; then
773 for tarball in $targz $tarbz2 $tarxz; do
774 if [ x$DRY_RUN = x ]; then
775 sha1sum=`$SHA1SUM $tarball | cut -d' ' -f1`
776 $top_src/util/modular/update-moduleset.sh $JH_MODULESET $sha1sum $tarball
777 echo "Info: updated jh moduleset: \"$JH_MODULESET\""
778 else
779 echo "Info: skipping jh moduleset \"$JH_MODULESET\" update in dry-run mode."
782 # $tar* may be unset, so simply loop through all of them and the
783 # first one that is set updates the module file
784 break
785 done
789 # --------- Successful completion --------------------------
790 cd $top_src
791 return 0
795 #------------------------------------------------------------------------------
796 # Function: usage
797 #------------------------------------------------------------------------------
798 # Displays the script usage and exits successfully
800 usage() {
801 basename="`expr "//$0" : '.*/\([^/]*\)'`"
802 cat <<HELP
804 Usage: $basename [options] path...
806 Where "path" is a relative path to a git module, including '.'.
808 Options:
809 --dist make 'dist' instead of 'distcheck'; use with caution
810 --distcheck Default, ignored for compatibility
811 --dry-run Does everything except tagging and uploading tarballs
812 --force Force overwriting an existing release
813 --gpgkey <key> Specify the key used to sign the git tag/release tarballs
814 --help Display this help and exit successfully
815 --modfile <file> Release the git modules specified in <file>
816 --moduleset <file> The jhbuild moduleset full pathname to be updated
817 --no-quit Do not quit after error; just print error message
818 --user <name>@ Username of your fdo account if not configured in ssh
820 Environment variables defined by the "make" program and used by release.sh:
821 MAKE The name of the make command [make]
822 MAKEFLAGS: Options to pass to all \$(MAKE) invocations
824 HELP
827 #------------------------------------------------------------------------------
828 # Script main line
829 #------------------------------------------------------------------------------
832 # Choose which make program to use (could be gmake)
833 MAKE=${MAKE:="make"}
835 # Choose which grep program to use (on Solaris, must be gnu grep)
836 if [ "x$GREP" = "x" ] ; then
837 if [ -x /usr/gnu/bin/grep ] ; then
838 GREP=/usr/gnu/bin/grep
839 else
840 GREP=grep
844 # Find path for GnuPG v2
845 if [ "x$GPG" = "x" ] ; then
846 if [ -x /usr/bin/gpg2 ] ; then
847 GPG=/usr/bin/gpg2
848 else
849 GPG=gpg
853 # Avoid problems if GPGKEY is already set in the environment
854 unset GPGKEY
856 # Set the default make tarball creation command
857 MAKE_DIST_CMD=distcheck
859 # Process command line args
860 while [ $# != 0 ]
862 case $1 in
863 # Use 'dist' rather than 'distcheck' to create tarballs
864 # You really only want to do this if you're releasing a module you can't
865 # possibly build-test. Please consider carefully the wisdom of doing so.
866 --dist)
867 MAKE_DIST_CMD=dist
869 # Use 'distcheck' to create tarballs
870 --distcheck)
871 MAKE_DIST_CMD=distcheck
873 # Does everything except uploading tarball
874 --dry-run)
875 DRY_RUN=yes
877 # Force overwriting an existing release
878 # Use only if nothing changed in the git repo
879 --force)
880 FORCE=yes
882 # Allow user specified GPG key
883 --gpgkey)
884 check_option_args $1 $2
885 shift
886 check_gpgkey $1
887 GPGKEY="-u $1"
889 # Display this help and exit successfully
890 --help)
891 usage
892 exit 0
894 # Release the git modules specified in <file>
895 --modfile)
896 check_option_args $1 $2
897 shift
898 MODFILE=$1
900 # The jhbuild moduleset to update with relase info
901 --moduleset)
902 check_option_args $1 $2
903 shift
904 JH_MODULESET=$1
906 # Do not quit after error; just print error message
907 --no-quit)
908 NO_QUIT=yes
910 # Username of your fdo account if not configured in ssh
911 --user)
912 check_option_args $1 $2
913 shift
914 USER_NAME=$1
916 --*)
917 echo ""
918 echo "Error: unknown option: $1"
919 echo ""
920 usage
921 exit 1
924 echo ""
925 echo "Error: unknown option: $1"
926 echo ""
927 usage
928 exit 1
931 if [ x"${MODFILE}" != x ]; then
932 echo ""
933 echo "Error: specifying both modules and --modfile is not permitted"
934 echo ""
935 usage
936 exit 1
938 INPUT_MODULES="${INPUT_MODULES} $1"
940 esac
942 shift
943 done
945 # If no modules specified (blank cmd line) display help
946 check_modules_specification
948 # Read the module file and normalize input in INPUT_MODULES
949 read_modfile
951 # Loop through each module to release
952 # Exit on error if --no-quit no specified
953 process_modules
955 # Print the epilog with final status
956 print_epilog