X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=fetch.c;h=73bde07aeaeea67e44aef7aec1b79d5806e80a1b;hb=7b0c996679e975b666fd27c922e1e0837b611c98;hp=7db35f0dcc38276e32152a99b278429be955b992;hpb=22c6e1d0f76f58a425065d3e8e447b6366ccd98c;p=git.git diff --git a/fetch.c b/fetch.c index 7db35f0d..73bde07a 100644 --- a/fetch.c +++ b/fetch.c @@ -15,6 +15,7 @@ int get_tree = 0; int get_history = 0; int get_all = 0; int get_verbosely = 0; +int get_recover = 0; static unsigned char current_commit_sha1[20]; void pull_say(const char *fmt, const char *hex) @@ -33,36 +34,33 @@ static void report_missing(const char *what, const unsigned char *missing) what, missing_hex, sha1_to_hex(current_commit_sha1)); } -static int make_sure_we_have_it(const char *what, unsigned char *sha1) -{ - int status = 0; - - if (!has_sha1_file(sha1)) { - status = fetch(sha1); - if (status && what) - report_missing(what, sha1); - } - return status; -} - -static int process(unsigned char *sha1, const char *type); +static int process(struct object *obj); static int process_tree(struct tree *tree) { - struct tree_entry_list *entries; + struct tree_entry_list *entry; if (parse_tree(tree)) return -1; - for (entries = tree->entries; entries; entries = entries->next) { - if (process(entries->item.any->sha1, - entries->directory ? tree_type : blob_type)) + entry = tree->entries; + tree->entries = NULL; + while (entry) { + struct tree_entry_list *next = entry->next; + if (process(entry->item.any)) return -1; + free(entry->name); + free(entry); + entry = next; } return 0; } -struct commit_list *complete = NULL; +#define COMPLETE (1U << 0) +#define SEEN (1U << 1) +#define TO_SCAN (1U << 2) + +static struct commit_list *complete = NULL; static int process_commit(struct commit *commit) { @@ -70,17 +68,18 @@ static int process_commit(struct commit *commit) return -1; while (complete && complete->item->date >= commit->date) { - pop_most_recent_commit(&complete, 1); + pop_most_recent_commit(&complete, COMPLETE); } - - if (commit->object.flags & 1) + if (commit->object.flags & COMPLETE) return 0; memcpy(current_commit_sha1, commit->object.sha1, 20); + pull_say("walk %s\n", sha1_to_hex(commit->object.sha1)); + if (get_tree) { - if (process(commit->tree->object.sha1, tree_type)) + if (process(&commit->tree->object)) return -1; if (!get_all) get_tree = 0; @@ -88,8 +87,7 @@ static int process_commit(struct commit *commit) if (get_history) { struct commit_list *parents = commit->parents; for (; parents; parents = parents->next) { - if (process(parents->item->object.sha1, - commit_type)) + if (process(&parents->item->object)) return -1; } } @@ -100,7 +98,7 @@ static int process_tag(struct tag *tag) { if (parse_tag(tag)) return -1; - return process(tag->tagged->sha1, NULL); + return process(tag->tagged); } static struct object_list *process_queue = NULL; @@ -131,43 +129,49 @@ static int process_object(struct object *obj) obj->type, sha1_to_hex(obj->sha1)); } -static int process(unsigned char *sha1, const char *type) +static int process(struct object *obj) { - struct object *obj = lookup_object_type(sha1, type); + if (obj->flags & SEEN) + return 0; + obj->flags |= SEEN; - if (has_sha1_file(sha1)) { - parse_object(sha1); + if (has_sha1_file(obj->sha1)) { /* We already have it, so we should scan it now. */ - return process_object(obj); + obj->flags |= TO_SCAN; + } else { + if (obj->flags & COMPLETE) + return 0; + prefetch(obj->sha1); } - if (object_list_contains(process_queue, obj)) - return 0; + object_list_insert(obj, process_queue_end); process_queue_end = &(*process_queue_end)->next; - - //fprintf(stderr, "prefetch %s\n", sha1_to_hex(sha1)); - prefetch(sha1); - return 0; } static int loop(void) { + struct object_list *elem; + while (process_queue) { struct object *obj = process_queue->item; - /* - fprintf(stderr, "%d objects to pull\n", - object_list_length(process_queue)); - */ - process_queue = process_queue->next; + elem = process_queue; + process_queue = elem->next; + free(elem); if (!process_queue) process_queue_end = &process_queue; - //fprintf(stderr, "fetch %s\n", sha1_to_hex(obj->sha1)); - - if (make_sure_we_have_it(obj->type ? obj->type : "object", - obj->sha1)) - return -1; + /* If we are not scanning this object, we placed it in + * the queue because we needed to fetch it first. + */ + if (! (obj->flags & TO_SCAN)) { + if (fetch(obj->sha1)) { + report_missing(obj->type + ? obj->type + : "object", obj->sha1); + return -1; + } + } if (!obj->type) parse_object(obj->sha1); if (process_object(obj)) @@ -190,14 +194,10 @@ static int interpret_target(char *target, unsigned char *sha1) static int mark_complete(const char *path, const unsigned char *sha1) { - struct object *obj = parse_object(sha1); - while (obj->type == tag_type) { - obj = ((struct tag *) obj)->tagged; - parse_object(obj->sha1); - } - if (obj->type == commit_type) { - obj->flags |= 1; - insert_by_date((struct commit *) obj, &complete); + struct commit *commit = lookup_commit_reference_gently(sha1, 1); + if (commit) { + commit->object.flags |= COMPLETE; + insert_by_date(commit, &complete); } return 0; } @@ -207,18 +207,22 @@ int pull(char *target) unsigned char sha1[20]; int fd = -1; + save_commit_buffer = 0; + track_object_refs = 0; if (write_ref && current_ref) { fd = lock_ref_sha1(write_ref, current_ref); if (fd < 0) return -1; } - for_each_ref(mark_complete); + if (!get_recover) { + for_each_ref(mark_complete); + } if (interpret_target(target, sha1)) return error("Could not interpret %s as something to pull", target); - if (process(sha1, NULL)) + if (process(lookup_unknown_object(sha1))) return -1; if (loop()) return -1;