Merge branch 'bc/submodule-foreach-stdin-fix-1.7.4' into maint
authorJunio C Hamano <gitster@pobox.com>
Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 16 Aug 2011 18:23:26 +0000 (11:23 -0700)
* bc/submodule-foreach-stdin-fix-1.7.4:
git-submodule.sh: preserve stdin for the command spawned by foreach
t/t7407: demonstrate that the command called by 'submodule foreach' loses stdin

1  2 
git-submodule.sh
t/t7407-submodule-foreach.sh
diff --combined git-submodule.sh
index d189a24c71c44806a9c1381e2a8e5993269e568a,07dc675cef2c71e487648a4bd8cc18f4d93db917..9c6dca5a1590a22ec7478e46b7d4660c7d1beb01
@@@ -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>...]"
@@@ -37,24 -37,12 +37,24 @@@ resolve_relative_url (
                die "remote ($remote) does not have a url defined in .git/config"
        url="$1"
        remoteurl=${remoteurl%/}
 +      sep=/
        while test -n "$url"
        do
                case "$url" in
                ../*)
                        url="${url#../}"
 -                      remoteurl="${remoteurl%/*}"
 +                      case "$remoteurl" in
 +                      */*)
 +                              remoteurl="${remoteurl%/*}"
 +                              ;;
 +                      *:*)
 +                              remoteurl="${remoteurl%:*}"
 +                              sep=:
 +                              ;;
 +                      *)
 +                              die "cannot strip one component off url '$remoteurl'"
 +                              ;;
 +                      esac
                        ;;
                ./*)
                        url="${url#./}"
@@@ -63,7 -51,7 +63,7 @@@
                        break;;
                esac
        done
 -      echo "$remoteurl/${url%/}"
 +      echo "$remoteurl$sep${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";
 +      }
 +      '
  }
  
  #
@@@ -122,6 -93,20 +122,6 @@@ module_clone(
        url=$2
        reference="$3"
  
 -      # If there already is a directory at the submodule path,
 -      # expect it to be empty (since that is the default checkout
 -      # action) and try to remove it.
 -      # Note: if $path is a symlink to a directory the test will
 -      # succeed but the rmdir will fail. We might want to fix this.
 -      if test -d "$path"
 -      then
 -              rmdir "$path" 2>/dev/null ||
 -              die "Directory '$path' exists, but is neither empty nor a git repository"
 -      fi
 -
 -      test -e "$path" &&
 -      die "A file already exist at path '$path'"
 -
        if test -n "$reference"
        then
                git-clone "$reference" -n "$url" "$path"
@@@ -256,7 -241,7 +256,7 @@@ cmd_add(
                        # ash fails to wordsplit ${branch:+-b "$branch"...}
                        case "$branch" in
                        '') git checkout -f -q ;;
 -                      ?*) git checkout -f -q -b "$branch" "origin/$branch" ;;
 +                      ?*) git checkout -f -q -B "$branch" "origin/$branch" ;;
                        esac
                ) || die "Unable to checkout submodule '$path'"
        fi
@@@ -300,6 -285,10 +300,10 @@@ cmd_foreach(
  
        toplevel=$(pwd)
  
+       # dup stdin so that it can be restored when running the external
+       # command in the subshell (and a recursive call to this function)
+       exec 3<&0
        module_list |
        while read mode sha1 stage path
        do
                                then
                                        cmd_foreach "--recursive" "$@"
                                fi
-                       ) ||
+                       ) <&3 3<&- ||
                        die "Stopping at '$path'; script returned non-zero status."
                fi
        done
@@@ -402,9 -391,6 +406,9 @@@ cmd_update(
                -N|--no-fetch)
                        nofetch=1
                        ;;
 +              -f|--force)
 +                      force=$1
 +                      ;;
                -r|--rebase)
                        update="rebase"
                        ;;
                cmd_init "--" "$@" || return
        fi
  
 +      cloned_modules=
        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 -d "$path"/.git -o -f "$path"/.git
                then
                        module_clone "$path" "$url" "$reference"|| exit
 +                      cloned_modules="$cloned_modules;$name"
                        subsha1=
                else
                        subsha1=$(clear_local_git_env; cd "$path" &&
  
                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
  
 +                      # Is this something we just cloned?
 +                      case ";$cloned_modules;" in
 +                      *";$name;"*)
 +                              # then there is no local change to integrate
 +                              update_module= ;;
 +                      esac
 +
                        case "$update_module" in
                        rebase)
                                command="git rebase"
                                msg="merged in"
                                ;;
                        *)
 -                              command="git checkout $force -q"
 +                              command="git checkout $subforce -q"
                                action="checkout"
                                msg="checked out"
                                ;;
@@@ -799,11 -767,6 +803,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"
@@@ -874,12 -837,11 +878,12 @@@ cmd_sync(
                        ;;
                esac
  
 +              say "Synchronizing submodule url for '$name'"
 +              git config submodule."$name".url "$url"
 +
                if test -e "$path"/.git
                then
                (
 -                      say "Synchronizing submodule url for '$name'"
 -                      git config submodule."$name".url "$url"
                        clear_local_git_env
                        cd "$path"
                        remote=$(get_default_remote)
index e5be13c271c92ce7c51601ee1eaf966d849d8ae4,8a74ccac5f875368d559be876feaed51dfc2af66..835a50624114253b634896e1cceae43578a279bf
@@@ -238,10 -238,6 +238,10 @@@ test_expect_success 'ensure "status --c
                ) &&
                git submodule status --cached --recursive -- nested1 > ../actual
        ) &&
 +      if test_have_prereq MINGW
 +      then
 +              dos2unix actual
 +      fi &&
        test_cmp expect actual
  '
  
@@@ -292,4 -288,22 +292,22 @@@ test_expect_success 'use "update --recu
        )
  '
  
+ test_expect_success 'command passed to foreach retains notion of stdin' '
+       (
+               cd super &&
+               git submodule foreach echo success >../expected &&
+               yes | git submodule foreach "read y && test \"x\$y\" = xy && echo success" >../actual
+       ) &&
+       test_cmp expected actual
+ '
+ test_expect_success 'command passed to foreach --recursive retains notion of stdin' '
+       (
+               cd clone2 &&
+               git submodule foreach --recursive echo success >../expected &&
+               yes | git submodule foreach --recursive "read y && test \"x\$y\" = xy && echo success" >../actual
+       ) &&
+       test_cmp expected actual
+ '
  test_done