git-fetch: rewrite another shell loop in C
authorJunio C Hamano <junkio@cox.net>
Tue, 16 Jan 2007 10:31:36 +0000 (02:31 -0800)
committerJunio C Hamano <junkio@cox.net>
Wed, 14 Feb 2007 05:43:53 +0000 (21:43 -0800)
Move another shell loop that canonicalizes the list of refs for
underlying git-fetch-pack and fetch-native-store into C.

This seems to shave the runtime for the same 1000 branch
repository from 30 seconds down to 15 seconds (it used to be 2
and half minutes with the original version).

Signed-off-by: Junio C Hamano <junkio@cox.net>
builtin-fetch--tool.c
git-fetch.sh
index 24343ac9b0f9f8f02034a8c921b698f48b0188ff..705a6649a996202f6f7a9da52ddd0292a55d6637 100644 (file)
@@ -283,6 +283,46 @@ static int fetch_native_store(FILE *fp,
        return err;
 }
 
+static int parse_reflist(const char *reflist)
+{
+       const char *ref;
+
+       printf("refs='");
+       for (ref = reflist; ref; ) {
+               const char *next;
+               while (*ref && isspace(*ref))
+                       ref++;
+               if (!*ref)
+                       break;
+               for (next = ref; *next && !isspace(*next); next++)
+                       ;
+               printf("\n%.*s", (int)(next - ref), ref);
+               ref = next;
+       }
+       printf("'\n");
+
+       printf("rref='");
+       for (ref = reflist; ref; ) {
+               const char *next, *colon;
+               while (*ref && isspace(*ref))
+                       ref++;
+               if (!*ref)
+                       break;
+               for (next = ref; *next && !isspace(*next); next++)
+                       ;
+               if (*ref == '.')
+                       ref++;
+               if (*ref == '+')
+                       ref++;
+               colon = strchr(ref, ':');
+               putchar('\n');
+               printf("%.*s", (int)((colon ? colon : next) - ref), ref);
+               ref = next;
+       }
+       printf("'\n");
+       return 0;
+}
+
 int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
 {
        int verbose = 0;
@@ -335,5 +375,11 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
                fclose(fp);
                return result;
        }
+       if (!strcmp("parse-reflist", argv[1])) {
+               if (argc != 3)
+                       return error("parse-reflist takes 1 arg");
+               return parse_reflist(argv[2]);
+       }
+
        return error("Unknown subcommand: %s", argv[1]);
 }
index b74dd9a309fedc27ebe53ff3c2106d0412a9f785..3bed4091a3826909878938239970a5d947c70d2c 100755 (executable)
@@ -155,35 +155,9 @@ then
 fi
 
 fetch_native () {
-  reflist="$1"
-  refs=
-  rref=
-
-  for ref in $reflist
-  do
-      refs="$refs$LF$ref"
-
-      # 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
-         ref=$(expr "z$ref" : 'z+\(.*\)')
-      else
-         single_force=
-      fi
-      remote_name=$(expr "z$ref" : 'z\([^:]*\):')
-      local_name=$(expr "z$ref" : 'z[^:]*:\(.*\)')
 
-      rref="$rref$LF$remote_name"
-  done
+  eval=$(git-fetch--tool parse-reflist "$1")
+  eval "$eval"
 
     ( : subshell because we muck with IFS
       IFS="    $LF"