diff --git a/revision.c b/revision.c
index bcdb6a12122871e743dd3b2362ca7bd5b1b787df..ce70f48ce0880e8b43c3f62cd13bc185bfee8c4b 100644 (file)
--- a/revision.c
+++ b/revision.c
#include "revision.h"
#include "grep.h"
#include "reflog-walk.h"
#include "revision.h"
#include "grep.h"
#include "reflog-walk.h"
+#include "patch-ids.h"
static char *path_name(struct name_path *path, const char *name)
{
static char *path_name(struct name_path *path, const char *name)
{
if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
if (parse_tree(tree) < 0)
die("bad tree %s", sha1_to_hex(obj->sha1));
- desc.buf = tree->buffer;
- desc.size = tree->size;
+ init_tree_desc(&desc, tree->buffer, tree->size);
while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
mark_tree_uninteresting(lookup_tree(entry.sha1));
while (tree_entry(&desc, &entry)) {
if (S_ISDIR(entry.mode))
mark_tree_uninteresting(lookup_tree(entry.sha1));
{
int retval;
void *tree;
{
int retval;
void *tree;
+ unsigned long size;
struct tree_desc empty, real;
if (!t1)
return 0;
struct tree_desc empty, real;
if (!t1)
return 0;
- tree = read_object_with_reference(t1->object.sha1, tree_type, &real.size, NULL);
+ tree = read_object_with_reference(t1->object.sha1, tree_type, &size, NULL);
if (!tree)
return 0;
if (!tree)
return 0;
- real.buf = tree;
-
- empty.buf = "";
- empty.size = 0;
+ init_tree_desc(&real, tree, size);
+ init_tree_desc(&empty, "", 0);
tree_difference = REV_TREE_SAME;
revs->pruning.has_changes = 0;
tree_difference = REV_TREE_SAME;
revs->pruning.has_changes = 0;
@@ -362,6 +361,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st
{
struct commit_list *parent = commit->parents;
unsigned left_flag;
{
struct commit_list *parent = commit->parents;
unsigned left_flag;
+ int add, rest;
if (commit->object.flags & ADDED)
return;
if (commit->object.flags & ADDED)
return;
@@ -407,19 +407,100 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st
return;
left_flag = (commit->object.flags & SYMMETRIC_LEFT);
return;
left_flag = (commit->object.flags & SYMMETRIC_LEFT);
- parent = commit->parents;
- while (parent) {
+
+ rest = !revs->first_parent_only;
+ for (parent = commit->parents, add = 1; parent; add = rest) {
struct commit *p = parent->item;
parent = parent->next;
struct commit *p = parent->item;
parent = parent->next;
-
parse_commit(p);
p->object.flags |= left_flag;
if (p->object.flags & SEEN)
continue;
p->object.flags |= SEEN;
parse_commit(p);
p->object.flags |= left_flag;
if (p->object.flags & SEEN)
continue;
p->object.flags |= SEEN;
- insert_by_date(p, list);
+ if (add)
+ insert_by_date(p, list);
+ }
+}
+
+static void cherry_pick_list(struct commit_list *list)
+{
+ struct commit_list *p;
+ int left_count = 0, right_count = 0;
+ int left_first;
+ struct patch_ids ids;
+
+ /* First count the commits on the left and on the right */
+ for (p = list; p; p = p->next) {
+ struct commit *commit = p->item;
+ unsigned flags = commit->object.flags;
+ if (flags & BOUNDARY)
+ ;
+ else if (flags & SYMMETRIC_LEFT)
+ left_count++;
+ else
+ right_count++;
+ }
+
+ left_first = left_count < right_count;
+ init_patch_ids(&ids);
+
+ /* Compute patch-ids for one side */
+ for (p = list; p; p = p->next) {
+ struct commit *commit = p->item;
+ unsigned flags = commit->object.flags;
+
+ if (flags & BOUNDARY)
+ continue;
+ /*
+ * If we have fewer left, left_first is set and we omit
+ * commits on the right branch in this loop. If we have
+ * fewer right, we skip the left ones.
+ */
+ if (left_first != !!(flags & SYMMETRIC_LEFT))
+ continue;
+ commit->util = add_commit_patch_id(commit, &ids);
+ }
+
+ /* Check the other side */
+ for (p = list; p; p = p->next) {
+ struct commit *commit = p->item;
+ struct patch_id *id;
+ unsigned flags = commit->object.flags;
+
+ if (flags & BOUNDARY)
+ continue;
+ /*
+ * If we have fewer left, left_first is set and we omit
+ * commits on the left branch in this loop.
+ */
+ if (left_first == !!(flags & SYMMETRIC_LEFT))
+ continue;
+
+ /*
+ * Have we seen the same patch id?
+ */
+ id = has_commit_patch_id(commit, &ids);
+ if (!id)
+ continue;
+ id->seen = 1;
+ commit->object.flags |= SHOWN;
}
}
+
+ /* Now check the original side for seen ones */
+ for (p = list; p; p = p->next) {
+ struct commit *commit = p->item;
+ struct patch_id *ent;
+
+ ent = commit->util;
+ if (!ent)
+ continue;
+ if (ent->seen)
+ commit->object.flags |= SHOWN;
+ commit->util = NULL;
+ }
+
+ free_patch_ids(&ids);
}
static void limit_list(struct rev_info *revs)
}
static void limit_list(struct rev_info *revs)
continue;
p = &commit_list_insert(commit, p)->next;
}
continue;
p = &commit_list_insert(commit, p)->next;
}
+ if (revs->cherry_pick)
+ cherry_pick_list(newlist);
+
revs->commits = newlist;
}
revs->commits = newlist;
}
add_pending_object(cb->all_revs, o, "");
}
else if (!cb->warned_bad_reflog) {
add_pending_object(cb->all_revs, o, "");
}
else if (!cb->warned_bad_reflog) {
- warn("reflog of '%s' references pruned commits",
+ warning("reflog of '%s' references pruned commits",
cb->name_for_errormsg);
cb->warned_bad_reflog = 1;
}
cb->name_for_errormsg);
cb->warned_bad_reflog = 1;
}
revs->min_age = -1;
revs->skip_count = -1;
revs->max_count = -1;
revs->min_age = -1;
revs->skip_count = -1;
revs->max_count = -1;
+ revs->subject_prefix = "PATCH";
revs->prune_fn = NULL;
revs->prune_data = NULL;
revs->prune_fn = NULL;
revs->prune_data = NULL;
@@ -849,6 +934,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
handle_all(revs, flags);
continue;
}
handle_all(revs, flags);
continue;
}
+ if (!strcmp(arg, "--first-parent")) {
+ revs->first_parent_only = 1;
+ continue;
+ }
if (!strcmp(arg, "--reflog")) {
handle_reflog(revs, flags);
continue;
if (!strcmp(arg, "--reflog")) {
handle_reflog(revs, flags);
continue;
@@ -909,6 +998,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->left_right = 1;
continue;
}
revs->left_right = 1;
continue;
}
+ if (!strcmp(arg, "--cherry-pick")) {
+ revs->cherry_pick = 1;
+ continue;
+ }
if (!strcmp(arg, "--objects")) {
revs->tag_objects = 1;
revs->tree_objects = 1;
if (!strcmp(arg, "--objects")) {
revs->tag_objects = 1;
revs->tree_objects = 1;
@@ -1038,7 +1131,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
if (!prefixcmp(arg, "--encoding=")) {
arg += 11;
if (strcmp(arg, "none"))
- git_log_output_encoding = strdup(arg);
+ git_log_output_encoding = xstrdup(arg);
else
git_log_output_encoding = "";
continue;
else
git_log_output_encoding = "";
continue;