summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLibravatar Junio C Hamano <junkio@cox.net>2007-01-16 13:43:28 -0800
committerLibravatar Junio C Hamano <junkio@cox.net>2007-02-13 21:43:53 -0800
commit86551586da8cba6c06ac04783a656843a4e47f35 (patch)
treefdc192784ed672835244a55220fb35869ec1b274
parentgit-fetch: rewrite another shell loop in C (diff)
downloadtgif-86551586da8cba6c06ac04783a656843a4e47f35.tar.xz
git-fetch: rewrite expand_ref_wildcard in C
This does not seem to make measurable improvement when dealing with 1000 unpacked refs, but we would need something like it if we were to do a full rewrite in C somedaoy. Signed-off-by: Junio C Hamano <junkio@cox.net>
-rw-r--r--builtin-fetch--tool.c90
-rwxr-xr-xgit-parse-remote.sh46
2 files changed, 91 insertions, 45 deletions
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index 705a6649a9..3090ffea20 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -323,6 +323,91 @@ static int parse_reflist(const char *reflist)
return 0;
}
+static int expand_refs_wildcard(const char *ls_remote_result, int numrefs,
+ const char **refs)
+{
+ int i, matchlen, replacelen;
+ int found_one = 0;
+ const char *remote = *refs++;
+ numrefs--;
+
+ if (numrefs == 0) {
+ fprintf(stderr, "Nothing specified for fetching with remote.%s.fetch\n",
+ remote);
+ printf("empty\n");
+ }
+
+ for (i = 0; i < numrefs; i++) {
+ const char *ref = refs[i];
+ const char *lref = ref;
+ const char *colon;
+ const char *tail;
+ const char *ls;
+ const char *next;
+
+ if (*lref == '+')
+ lref++;
+ colon = strchr(lref, ':');
+ tail = lref + strlen(lref);
+ if (!(colon &&
+ 2 < colon - lref &&
+ colon[-1] == '*' &&
+ colon[-2] == '/' &&
+ 2 < tail - (colon + 1) &&
+ tail[-1] == '*' &&
+ tail[-2] == '/')) {
+ /* not a glob */
+ if (!found_one++)
+ printf("explicit\n");
+ printf("%s\n", ref);
+ continue;
+ }
+
+ /* glob */
+ if (!found_one++)
+ printf("glob\n");
+
+ /* lref to colon-2 is remote hierarchy name;
+ * colon+1 to tail-2 is local.
+ */
+ matchlen = (colon-1) - lref;
+ replacelen = (tail-1) - (colon+1);
+ for (ls = ls_remote_result; ls; ls = next) {
+ const char *eol;
+ unsigned char sha1[20];
+ int namelen;
+
+ while (*ls && isspace(*ls))
+ ls++;
+ next = strchr(ls, '\n');
+ eol = !next ? (ls + strlen(ls)) : next;
+ if (!memcmp("^{}", eol-3, 3))
+ continue;
+ if (get_sha1_hex(ls, sha1))
+ continue;
+ ls += 40;
+ while (ls < eol && isspace(*ls))
+ ls++;
+ /* ls to next (or eol) is the name.
+ * is it identical to lref to colon-2?
+ */
+ if ((eol - ls) <= matchlen ||
+ strncmp(ls, lref, matchlen))
+ continue;
+
+ /* Yes, it is a match */
+ namelen = eol - ls;
+ if (lref != ref)
+ putchar('+');
+ printf("%.*s:%.*s%.*s\n",
+ namelen, ls,
+ replacelen, colon + 1,
+ namelen - matchlen, ls + matchlen);
+ }
+ }
+ return 0;
+}
+
int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
{
int verbose = 0;
@@ -380,6 +465,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
return error("parse-reflist takes 1 arg");
return parse_reflist(argv[2]);
}
+ if (!strcmp("expand-refs-wildcard", argv[1])) {
+ if (argc < 4)
+ return error("expand-refs-wildcard takes at least 2 args");
+ return expand_refs_wildcard(argv[2], argc - 3, argv + 3);
+ }
return error("Unknown subcommand: %s", argv[1]);
}
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 5208ee6ce0..9b19a21667 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -81,51 +81,7 @@ get_remote_default_refs_for_push () {
# is to help prevent randomly "globbed" ref from being chosen as
# a merge candidate
expand_refs_wildcard () {
- remote="$1"
- shift
- first_one=yes
- if test "$#" = 0
- then
- echo empty
- echo >&2 "Nothing specified for fetching with remote.$remote.fetch"
- fi
- for ref
- do
- lref=${ref#'+'}
- # a non glob pattern is given back as-is.
- expr "z$lref" : 'zrefs/.*/\*:refs/.*/\*$' >/dev/null || {
- if test -n "$first_one"
- then
- echo "explicit"
- first_one=
- fi
- echo "$ref"
- continue
- }
-
- # glob
- if test -n "$first_one"
- then
- echo "glob"
- first_one=
- fi
- from=`expr "z$lref" : 'z\(refs/.*/\)\*:refs/.*/\*$'`
- to=`expr "z$lref" : 'zrefs/.*/\*:\(refs/.*/\)\*$'`
- local_force=
- test "z$lref" = "z$ref" || local_force='+'
- echo "$ls_remote_result" |
- sed -e '/\^{}$/d' |
- (
- IFS=' '
- while read sha1 name
- do
- # ignore the ones that do not start with $from
- mapped=${name#"$from"}
- test "z$name" = "z$mapped" && continue
- echo "${local_force}${name}:${to}${mapped}"
- done
- )
- done
+ git fetch--tool expand-refs-wildcard "$ls_remote_result" "$@"
}
# Subroutine to canonicalize remote:local notation.