- int count = 0;
-
- for (;;) {
- static char line[1000];
- unsigned char sha1[20];
- char *refname;
- int len;
-
- len = packet_read_line(fd, line, sizeof(line));
- if (!len)
- break;
- if (line[len-1] == '\n')
- line[--len] = 0;
- if (len < 42 || get_sha1_hex(line, sha1))
- die("git-fetch-pack: protocol error - expected ref descriptor, got '%s'", line);
- refname = line+41;
- if (nr_match && !path_match(refname, nr_match, match))
+ struct ref **return_refs;
+ struct ref *newlist = NULL;
+ struct ref **newtail = &newlist;
+ struct ref *ref, *next;
+ struct ref *fastarray[32];
+
+ if (nr_match && !fetch_all) {
+ if (ARRAY_SIZE(fastarray) < nr_match)
+ return_refs = xcalloc(nr_match, sizeof(struct ref *));
+ else {
+ return_refs = fastarray;
+ memset(return_refs, 0, sizeof(struct ref *) * nr_match);
+ }
+ }
+ else
+ return_refs = NULL;
+
+ for (ref = *refs; ref; ref = next) {
+ next = ref->next;
+ if (!memcmp(ref->name, "refs/", 5) &&
+ check_ref_format(ref->name + 5))
+ ; /* trash */
+ else if (fetch_all) {
+ *newtail = ref;
+ ref->next = NULL;
+ newtail = &ref->next;
+ continue;
+ }
+ else {
+ int order = path_match(ref->name, nr_match, match);
+ if (order) {
+ return_refs[order-1] = ref;
+ continue; /* we will link it later */
+ }
+ }
+ free(ref);
+ }
+
+ if (!fetch_all) {
+ int i;
+ for (i = 0; i < nr_match; i++) {
+ ref = return_refs[i];
+ if (ref) {
+ *newtail = ref;
+ ref->next = NULL;
+ newtail = &ref->next;
+ }
+ }
+ if (return_refs != fastarray)
+ free(return_refs);
+ }
+ *refs = newlist;
+}
+
+static int everything_local(struct ref **refs, int nr_match, char **match)
+{
+ struct ref *ref;
+ int retval;
+ unsigned long cutoff = 0;
+
+ track_object_refs = 0;
+ save_commit_buffer = 0;
+
+ for (ref = *refs; ref; ref = ref->next) {
+ struct object *o;
+
+ o = parse_object(ref->old_sha1);
+ if (!o)
+ continue;
+
+ /* We already have it -- which may mean that we were
+ * in sync with the other side at some time after
+ * that (it is OK if we guess wrong here).
+ */
+ if (o->type == commit_type) {
+ struct commit *commit = (struct commit *)o;
+ if (!cutoff || cutoff < commit->date)
+ cutoff = commit->date;
+ }
+ }
+
+ for_each_ref(mark_complete);
+ if (cutoff)
+ mark_recent_complete_commits(cutoff);
+
+ /*
+ * Mark all complete remote refs as common refs.
+ * Don't mark them common yet; the server has to be told so first.
+ */
+ for (ref = *refs; ref; ref = ref->next) {
+ struct object *o = deref_tag(lookup_object(ref->old_sha1),
+ NULL, 0);
+
+ if (!o || o->type != commit_type || !(o->flags & COMPLETE))
+ continue;
+
+ if (!(o->flags & SEEN)) {
+ rev_list_push((struct commit *)o, COMMON_REF | SEEN);
+
+ mark_common((struct commit *)o, 1, 1);
+ }
+ }
+
+ filter_refs(refs, nr_match, match);
+
+ for (retval = 1, ref = *refs; ref ; ref = ref->next) {
+ const unsigned char *remote = ref->old_sha1;
+ unsigned char local[20];
+ struct object *o;
+
+ o = lookup_object(remote);
+ if (!o || !(o->flags & COMPLETE)) {
+ retval = 0;
+ if (!verbose)
+ continue;
+ fprintf(stderr,
+ "want %s (%s)\n", sha1_to_hex(remote),
+ ref->name);