#!/bin/sh #+ # Name: # update-modules # Purpose: # Update or initialise the git submodules # Type of Module: # Bourne shell script # Usage: # update-modules [-f] [submodule] # Description: # This script attempts to safely update or initialise the content of all # the submodules or the given submodule. It should be ran whenever a # submodule is known to be out-of-date, or when the submodules have not # yet been initialised. It can also be run at other times to get a listing # of the submodules and their status. # # The script can update or initialise a single submodule, or if no # command-line argument is given all the known submodules. Note that after # any new submodules are added to the repository these must be made known # by a git-pull or git-fetch before running this script. # # If any of the submodules contain local changes then this script will # refuse to run as the update process is destructive (although most # committed changes will be recoverable, see git-reflog). Note this means # that no changes to any submodules will be made, regardless of whether # they could be updated and/or initialized or not until the problem has # been resolved. # # In extreme circumstances when you do not have any changes to preserve # the "-f" flag can be used to skip all safety checks. # # It is necessary that this script be ran at least once after a # repository clone is created. This will be done by the bootstrap # script. # Notes: # Recovering after errors: If a submodule fails to clone (typical causes # are usually network errors or badly configured git) on the initial # update the container directory can often be automatically removed. In # that case you'll need to re-create it before updating will succeed. It # can also be a good idea to remove the partial repository that a failed # clone can give you, so for instance if the Perl module failed to clone # you should do: # # rm -rf thirdparty/perlsys/perl/perl # mkdir thirdparty/perlsys/perl/perl # # before attempting to continue. # Authors: # PWD: P.W. Draper (JAC, Durham University) # {enter_new_authors_here} # Copyright: # Copyright (C) 2009 Science and Technology Facilities Council. # All Rights Reserved. # Licence: # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be # useful, but WITHOUT ANY WARRANTY; without even the implied warranty # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street,Fifth Floor, Boston, MA # 02110-1301, USA # History: # 10-FEB-2009: (PWD): # Original version. # {enter_further_changes_here} #- echo "" echo "Updating local repository submodules:" # Parse any command-line arguments. We just have two -f and/or a submodule. check=1 if test "$1" != ""; then if test "$1" = "-f"; then check=0 shift fi submodule="$1" else submodule="" fi # Get a summary of the submodules. If this returns any content then one or # more have been modified and/or committed and may need to be pushed or reset # before proceeding. Could also mean that the module just needs updating. summary=`git submodule summary $submodule` if test "$check" = "1" -a "$summary" != ""; then # Check for modules that have modifications committed. git ls-files --stage -- $submodule | grep '^160000 ' | while read mode sha1 stage path; do if git diff-files --quiet -- "$path"; then # Submodule is unmodified. : else # Submodule is modified. Either internally, needs an update # or could be missing. if test -d $path; then # We want to check internally, ask submodule if it has the # requested SHA as its head, if not it may need an update. if GIT_DIR=$path/.git git rev-parse --verify $sha1^0 >/dev/null 2>&1; then # Contains the requested SHA already, that's OK as long # as the branch isn't ahead of the remote tracked version. # If we're not on a branch then there's no test available. branch=`GIT_DIR=$path/.git git symbolic-ref HEAD 2>/dev/null | sed 's,refs/heads/,,'` if test "$branch" != ""; then ahead=`GIT_DIR=$path/.git git log origin/$branch..$branch 2>/dev/null` if test "$ahead" != ""; then echo "ERROR: a submodule is ahead of remote branch, not updating anything" echo "... $path" echo " `git submodule summary $path`" exit 1 fi fi fi else # No directory! That's an error. echo "ERROR: missing submodule directory, not updating anything" echo "... $path" exit 1 fi fi done if test "$?" != "0"; then # Last command in sub-shell exited in error. So stop. exit 1 fi fi # The above will not report modified files that have not been committed. # This isn't important, but probably indicates some activity in the submodule # so refuse to proceed when they are present as well. if test "$submodule" = ""; then # Get a list of all the paths to the submodules. submodule_list="`git config -f .gitmodules --get-regexp '.*\.path$' | awk '{print $2}'`" else submodule_list="$submodule" # Verify this a submodule, which may not be initialised yet. found="`git config -f .gitmodules --get-regexp ".*${submodule}\.path$" | awk '{print $2}'`" if test "$found" = ""; then echo "ERROR: no such submodule: ... $submodule" exit 1 fi fi if test "$check" = "1"; then for m in $submodule_list; do if test -d "$m"; then # May not be checked in yet, so no repository in place. Check that # by counting the files, must be more than ". ..", if this is a # submodule. nfiles=`cd $m && ls -a | wc -w` if test $nfiles -gt 2 ; then (cd $m && git diff) >/dev/null 2>&1 ; # XXX hack need to update submodule index? # Check for local modifications. Force this command to use the # submodule repository, not the current one. If this is really a # repository that is OK, otherwise (i.e bad repository, none # repository files present) an error will occur. modified=`cd $m && git --git-dir .git diff-index --name-status HEAD 2>&1` if test "$?" != "0"; then echo "ERROR: submodule repository query failed, not updating anything" echo "... $m" echo " $modified" exit 1 fi if test "$modified" != ""; then echo "ERROR: submodule has modified files, not updating anything" echo "... $m" echo " $modified" | head exit 1 fi else echo "... $m requires initialisation" fi else echo "ERROR: submodule directory is missing, not updating anything" echo "... $m" exit 1 fi done fi # No modifications, or told to not check, so safe to check for updates. Note # we always init to capture any new submodules added since the last update. git submodule init $submodule if test "$?" != "0"; then echo "ERROR: failed to initialise a submodule" exit 1 fi git submodule update $submodule if test "$?" != "0"; then echo "ERROR: failed to update a submodule" exit 1 fi # Success output the status of the submodules. git submodule status $submodule | awk '{print "...",$2,$3}' echo "" exit