From 28b8e61fc63b6776a91e8afd03c7171fbf0779b0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 22 Nov 2006 21:57:14 -0800 Subject: git-fetch: reuse ls-remote result. This will become necessary to update the dumb protocol transports to fetch from a repository with packed and then pruned tags. Signed-off-by: Junio C Hamano --- git-fetch.sh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'git-fetch.sh') diff --git a/git-fetch.sh b/git-fetch.sh index eb32476bbd..170c2cb048 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -88,6 +88,10 @@ then : >"$GIT_DIR/FETCH_HEAD" fi +# Global that is reused later +ls_remote_result=$(git ls-remote $upload_pack "$remote") || + die "Cannot find the reflist at $remote" + append_fetch_head () { head_="$1" remote_="$2" @@ -233,10 +237,7 @@ reflist=$(get_remote_refs_for_fetch "$@") if test "$tags" then taglist=`IFS=" " && - ( - git-ls-remote $upload_pack --tags "$remote" || - echo fail ouch - ) | + echo "$ls_remote_result" | while read sha1 name do case "$sha1" in @@ -245,6 +246,8 @@ then esac case "$name" in *^*) continue ;; + refs/tags/*) ;; + *) continue ;; esac if git-check-ref-format "$name" then @@ -431,7 +434,7 @@ case "$no_tags$tags" in # effective only when we are following remote branch # using local tracking branch. taglist=$(IFS=" " && - git-ls-remote $upload_pack --tags "$remote" | + echo "$ls_remote_result" | sed -n -e 's|^\('"$_x40"'\) \(refs/tags/.*\)^{}$|\1 \2|p' \ -e 's|^\('"$_x40"'\) \(refs/tags/.*\)$|\1 \2|p' | while read sha1 name -- cgit v1.3-5-g9baa From 2986c02217f98809d8990e7679edf0f5d99f904d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 22 Nov 2006 22:24:09 -0800 Subject: git-fetch: fix dumb protocol transport to fetch from pack-pruned ref Earlier, commit walkers downloaded loose refs from refs/ hierarchy of the remote side to find where to start walking; this would not work for a repository whose refs are packed and then pruned. With the previous change, we have ls-remote output from the remote in-core; we can use the value from there without requiring loose refs anymore. Signed-off-by: Junio C Hamano --- git-fetch.sh | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) (limited to 'git-fetch.sh') diff --git a/git-fetch.sh b/git-fetch.sh index 170c2cb048..06b66b968d 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -307,22 +307,20 @@ fetch_main () { "`git-repo-config --bool http.noEPSV`" = true ]; then noepsv_opt="--disable-epsv" fi - max_depth=5 - depth=0 - head="ref: $remote_name" - while (expr "z$head" : "zref:" && expr $depth \< $max_depth) >/dev/null - do - remote_name_quoted=$(@@PERL@@ -e ' - my $u = $ARGV[0]; - $u =~ s/^ref:\s*//; - $u =~ s{([^-a-zA-Z0-9/.])}{sprintf"%%%02x",ord($1)}eg; - print "$u"; - ' "$head") - head=$(curl -nsfL $curl_extra_args $noepsv_opt "$remote/$remote_name_quoted") - depth=$( expr \( $depth + 1 \) ) - done + + # Find $remote_name from ls-remote output. + head=$( + IFS=' ' + echo "$ls_remote_result" | + while read sha1 name + do + test "z$name" = "z$remote_name" || continue + echo "$sha1" + break + done + ) expr "z$head" : "z$_x40\$" >/dev/null || - die "Failed to fetch $remote_name from $remote" + die "No such ref $remote_name at $remote" echo >&2 "Fetching $remote_name from $remote using $proto" git-http-fetch -v -a "$head" "$remote/" || exit ;; -- cgit v1.3-5-g9baa From f64d7fd267c501f501e18a888e3e1e0c5b56458f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 25 Nov 2006 01:04:28 -0800 Subject: git-fetch: exit with non-zero status when fast-forward check fails When update_local_ref() refuses to update a branch head due to fast-forward check, it was not propagated properly in the call chain and the command did not exit with non-zero status as a result. Signed-off-by: Junio C Hamano --- git-fetch.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'git-fetch.sh') diff --git a/git-fetch.sh b/git-fetch.sh index eb32476bbd..4425562098 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -359,7 +359,7 @@ fetch_main () { esac append_fetch_head "$head" "$remote" \ - "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" + "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" || exit done @@ -413,15 +413,16 @@ fetch_main () { done local_name=$(expr "z$found" : 'z[^:]*:\(.*\)') append_fetch_head "$sha1" "$remote" \ - "$remote_name" "$remote_nick" "$local_name" "$not_for_merge" - done + "$remote_name" "$remote_nick" "$local_name" \ + "$not_for_merge" || exit + done && if [ "$pack_lockfile" ]; then rm -f "$pack_lockfile"; fi ) || exit ;; esac } -fetch_main "$reflist" +fetch_main "$reflist" || exit # automated tag following case "$no_tags$tags" in @@ -449,7 +450,7 @@ case "$no_tags$tags" in case "$taglist" in '') ;; ?*) - fetch_main "$taglist" ;; + fetch_main "$taglist" || exit ;; esac esac -- cgit v1.3-5-g9baa From 4da9028578ffaaf8985e1436e2e1cf16bd3b9023 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 14 Dec 2006 00:36:23 -0800 Subject: git-fetch: make it work from within a subdirectory. Signed-off-by: Junio C Hamano --- git-fetch.sh | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'git-fetch.sh') diff --git a/git-fetch.sh b/git-fetch.sh index 4eecf148ea..fb35815a5f 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -2,7 +2,13 @@ # USAGE=' ...' +SUBDIRECTORY_OK=Yes . git-sh-setup +TOP=$(git-rev-parse --show-cdup) +if test ! -z "$TOP" +then + cd "$TOP" +fi . git-parse-remote _x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]' _x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40" -- cgit v1.3-5-g9baa From ed9f7c954c26ec6d517bdca3d8e4b895278d1b2b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Dec 2006 17:57:19 -0800 Subject: git-fetch: Avoid reading packed refs over and over again When checking which tags to fetch, the old code used to call git-show-ref --verify for each remote tag. Since reading even packed refs is not a cheap operation when there are a lot of local refs, the code became quite slow. This fixes it by teaching git-show-ref to filter out existing refs using a new mode of operation of git-show-ref. Signed-off-by: Junio C Hamano --- builtin-show-ref.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++- git-fetch.sh | 12 +++-------- 2 files changed, 62 insertions(+), 10 deletions(-) (limited to 'git-fetch.sh') diff --git a/builtin-show-ref.c b/builtin-show-ref.c index 073979855b..b36f15eeaa 100644 --- a/builtin-show-ref.c +++ b/builtin-show-ref.c @@ -2,8 +2,9 @@ #include "refs.h" #include "object.h" #include "tag.h" +#include "path-list.h" -static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=]] [--abbrev[=]] [--tags] [--heads] [--] [pattern*]"; +static const char show_ref_usage[] = "git show-ref [-q|--quiet] [--verify] [-h|--head] [-d|--dereference] [-s|--hash[=]] [--abbrev[=]] [--tags] [--heads] [--] [pattern*] | --filter-invalid < ref-list"; static int deref_tags = 0, show_head = 0, tags_only = 0, heads_only = 0, found_match = 0, verify = 0, quiet = 0, hash_only = 0, abbrev = 0; @@ -86,6 +87,59 @@ match: return 0; } +static int add_existing(const char *refname, const unsigned char *sha1, int flag, void *cbdata) +{ + struct path_list *list = (struct path_list *)cbdata; + path_list_insert(refname, list); + return 0; +} + +/* + * read "^(?:\s)?(?:\^\{\})?$" from the standard input, + * and + * (1) strip "^{}" at the end of line if any; + * (2) ignore if match is provided and does not head-match refname; + * (3) warn if refname is not a well-formed refname and skip; + * (4) ignore if refname is a ref that exists in the local repository; + * (5) otherwise output the line. + */ +static int exclude_existing(const char *match) +{ + static struct path_list existing_refs = { NULL, 0, 0, 0 }; + char buf[1024]; + int matchlen = match ? strlen(match) : 0; + + for_each_ref(add_existing, &existing_refs); + while (fgets(buf, sizeof(buf), stdin)) { + int len = strlen(buf); + char *ref; + if (len > 0 && buf[len - 1] == '\n') + buf[--len] = '\0'; + if (!strcmp(buf + len - 3, "^{}")) { + len -= 3; + buf[len] = '\0'; + } + for (ref = buf + len; buf < ref; ref--) + if (isspace(ref[-1])) + break; + if (match) { + int reflen = buf + len - ref; + if (reflen < matchlen) + continue; + if (strncmp(ref, match, matchlen)) + continue; + } + if (check_ref_format(ref)) { + fprintf(stderr, "warning: ref '%s' ignored\n", ref); + continue; + } + if (!path_list_has_path(&existing_refs, ref)) { + printf("%s\n", buf); + } + } + return 0; +} + int cmd_show_ref(int argc, const char **argv, const char *prefix) { int i; @@ -153,6 +207,10 @@ int cmd_show_ref(int argc, const char **argv, const char *prefix) heads_only = 1; continue; } + if (!strcmp(arg, "--exclude-existing")) + return exclude_existing(NULL); + if (!strncmp(arg, "--exclude-existing=", 19)) + return exclude_existing(arg + 19); usage(show_ref_usage); } if (show_head) diff --git a/git-fetch.sh b/git-fetch.sh index fb35815a5f..38101a6ace 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -242,7 +242,7 @@ esac reflist=$(get_remote_refs_for_fetch "$@") if test "$tags" then - taglist=`IFS=" " && + taglist=`IFS=' ' && echo "$ls_remote_result" | while read sha1 name do @@ -438,17 +438,11 @@ case "$no_tags$tags" in *:refs/*) # effective only when we are following remote branch # using local tracking branch. - taglist=$(IFS=" " && + taglist=$(IFS=' ' && echo "$ls_remote_result" | - sed -n -e 's|^\('"$_x40"'\) \(refs/tags/.*\)^{}$|\1 \2|p' \ - -e 's|^\('"$_x40"'\) \(refs/tags/.*\)$|\1 \2|p' | + git-show-ref --exclude-existing=refs/tags/ | while read sha1 name do - git-show-ref --verify --quiet -- "$name" && continue - git-check-ref-format "$name" || { - echo >&2 "warning: tag ${name} ignored" - continue - } git-cat-file -t "$sha1" >/dev/null 2>&1 || continue echo >&2 "Auto-following $name" echo ".${name}:${name}" -- cgit v1.3-5-g9baa From b3d9899324af174ff123498b5c7ded3749aac2bc Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 18 Dec 2006 15:16:58 -0500 Subject: make git a bit less cryptic on fetch errors The remote server might not want to tell why it doesn't like us for security reasons, but let's make the client report such error in a bit less confusing way. The remote failure remains a mystery, but the local message might be a bit less so. [jc: with a gentle wording updates from Andy Parkins] Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- git-fetch.sh | 2 +- git-ls-remote.sh | 2 +- pkt-line.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'git-fetch.sh') diff --git a/git-fetch.sh b/git-fetch.sh index 38101a6ace..ffbd44f0e1 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -96,7 +96,7 @@ fi # Global that is reused later ls_remote_result=$(git ls-remote $upload_pack "$remote") || - die "Cannot find the reflist at $remote" + die "Cannot get the repository state from $remote" append_fetch_head () { head_="$1" diff --git a/git-ls-remote.sh b/git-ls-remote.sh index 0f88953f29..03b624ef33 100755 --- a/git-ls-remote.sh +++ b/git-ls-remote.sh @@ -94,7 +94,7 @@ while read sha1 path do case "$sha1" in failed) - die "Failed to find remote refs" + exit 1 ;; esac case "$path" in refs/heads/*) diff --git a/pkt-line.c b/pkt-line.c index c1e81f976f..b4cb7e2756 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -72,7 +72,7 @@ static void safe_read(int fd, void *buffer, unsigned size) if (ret < 0) die("read error (%s)", strerror(errno)); if (!ret) - die("unexpected EOF"); + die("The remote end hung up unexpectedly"); n += ret; } } -- cgit v1.3-5-g9baa