release.sh: add support for meson projects
[xorg-util-modular.git] / release.sh
blob783b2ce1d88393e8414adaa285f803174b788eb4
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=C
13 #------------------------------------------------------------------------------
14 # Function: check_local_changes
15 #------------------------------------------------------------------------------
17 check_local_changes() {
18 git diff --quiet HEAD > /dev/null 2>&1
19 if [ $? -ne 0 ]; then
20 echo ""
21 echo "Uncommitted changes found. Did you forget to commit? Aborting."
22 echo ""
23 echo "You can perform a 'git stash' to save your local changes and"
24 echo "a 'git stash apply' to recover them after the tarball release."
25 echo "Make sure to rebuild and run 'make distcheck' again."
26 echo ""
27 echo "Alternatively, you can clone the module in another directory"
28 echo "and run ./configure. No need to build if testing was finished."
29 echo ""
30 return 1
32 return 0
35 #------------------------------------------------------------------------------
36 # Function: check_option_args
37 #------------------------------------------------------------------------------
39 # perform sanity checks on cmdline args which require arguments
40 # arguments:
41 # $1 - the option being examined
42 # $2 - the argument to the option
43 # returns:
44 # if it returns, everything is good
45 # otherwise it exit's
46 check_option_args() {
47 option=$1
48 arg=$2
50 # check for an argument
51 if [ x"$arg" = x ]; then
52 echo ""
53 echo "Error: the '$option' option is missing its required argument."
54 echo ""
55 usage
56 exit 1
59 # does the argument look like an option?
60 echo $arg | $GREP "^-" > /dev/null
61 if [ $? -eq 0 ]; then
62 echo ""
63 echo "Error: the argument '$arg' of option '$option' looks like an option itself."
64 echo ""
65 usage
66 exit 1
70 #------------------------------------------------------------------------------
71 # Function: check_gpgkey
72 #------------------------------------------------------------------------------
74 # check if the gpg key provided is known/available
75 # arguments:
76 # $1 - the gpg key
77 # returns:
78 # if it returns, everything is good
79 # otherwise it exit's
80 check_gpgkey() {
81 arg=$1
83 $GPG --list-keys "$arg" &>/dev/null
84 if [ $? -ne 0 ]; then
85 echo ""
86 echo "Error: the argument '$arg' is not a known gpg key."
87 echo ""
88 usage
89 exit 1
93 #------------------------------------------------------------------------------
94 # Function: check_modules_specification
95 #------------------------------------------------------------------------------
97 check_modules_specification() {
99 if [ x"$MODFILE" = x ]; then
100 if [ x"${INPUT_MODULES}" = x ]; then
101 echo ""
102 echo "Error: no modules specified (blank command line)."
103 usage
104 exit 1
110 #------------------------------------------------------------------------------
111 # Function: generate_announce
112 #------------------------------------------------------------------------------
114 generate_announce()
116 cat <<RELEASE
117 Subject: [ANNOUNCE] $pkg_name $pkg_version
118 To: $list_to
119 Cc: $list_cc
121 `git log --no-merges "$tag_range" | git shortlog`
123 git tag: $tag_name
125 RELEASE
127 for tarball in $tarbz2 $targz $tarxz; do
128 tarball=`basename $tarball`
129 cat <<RELEASE
130 https://$host_current/$section_path/$tarball
131 MD5: `$MD5SUM $tarball`
132 SHA1: `$SHA1SUM $tarball`
133 SHA256: `$SHA256SUM $tarball`
134 SHA512: `$SHA512SUM $tarball`
135 PGP: https://${host_current}/${section_path}/${tarball}.sig
137 RELEASE
138 done
141 #------------------------------------------------------------------------------
142 # Function: read_modfile
143 #------------------------------------------------------------------------------
145 # Read the module names from the file and set a variable to hold them
146 # This will be the same interface as cmd line supplied modules
148 read_modfile() {
150 if [ x"$MODFILE" != x ]; then
151 # Make sure the file is sane
152 if [ ! -r "$MODFILE" ]; then
153 echo "Error: module file '$MODFILE' is not readable or does not exist."
154 exit 1
156 # read from input file, skipping blank and comment lines
157 while read line; do
158 # skip blank lines
159 if [ x"$line" = x ]; then
160 continue
162 # skip comment lines
163 if echo "$line" | $GREP -q "^#" ; then
164 continue;
166 INPUT_MODULES="$INPUT_MODULES $line"
167 done <"$MODFILE"
169 return 0
172 #------------------------------------------------------------------------------
173 # Function: print_epilog
174 #------------------------------------------------------------------------------
176 print_epilog() {
178 epilog="======== Successful Completion"
179 if [ x"$NO_QUIT" != x ]; then
180 if [ x"$failed_modules" != x ]; then
181 epilog="======== Partial Completion"
183 elif [ x"$failed_modules" != x ]; then
184 epilog="======== Stopped on Error"
187 echo ""
188 echo "$epilog `date`"
190 # Report about modules that failed for one reason or another
191 if [ x"$failed_modules" != x ]; then
192 echo " List of failed modules:"
193 for mod in $failed_modules; do
194 echo " $mod"
195 done
196 echo "========"
197 echo ""
201 #------------------------------------------------------------------------------
202 # Function: process_modules
203 #------------------------------------------------------------------------------
205 # Loop through each module to release
206 # Exit on error if --no-quit was not specified
208 process_modules() {
209 for MODULE_RPATH in ${INPUT_MODULES}; do
210 if ! process_module ; then
211 echo "Error: processing module \"$MODULE_RPATH\" failed."
212 failed_modules="$failed_modules $MODULE_RPATH"
213 if [ x"$NO_QUIT" = x ]; then
214 print_epilog
215 exit 1
218 done
221 #------------------------------------------------------------------------------
222 # Function: get_section
223 #------------------------------------------------------------------------------
224 # Code 'return 0' on success
225 # Code 'return 1' on error
226 # Sets global variable $section
227 get_section() {
228 local module_url
229 local full_module_url
231 # Obtain the git url in order to find the section to which this module belongs
232 full_module_url=`git config --get remote.$remote_name.url | sed 's:\.git$::'`
233 if [ $? -ne 0 ]; then
234 echo "Error: unable to obtain git url for remote \"$remote_name\"."
235 return 1
238 # The last part of the git url will tell us the section. Look for xorg first
239 module_url=`echo "$full_module_url" | $GREP -o "xorg/.*"`
240 if [ $? -eq 0 ]; then
241 module_url=`echo $module_url | rev | cut -d'/' -f1,2 | rev`
242 else
243 # The look for mesa, xcb, etc...
244 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"`
245 if [ $? -eq 0 ]; then
246 module_url=`echo $module_url | cut -d'/' -f2,3`
247 else
248 echo "Error: unable to locate a valid project url from \"$full_module_url\"."
249 echo "Cannot establish url as one of xorg, mesa, xcb, xf86-video-nouveau, xkeyboard-config or wayland"
250 cd $top_src
251 return 1
255 # Find the section (subdirs) where the tarballs are to be uploaded
256 # The module relative path can be app/xfs, xserver, or mesa/drm for example
257 section=`echo $module_url | cut -d'/' -f1`
258 if [ $? -ne 0 ]; then
259 echo "Error: unable to extract section from $module_url first field."
260 return 1
263 if [ x"$section" = xmesa ]; then
264 section=`echo $module_url | cut -d'/' -f2`
265 if [ $? -ne 0 ]; then
266 echo "Error: unable to extract section from $module_url second field."
267 return 1
268 elif [ x"$section" != xdrm ] &&
269 [ x"$section" != xmesa ] &&
270 [ x"$section" != xglu ] &&
271 [ x"$section" != xdemos ]; then
272 echo "Error: section $section is not supported, only libdrm, mesa, glu and demos are."
273 return 1
277 if [ x"$section" = xwayland -o x"$section" = xxorg ]; then
278 section=`echo $module_url | cut -d'/' -f2`
279 if [ $? -ne 0 ]; then
280 echo "Error: unable to extract section from $module_url second field."
281 return 1
285 return 0
288 # Function: sign_or_fail
289 #------------------------------------------------------------------------------
291 # Sign the given file, if any
292 # Output the name of the signature generated to stdout (all other output to
293 # stderr)
294 # Return 0 on success, 1 on fail
296 sign_or_fail() {
297 if [ -n "$1" ]; then
298 sig=$1.sig
299 rm -f $sig
300 $GPG -b $GPGKEY $1 1>&2
301 if [ $? -ne 0 ]; then
302 echo "Error: failed to sign $1." >&2
303 return 1
305 echo $sig
307 return 0
310 #------------------------------------------------------------------------------
311 # Function: process_module
312 #------------------------------------------------------------------------------
313 # Code 'return 0' on success to process the next module
314 # Code 'return 1' on error to process next module if invoked with --no-quit
316 process_module() {
318 local use_autogen=0
319 local use_meson=0
321 top_src=`pwd`
322 echo ""
323 echo "======== Processing \"$top_src/$MODULE_RPATH\""
325 # This is the location where the script has been invoked
326 if [ ! -d $MODULE_RPATH ] ; then
327 echo "Error: $MODULE_RPATH cannot be found under $top_src."
328 return 1
331 # Change directory to be in the git module
332 cd $MODULE_RPATH
333 if [ $? -ne 0 ]; then
334 echo "Error: failed to cd to $MODULE_RPATH."
335 return 1
338 # ----- Now in the git module *root* directory ----- #
340 # Check that this is indeed a git module
341 # Don't assume that $(top_srcdir)/.git is a directory. It may be
342 # a gitlink file if $(top_srcdir) is a submodule checkout or a linked
343 # worktree.
344 if [ ! -e .git ]; then
345 echo "Error: there is no git module here: `pwd`"
346 return 1
349 # Determine what is the current branch and the remote name
350 current_branch=`git branch | $GREP "\*" | sed -e "s/\* //"`
351 remote_name=`git config --get branch.$current_branch.remote`
352 remote_branch=`git config --get branch.$current_branch.merge | cut -d'/' -f3,4`
353 echo "Info: working off the \"$current_branch\" branch tracking the remote \"$remote_name/$remote_branch\"."
355 # Obtain the section
356 get_section
357 if [ $? -ne 0 ]; then
358 cd $top_src
359 return 1
362 # Check for uncommitted/queued changes.
363 check_local_changes
364 if [ $? -ne 0 ]; then
365 return 1
368 if [ -f autogen.sh ]; then
369 use_autogen=1
370 elif [ -f meson.build ]; then
371 use_meson=1
372 else
373 echo "Cannot find autogen.sh or meson.build"
374 return 1
377 if [ $use_autogen != 0 ]; then
378 # If AC_CONFIG_AUX_DIR isn't set, libtool will search down to ../.. for
379 # install-sh and then just guesses that's the aux dir, dumping
380 # config.sub and other files into that directory. make distclean then
381 # complains about leftover files. So let's put our real module dir out
382 # of reach of libtool.
384 # We use release/$section/$build_dir because git worktree will pick the
385 # last part as branch identifier, so it needs to be random to avoid
386 # conflicts.
387 build_dir="release/$section"
388 mkdir -p "$build_dir"
390 # Create tmpdir for the release
391 build_dir=`mktemp -d -p "$build_dir" build.XXXXXXXXXX`
392 if [ $? -ne 0 ]; then
393 echo "Error: could not create a temporary directory for the release"
394 echo "Do you have coreutils' mktemp ?"
395 return 1
398 # Worktree removal is intentionally left to the user, due to:
399 # - currently we cannot select only one worktree to prune
400 # - requires to removal of $build_dir which might contradict with the
401 # user decision to keep some artefacts like tarballs or other
402 echo "Info: creating new git worktree."
403 git worktree add $build_dir
404 if [ $? -ne 0 ]; then
405 echo "Error: failed to create a git worktree."
406 cd $top_src
407 return 1
410 cd $build_dir
411 if [ $? -ne 0 ]; then
412 echo "Error: failed to cd to $MODULE_RPATH/$build_dir."
413 cd $top_src
414 return 1
417 echo "Info: running autogen.sh"
418 ./autogen.sh >/dev/null
420 if [ $? -ne 0 ]; then
421 echo "Error: failed to configure module."
422 cd $top_src
423 return 1
426 # Run 'make dist/distcheck' to ensure the tarball matches the git module content
427 # Important to run make dist/distcheck before looking in Makefile, may need to reconfigure
428 echo "Info: running \"make $MAKE_DIST_CMD\" to create tarballs:"
429 ${MAKE} $MAKEFLAGS $MAKE_DIST_CMD > /dev/null
430 if [ $? -ne 0 ]; then
431 echo "Error: \"$MAKE $MAKEFLAGS $MAKE_DIST_CMD\" failed."
432 cd $top_src
433 return 1
436 # Find out the tarname from the makefile
437 pkg_name=`$GREP '^PACKAGE = ' Makefile | sed 's|PACKAGE = ||'`
438 pkg_version=`$GREP '^VERSION = ' Makefile | sed 's|VERSION = ||'`
439 tar_root="."
440 else
441 # meson sets up ninja dist so we don't have to do worktrees and it
442 # has the builddir enabled by default
443 build_dir="builddir"
444 meson $build_dir
445 if [ $? -ne 0 ]; then
446 echo "Error: failed to configure module."
447 cd $top_src
448 return 1
451 echo "Info: running \"ninja dist\" to create tarballs:"
452 ninja -C $build_dir dist
453 if [ $? -ne 0 ]; then
454 echo "Error: ninja dist failed"
455 cd $top_src
456 return 1
459 # Find out the package name from the meson.build file
460 pkg_name=`$GREP '^project(' meson.build | sed "s|project([\'\"]\([^\'\"]\+\)[\'\"].*|\1|"`
461 pkg_version=`git describe`
462 tar_root="$build_dir/meson-dist"
465 tar_name="$pkg_name-$pkg_version"
466 targz="$tar_root/$tar_name.tar.gz"
467 tarbz2="$tar_root/$tar_name.tar.bz2"
468 tarxz="$tar_root/$tar_name.tar.xz"
470 [ -e $targz ] && ls -l $targz || unset targz
471 [ -e $tarbz2 ] && ls -l $tarbz2 || unset tarbz2
472 [ -e $tarxz ] && ls -l $tarxz || unset tarxz
474 if [ -z "$targz" -a -z "$tarbz2" -a -z "$tarxz" ]; then
475 echo "Error: no compatible tarballs found."
476 cd $top_src
477 return 1
480 # wayland/weston/libinput tag with the version number only
481 tag_name="$tar_name"
482 if [ x"$section" = xwayland ] ||
483 [ x"$section" = xweston ] ||
484 [ x"$section" = xlibinput ]; then
485 tag_name="$pkg_version"
488 # evemu tag with the version number prefixed by 'v'
489 if [ x"$section" = xevemu ]; then
490 tag_name="v$pkg_version"
493 gpgsignerr=0
494 siggz="$(sign_or_fail ${targz})"
495 gpgsignerr=$((${gpgsignerr} + $?))
496 sigbz2="$(sign_or_fail ${tarbz2})"
497 gpgsignerr=$((${gpgsignerr} + $?))
498 sigxz="$(sign_or_fail ${tarxz})"
499 gpgsignerr=$((${gpgsignerr} + $?))
500 if [ ${gpgsignerr} -ne 0 ]; then
501 echo "Error: unable to sign at least one of the tarballs."
502 cd $top_src
503 return 1
506 # Obtain the top commit SHA which should be the version bump
507 # It should not have been tagged yet (the script will do it later)
508 local_top_commit_sha=`git rev-list --max-count=1 HEAD`
509 if [ $? -ne 0 ]; then
510 echo "Error: unable to obtain the local top commit id."
511 cd $top_src
512 return 1
515 # Check that the top commit looks like a version bump
516 git diff --unified=0 HEAD^ | $GREP -F $pkg_version >/dev/null 2>&1
517 if [ $? -ne 0 ]; then
518 # Wayland repos use m4_define([wayland_major_version], [0])
519 git diff --unified=0 HEAD^ | $GREP -E "(major|minor|micro)_version" >/dev/null 2>&1
520 if [ $? -ne 0 ]; then
521 echo "Error: the local top commit does not look like a version bump."
522 echo " the diff does not contain the string \"$pkg_version\"."
523 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
524 echo " the local top commit is: \"$local_top_commit_descr\""
525 cd $top_src
526 return 1
530 # Check that the top commit has been pushed to remote
531 remote_top_commit_sha=`git rev-list --max-count=1 $remote_name/$remote_branch`
532 if [ $? -ne 0 ]; then
533 echo "Error: unable to obtain top commit from the remote repository."
534 cd $top_src
535 return 1
537 if [ x"$remote_top_commit_sha" != x"$local_top_commit_sha" ]; then
538 echo "Error: the local top commit has not been pushed to the remote."
539 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
540 echo " the local top commit is: \"$local_top_commit_descr\""
541 cd $top_src
542 return 1
545 # If a tag exists with the tar name, ensure it is tagging the top commit
546 # It may happen if the version set in configure.ac has been previously released
547 tagged_commit_sha=`git rev-list --max-count=1 $tag_name 2>/dev/null`
548 if [ $? -eq 0 ]; then
549 # Check if the tag is pointing to the top commit
550 if [ x"$tagged_commit_sha" != x"$remote_top_commit_sha" ]; then
551 echo "Error: the \"$tag_name\" already exists."
552 echo " this tag is not tagging the top commit."
553 remote_top_commit_descr=`git log --oneline --max-count=1 $remote_top_commit_sha`
554 echo " the top commit is: \"$remote_top_commit_descr\""
555 local_tag_commit_descr=`git log --oneline --max-count=1 $tagged_commit_sha`
556 echo " tag \"$tag_name\" is tagging some other commit: \"$local_tag_commit_descr\""
557 cd $top_src
558 return 1
559 else
560 echo "Info: module already tagged with \"$tag_name\"."
562 else
563 # Tag the top commit with the tar name
564 if [ x"$DRY_RUN" = x ]; then
565 git tag $GPGKEY -s -m $tag_name $tag_name
566 if [ $? -ne 0 ]; then
567 echo "Error: unable to tag module with \"$tag_name\"."
568 cd $top_src
569 return 1
570 else
571 echo "Info: module tagged with \"$tag_name\"."
573 else
574 echo "Info: skipping the commit tagging in dry-run mode."
578 # --------- Now the tarballs are ready to upload ----------
580 # The hostname which is used to connect to the development resources
581 hostname="annarchy.freedesktop.org"
583 # Some hostnames are also used as /srv subdirs
584 host_fdo="www.freedesktop.org"
585 host_xorg="xorg.freedesktop.org"
586 host_dri="dri.freedesktop.org"
587 host_mesa="mesa.freedesktop.org"
588 host_wayland="wayland.freedesktop.org"
590 # Mailing lists where to post the all [Announce] e-mails
591 list_to="xorg-announce@lists.x.org"
593 # Mailing lists to be CC according to the project (xorg|dri|xkb)
594 list_xorg_user="xorg@lists.x.org"
595 list_dri_devel="dri-devel@lists.freedesktop.org"
596 list_mesa_announce="mesa-announce@lists.freedesktop.org"
597 list_mesa_devel="mesa-dev@lists.freedesktop.org"
599 list_xkb="xkb@listserv.bat.ru"
600 list_xcb="xcb@lists.freedesktop.org"
601 list_nouveau="nouveau@lists.freedesktop.org"
602 list_wayland="wayland-devel@lists.freedesktop.org"
603 list_input="input-tools@lists.freedesktop.org"
605 host_current=$host_xorg
606 section_path=archive/individual/$section
607 srv_path="/srv/$host_current/$section_path"
608 list_cc=$list_xorg_user
610 # Handle special cases such as non xorg projects or migrated xorg projects
611 # Nouveau has its own list and section, but goes with the other drivers
612 if [ x"$section" = xnouveau ]; then
613 section_path=archive/individual/driver
614 srv_path="/srv/$host_current/$section_path"
615 list_cc=$list_nouveau
618 # Xcb has a separate mailing list
619 if [ x"$section" = xxcb ]; then
620 list_cc=$list_xcb
623 # Module mesa/drm goes in the dri "libdrm" section
624 if [ x"$section" = xdrm ]; then
625 host_current=$host_dri
626 section_path=libdrm
627 srv_path="/srv/$host_current/www/$section_path"
628 list_cc=$list_dri_devel
629 elif [ x"$section" = xmesa ]; then
630 host_current=$host_mesa
631 section_path=archive
632 srv_path="/srv/$host_current/www/$section_path"
633 list_to=$list_mesa_announce
634 list_cc=$list_mesa_devel
635 elif [ x"$section" = xdemos ] || [ x"$section" = xglu ]; then
636 host_current=$host_mesa
637 section_path=archive/$section
638 srv_path="/srv/$host_current/www/$section_path"
639 list_to=$list_mesa_announce
640 list_cc=$list_mesa_devel
643 # Module xkeyboard-config goes in a subdir of the xorg "data" section
644 if [ x"$section" = xxkeyboard-config ]; then
645 host_current=$host_xorg
646 section_path=archive/individual/data/$section
647 srv_path="/srv/$host_current/$section_path"
648 list_cc=$list_xkb
651 if [ x"$section" = xlibevdev ]; then
652 host_current=$host_fdo
653 section_path="software/$section"
654 srv_path="/srv/$host_current/www/$section_path"
655 list_to=$list_input
656 unset list_cc
659 if [ x"$section" = xwayland ] ||
660 [ x"$section" = xweston ]; then
661 host_current=$host_wayland
662 section_path="releases"
663 srv_path="/srv/$host_current/www/$section_path"
664 list_to=$list_wayland
665 unset list_cc
666 elif [ x"$section" = xlibinput ]; then
667 host_current=$host_fdo
668 section_path="software/libinput"
669 srv_path="/srv/$host_current/www/$section_path"
670 list_to=$list_wayland
671 unset list_cc
672 elif [ x"$section" = xevemu ]; then
673 host_current=$host_fdo
674 section_path="software/evemu"
675 srv_path="/srv/$host_current/www/$section_path"
676 list_to=$list_input
677 unset list_cc
680 # Use personal web space on the host for unit testing (leave commented out)
681 # srv_path="~/public_html$srv_path"
683 # Check that the server path actually does exist
684 echo "Info: checking if path exists on web server:"
685 ssh $USER_NAME$hostname ls $srv_path >/dev/null 2>&1
686 if [ $? -ne 0 ]; then
687 echo "Error: the path \"$srv_path\" on the web server does not exist."
688 cd $top_src
689 return 1
692 # Check for already existing tarballs
693 for tarball in $targz $tarbz2 $tarxz; do
694 echo "Info: checking if tarball $tarball already exists on web server:"
695 ssh $USER_NAME$hostname ls $srv_path/$tarball >/dev/null 2>&1
696 if [ $? -eq 0 ]; then
697 if [ "x$FORCE" = "xyes" ]; then
698 echo "Warning: overwriting released tarballs due to --force option."
699 else
700 echo "Error: tarball $tar_name already exists. Use --force to overwrite."
701 cd $top_src
702 return 1
705 done
707 # Upload to host using the 'scp' remote file copy program
708 if [ x"$DRY_RUN" = x ]; then
709 echo "Info: uploading tarballs to web server:"
710 scp $targz $tarbz2 $tarxz $siggz $sigbz2 $sigxz $USER_NAME$hostname:$srv_path
711 if [ $? -ne 0 ]; then
712 echo "Error: the tarballs uploading failed."
713 cd $top_src
714 return 1
716 else
717 echo "Info: skipping tarballs uploading in dry-run mode."
718 echo " \"$srv_path\"."
721 # Pushing the top commit tag to the remote repository
722 if [ x$DRY_RUN = x ]; then
723 echo "Info: pushing tag \"$tag_name\" to remote \"$remote_name\":"
724 git push $remote_name $tag_name
725 if [ $? -ne 0 ]; then
726 echo "Error: unable to push tag \"$tag_name\" to the remote repository."
727 echo " it is recommended you fix this manually and not run the script again"
728 cd $top_src
729 return 1
731 else
732 echo "Info: skipped pushing tag \"$tag_name\" to the remote repository in dry-run mode."
735 MD5SUM=`which md5sum || which gmd5sum`
736 SHA1SUM=`which sha1sum || which gsha1sum`
737 SHA256SUM=`which sha256sum || which gsha256sum`
738 SHA512SUM=`which sha512sum || which gsha512sum`
740 # --------- Generate the announce e-mail ------------------
741 # Failing to generate the announce is not considered a fatal error
743 # Git-describe returns only "the most recent tag", it may not be the expected one
744 # However, we only use it for the commit history which will be the same anyway.
745 tag_previous=`git describe --abbrev=0 HEAD^ 2>/dev/null`
746 # Git fails with rc=128 if no tags can be found prior to HEAD^
747 if [ $? -ne 0 ]; then
748 if [ $? -ne 0 ]; then
749 echo "Warning: unable to find a previous tag."
750 echo " perhaps a first release on this branch."
751 echo " Please check the commit history in the announce."
754 if [ x"$tag_previous" != x ]; then
755 # The top commit may not have been tagged in dry-run mode. Use commit.
756 tag_range=$tag_previous..$local_top_commit_sha
757 else
758 tag_range=$tag_name
760 pushd "$tar_root"
761 generate_announce > "$tar_name.announce"
762 popd
763 echo "Info: [ANNOUNCE] template generated in \"$build_dir/$tar_name.announce\" file."
764 echo " Please pgp sign and send it."
766 # --------- Update the JH Build moduleset -----------------
767 # Failing to update the jh moduleset is not considered a fatal error
768 if [ x"$JH_MODULESET" != x ]; then
769 for tarball in $targz $tarbz2 $tarxz; do
770 if [ x$DRY_RUN = x ]; then
771 sha1sum=`$SHA1SUM $tarball | cut -d' ' -f1`
772 $top_src/util/modular/update-moduleset.sh $JH_MODULESET $sha1sum $tarball
773 echo "Info: updated jh moduleset: \"$JH_MODULESET\""
774 else
775 echo "Info: skipping jh moduleset \"$JH_MODULESET\" update in dry-run mode."
778 # $tar* may be unset, so simply loop through all of them and the
779 # first one that is set updates the module file
780 break
781 done
785 # --------- Successful completion --------------------------
786 cd $top_src
787 return 0
791 #------------------------------------------------------------------------------
792 # Function: usage
793 #------------------------------------------------------------------------------
794 # Displays the script usage and exits successfully
796 usage() {
797 basename="`expr "//$0" : '.*/\([^/]*\)'`"
798 cat <<HELP
800 Usage: $basename [options] path...
802 Where "path" is a relative path to a git module, including '.'.
804 Options:
805 --dist make 'dist' instead of 'distcheck'; use with caution
806 --distcheck Default, ignored for compatibility
807 --dry-run Does everything except tagging and uploading tarballs
808 --force Force overwriting an existing release
809 --gpgkey <key> Specify the key used to sign the git tag/release tarballs
810 --help Display this help and exit successfully
811 --modfile <file> Release the git modules specified in <file>
812 --moduleset <file> The jhbuild moduleset full pathname to be updated
813 --no-quit Do not quit after error; just print error message
814 --user <name>@ Username of your fdo account if not configured in ssh
816 Environment variables defined by the "make" program and used by release.sh:
817 MAKE The name of the make command [make]
818 MAKEFLAGS: Options to pass to all \$(MAKE) invocations
820 HELP
823 #------------------------------------------------------------------------------
824 # Script main line
825 #------------------------------------------------------------------------------
828 # Choose which make program to use (could be gmake)
829 MAKE=${MAKE:="make"}
831 # Choose which grep program to use (on Solaris, must be gnu grep)
832 if [ "x$GREP" = "x" ] ; then
833 if [ -x /usr/gnu/bin/grep ] ; then
834 GREP=/usr/gnu/bin/grep
835 else
836 GREP=grep
840 # Find path for GnuPG v2
841 if [ "x$GPG" = "x" ] ; then
842 if [ -x /usr/bin/gpg2 ] ; then
843 GPG=/usr/bin/gpg2
844 else
845 GPG=gpg
849 # Avoid problems if GPGKEY is already set in the environment
850 unset GPGKEY
852 # Set the default make tarball creation command
853 MAKE_DIST_CMD=distcheck
855 # Process command line args
856 while [ $# != 0 ]
858 case $1 in
859 # Use 'dist' rather than 'distcheck' to create tarballs
860 # You really only want to do this if you're releasing a module you can't
861 # possibly build-test. Please consider carefully the wisdom of doing so.
862 --dist)
863 MAKE_DIST_CMD=dist
865 # Use 'distcheck' to create tarballs
866 --distcheck)
867 MAKE_DIST_CMD=distcheck
869 # Does everything except uploading tarball
870 --dry-run)
871 DRY_RUN=yes
873 # Force overwriting an existing release
874 # Use only if nothing changed in the git repo
875 --force)
876 FORCE=yes
878 # Allow user specified GPG key
879 --gpgkey)
880 check_option_args $1 $2
881 shift
882 check_gpgkey $1
883 GPGKEY="-u $1"
885 # Display this help and exit successfully
886 --help)
887 usage
888 exit 0
890 # Release the git modules specified in <file>
891 --modfile)
892 check_option_args $1 $2
893 shift
894 MODFILE=$1
896 # The jhbuild moduleset to update with relase info
897 --moduleset)
898 check_option_args $1 $2
899 shift
900 JH_MODULESET=$1
902 # Do not quit after error; just print error message
903 --no-quit)
904 NO_QUIT=yes
906 # Username of your fdo account if not configured in ssh
907 --user)
908 check_option_args $1 $2
909 shift
910 USER_NAME=$1
912 --*)
913 echo ""
914 echo "Error: unknown option: $1"
915 echo ""
916 usage
917 exit 1
920 echo ""
921 echo "Error: unknown option: $1"
922 echo ""
923 usage
924 exit 1
927 if [ x"${MODFILE}" != x ]; then
928 echo ""
929 echo "Error: specifying both modules and --modfile is not permitted"
930 echo ""
931 usage
932 exit 1
934 INPUT_MODULES="${INPUT_MODULES} $1"
936 esac
938 shift
939 done
941 # If no modules specified (blank cmd line) display help
942 check_modules_specification
944 # Read the module file and normalize input in INPUT_MODULES
945 read_modfile
947 # Loop through each module to release
948 # Exit on error if --no-quit no specified
949 process_modules
951 # Print the epilog with final status
952 print_epilog