Merge branch 'nm/submodule-update-force'
authorJunio C Hamano <gitster@pobox.com>
Mon, 2 May 2011 22:58:36 +0000 (15:58 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 2 May 2011 22:58:36 +0000 (15:58 -0700)
* nm/submodule-update-force:
submodule: Add --force option for git submodule update

Conflicts:
t/t7406-submodule-update.sh

1  2 
Documentation/git-submodule.txt
git-submodule.sh
t/t7406-submodule-update.sh
index 1a16ff60448a72bebcba2daff7dbabc5feed8a4c,9f84da7ad61260f0b151d60a51bee4151a96151f..5e7a4130eeec48c27abf92b37834613692446723
@@@ -101,10 -101,9 +101,10 @@@ status:
        currently checked out commit for each submodule, along with the
        submodule path and the output of 'git describe' for the
        SHA-1. Each SHA-1 will be prefixed with `-` if the submodule is not
 -      initialized and `+` if the currently checked out submodule commit
 +      initialized, `+` if the currently checked out submodule commit
        does not match the SHA-1 found in the index of the containing
 -      repository. This command is the default command for 'git submodule'.
 +      repository and `U` if the submodule has merge conflicts.
 +      This command is the default command for 'git submodule'.
  +
  If '--recursive' is specified, this command will recurse into nested
  submodules, and show their status as well.
@@@ -186,8 -185,10 +186,10 @@@ OPTION
  
  -f::
  --force::
-       This option is only valid for the add command.
-       Allow adding an otherwise ignored submodule path.
+       This option is only valid for add and update commands.
+       When running add, allow adding an otherwise ignored submodule path.
+       When running update, throw away local changes in submodules when
+       switching to a different commit.
  
  --cached::
        This option is only valid for status and summary commands.  These
@@@ -258,6 -259,11 +260,6 @@@ This file should be formatted in the sa
  to each submodule url is "submodule.$name.url".  See linkgit:gitmodules[5]
  for details.
  
 -
 -AUTHOR
 -------
 -Written by Lars Hjemli <hjemli@gmail.com>
 -
  GIT
  ---
  Part of the linkgit:git[1] suite
diff --combined git-submodule.sh
index b010a673097a9cfcf009b307114669b6221d066c,f7327090bbe80b3bc553d0fe8774a02c76c48749..bf110e9cb77a0e9930c427408e18d323db2c8916
@@@ -8,7 -8,7 +8,7 @@@ dashless=$(basename "$0" | sed -e 's/-
  USAGE="[--quiet] add [-b branch] [-f|--force] [--reference <repository>] [--] <repository> [<path>]
     or: $dashless [--quiet] status [--cached] [--recursive] [--] [<path>...]
     or: $dashless [--quiet] init [--] [<path>...]
-    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
+    or: $dashless [--quiet] update [--init] [-N|--no-fetch] [-f|--force] [--rebase] [--reference <repository>] [--merge] [--recursive] [--] [<path>...]
     or: $dashless [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
     or: $dashless [--quiet] foreach [--recursive] <command>
     or: $dashless [--quiet] sync [--] [<path>...]"
@@@ -72,24 -72,7 +72,24 @@@ resolve_relative_url (
  #
  module_list()
  {
 -      git ls-files --error-unmatch --stage -- "$@" | sane_grep '^160000 '
 +      git ls-files --error-unmatch --stage -- "$@" |
 +      perl -e '
 +      my %unmerged = ();
 +      my ($null_sha1) = ("0" x 40);
 +      while (<STDIN>) {
 +              chomp;
 +              my ($mode, $sha1, $stage, $path) =
 +                      /^([0-7]+) ([0-9a-f]{40}) ([0-3])\t(.*)$/;
 +              next unless $mode eq "160000";
 +              if ($stage ne "0") {
 +                      if (!$unmerged{$path}++) {
 +                              print "$mode $null_sha1 U\t$path\n";
 +                      }
 +                      next;
 +              }
 +              print "$_\n";
 +      }
 +      '
  }
  
  #
@@@ -402,6 -385,9 +402,9 @@@ cmd_update(
                -N|--no-fetch)
                        nofetch=1
                        ;;
+               -f|--force)
+                       force=$1
+                       ;;
                -r|--rebase)
                        update="rebase"
                        ;;
        module_list "$@" |
        while read mode sha1 stage path
        do
 +              if test "$stage" = U
 +              then
 +                      echo >&2 "Skipping unmerged submodule $path"
 +                      continue
 +              fi
                name=$(module_name "$path") || exit
                url=$(git config submodule."$name".url)
                update_module=$(git config submodule."$name".update)
  
                if test "$subsha1" != "$sha1"
                then
-                       force=
-                       if test -z "$subsha1"
+                       subforce=$force
+                       # If we don't already have a -f flag and the submodule has never been checked out
+                       if test -z "$subsha1" -a -z "$force"
                        then
-                               force="-f"
+                               subforce="-f"
                        fi
  
                        if test -z "$nofetch"
                        then
 +                              # Run fetch only if $sha1 isn't present or it
 +                              # is not reachable from a ref.
                                (clear_local_git_env; cd "$path" &&
 -                                      git-fetch) ||
 +                                      ((rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
 +                                       test -z "$rev") || git-fetch)) ||
                                die "Unable to fetch in submodule path '$path'"
                        fi
  
                                msg="merged in"
                                ;;
                        *)
-                               command="git checkout $force -q"
+                               command="git checkout $subforce -q"
                                action="checkout"
                                msg="checked out"
                                ;;
@@@ -795,11 -774,6 +799,11 @@@ cmd_status(
                name=$(module_name "$path") || exit
                url=$(git config submodule."$name".url)
                displaypath="$prefix$path"
 +              if test "$stage" = U
 +              then
 +                      say "U$sha1 $displaypath"
 +                      continue
 +              fi
                if test -z "$url" || ! test -d "$path"/.git -o -f "$path"/.git
                then
                        say "-$sha1 $displaypath"
index bf7c788735d6e3e0ecf56e7a2f82826701ee1789,5d24d9ff74595174a4549bb165fcc8a0800d8120..4f16fcce2bfcb63f437fa6b495fdb5c4370fccc1
@@@ -74,26 -74,29 +74,49 @@@ test_expect_success 'submodule update d
        )
  '
  
 +apos="'";
 +test_expect_success 'submodule update does not fetch already present commits' '
 +      (cd submodule &&
 +        echo line3 >> file &&
 +        git add file &&
 +        test_tick &&
 +        git commit -m "upstream line3"
 +      ) &&
 +      (cd super/submodule &&
 +        head=$(git rev-parse --verify HEAD) &&
 +        echo "Submodule path ${apos}submodule$apos: checked out $apos$head$apos" > ../../expected &&
 +        git reset --hard HEAD~1
 +      ) &&
 +      (cd super &&
 +        git submodule update > ../actual 2> ../actual.err
 +      ) &&
 +      test_cmp expected actual &&
 +      ! test -s actual.err
 +'
 +
+ test_expect_success 'submodule update should fail due to local changes' '
+       (cd super/submodule &&
+        git reset --hard HEAD~1 &&
+        echo "local change" > file
+       ) &&
+       (cd super &&
+        (cd submodule &&
+         compare_head
+        ) &&
+        test_must_fail git submodule update submodule
+       )
+ '
+ test_expect_success 'submodule update should throw away changes with --force ' '
+       (cd super &&
+        (cd submodule &&
+         compare_head
+        ) &&
+        git submodule update --force submodule &&
+        cd submodule &&
+        ! compare_head
+       )
+ '
  test_expect_success 'submodule update --rebase staying on master' '
        (cd super/submodule &&
          git checkout master