It makes git-parse-remote.sh, git-fetch--tool and almost all git-fetch independent of the merge logic. git-fetch fetches the branches from the remote and saves this information in .git/FETCH_FETCHED (a temporary file), and at the end it generates the file .git/FETCH_HEAD. The current merge behaviour is unchanged. Signed-off-by: Santi Béjar <sbejar@xxxxxxxxx> --- Hi *, this time the net effect is to add 10 lines :( This applies to next. Regards, Santi builtin-fetch--tool.c | 49 ++++++++++-------------------- git-fetch.sh | 78 +++++++++++++++++++++++++++++++++++++++++------- git-parse-remote.sh | 65 ++++++++++++----------------------------- 3 files changed, 101 insertions(+), 91 deletions(-) diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index e9d6764..2cee058 100644 --- a/builtin-fetch--tool.c +++ b/builtin-fetch--tool.c @@ -138,8 +138,7 @@ static int update_local_ref(const char *name, static int append_fetch_head(FILE *fp, const char *head, const char *remote, - const char *remote_name, const char *remote_nick, - const char *local_name, int not_for_merge, + const char *remote_name, const char *local_name, int verbose, int force) { struct commit *commit; @@ -151,8 +150,6 @@ static int append_fetch_head(FILE *fp, if (get_sha1(head, sha1)) return error("Not a valid object name: %s", head); commit = lookup_commit_reference(sha1); - if (!commit) - not_for_merge = 1; if (!strcmp(remote_name, "HEAD")) { kind = ""; @@ -189,9 +186,9 @@ static int append_fetch_head(FILE *fp, note_len += sprintf(note + note_len, "'%s' of ", what); } note_len += sprintf(note + note_len, "%.*s", remote_len, remote); - fprintf(fp, "%s\t%s\t%s\n", + fprintf(fp, "%s\t%s:%s\t%s\n", sha1_to_hex(commit ? commit->object.sha1 : sha1), - not_for_merge ? "not-for-merge" : "", + remote_name, local_name, note); return update_local_ref(local_name, head, note, verbose, force); } @@ -211,14 +208,14 @@ static void remove_keep_on_signal(int signo) } static char *find_local_name(const char *remote_name, const char *refs, - int *force_p, int *not_for_merge_p) + int *force_p) { const char *ref = refs; int len = strlen(remote_name); while (ref) { const char *next; - int single_force, not_for_merge; + int single_force; while (*ref == '\n') ref++; @@ -226,19 +223,11 @@ static char *find_local_name(const char *remote_name, const char *refs, break; next = strchr(ref, '\n'); - single_force = not_for_merge = 0; + single_force = 0; if (*ref == '+') { single_force = 1; ref++; } - if (*ref == '.') { - not_for_merge = 1; - ref++; - if (*ref == '+') { - single_force = 1; - ref++; - } - } if (!strncmp(remote_name, ref, len) && ref[len] == ':') { const char *local_part = ref + len + 1; char *ret; @@ -252,7 +241,6 @@ static char *find_local_name(const char *remote_name, const char *refs, memcpy(ret, local_part, retlen); ret[retlen] = 0; *force_p = single_force; - *not_for_merge_p = not_for_merge; return ret; } ref = next; @@ -262,7 +250,6 @@ static char *find_local_name(const char *remote_name, const char *refs, static int fetch_native_store(FILE *fp, const char *remote, - const char *remote_nick, const char *refs, int verbose, int force) { @@ -276,7 +263,7 @@ static int fetch_native_store(FILE *fp, int len; char *cp; char *local_name; - int single_force, not_for_merge; + int single_force; for (cp = buffer; *cp && !isspace(*cp); cp++) ; @@ -298,12 +285,11 @@ static int fetch_native_store(FILE *fp, } local_name = find_local_name(cp, refs, - &single_force, ¬_for_merge); + &single_force); if (!local_name) continue; err |= append_fetch_head(fp, - buffer, remote, cp, remote_nick, - local_name, not_for_merge, + buffer, remote, cp, local_name, verbose, force || single_force); } return err; @@ -336,8 +322,6 @@ static int parse_reflist(const char *reflist) break; for (next = ref; *next && !isspace(*next); next++) ; - if (*ref == '.') - ref++; if (*ref == '+') ref++; colon = strchr(ref, ':'); @@ -460,12 +444,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix) int result; FILE *fp; - if (argc != 8) - return error("append-fetch-head takes 6 args"); - fp = fopen(git_path("FETCH_HEAD"), "a"); + if (argc != 6) + return error("append-fetch-head takes 4 args"); + fp = fopen(git_path("FETCH_FETCHED"), "a"); result = append_fetch_head(fp, argv[2], argv[3], argv[4], argv[5], - argv[6], !!argv[7][0], verbose, force); fclose(fp); return result; @@ -474,10 +457,10 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix) int result; FILE *fp; - if (argc != 5) - return error("fetch-native-store takes 3 args"); - fp = fopen(git_path("FETCH_HEAD"), "a"); - result = fetch_native_store(fp, argv[2], argv[3], argv[4], + if (argc != 4) + return error("fetch-native-store takes 2 args"); + fp = fopen(git_path("FETCH_FETCHED"), "a"); + result = fetch_native_store(fp, argv[2], argv[3], verbose, force); fclose(fp); return result; diff --git a/git-fetch.sh b/git-fetch.sh index 9d45dd2..58cbef1 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -79,9 +79,9 @@ do shift done +origin=$(get_default_remote) case "$#" in 0) - origin=$(get_default_remote) test -n "$(get_remote_url ${origin})" || die "Where do you want to fetch from today?" set x $origin ; shift ;; @@ -103,6 +103,8 @@ if test "" = "$append" then : >"$GIT_DIR/FETCH_HEAD" fi +: >"$GIT_DIR/FETCH_FETCHED" +trap 'rm -f "$GIT_DIR"/FETCH_FETCHED' 0 1 2 3 15 # Global that is reused later ls_remote_result=$(git ls-remote $exec "$remote") || @@ -145,7 +147,7 @@ then git-show-ref --exclude-existing=refs/tags/ | while read sha1 name do - echo ".${name}:${name}" + echo "${name}:${name}" done` || exit if test "$#" -gt 1 then @@ -182,7 +184,7 @@ fetch_native () { test -n "$force" && flags="$flags -f" GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION" \ git-fetch--tool $flags native-store \ - "$remote" "$remote_nick" "$refs" + "$remote" "$refs" ) ) || exit @@ -199,13 +201,6 @@ fetch_dumb () { # These are relative path from $GIT_DIR, typically starting at refs/ # but may be HEAD - if expr "z$ref" : 'z\.' >/dev/null - then - not_for_merge=t - ref=$(expr "z$ref" : 'z\.\(.*\)') - else - not_for_merge= - fi if expr "z$ref" : 'z+' >/dev/null then single_force=t @@ -283,7 +278,7 @@ fetch_dumb () { esac append_fetch_head "$head" "$remote" \ - "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit + "$remote_name" "$remote_nick" "$local_name" || exit done @@ -316,7 +311,7 @@ case "$no_tags$tags" in do git-cat-file -t "$sha1" >/dev/null 2>&1 || continue echo >&2 "Auto-following $name" - echo ".${name}:${name}" + echo "${name}:${name}" done) esac case "$taglist" in @@ -344,3 +339,62 @@ case "$orig_head" in fi ;; esac +# Generate $GIT_DIR/FETCH_HEAD +case ",$#,$remote_nick," in +,1,$origin,) + # Fetch default: merge the branches in branch.*.merge that match + # the fetched ones or the first one + curr_branch=$(git-symbolic-ref -q HEAD | sed -e 's|^refs/heads/||') + merge_branches=$(git-config \ + --get-all "branch.${curr_branch}.merge" | sort -u) + fetch_branches=$(get_remote_default_refs_for_fetch -n $remote_nick | + sed -e 's/:.*$//g' -e 's/^+//' | sort -u) + test -n "$merge_branches" && test -n "$fetch_branches" && + merge_branches=$(printf '%s\n%s' "$merge_branches" "$fetch_branches" | + sort | uniq -d) + + [ -z "$merge_branches" ] || + test "$(get_data_source $remote_nick)" = branches && merge_first=yes;; +,1,$remote,) + # Remote is a URL, merge the default branch HEAD + merge_branches=HEAD;; +,1,*) + # Remote is a shorthand diferent from the default, + # merge the first fetched branch + merge_first=yes ;; +*) + # Merge the branches given in the command line + merge_branches=$(for ref in $(get_remote_refs_for_fetch "$@") ; do + expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:" + echo "$(expr "z$ref" : 'z\([^:]*\):')"; done);; +esac + +if test "$merge_first" = "yes" ; then + merge_branches= + # Do not merge the first branch if it was specified with a glob + test "$(get_remote_default_refs_for_fetch -t $remote_nick)" != "explicit" && + merge_first= +else + merge_branches=$(canon_refs_list_for_fetch $merge_branches | sed 's/:.*$//g') +fi + +while IFS=' ' read hash ref note ; do + # 2.6.11-tree tag would not be happy to be fed to resolve. + if git-cat-file commit "$hash" >/dev/null 2>&1 + then + hashc=$(git-rev-parse --verify "$hash^0") || exit + remote_branch=$(expr "z$ref" : 'z\([^:]*\):') + for merge_branch in $merge_branches ; do + [ "$merge_branch" = "$remote_branch" ] && + echo "$hashc $note" && continue 2 + done + else + echo "$hash not-for-merge $note" && continue + fi + if ! test "$merge_first" || test "$merge_first" = "done" ; then + echo "$hash not-for-merge $note" + else + echo "$hash $note" + merge_first=done + fi +done < "$GIT_DIR"/FETCH_FETCHED >> "$GIT_DIR/FETCH_HEAD" diff --git a/git-parse-remote.sh b/git-parse-remote.sh index c46131f..99e7184 100755 --- a/git-parse-remote.sh +++ b/git-parse-remote.sh @@ -70,8 +70,7 @@ get_remote_default_refs_for_push () { esac } -# Called from canon_refs_list_for_fetch -d "$remote", which -# is called from get_remote_default_refs_for_fetch to grok +# Called from get_remote_default_refs_for_fetch to grok # refspecs that are retrieved from the configuration, but not # from get_remote_refs_for_fetch when it deals with refspecs # supplied on the command line. $ls_remote_result has the list @@ -87,30 +86,6 @@ expand_refs_wildcard () { # Subroutine to canonicalize remote:local notation. canon_refs_list_for_fetch () { - # If called from get_remote_default_refs_for_fetch - # leave the branches in branch.${curr_branch}.merge alone, - # or the first one otherwise; add prefix . to the rest - # to prevent the secondary branches to be merged by default. - merge_branches= - curr_branch= - if test "$1" = "-d" - then - shift ; remote="$1" ; shift - set $(expand_refs_wildcard "$remote" "$@") - is_explicit="$1" - shift - if test "$remote" = "$(get_default_remote)" - then - curr_branch=$(git-symbolic-ref -q HEAD | \ - sed -e 's|^refs/heads/||') - merge_branches=$(git-config \ - --get-all "branch.${curr_branch}.merge") - fi - if test -z "$merge_branches" && test $is_explicit != explicit - then - merge_branches=..this.will.never.match.any.ref.. - fi - fi for ref do force= @@ -123,18 +98,6 @@ canon_refs_list_for_fetch () { expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:" remote=$(expr "z$ref" : 'z\([^:]*\):') local=$(expr "z$ref" : 'z[^:]*:\(.*\)') - dot_prefix=. - if test -z "$merge_branches" - then - merge_branches=$remote - dot_prefix= - else - for merge_branch in $merge_branches - do - [ "$remote" = "$merge_branch" ] && - dot_prefix= && break - done - fi case "$remote" in '' | HEAD ) remote=HEAD ;; refs/heads/* | refs/tags/* | refs/remotes/*) ;; @@ -153,32 +116,42 @@ canon_refs_list_for_fetch () { git-check-ref-format "$local_ref_name" || die "* refusing to create funny ref '$local_ref_name' locally" fi - echo "${dot_prefix}${force}${remote}:${local}" + echo "${force}${remote}:${local}" done } # Returns list of src: (no store), or src:dst (store) get_remote_default_refs_for_fetch () { + test "$1" = -t && type=yes && shift + test "$1" = -n && canon=no && shift data_source=$(get_data_source "$1") case "$data_source" in '') - echo "HEAD:" ;; + set explicit "HEAD:" ;; config) - canon_refs_list_for_fetch -d "$1" \ - $(git-config --get-all "remote.$1.fetch") ;; + set $(expand_refs_wildcard "$1" \ + $(git-config --get-all "remote.$1.fetch")) ;; branches) remote_branch=$(sed -ne '/#/s/.*#//p' "$GIT_DIR/branches/$1") case "$remote_branch" in '') remote_branch=master ;; esac - echo "refs/heads/${remote_branch}:refs/heads/$1" + set explicit "refs/heads/${remote_branch}:refs/heads/$1" ;; remotes) - canon_refs_list_for_fetch -d "$1" $(sed -ne '/^Pull: */{ - s///p - }' "$GIT_DIR/remotes/$1") + set $(expand_refs_wildcard "$1" $(sed -ne '/^Pull: */s///p'\ + "$GIT_DIR/remotes/$1")) ;; *) die "internal error: get-remote-default-ref-for-push $1" ;; esac + if test "$type" = yes ; then + echo $1 + elif test "$canon" = no ; then + shift + for ref ; do echo "$ref" ; done + else + shift + canon_refs_list_for_fetch "$@" + fi } get_remote_refs_for_push () { -- 1.5.0.3.897.g91a70-dirty - To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html