ref-filter: add an 'rstrip=<N>' option to atoms which deal with refnames
[gitweb.git] / revision.c
index 8a29cb03c51be119589a763b170809b8208e1857..b37dbec378f3ae1a33d00d591c1042c609e45fa4 100644 (file)
@@ -1275,7 +1275,7 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned flags)
                if (S_ISGITLINK(ce->ce_mode))
                        continue;
 
-               blob = lookup_blob(ce->sha1);
+               blob = lookup_blob(ce->oid.hash);
                if (!blob)
                        die("unable to add index blob to traversal");
                add_pending_object_with_path(revs, &blob->object, "",
@@ -1289,12 +1289,14 @@ void add_index_objects_to_pending(struct rev_info *revs, unsigned flags)
        }
 }
 
-static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
+static int add_parents_only(struct rev_info *revs, const char *arg_, int flags,
+                           int exclude_parent)
 {
        unsigned char sha1[20];
        struct object *it;
        struct commit *commit;
        struct commit_list *parents;
+       int parent_number;
        const char *arg = arg_;
 
        if (*arg == '^') {
@@ -1316,7 +1318,15 @@ static int add_parents_only(struct rev_info *revs, const char *arg_, int flags)
        if (it->type != OBJ_COMMIT)
                return 0;
        commit = (struct commit *)it;
-       for (parents = commit->parents; parents; parents = parents->next) {
+       if (exclude_parent &&
+           exclude_parent > commit_list_count(commit->parents))
+               return 0;
+       for (parents = commit->parents, parent_number = 1;
+            parents;
+            parents = parents->next, parent_number++) {
+               if (exclude_parent && parent_number != exclude_parent)
+                       continue;
+
                it = &parents->item->object;
                it->flags |= flags;
                add_rev_cmdline(revs, it, arg_, REV_CMD_PARENTS_ONLY, flags);
@@ -1519,17 +1529,33 @@ int handle_revision_arg(const char *arg_, struct rev_info *revs, int flags, unsi
                }
                *dotdot = '.';
        }
+
        dotdot = strstr(arg, "^@");
        if (dotdot && !dotdot[2]) {
                *dotdot = 0;
-               if (add_parents_only(revs, arg, flags))
+               if (add_parents_only(revs, arg, flags, 0))
                        return 0;
                *dotdot = '^';
        }
        dotdot = strstr(arg, "^!");
        if (dotdot && !dotdot[2]) {
                *dotdot = 0;
-               if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM)))
+               if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM), 0))
+                       *dotdot = '^';
+       }
+       dotdot = strstr(arg, "^-");
+       if (dotdot) {
+               int exclude_parent = 1;
+
+               if (dotdot[2]) {
+                       char *end;
+                       exclude_parent = strtoul(dotdot + 2, &end, 10);
+                       if (*end != '\0' || !exclude_parent)
+                               return -1;
+               }
+
+               *dotdot = 0;
+               if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM), exclude_parent))
                        *dotdot = '^';
        }