#include "cache.h"
+#include "refs.h"
#include "tag.h"
#include "commit.h"
#include "tree.h"
static int verbose_header = 0;
static int show_parents = 0;
static int hdr_termination = 0;
-static const char *prefix = "";
+static const char *commit_prefix = "";
static unsigned long max_age = -1;
static unsigned long min_age = -1;
static int max_count = -1;
{
commit->object.flags |= SHOWN;
if (show_breaks) {
- prefix = "| ";
+ commit_prefix = "| ";
if (commit->object.flags & DISCONTINUITY) {
- prefix = "^ ";
+ commit_prefix = "^ ";
} else if (commit->object.flags & BOUNDARY) {
- prefix = "= ";
+ commit_prefix = "= ";
}
}
- printf("%s%s", prefix, sha1_to_hex(commit->object.sha1));
+ printf("%s%s", commit_prefix, sha1_to_hex(commit->object.sha1));
if (show_parents) {
struct commit_list *parents = commit->parents;
while (parents) {
return CONTINUE;
if (max_age != -1 && (commit->date < max_age)) {
stop_traversal=1;
- return merge_order?CONTINUE:STOP;
+ return CONTINUE;
}
if (max_count != -1 && !max_count--)
return STOP;
die("bad tree object %s", sha1_to_hex(obj->sha1));
obj->flags |= SEEN;
p = add_object(obj, p, name);
- for (entry = tree->entries ; entry ; entry = entry->next) {
+ entry = tree->entries;
+ tree->entries = NULL;
+ while (entry) {
+ struct tree_entry_list *next = entry->next;
if (entry->directory)
p = process_tree(entry->item.tree, p, entry->name);
else
p = process_blob(entry->item.blob, p, entry->name);
+ free(entry);
+ entry = next;
}
return p;
}
die("unknown pending object %s (%s)", sha1_to_hex(obj->sha1), name);
}
while (objects) {
- printf("%s %s\n", sha1_to_hex(objects->item->sha1), objects->name);
+ /* An object with name "foo\n0000000000000000000000000000000000000000"
+ * can be used confuse downstream git-pack-objects very badly.
+ */
+ const char *ep = strchr(objects->name, '\n');
+ if (ep) {
+ printf("%s %.*s\n", sha1_to_hex(objects->item->sha1),
+ (int) (ep - objects->name),
+ objects->name);
+ }
+ else
+ printf("%s %s\n", sha1_to_hex(objects->item->sha1), objects->name);
objects = objects->next;
}
}
if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
entry = tree->entries;
+ tree->entries = NULL;
while (entry) {
+ struct tree_entry_list *next = entry->next;
if (entry->directory)
mark_tree_uninteresting(entry->item.tree);
else
mark_blob_uninteresting(entry->item.blob);
- entry = entry->next;
+ free(entry);
+ entry = next;
}
}
{
struct commit_list *parents = commit->parents;
- if (tree_objects)
- mark_tree_uninteresting(commit->tree);
while (parents) {
struct commit *commit = parents->item;
commit->object.flags |= UNINTERESTING;
continue;
return 0;
}
-
- /*
- * Ok, go back and mark all the edge trees uninteresting,
- * since otherwise we can have situations where a parent
- * that was marked uninteresting (and we never even had
- * to look at) had lots of objects that we don't want to
- * include.
- *
- * NOTE! This still doesn't mean that the object list is
- * "correct", since we may end up listing objects that
- * even older commits (that we don't list) do actually
- * reference, but it gets us to a minimal list (or very
- * close) in practice.
- */
- if (!tree_objects)
- return 1;
-
- while (orig) {
- struct commit *commit = orig->item;
- if (!parse_commit(commit) && commit->tree)
- mark_tree_uninteresting(commit->tree);
- orig = orig->next;
- }
return 1;
}
return best;
}
+static void mark_edges_uninteresting(struct commit_list *list)
+{
+ for ( ; list; list = list->next) {
+ struct commit_list *parents = list->item->parents;
+
+ for ( ; parents; parents = parents->next) {
+ struct commit *commit = parents->item;
+ if (commit->object.flags & UNINTERESTING)
+ mark_tree_uninteresting(commit->tree);
+ }
+ }
+}
+
static struct commit_list *limit_list(struct commit_list *list)
{
struct commit_list *newlist = NULL;
struct commit *commit = pop_most_recent_commit(&list, SEEN);
struct object *obj = &commit->object;
+ if (max_age != -1 && (commit->date < max_age))
+ obj->flags |= UNINTERESTING;
if (unpacked && has_sha1_pack(obj->sha1))
obj->flags |= UNINTERESTING;
if (obj->flags & UNINTERESTING) {
break;
continue;
}
+ if (min_age != -1 && (commit->date > min_age))
+ continue;
p = &commit_list_insert(commit, p)->next;
}
+ if (tree_objects)
+ mark_edges_uninteresting(newlist);
if (bisect_list)
newlist = find_bisection(newlist);
return newlist;
if (tag_objects && !(object->flags & UNINTERESTING))
add_pending_object(object, tag->tag);
object = parse_object(tag->tagged->sha1);
+ if (!object)
+ die("bad object %s", sha1_to_hex(tag->tagged->sha1));
}
/*
commit_list_insert(com, lst);
}
+/* for_each_ref() callback does not allow user data -- Yuck. */
+static struct commit_list **global_lst;
+
+static int include_one_commit(const char *path, const unsigned char *sha1)
+{
+ struct commit *com = get_commit_reference(path, 0);
+ handle_one_commit(com, global_lst);
+ return 0;
+}
+
+static void handle_all(struct commit_list **lst)
+{
+ global_lst = lst;
+ for_each_ref(include_one_commit);
+ global_lst = NULL;
+}
int main(int argc, char **argv)
{
struct commit_list *list = NULL;
int i, limited = 0;
+ setup_git_directory();
for (i = 1 ; i < argc; i++) {
int flags;
char *arg = argv[i];
}
if (!strncmp(arg, "--max-age=", 10)) {
max_age = atoi(arg + 10);
+ limited = 1;
continue;
}
if (!strncmp(arg, "--min-age=", 10)) {
min_age = atoi(arg + 10);
+ limited = 1;
continue;
}
if (!strcmp(arg, "--header")) {
verbose_header = 1;
hdr_termination = '\n';
if (commit_format == CMIT_FMT_ONELINE)
- prefix = "";
+ commit_prefix = "";
else
- prefix = "commit ";
+ commit_prefix = "commit ";
continue;
}
if (!strncmp(arg, "--no-merges", 11)) {
bisect_list = 1;
continue;
}
+ if (!strcmp(arg, "--all")) {
+ handle_all(&list);
+ continue;
+ }
if (!strcmp(arg, "--objects")) {
tag_objects = 1;
tree_objects = 1;
struct commit *exclude = NULL;
struct commit *include = NULL;
*dotdot = 0;
+ if (!*next)
+ next = "HEAD";
exclude = get_commit_reference(arg, UNINTERESTING);
include = get_commit_reference(next, 0);
if (exclude && include) {
handle_one_commit(include, &list);
continue;
}
- *next = '.';
+ *dotdot = '.';
}
if (*arg == '^') {
flags = UNINTERESTING;
handle_one_commit(commit, &list);
}
+ save_commit_buffer = verbose_header;
+ track_object_refs = 0;
+
if (!merge_order) {
sort_by_date(&list);
if (limited)