build.sh: add libXpresent
[xorg-util-modular.git] / release.sh
blob1da93a7f4cd69987557372fd899ddbd1fd9cd581
1 #!/usr/bin/env 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 SHA256: `$SHA256SUM $tarball`
133 SHA512: `$SHA512SUM $tarball`
134 PGP: https://${host_current}/${section_path}/${tarball}.sig
136 RELEASE
137 done
140 #------------------------------------------------------------------------------
141 # Function: read_modfile
142 #------------------------------------------------------------------------------
144 # Read the module names from the file and set a variable to hold them
145 # This will be the same interface as cmd line supplied modules
147 read_modfile() {
149 if [ x"$MODFILE" != x ]; then
150 # Make sure the file is sane
151 if [ ! -r "$MODFILE" ]; then
152 echo "Error: module file '$MODFILE' is not readable or does not exist."
153 exit 1
155 # read from input file, skipping blank and comment lines
156 while read line; do
157 # skip blank lines
158 if [ x"$line" = x ]; then
159 continue
161 # skip comment lines
162 if echo "$line" | $GREP -q "^#" ; then
163 continue;
165 INPUT_MODULES="$INPUT_MODULES $line"
166 done <"$MODFILE"
168 return 0
171 #------------------------------------------------------------------------------
172 # Function: print_epilog
173 #------------------------------------------------------------------------------
175 print_epilog() {
177 epilog="======== Successful Completion"
178 if [ x"$NO_QUIT" != x ]; then
179 if [ x"$failed_modules" != x ]; then
180 epilog="======== Partial Completion"
182 elif [ x"$failed_modules" != x ]; then
183 epilog="======== Stopped on Error"
186 echo ""
187 echo "$epilog `date`"
189 # Report about modules that failed for one reason or another
190 if [ x"$failed_modules" != x ]; then
191 echo " List of failed modules:"
192 for mod in $failed_modules; do
193 echo " $mod"
194 done
195 echo "========"
196 echo ""
200 #------------------------------------------------------------------------------
201 # Function: process_modules
202 #------------------------------------------------------------------------------
204 # Loop through each module to release
205 # Exit on error if --no-quit was not specified
207 process_modules() {
208 for MODULE_RPATH in ${INPUT_MODULES}; do
209 if ! process_module ; then
210 echo "Error: processing module \"$MODULE_RPATH\" failed."
211 failed_modules="$failed_modules $MODULE_RPATH"
212 if [ x"$NO_QUIT" = x ]; then
213 print_epilog
214 exit 1
217 done
220 #------------------------------------------------------------------------------
221 # Function: get_section
222 #------------------------------------------------------------------------------
223 # Code 'return 0' on success
224 # Code 'return 1' on error
225 # Sets global variable $section
226 get_section() {
227 local module_url
228 local full_module_url
230 # Obtain the git url in order to find the section to which this module belongs
231 full_module_url=`git config --get remote.$remote_name.url | sed 's:\.git$::'`
232 if [ $? -ne 0 ]; then
233 echo "Error: unable to obtain git url for remote \"$remote_name\"."
234 return 1
237 # The last part of the git url will tell us the section. Look for xorg first
238 module_url=`echo "$full_module_url" | $GREP -o "xorg/.*"`
239 if [ $? -eq 0 ]; then
240 module_url=`echo $module_url | rev | cut -d'/' -f1,2 | rev`
241 else
242 # The look for mesa, xcb, etc...
243 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"`
244 if [ $? -eq 0 ]; then
245 module_url=`echo $module_url | cut -d'/' -f2,3`
246 else
247 echo "Error: unable to locate a valid project url from \"$full_module_url\"."
248 echo "Cannot establish url as one of xorg, mesa, xcb, xf86-video-nouveau, xkeyboard-config or wayland"
249 cd $top_src
250 return 1
254 # Find the section (subdirs) where the tarballs are to be uploaded
255 # The module relative path can be app/xfs, xserver, or mesa/drm for example
256 section=`echo $module_url | cut -d'/' -f1`
257 if [ $? -ne 0 ]; then
258 echo "Error: unable to extract section from $module_url first field."
259 return 1
262 if [ x"$section" = xmesa ]; then
263 section=`echo $module_url | cut -d'/' -f2`
264 if [ $? -ne 0 ]; then
265 echo "Error: unable to extract section from $module_url second field."
266 return 1
267 elif [ x"$section" != xdrm ] &&
268 [ x"$section" != xmesa ] &&
269 [ x"$section" != xglu ] &&
270 [ x"$section" != xdemos ]; then
271 echo "Error: section $section is not supported, only libdrm, mesa, glu and demos are."
272 return 1
276 if [ x"$section" = xwayland -o x"$section" = xxorg ]; then
277 section=`echo $module_url | cut -d'/' -f2`
278 if [ $? -ne 0 ]; then
279 echo "Error: unable to extract section from $module_url second field."
280 return 1
284 return 0
287 # Function: sign_or_fail
288 #------------------------------------------------------------------------------
290 # Sign the given file, if any
291 # Output the name of the signature generated to stdout (all other output to
292 # stderr)
293 # Return 0 on success, 1 on fail
295 sign_or_fail() {
296 if [ -n "$1" ]; then
297 sig=$1.sig
298 rm -f $sig
299 $GPG -b $GPGKEY $1 1>&2
300 if [ $? -ne 0 ]; then
301 echo "Error: failed to sign $1." >&2
302 return 1
304 echo $sig
306 return 0
309 #------------------------------------------------------------------------------
310 # Function: process_module
311 #------------------------------------------------------------------------------
312 # Code 'return 0' on success to process the next module
313 # Code 'return 1' on error to process next module if invoked with --no-quit
315 process_module() {
317 local use_autogen=0
318 local use_meson=0
320 top_src=`pwd`
321 echo ""
322 echo "======== Processing \"$top_src/$MODULE_RPATH\""
324 # This is the location where the script has been invoked
325 if [ ! -d $MODULE_RPATH ] ; then
326 echo "Error: $MODULE_RPATH cannot be found under $top_src."
327 return 1
330 # Change directory to be in the git module
331 cd $MODULE_RPATH
332 if [ $? -ne 0 ]; then
333 echo "Error: failed to cd to $MODULE_RPATH."
334 return 1
337 # ----- Now in the git module *root* directory ----- #
339 # Check that this is indeed a git module
340 # Don't assume that $(top_srcdir)/.git is a directory. It may be
341 # a gitlink file if $(top_srcdir) is a submodule checkout or a linked
342 # worktree.
343 if [ ! -e .git ]; then
344 echo "Error: there is no git module here: `pwd`"
345 return 1
348 # Determine what is the current branch and the remote name
349 current_branch=`git branch | $GREP "\*" | sed -e "s/\* //"`
350 remote_name=`git config --get branch.$current_branch.remote`
351 remote_branch=`git config --get branch.$current_branch.merge | cut -d'/' -f3,4`
352 echo "Info: working off the \"$current_branch\" branch tracking the remote \"$remote_name/$remote_branch\"."
354 # Obtain the section
355 get_section
356 if [ $? -ne 0 ]; then
357 cd $top_src
358 return 1
361 # Check for uncommitted/queued changes.
362 check_local_changes
363 if [ $? -ne 0 ]; then
364 return 1
367 if [ -f autogen.sh ]; then
368 use_autogen=1
369 elif [ -f meson.build ]; then
370 use_meson=1
371 which jq >& /dev/null
372 if [ $? -ne 0 ]; then
373 echo "Cannot find required jq(1) to parse project metadata"
374 return 1
376 else
377 echo "Cannot find autogen.sh or meson.build"
378 return 1
381 if [ $use_autogen != 0 ]; then
382 # If AC_CONFIG_AUX_DIR isn't set, libtool will search down to ../.. for
383 # install-sh and then just guesses that's the aux dir, dumping
384 # config.sub and other files into that directory. make distclean then
385 # complains about leftover files. So let's put our real module dir out
386 # of reach of libtool.
388 # We use release/$section/$build_dir because git worktree will pick the
389 # last part as branch identifier, so it needs to be random to avoid
390 # conflicts.
391 build_dir="release/$section"
392 mkdir -p "$build_dir"
394 # Create tmpdir for the release
395 build_dir=`mktemp -d -p "$build_dir" build.XXXXXXXXXX`
396 if [ $? -ne 0 ]; then
397 echo "Error: could not create a temporary directory for the release"
398 echo "Do you have coreutils' mktemp ?"
399 return 1
402 # Worktree removal is intentionally left to the user, due to:
403 # - currently we cannot select only one worktree to prune
404 # - requires to removal of $build_dir which might contradict with the
405 # user decision to keep some artefacts like tarballs or other
406 echo "Info: creating new git worktree."
407 git worktree add $build_dir
408 if [ $? -ne 0 ]; then
409 echo "Error: failed to create a git worktree."
410 cd $top_src
411 return 1
414 cd $build_dir
415 if [ $? -ne 0 ]; then
416 echo "Error: failed to cd to $MODULE_RPATH/$build_dir."
417 cd $top_src
418 return 1
421 if [ -r ".gitmodules" ] ; then
422 git submodule update --init
423 if [ $? -ne 0 ]; then
424 echo "Error: failed to update git submodule"
425 cd $top_src
426 return 1
430 echo "Info: running autogen.sh"
431 ./autogen.sh >/dev/null
433 if [ $? -ne 0 ]; then
434 echo "Error: failed to configure module."
435 cd $top_src
436 return 1
439 # Run 'make dist/distcheck' to ensure the tarball matches the git module content
440 # Important to run make dist/distcheck before looking in Makefile, may need to reconfigure
441 echo "Info: running \"make $MAKE_DIST_CMD\" to create tarballs:"
442 ${MAKE} $MAKEFLAGS $MAKE_DIST_CMD > /dev/null
443 if [ $? -ne 0 ]; then
444 echo "Error: \"$MAKE $MAKEFLAGS $MAKE_DIST_CMD\" failed."
445 cd $top_src
446 return 1
449 # Find out the tarname from the makefile
450 pkg_name=`$GREP '^PACKAGE = ' Makefile | sed 's|PACKAGE = ||'`
451 pkg_version=`$GREP '^VERSION = ' Makefile | sed 's|VERSION = ||'`
452 tar_root="."
453 announce_dir=$tar_root
454 else
455 # meson sets up ninja dist so we don't have to do worktrees and it
456 # has the builddir enabled by default
457 build_dir="builddir"
458 if [ -e "$build_dir" ]; then
459 meson setup $build_dir --wipe
460 else
461 meson setup $build_dir
463 if [ $? -ne 0 ]; then
464 echo "Error: failed to configure module."
465 cd $top_src
466 return 1
469 echo "Info: running \"ninja dist\" to create tarball:"
470 ninja -C $build_dir dist
471 if [ $? -ne 0 ]; then
472 echo "Error: ninja dist failed"
473 cd $top_src
474 return 1
477 # Find out the package name from the meson.build file
478 pkg_name=$(meson introspect $build_dir --projectinfo | jq -r .descriptive_name)
479 pkg_version=$(meson introspect $build_dir --projectinfo | jq -r .version)
480 tar_root="$build_dir/meson-dist"
481 announce_dir=$tar_root
484 tar_name="$pkg_name-$pkg_version"
485 targz="$tar_root/$tar_name.tar.gz"
486 tarbz2="$tar_root/$tar_name.tar.bz2"
487 tarxz="$tar_root/$tar_name.tar.xz"
489 [ -e $targz ] && ls -l $targz || unset targz
490 [ -e $tarbz2 ] && ls -l $tarbz2 || unset tarbz2
491 [ -e $tarxz ] && ls -l $tarxz || unset tarxz
493 if [ -z "$targz" -a -z "$tarbz2" -a -z "$tarxz" ]; then
494 echo "Error: no compatible tarballs found."
495 cd $top_src
496 return 1
499 # wayland/weston/libinput tag with the version number only
500 tag_name="$tar_name"
501 if [ x"$section" = xwayland ] ||
502 [ x"$section" = xweston ] ||
503 [ x"$section" = xlibinput ]; then
504 tag_name="$pkg_version"
507 # evemu tag with the version number prefixed by 'v'
508 if [ x"$section" = xevemu ]; then
509 tag_name="v$pkg_version"
512 gpgsignerr=0
513 siggz="$(sign_or_fail ${targz})"
514 gpgsignerr=$((${gpgsignerr} + $?))
515 sigbz2="$(sign_or_fail ${tarbz2})"
516 gpgsignerr=$((${gpgsignerr} + $?))
517 sigxz="$(sign_or_fail ${tarxz})"
518 gpgsignerr=$((${gpgsignerr} + $?))
519 if [ ${gpgsignerr} -ne 0 ]; then
520 echo "Error: unable to sign at least one of the tarballs."
521 cd $top_src
522 return 1
525 # Obtain the top commit SHA which should be the version bump
526 # It should not have been tagged yet (the script will do it later)
527 local_top_commit_sha=`git rev-list --max-count=1 HEAD`
528 if [ $? -ne 0 ]; then
529 echo "Error: unable to obtain the local top commit id."
530 cd $top_src
531 return 1
534 # Check that the top commit looks like a version bump
535 git diff --unified=0 HEAD^ | $GREP -F $pkg_version >/dev/null 2>&1
536 if [ $? -ne 0 ]; then
537 # Wayland repos use m4_define([wayland_major_version], [0])
538 git diff --unified=0 HEAD^ | $GREP -E "(major|minor|micro)_version" >/dev/null 2>&1
539 if [ $? -ne 0 ]; then
540 echo "Error: the local top commit does not look like a version bump."
541 echo " the diff does not contain the string \"$pkg_version\"."
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
549 # Check that the top commit has been pushed to remote
550 remote_top_commit_sha=`git rev-list --max-count=1 $remote_name/$remote_branch`
551 if [ $? -ne 0 ]; then
552 echo "Error: unable to obtain top commit from the remote repository."
553 cd $top_src
554 return 1
556 if [ x"$remote_top_commit_sha" != x"$local_top_commit_sha" ]; then
557 echo "Error: the local top commit has not been pushed to the remote."
558 local_top_commit_descr=`git log --oneline --max-count=1 $local_top_commit_sha`
559 echo " the local top commit is: \"$local_top_commit_descr\""
560 cd $top_src
561 return 1
564 # If a tag exists with the tar name, ensure it is tagging the top commit
565 # It may happen if the version set in configure.ac has been previously released
566 tagged_commit_sha=`git rev-list --max-count=1 $tag_name 2>/dev/null`
567 if [ $? -eq 0 ]; then
568 # Check if the tag is pointing to the top commit
569 if [ x"$tagged_commit_sha" != x"$remote_top_commit_sha" ]; then
570 echo "Error: the \"$tag_name\" already exists."
571 echo " this tag is not tagging the top commit."
572 remote_top_commit_descr=`git log --oneline --max-count=1 $remote_top_commit_sha`
573 echo " the top commit is: \"$remote_top_commit_descr\""
574 local_tag_commit_descr=`git log --oneline --max-count=1 $tagged_commit_sha`
575 echo " tag \"$tag_name\" is tagging some other commit: \"$local_tag_commit_descr\""
576 cd $top_src
577 return 1
578 else
579 echo "Info: module already tagged with \"$tag_name\"."
581 else
582 # Tag the top commit with the tar name
583 if [ x"$DRY_RUN" = x ]; then
584 git tag $GPGKEY -s -m $tag_name $tag_name
585 if [ $? -ne 0 ]; then
586 echo "Error: unable to tag module with \"$tag_name\"."
587 cd $top_src
588 return 1
589 else
590 echo "Info: module tagged with \"$tag_name\"."
592 else
593 echo "Info: skipping the commit tagging in dry-run mode."
597 # --------- Now the tarballs are ready to upload ----------
599 # The hostname which is used to connect to the development resources
600 hostname="annarchy.freedesktop.org"
602 # Some hostnames are also used as /srv subdirs
603 host_fdo="www.freedesktop.org"
604 host_xorg="xorg.freedesktop.org"
605 host_dri="dri.freedesktop.org"
606 host_mesa="mesa.freedesktop.org"
607 host_wayland="wayland.freedesktop.org"
609 # Mailing lists where to post the all [Announce] e-mails
610 list_to="xorg-announce@lists.x.org"
612 # Mailing lists to be CC according to the project (xorg|dri|xkb)
613 list_xorg_user="xorg@lists.x.org"
614 list_dri_devel="dri-devel@lists.freedesktop.org"
615 list_mesa_announce="mesa-announce@lists.freedesktop.org"
616 list_mesa_devel="mesa-dev@lists.freedesktop.org"
618 list_xkb="xkb@listserv.bat.ru"
619 list_xcb="xcb@lists.freedesktop.org"
620 list_nouveau="nouveau@lists.freedesktop.org"
621 list_wayland="wayland-devel@lists.freedesktop.org"
622 list_input="input-tools@lists.freedesktop.org"
624 host_current=$host_xorg
625 section_path=archive/individual/$section
626 srv_path="/srv/$host_current/$section_path"
627 list_cc=$list_xorg_user
629 # Handle special cases such as non xorg projects or migrated xorg projects
630 # Nouveau has its own list and section, but goes with the other drivers
631 if [ x"$section" = xnouveau ]; then
632 section_path=archive/individual/driver
633 srv_path="/srv/$host_current/$section_path"
634 list_cc=$list_nouveau
637 # Xcb has a separate mailing list
638 if [ x"$section" = xxcb ]; then
639 list_cc=$list_xcb
642 # Module mesa/drm goes in the dri "libdrm" section
643 if [ x"$section" = xdrm ]; then
644 host_current=$host_dri
645 section_path=libdrm
646 srv_path="/srv/$host_current/www/$section_path"
647 list_cc=$list_dri_devel
648 elif [ x"$section" = xmesa ]; then
649 host_current=$host_mesa
650 section_path=archive
651 srv_path="/srv/$host_current/www/$section_path"
652 list_to=$list_mesa_announce
653 list_cc=$list_mesa_devel
654 elif [ x"$section" = xdemos ] || [ x"$section" = xglu ]; then
655 host_current=$host_mesa
656 section_path=archive/$section
657 srv_path="/srv/$host_current/www/$section_path"
658 list_to=$list_mesa_announce
659 list_cc=$list_mesa_devel
662 # Module xkeyboard-config goes in a subdir of the xorg "data" section
663 if [ x"$section" = xxkeyboard-config ]; then
664 host_current=$host_xorg
665 section_path=archive/individual/data/$section
666 srv_path="/srv/$host_current/$section_path"
667 list_cc=$list_xkb
670 if [ x"$section" = xlibevdev ]; then
671 host_current=$host_fdo
672 section_path="software/$section"
673 srv_path="/srv/$host_current/www/$section_path"
674 list_to=$list_input
675 unset list_cc
678 if [ x"$section" = xwayland ] ||
679 [ x"$section" = xweston ]; then
680 host_current=$host_wayland
681 section_path="releases"
682 srv_path="/srv/$host_current/www/$section_path"
683 list_to=$list_wayland
684 unset list_cc
685 elif [ x"$section" = xlibinput ]; then
686 host_current=$host_fdo
687 section_path="software/libinput"
688 srv_path="/srv/$host_current/www/$section_path"
689 list_to=$list_wayland
690 unset list_cc
691 elif [ x"$section" = xevemu ]; then
692 host_current=$host_fdo
693 section_path="software/evemu"
694 srv_path="/srv/$host_current/www/$section_path"
695 list_to=$list_input
696 unset list_cc
699 # Use personal web space on the host for unit testing (leave commented out)
700 # srv_path="~/public_html$srv_path"
702 # Check that the server path actually does exist
703 echo "Info: checking if path exists on web server:"
704 ssh $USER_NAME$hostname ls $srv_path >/dev/null 2>&1
705 if [ $? -ne 0 ]; then
706 echo "Error: the path \"$srv_path\" on the web server does not exist."
707 cd $top_src
708 return 1
711 # Check for already existing tarballs
712 for tarball in $targz $tarbz2 $tarxz; do
713 echo "Info: checking if tarball $tarball already exists on web server:"
714 ssh $USER_NAME$hostname ls $srv_path/$tarball >/dev/null 2>&1
715 if [ $? -eq 0 ]; then
716 if [ "x$FORCE" = "xyes" ]; then
717 echo "Warning: overwriting released tarballs due to --force option."
718 else
719 echo "Error: tarball $tar_name already exists. Use --force to overwrite."
720 cd $top_src
721 return 1
724 done
726 # Upload to host using the 'scp' remote file copy program
727 if [ x"$DRY_RUN" = x ]; then
728 echo "Info: uploading tarballs to web server:"
729 scp $targz $tarbz2 $tarxz $siggz $sigbz2 $sigxz $USER_NAME$hostname:$srv_path
730 if [ $? -ne 0 ]; then
731 echo "Error: the tarballs uploading failed."
732 cd $top_src
733 return 1
735 else
736 echo "Info: skipping tarballs uploading in dry-run mode."
737 echo " \"$srv_path\"."
740 # Pushing the top commit tag to the remote repository
741 if [ x$DRY_RUN = x ]; then
742 echo "Info: pushing tag \"$tag_name\" to remote \"$remote_name\":"
743 git push $remote_name $tag_name
744 if [ $? -ne 0 ]; then
745 echo "Error: unable to push tag \"$tag_name\" to the remote repository."
746 echo " it is recommended you fix this manually and not run the script again"
747 cd $top_src
748 return 1
750 else
751 echo "Info: skipped pushing tag \"$tag_name\" to the remote repository in dry-run mode."
754 SHA1SUM=`which sha1sum || which gsha1sum`
755 SHA256SUM=`which sha256sum || which gsha256sum`
756 SHA512SUM=`which sha512sum || which gsha512sum`
758 # --------- Generate the announce e-mail ------------------
759 # Failing to generate the announce is not considered a fatal error
761 # Git-describe returns only "the most recent tag", it may not be the expected one
762 # However, we only use it for the commit history which will be the same anyway.
763 if [ x"$FROM_TAG" != x ]; then
764 tag_previous=$FROM_TAG
765 else
766 tag_previous=`git describe --abbrev=0 HEAD^ 2>/dev/null`
768 # Git fails with rc=128 if no tags can be found prior to HEAD^
769 if [ $? -ne 0 ]; then
770 if [ $? -ne 0 ]; then
771 echo "Warning: unable to find a previous tag."
772 echo " perhaps a first release on this branch."
773 echo " Please check the commit history in the announce."
776 if [ x"$tag_previous" != x ]; then
777 # The top commit may not have been tagged in dry-run mode. Use commit.
778 tag_range=$tag_previous..$local_top_commit_sha
779 else
780 tag_range=$tag_name
782 pushd "$tar_root"
783 generate_announce > "$tar_name.announce"
784 popd
786 echo "Info: [ANNOUNCE] template generated in \"$announce_dir/$tar_name.announce\" file."
787 echo " Please pgp sign and send it."
789 # --------- Update the JH Build moduleset -----------------
790 # Failing to update the jh moduleset is not considered a fatal error
791 if [ x"$JH_MODULESET" != x ]; then
792 for tarball in $targz $tarbz2 $tarxz; do
793 if [ x$DRY_RUN = x ]; then
794 sha1sum=`$SHA1SUM $tarball | cut -d' ' -f1`
795 $top_src/util/modular/update-moduleset.sh $JH_MODULESET $sha1sum $tarball
796 echo "Info: updated jh moduleset: \"$JH_MODULESET\""
797 else
798 echo "Info: skipping jh moduleset \"$JH_MODULESET\" update in dry-run mode."
801 # $tar* may be unset, so simply loop through all of them and the
802 # first one that is set updates the module file
803 break
804 done
808 # --------- Successful completion --------------------------
809 cd $top_src
810 return 0
814 #------------------------------------------------------------------------------
815 # Function: usage
816 #------------------------------------------------------------------------------
817 # Displays the script usage and exits successfully
819 usage() {
820 basename="`expr "//$0" : '.*/\([^/]*\)'`"
821 cat <<HELP
823 Usage: $basename [options] path...
825 Where "path" is a relative path to a git module, including '.'.
827 Options:
828 --dist make 'dist' instead of 'distcheck'; use with caution
829 --distcheck Default, ignored for compatibility
830 --dry-run Does everything except tagging and uploading tarballs
831 --force Force overwriting an existing release
832 --gpgkey <key> Specify the key used to sign the git tag/release tarballs
833 --help Display this help and exit successfully
834 --modfile <file> Release the git modules specified in <file>
835 --moduleset <file> The jhbuild moduleset full pathname to be updated
836 --no-quit Do not quit after error; just print error message
837 --user <name>@ Username of your fdo account if not configured in ssh
838 --from-tag <tag> Generate logs since tag
840 Environment variables defined by the "make" program and used by release.sh:
841 MAKE The name of the make command [make]
842 MAKEFLAGS: Options to pass to all \$(MAKE) invocations
844 HELP
847 #------------------------------------------------------------------------------
848 # Script main line
849 #------------------------------------------------------------------------------
852 # Choose which make program to use (could be gmake)
853 MAKE=${MAKE:="make"}
855 # Choose which grep program to use (on Solaris, must be gnu grep)
856 if [ "x$GREP" = "x" ] ; then
857 if [ -x /usr/gnu/bin/grep ] ; then
858 GREP=/usr/gnu/bin/grep
859 else
860 GREP=grep
864 # Find path for GnuPG v2
865 if [ "x$GPG" = "x" ] ; then
866 if [ -x /usr/bin/gpg2 ] ; then
867 GPG=/usr/bin/gpg2
868 else
869 GPG=gpg
873 # Avoid problems if GPGKEY is already set in the environment
874 unset GPGKEY
876 # Set the default make tarball creation command
877 MAKE_DIST_CMD=distcheck
879 # Process command line args
880 while [ $# != 0 ]
882 case $1 in
883 # Use 'dist' rather than 'distcheck' to create tarballs
884 # You really only want to do this if you're releasing a module you can't
885 # possibly build-test. Please consider carefully the wisdom of doing so.
886 --dist)
887 MAKE_DIST_CMD=dist
889 # Use 'distcheck' to create tarballs
890 --distcheck)
891 MAKE_DIST_CMD=distcheck
893 # Does everything except uploading tarball
894 --dry-run)
895 DRY_RUN=yes
897 # Force overwriting an existing release
898 # Use only if nothing changed in the git repo
899 --force)
900 FORCE=yes
902 # Allow user specified GPG key
903 --gpgkey)
904 check_option_args $1 $2
905 shift
906 check_gpgkey $1
907 GPGKEY="-u $1"
909 # Display this help and exit successfully
910 --help)
911 usage
912 exit 0
914 # Release the git modules specified in <file>
915 --modfile)
916 check_option_args $1 $2
917 shift
918 MODFILE=$1
920 # The jhbuild moduleset to update with release info
921 --moduleset)
922 check_option_args $1 $2
923 shift
924 JH_MODULESET=$1
926 # Do not quit after error; just print error message
927 --no-quit)
928 NO_QUIT=yes
930 # Username of your fdo account if not configured in ssh
931 --user)
932 check_option_args $1 $2
933 shift
934 USER_NAME=$1
936 --from-tag)
937 check_option_args $1 $2
938 shift
939 FROM_TAG=$1
941 --*)
942 echo ""
943 echo "Error: unknown option: $1"
944 echo ""
945 usage
946 exit 1
949 echo ""
950 echo "Error: unknown option: $1"
951 echo ""
952 usage
953 exit 1
956 if [ x"${MODFILE}" != x ]; then
957 echo ""
958 echo "Error: specifying both modules and --modfile is not permitted"
959 echo ""
960 usage
961 exit 1
963 INPUT_MODULES="${INPUT_MODULES} $1"
965 esac
967 shift
968 done
970 umask=$(umask)
971 if [ "${umask}" != "022" -a "${umask}" != "0022" ]; then
972 echo ""
973 echo "Error: umask is not 022"
974 echo ""
975 exit 1
978 # If no modules specified (blank cmd line) display help
979 check_modules_specification
981 # Read the module file and normalize input in INPUT_MODULES
982 read_modfile
984 # Loop through each module to release
985 # Exit on error if --no-quit no specified
986 process_modules
988 # Print the epilog with final status
989 print_epilog