Merge branch 'sb/submodule-update-dot-branch'
authorJunio C Hamano <gitster@pobox.com>
Wed, 10 Aug 2016 19:33:20 +0000 (12:33 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 10 Aug 2016 19:33:20 +0000 (12:33 -0700)
A few updates to "git submodule update".

Use of "| wc -l" break with BSD variant of 'wc'.

* sb/submodule-update-dot-branch:
t7406: fix breakage on OSX
submodule update: allow '.' for branch value
submodule--helper: add remote-branch helper
submodule-config: keep configured branch around
submodule--helper: fix usage string for relative-path
submodule update: narrow scope of local variable
submodule update: respect depth in subsequent fetches
t7406: future proof tests with hard coded depth

1  2 
builtin/submodule--helper.c
git-submodule.sh
submodule-config.c
index 6f6d67a4694a83f18f86f5de2d9d64fd4e449a5e,f1acc4dc96ff45094d48ba9e18afa8d03f8e812e..b09632e468e6b64e0329a685e0f3ba7517884c5c
@@@ -795,7 -795,7 +795,7 @@@ static int update_clone_task_finished(i
                suc->failed_clones[suc->failed_clones_nr++] = ce;
                return 0;
        } else {
 -              idx = suc->current - suc->list.nr;
 +              idx -= suc->list.nr;
                ce  = suc->failed_clones[idx];
                strbuf_addf(err, _("Failed to clone '%s' a second time, aborting"),
                            ce->name);
@@@ -892,13 -892,64 +892,64 @@@ static int resolve_relative_path(int ar
  {
        struct strbuf sb = STRBUF_INIT;
        if (argc != 3)
-               die("submodule--helper relative_path takes exactly 2 arguments, got %d", argc);
+               die("submodule--helper relative-path takes exactly 2 arguments, got %d", argc);
  
        printf("%s", relative_path(argv[1], argv[2], &sb));
        strbuf_release(&sb);
        return 0;
  }
  
+ static const char *remote_submodule_branch(const char *path)
+ {
+       const struct submodule *sub;
+       gitmodules_config();
+       git_config(submodule_config, NULL);
+       sub = submodule_from_path(null_sha1, path);
+       if (!sub)
+               return NULL;
+       if (!sub->branch)
+               return "master";
+       if (!strcmp(sub->branch, ".")) {
+               unsigned char sha1[20];
+               const char *refname = resolve_ref_unsafe("HEAD", 0, sha1, NULL);
+               if (!refname)
+                       die(_("No such ref: %s"), "HEAD");
+               /* detached HEAD */
+               if (!strcmp(refname, "HEAD"))
+                       die(_("Submodule (%s) branch configured to inherit "
+                             "branch from superproject, but the superproject "
+                             "is not on any branch"), sub->name);
+               if (!skip_prefix(refname, "refs/heads/", &refname))
+                       die(_("Expecting a full ref name, got %s"), refname);
+               return refname;
+       }
+       return sub->branch;
+ }
+ static int resolve_remote_submodule_branch(int argc, const char **argv,
+               const char *prefix)
+ {
+       const char *ret;
+       struct strbuf sb = STRBUF_INIT;
+       if (argc != 2)
+               die("submodule--helper remote-branch takes exactly one arguments, got %d", argc);
+       ret = remote_submodule_branch(argv[1]);
+       if (!ret)
+               die("submodule %s doesn't exist", argv[1]);
+       printf("%s", ret);
+       strbuf_release(&sb);
+       return 0;
+ }
  struct cmd_struct {
        const char *cmd;
        int (*fn)(int, const char **, const char *);
@@@ -912,7 -963,8 +963,8 @@@ static struct cmd_struct commands[] = 
        {"relative-path", resolve_relative_path},
        {"resolve-relative-url", resolve_relative_url},
        {"resolve-relative-url-test", resolve_relative_url_test},
-       {"init", module_init}
+       {"init", module_init},
+       {"remote-branch", resolve_remote_submodule_branch}
  };
  
  int cmd_submodule__helper(int argc, const char **argv, const char *prefix)
diff --combined git-submodule.sh
index c90dc335d145fa0a16efbe41873a525b596b806d,8c5e8982ab9980daf14b144a5b41b191289fb1a2..b57f87de658b627c48ec672faaab3dc6aac3b505
@@@ -49,7 -49,7 +49,7 @@@ die_if_unmatched (
  {
        if test "$1" = "#unmatched"
        then
 -              exit 1
 +              exit ${2:-1}
        fi
  }
  
@@@ -312,11 -312,11 +312,11 @@@ cmd_foreach(
  
        {
                git submodule--helper list --prefix "$wt_prefix" ||
 -              echo "#unmatched"
 +              echo "#unmatched" $?
        } |
        while read mode sha1 stage sm_path
        do
 -              die_if_unmatched "$mode"
 +              die_if_unmatched "$mode" "$sha1"
                if test -e "$sm_path"/.git
                then
                        displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
@@@ -421,11 -421,11 +421,11 @@@ cmd_deinit(
  
        {
                git submodule--helper list --prefix "$wt_prefix" "$@" ||
 -              echo "#unmatched"
 +              echo "#unmatched" $?
        } |
        while read mode sha1 stage sm_path
        do
 -              die_if_unmatched "$mode"
 +              die_if_unmatched "$mode" "$sha1"
                name=$(git submodule--helper name "$sm_path") || exit
  
                displaypath=$(git submodule--helper relative-path "$sm_path" "$wt_prefix")
@@@ -479,7 -479,8 +479,8 @@@ fetch_in_submodule () 
        '')
                git fetch ;;
        *)
-               git fetch $(get_default_remote) "$2" ;;
+               shift
+               git fetch $(get_default_remote) "$@" ;;
        esac
  )
  
@@@ -579,16 -580,15 +580,15 @@@ cmd_update(
                ${depth:+--depth "$depth"} \
                ${recommend_shallow:+"$recommend_shallow"} \
                ${jobs:+$jobs} \
 -              "$@" || echo "#unmatched"
 +              "$@" || echo "#unmatched" $?
        } | {
        err=
        while read mode sha1 stage just_cloned sm_path
        do
 -              die_if_unmatched "$mode"
 +              die_if_unmatched "$mode" "$sha1"
  
                name=$(git submodule--helper name "$sm_path") || exit
                url=$(git config submodule."$name".url)
-               branch=$(get_submodule_config "$name" branch master)
                if ! test -z "$update"
                then
                        update_module=$update
  
                if test -n "$remote"
                then
+                       branch=$(git submodule--helper remote-branch "$sm_path")
                        if test -z "$nofetch"
                        then
                                # Fetch remote before determining tracking $sha1
-                               fetch_in_submodule "$sm_path" ||
+                               fetch_in_submodule "$sm_path" $depth ||
                                die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
                        fi
                        remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
                                # Run fetch only if $sha1 isn't present or it
                                # is not reachable from a ref.
                                is_tip_reachable "$sm_path" "$sha1" ||
-                               fetch_in_submodule "$sm_path" ||
+                               fetch_in_submodule "$sm_path" $depth ||
                                die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
  
                                # Now we tried the usual fetch, but $sha1 may
                                # not be reachable from any of the refs
                                is_tip_reachable "$sm_path" "$sha1" ||
-                               fetch_in_submodule "$sm_path" "$sha1" ||
+                               fetch_in_submodule "$sm_path" $depth "$sha1" ||
                                die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")"
                        fi
  
@@@ -992,11 -993,11 +993,11 @@@ cmd_status(
  
        {
                git submodule--helper list --prefix "$wt_prefix" "$@" ||
 -              echo "#unmatched"
 +              echo "#unmatched" $?
        } |
        while read mode sha1 stage sm_path
        do
 -              die_if_unmatched "$mode"
 +              die_if_unmatched "$mode" "$sha1"
                name=$(git submodule--helper name "$sm_path") || exit
                url=$(git config submodule."$name".url)
                displaypath=$(git submodule--helper relative-path "$prefix$sm_path" "$wt_prefix")
@@@ -1073,11 -1074,11 +1074,11 @@@ cmd_sync(
        cd_to_toplevel
        {
                git submodule--helper list --prefix "$wt_prefix" "$@" ||
 -              echo "#unmatched"
 +              echo "#unmatched" $?
        } |
        while read mode sha1 stage sm_path
        do
 -              die_if_unmatched "$mode"
 +              die_if_unmatched "$mode" "$sha1"
                name=$(git submodule--helper name "$sm_path")
                url=$(git config -f .gitmodules --get submodule."$name".url)
  
diff --combined submodule-config.c
index d22a851d2705fc44c608cdde1c31bea40b454ebb,ebee1e4795738578662ddfa17fe3d0a0afb19542..098085be69b97687b0febfe9e29c6dc0c64569a1
@@@ -59,6 -59,7 +59,7 @@@ static void free_one_config(struct subm
  {
        free((void *) entry->config->path);
        free((void *) entry->config->name);
+       free((void *) entry->config->branch);
        free((void *) entry->config->update_strategy.command);
        free(entry->config);
  }
@@@ -199,6 -200,7 +200,7 @@@ static struct submodule *lookup_or_crea
        submodule->update_strategy.command = NULL;
        submodule->fetch_recurse = RECURSE_SUBMODULES_NONE;
        submodule->ignore = NULL;
+       submodule->branch = NULL;
        submodule->recommend_shallow = -1;
  
        hashcpy(submodule->gitmodules_sha1, gitmodules_sha1);
@@@ -358,9 -360,16 +360,16 @@@ static int parse_config(const char *var
                if (!me->overwrite && submodule->recommend_shallow != -1)
                        warn_multiple_config(me->commit_sha1, submodule->name,
                                             "shallow");
-               else {
+               else
                        submodule->recommend_shallow =
                                git_config_bool(var, value);
+       } else if (!strcmp(item.buf, "branch")) {
+               if (!me->overwrite && submodule->branch)
+                       warn_multiple_config(me->commit_sha1, submodule->name,
+                                            "branch");
+               else {
+                       free((void *)submodule->branch);
+                       submodule->branch = xstrdup(value);
                }
        }
  
  }
  
  static int gitmodule_sha1_from_commit(const unsigned char *commit_sha1,
 -                                    unsigned char *gitmodules_sha1)
 +                                    unsigned char *gitmodules_sha1,
 +                                    struct strbuf *rev)
  {
 -      struct strbuf rev = STRBUF_INIT;
        int ret = 0;
  
        if (is_null_sha1(commit_sha1)) {
                return 1;
        }
  
 -      strbuf_addf(&rev, "%s:.gitmodules", sha1_to_hex(commit_sha1));
 -      if (get_sha1(rev.buf, gitmodules_sha1) >= 0)
 +      strbuf_addf(rev, "%s:.gitmodules", sha1_to_hex(commit_sha1));
 +      if (get_sha1(rev->buf, gitmodules_sha1) >= 0)
                ret = 1;
  
 -      strbuf_release(&rev);
        return ret;
  }
  
@@@ -398,7 -408,7 +407,7 @@@ static const struct submodule *config_f
  {
        struct strbuf rev = STRBUF_INIT;
        unsigned long config_size;
 -      char *config;
 +      char *config = NULL;
        unsigned char sha1[20];
        enum object_type type;
        const struct submodule *submodule = NULL;
                return entry->config;
        }
  
 -      if (!gitmodule_sha1_from_commit(commit_sha1, sha1))
 -              return NULL;
 +      if (!gitmodule_sha1_from_commit(commit_sha1, sha1, &rev))
 +              goto out;
  
        switch (lookup_type) {
        case lookup_name:
                break;
        }
        if (submodule)
 -              return submodule;
 +              goto out;
  
        config = read_sha1_file(sha1, &type, &config_size);
 -      if (!config)
 -              return NULL;
 -
 -      if (type != OBJ_BLOB) {
 -              free(config);
 -              return NULL;
 -      }
 +      if (!config || type != OBJ_BLOB)
 +              goto out;
  
        /* fill the submodule config into the cache */
        parameter.cache = cache;
        parameter.commit_sha1 = commit_sha1;
        parameter.gitmodules_sha1 = sha1;
        parameter.overwrite = 0;
 -      git_config_from_mem(parse_config, "submodule-blob", rev.buf,
 +      git_config_from_mem(parse_config, CONFIG_ORIGIN_SUBMODULE_BLOB, rev.buf,
                        config, config_size, &parameter);
 +      strbuf_release(&rev);
        free(config);
  
        switch (lookup_type) {
        default:
                return NULL;
        }
 +
 +out:
 +      strbuf_release(&rev);
 +      free(config);
 +      return submodule;
  }
  
  static const struct submodule *config_from_path(struct submodule_cache *cache,