From 86551586da8cba6c06ac04783a656843a4e47f35 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 16 Jan 2007 13:43:28 -0800 Subject: [PATCH] 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 --- builtin-fetch--tool.c | 90 +++++++++++++++++++++++++++++++++++++++++++ git-parse-remote.sh | 46 +--------------------- 2 files changed, 91 insertions(+), 45 deletions(-) diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c index 705a6649a..3090ffea2 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 5208ee6ce..9b19a2166 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. -- 2.30.2