fetch-pack: output refs in the order they were given on the command line.
[gitweb.git] / fetch-pack.c
index 535de10660bbc381d4f826be597fc7f404d317ca..8daa93d024158e6d8daff304db57ac80d1803c65 100644 (file)
@@ -7,8 +7,9 @@
 static int keep_pack;
 static int quiet;
 static int verbose;
+static int fetch_all;
 static const char fetch_pack_usage[] =
-"git-fetch-pack [-q] [-v] [-k] [--thin] [--exec=upload-pack] [host:]directory <refs>...";
+"git-fetch-pack [--all] [-q] [-v] [-k] [--thin] [--exec=upload-pack] [host:]directory <refs>...";
 static const char *exec = "git-upload-pack";
 
 #define COMPLETE       (1U << 0)
@@ -261,21 +262,58 @@ static void mark_recent_complete_commits(unsigned long cutoff)
 
 static void filter_refs(struct ref **refs, int nr_match, char **match)
 {
-       struct ref *prev, *current, *next;
-
-       for (prev = NULL, current = *refs; current; current = next) {
-               next = current->next;
-               if ((!memcmp(current->name, "refs/", 5) &&
-                                       check_ref_format(current->name + 5)) ||
-                               !path_match(current->name, nr_match, match)) {
-                       if (prev == NULL)
-                               *refs = next;
-                       else
-                               prev->next = next;
-                       free(current);
-               } else
-                       prev = current;
+       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)
@@ -376,7 +414,11 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
                goto all_done;
        }
        if (find_common(fd, sha1, ref) < 0)
-               fprintf(stderr, "warning: no common commits\n");
+               if (!keep_pack)
+                       /* When cloning, it is not unusual to have
+                        * no common commit.
+                        */
+                       fprintf(stderr, "warning: no common commits\n");
 
        if (keep_pack)
                status = receive_keep_pack(fd, "git-fetch-pack", quiet);
@@ -426,6 +468,10 @@ int main(int argc, char **argv)
                                use_thin_pack = 1;
                                continue;
                        }
+                       if (!strcmp("--all", arg)) {
+                               fetch_all = 1;
+                               continue;
+                       }
                        if (!strcmp("-v", arg)) {
                                verbose = 1;
                                continue;