summaryrefslogtreecommitdiff
path: root/builtin-fetch--tool.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2007-01-16 01:53:29 -0800
committerJunio C Hamano <junkio@cox.net>2007-02-13 21:43:53 -0800
commitfbe2687eba70385dab7e3d1f5cdcdfdc11dfe0ec (patch)
tree6ff13c522e5be353d930d86d77227002026c8166 /builtin-fetch--tool.c
parentd4289fff870a85b1b7e55ead2a5baf98847fc72a (diff)
downloadgit-fbe2687eba70385dab7e3d1f5cdcdfdc11dfe0ec.tar.gz
git-fetch: move more code into C.
This adds "native-store" subcommand to git-fetch--tool to move a huge loop implemented in shell into C. This shaves about 70% of the runtime to fetch and update 1000 tracking branches with a single fetch. Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'builtin-fetch--tool.c')
-rw-r--r--builtin-fetch--tool.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/builtin-fetch--tool.c b/builtin-fetch--tool.c
index 3075ba04af..24343ac9b0 100644
--- a/builtin-fetch--tool.c
+++ b/builtin-fetch--tool.c
@@ -170,6 +170,119 @@ static int append_fetch_head(FILE *fp,
return update_local_ref(local_name, head, note, verbose, force);
}
+static char *keep;
+static void remove_keep(void)
+{
+ if (keep && *keep)
+ unlink(keep);
+}
+
+static void remove_keep_on_signal(int signo)
+{
+ remove_keep();
+ signal(SIGINT, SIG_DFL);
+ raise(signo);
+}
+
+static char *find_local_name(const char *remote_name, const char *refs,
+ int *force_p, int *not_for_merge_p)
+{
+ const char *ref = refs;
+ int len = strlen(remote_name);
+
+ while (ref) {
+ const char *next;
+ int single_force, not_for_merge;
+
+ while (*ref == '\n')
+ ref++;
+ if (!*ref)
+ break;
+ next = strchr(ref, '\n');
+
+ single_force = not_for_merge = 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;
+ int retlen;
+
+ if (!next)
+ retlen = strlen(local_part);
+ else
+ retlen = next - local_part;
+ ret = xmalloc(retlen + 1);
+ memcpy(ret, local_part, retlen);
+ ret[retlen] = 0;
+ *force_p = single_force;
+ *not_for_merge_p = not_for_merge;
+ return ret;
+ }
+ ref = next;
+ }
+ return NULL;
+}
+
+static int fetch_native_store(FILE *fp,
+ const char *remote,
+ const char *remote_nick,
+ const char *refs,
+ int verbose, int force)
+{
+ char buffer[1024];
+ int err = 0;
+
+ signal(SIGINT, remove_keep_on_signal);
+ atexit(remove_keep);
+
+ while (fgets(buffer, sizeof(buffer), stdin)) {
+ int len;
+ char *cp;
+ char *local_name;
+ int single_force, not_for_merge;
+
+ for (cp = buffer; *cp && !isspace(*cp); cp++)
+ ;
+ if (*cp)
+ *cp++ = 0;
+ len = strlen(cp);
+ if (len && cp[len-1] == '\n')
+ cp[--len] = 0;
+ if (!strcmp(buffer, "failed"))
+ die("Fetch failure: %s", remote);
+ if (!strcmp(buffer, "pack"))
+ continue;
+ if (!strcmp(buffer, "keep")) {
+ char *od = get_object_directory();
+ int len = strlen(od) + strlen(cp) + 50;
+ keep = xmalloc(len);
+ sprintf(keep, "%s/pack/pack-%s.keep", od, cp);
+ continue;
+ }
+
+ local_name = find_local_name(cp, refs,
+ &single_force, &not_for_merge);
+ if (!local_name)
+ continue;
+ err |= append_fetch_head(fp,
+ buffer, remote, cp, remote_nick,
+ local_name, not_for_merge,
+ verbose, force || single_force);
+ }
+ return err;
+}
+
int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
{
int verbose = 0;
@@ -210,5 +323,17 @@ int cmd_fetch__tool(int argc, const char **argv, const char *prefix)
return update_local_ref(argv[2], argv[3], argv[4],
verbose, force);
}
+ if (!strcmp("native-store", argv[1])) {
+ 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],
+ verbose, force);
+ fclose(fp);
+ return result;
+ }
return error("Unknown subcommand: %s", argv[1]);
}