Merge part of branch 'jc/upload-pack'
[gitweb.git] / revision.c
index 5a91d06b980d710e30a80c353a636ca1ca6b9a55..6a2539b623512917479be3e6601ee8b8bef4953d 100644 (file)
@@ -416,7 +416,8 @@ static void limit_list(struct rev_info *revs)
 
                if (revs->max_age != -1 && (commit->date < revs->max_age))
                        obj->flags |= UNINTERESTING;
-               if (revs->unpacked && has_sha1_pack(obj->sha1))
+               if (revs->unpacked &&
+                   has_sha1_pack(obj->sha1, revs->ignore_packed))
                        obj->flags |= UNINTERESTING;
                add_parents_to_list(revs, commit, &list);
                if (obj->flags & UNINTERESTING) {
@@ -496,7 +497,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
                it = get_reference(revs, arg, sha1, 0);
                if (it->type != OBJ_TAG)
                        break;
-               memcpy(sha1, ((struct tag*)it)->tagged->sha1, 20);
+               hashcpy(sha1, ((struct tag*)it)->tagged->sha1);
        }
        if (it->type != OBJ_COMMIT)
                return 0;
@@ -592,6 +593,95 @@ static void prepare_show_merge(struct rev_info *revs)
        revs->prune_data = prune;
 }
 
+int handle_revision_arg(const char *arg, struct rev_info *revs,
+                       int flags,
+                       int cant_be_filename)
+{
+       char *dotdot;
+       struct object *object;
+       unsigned char sha1[20];
+       int local_flags;
+
+       dotdot = strstr(arg, "..");
+       if (dotdot) {
+               unsigned char from_sha1[20];
+               const char *next = dotdot + 2;
+               const char *this = arg;
+               int symmetric = *next == '.';
+               unsigned int flags_exclude = flags ^ UNINTERESTING;
+
+               *dotdot = 0;
+               next += symmetric;
+
+               if (!*next)
+                       next = "HEAD";
+               if (dotdot == arg)
+                       this = "HEAD";
+               if (!get_sha1(this, from_sha1) &&
+                   !get_sha1(next, sha1)) {
+                       struct commit *a, *b;
+                       struct commit_list *exclude;
+
+                       a = lookup_commit_reference(from_sha1);
+                       b = lookup_commit_reference(sha1);
+                       if (!a || !b) {
+                               die(symmetric ?
+                                   "Invalid symmetric difference expression %s...%s" :
+                                   "Invalid revision range %s..%s",
+                                   arg, next);
+                       }
+
+                       if (!cant_be_filename) {
+                               *dotdot = '.';
+                               verify_non_filename(revs->prefix, arg);
+                       }
+
+                       if (symmetric) {
+                               exclude = get_merge_bases(a, b, 1);
+                               add_pending_commit_list(revs, exclude,
+                                                       flags_exclude);
+                               free_commit_list(exclude);
+                               a->object.flags |= flags;
+                       } else
+                               a->object.flags |= flags_exclude;
+                       b->object.flags |= flags;
+                       add_pending_object(revs, &a->object, this);
+                       add_pending_object(revs, &b->object, next);
+                       return 0;
+               }
+               *dotdot = '.';
+       }
+       dotdot = strstr(arg, "^@");
+       if (dotdot && !dotdot[2]) {
+               *dotdot = 0;
+               if (add_parents_only(revs, arg, flags))
+                       return 0;
+               *dotdot = '^';
+       }
+       local_flags = 0;
+       if (*arg == '^') {
+               local_flags = UNINTERESTING;
+               arg++;
+       }
+       if (get_sha1(arg, sha1))
+               return -1;
+       if (!cant_be_filename)
+               verify_non_filename(revs->prefix, arg);
+       object = get_reference(revs, arg, sha1, flags ^ local_flags);
+       add_pending_object(revs, object, arg);
+       return 0;
+}
+
+static void add_ignore_packed(struct rev_info *revs, const char *name)
+{
+       int num = ++revs->num_ignore_packed;
+
+       revs->ignore_packed = xrealloc(revs->ignore_packed,
+                                      sizeof(const char **) * (num + 1));
+       revs->ignore_packed[num-1] = name;
+       revs->ignore_packed[num] = NULL;
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -620,12 +710,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
 
        flags = show_merge = 0;
        for (i = 1; i < argc; i++) {
-               struct object *object;
                const char *arg = argv[i];
-               unsigned char sha1[20];
-               char *dotdot;
-               int local_flags;
-
                if (*arg == '-') {
                        int opts;
                        if (!strncmp(arg, "--max-count=", 12)) {
@@ -737,6 +822,14 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        }
                        if (!strcmp(arg, "--unpacked")) {
                                revs->unpacked = 1;
+                               free(revs->ignore_packed);
+                               revs->ignore_packed = NULL;
+                               revs->num_ignore_packed = 0;
+                               continue;
+                       }
+                       if (!strncmp(arg, "--unpacked=", 11)) {
+                               revs->unpacked = 1;
+                               add_ignore_packed(revs, arg+11);
                                continue;
                        }
                        if (!strcmp(arg, "-r")) {
@@ -816,6 +909,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                                revs->simplify_history = 0;
                                continue;
                        }
+                       if (!strcmp(arg, "--relative-date")) {
+                               revs->relative_date = 1;
+                               continue;
+                       }
                        opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
                        if (opts > 0) {
                                revs->diff = 1;
@@ -826,71 +923,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        left++;
                        continue;
                }
-               dotdot = strstr(arg, "..");
-               if (dotdot) {
-                       unsigned char from_sha1[20];
-                       const char *next = dotdot + 2;
-                       const char *this = arg;
-                       int symmetric = *next == '.';
-                       unsigned int flags_exclude = flags ^ UNINTERESTING;
-
-                       *dotdot = 0;
-                       next += symmetric;
-
-                       if (!*next)
-                               next = "HEAD";
-                       if (dotdot == arg)
-                               this = "HEAD";
-                       if (!get_sha1(this, from_sha1) &&
-                           !get_sha1(next, sha1)) {
-                               struct commit *a, *b;
-                               struct commit_list *exclude;
-
-                               a = lookup_commit_reference(from_sha1);
-                               b = lookup_commit_reference(sha1);
-                               if (!a || !b) {
-                                       die(symmetric ?
-                                           "Invalid symmetric difference expression %s...%s" :
-                                           "Invalid revision range %s..%s",
-                                           arg, next);
-                               }
-
-                               if (!seen_dashdash) {
-                                       *dotdot = '.';
-                                       verify_non_filename(revs->prefix, arg);
-                               }
-
-                               if (symmetric) {
-                                       exclude = get_merge_bases(a, b, 1);
-                                       add_pending_commit_list(revs, exclude,
-                                                               flags_exclude);
-                                       free_commit_list(exclude);
-                                       a->object.flags |= flags;
-                               } else
-                                       a->object.flags |= flags_exclude;
-                               b->object.flags |= flags;
-                               add_pending_object(revs, &a->object, this);
-                               add_pending_object(revs, &b->object, next);
-                               continue;
-                       }
-                       *dotdot = '.';
-               }
-               dotdot = strstr(arg, "^@");
-               if (dotdot && !dotdot[2]) {
-                       *dotdot = 0;
-                       if (add_parents_only(revs, arg, flags))
-                               continue;
-                       *dotdot = '^';
-               }
-               local_flags = 0;
-               if (*arg == '^') {
-                       local_flags = UNINTERESTING;
-                       arg++;
-               }
-               if (get_sha1(arg, sha1)) {
-                       int j;
 
-                       if (seen_dashdash || local_flags)
+               if (handle_revision_arg(arg, revs, flags, seen_dashdash)) {
+                       int j;
+                       if (seen_dashdash || *arg == '^')
                                die("bad revision '%s'", arg);
 
                        /* If we didn't have a "--":
@@ -902,14 +938,12 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
                        for (j = i; j < argc; j++)
                                verify_filename(revs->prefix, argv[j]);
 
-                       revs->prune_data = get_pathspec(revs->prefix, argv + i);
+                       revs->prune_data = get_pathspec(revs->prefix,
+                                                       argv + i);
                        break;
                }
-               if (!seen_dashdash)
-                       verify_non_filename(revs->prefix, arg);
-               object = get_reference(revs, arg, sha1, flags ^ local_flags);
-               add_pending_object(revs, object, arg);
        }
+
        if (show_merge)
                prepare_show_merge(revs);
        if (def && !revs->pending.nr) {
@@ -1042,7 +1076,8 @@ struct commit *get_revision(struct rev_info *revs)
                 */
                if (!revs->limited) {
                        if ((revs->unpacked &&
-                            has_sha1_pack(commit->object.sha1)) ||
+                            has_sha1_pack(commit->object.sha1,
+                                          revs->ignore_packed)) ||
                            (revs->max_age != -1 &&
                             (commit->date < revs->max_age)))
                                continue;