Handle symlinks graciously
[git.git] / rev-list.c
index 2b82b8a..d060966 100644 (file)
 #define TREECHANGE     (1u << 4)
 
 static const char rev_list_usage[] =
-       "git-rev-list [OPTION] commit-id <commit-id>\n"
-                     "  --max-count=nr\n"
-                     "  --max-age=epoch\n"
-                     "  --min-age=epoch\n"
-                     "  --parents\n"
-                     "  --bisect\n"
-                     "  --objects\n"
-                     "  --unpacked\n"
-                     "  --header\n"
-                     "  --pretty\n"
-                     "  --no-merges\n"
-                     "  --merge-order [ --show-breaks ]\n"
-                     "  --topo-order";
+"git-rev-list [OPTION] <commit-id>... [ -- paths... ]\n"
+"  limiting output:\n"
+"    --max-count=nr\n"
+"    --max-age=epoch\n"
+"    --min-age=epoch\n"
+"    --sparse\n"
+"    --no-merges\n"
+"    --all\n"
+"  ordering output:\n"
+"    --merge-order [ --show-breaks ]\n"
+"    --topo-order\n"
+"  formatting output:\n"
+"    --parents\n"
+"    --objects\n"
+"    --unpacked\n"
+"    --header | --pretty\n"
+"  special purpose:\n"
+"    --bisect"
+;
 
 static int dense = 1;
 static int unpacked = 0;
@@ -118,8 +124,6 @@ static int filter_commit(struct commit * commit)
                stop_traversal=1;
                return CONTINUE;
        }
-       if (max_count != -1 && !max_count--)
-               return STOP;
        if (no_merges && (commit->parents && commit->parents->next))
                return CONTINUE;
        if (paths && dense) {
@@ -142,6 +146,9 @@ static int process_commit(struct commit * commit)
                return CONTINUE;
        }
 
+       if (max_count != -1 && !max_count--)
+               return STOP;
+
        show_commit(commit);
 
        return CONTINUE;
@@ -343,7 +350,8 @@ static int count_distance(struct commit_list *entry)
 
                if (commit->object.flags & (UNINTERESTING | COUNTED))
                        break;
-               nr++;
+               if (!paths || (commit->object.flags & TREECHANGE))
+                       nr++;
                commit->object.flags |= COUNTED;
                p = commit->parents;
                entry = p;
@@ -355,6 +363,7 @@ static int count_distance(struct commit_list *entry)
                        }
                }
        }
+
        return nr;
 }
 
@@ -375,15 +384,20 @@ static struct commit_list *find_bisection(struct commit_list *list)
        nr = 0;
        p = list;
        while (p) {
-               nr++;
+               if (!paths || (p->item->object.flags & TREECHANGE))
+                       nr++;
                p = p->next;
        }
        closest = 0;
        best = list;
 
-       p = list;
-       while (p) {
-               int distance = count_distance(p);
+       for (p = list; p; p = p->next) {
+               int distance;
+
+               if (paths && !(p->item->object.flags & TREECHANGE))
+                       continue;
+
+               distance = count_distance(p);
                clear_distance(list);
                if (nr - distance < distance)
                        distance = nr - distance;
@@ -391,7 +405,6 @@ static struct commit_list *find_bisection(struct commit_list *list)
                        best = p;
                        closest = distance;
                }
-               p = p->next;
        }
        if (best)
                best->next = NULL;
@@ -837,7 +850,8 @@ int main(int argc, const char **argv)
                handle_one_commit(commit, &list);
        }
 
-       if (!list)
+       if (!list &&
+           (!(tag_objects||tree_objects||blob_objects) && !pending_objects))
                usage(rev_list_usage);
 
        paths = get_pathspec(prefix, argv + i);