Merge branch 'rs/cherry'
* rs/cherry: Make git-cherry handle root trees Built-in cherry
This commit is contained in:
commit
56532fa147
4
Makefile
4
Makefile
@ -159,7 +159,7 @@ BASIC_LDFLAGS =
|
|||||||
|
|
||||||
SCRIPT_SH = \
|
SCRIPT_SH = \
|
||||||
git-bisect.sh git-checkout.sh \
|
git-bisect.sh git-checkout.sh \
|
||||||
git-cherry.sh git-clean.sh git-clone.sh git-commit.sh \
|
git-clean.sh git-clone.sh git-commit.sh \
|
||||||
git-fetch.sh \
|
git-fetch.sh \
|
||||||
git-ls-remote.sh \
|
git-ls-remote.sh \
|
||||||
git-merge-one-file.sh git-parse-remote.sh \
|
git-merge-one-file.sh git-parse-remote.sh \
|
||||||
@ -212,7 +212,7 @@ PROGRAMS = \
|
|||||||
EXTRA_PROGRAMS =
|
EXTRA_PROGRAMS =
|
||||||
|
|
||||||
BUILT_INS = \
|
BUILT_INS = \
|
||||||
git-format-patch$X git-show$X git-whatchanged$X \
|
git-format-patch$X git-show$X git-whatchanged$X git-cherry$X \
|
||||||
git-get-tar-commit-id$X \
|
git-get-tar-commit-id$X \
|
||||||
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
|
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))
|
||||||
|
|
||||||
|
113
builtin-log.c
113
builtin-log.c
@ -171,8 +171,11 @@ static void reopen_stdout(struct commit *commit, int nr, int keep_subject)
|
|||||||
static int get_patch_id(struct commit *commit, struct diff_options *options,
|
static int get_patch_id(struct commit *commit, struct diff_options *options,
|
||||||
unsigned char *sha1)
|
unsigned char *sha1)
|
||||||
{
|
{
|
||||||
diff_tree_sha1(commit->parents->item->object.sha1, commit->object.sha1,
|
if (commit->parents)
|
||||||
"", options);
|
diff_tree_sha1(commit->parents->item->object.sha1,
|
||||||
|
commit->object.sha1, "", options);
|
||||||
|
else
|
||||||
|
diff_root_tree_sha1(commit->object.sha1, "", options);
|
||||||
diffcore_std(options);
|
diffcore_std(options);
|
||||||
return diff_flush_patch_id(options, sha1);
|
return diff_flush_patch_id(options, sha1);
|
||||||
}
|
}
|
||||||
@ -437,3 +440,109 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_pending_commit(const char *arg, struct rev_info *revs, int flags)
|
||||||
|
{
|
||||||
|
unsigned char sha1[20];
|
||||||
|
if (get_sha1(arg, sha1) == 0) {
|
||||||
|
struct commit *commit = lookup_commit_reference(sha1);
|
||||||
|
if (commit) {
|
||||||
|
commit->object.flags |= flags;
|
||||||
|
add_pending_object(revs, &commit->object, arg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char cherry_usage[] =
|
||||||
|
"git-cherry [-v] <upstream> [<head>] [<limit>]";
|
||||||
|
int cmd_cherry(int argc, const char **argv, const char *prefix)
|
||||||
|
{
|
||||||
|
struct rev_info revs;
|
||||||
|
struct diff_options patch_id_opts;
|
||||||
|
struct commit *commit;
|
||||||
|
struct commit_list *list = NULL;
|
||||||
|
const char *upstream;
|
||||||
|
const char *head = "HEAD";
|
||||||
|
const char *limit = NULL;
|
||||||
|
int verbose = 0;
|
||||||
|
|
||||||
|
if (argc > 1 && !strcmp(argv[1], "-v")) {
|
||||||
|
verbose = 1;
|
||||||
|
argc--;
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (argc) {
|
||||||
|
case 4:
|
||||||
|
limit = argv[3];
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 3:
|
||||||
|
head = argv[2];
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case 2:
|
||||||
|
upstream = argv[1];
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(cherry_usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_revisions(&revs, prefix);
|
||||||
|
revs.diff = 1;
|
||||||
|
revs.combine_merges = 0;
|
||||||
|
revs.ignore_merges = 1;
|
||||||
|
revs.diffopt.recursive = 1;
|
||||||
|
|
||||||
|
if (add_pending_commit(head, &revs, 0))
|
||||||
|
die("Unknown commit %s", head);
|
||||||
|
if (add_pending_commit(upstream, &revs, UNINTERESTING))
|
||||||
|
die("Unknown commit %s", upstream);
|
||||||
|
|
||||||
|
/* Don't say anything if head and upstream are the same. */
|
||||||
|
if (revs.pending.nr == 2) {
|
||||||
|
struct object_array_entry *o = revs.pending.objects;
|
||||||
|
if (hashcmp(o[0].item->sha1, o[1].item->sha1) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_patch_ids(&revs, &patch_id_opts, prefix);
|
||||||
|
|
||||||
|
if (limit && add_pending_commit(limit, &revs, UNINTERESTING))
|
||||||
|
die("Unknown commit %s", limit);
|
||||||
|
|
||||||
|
/* reverse the list of commits */
|
||||||
|
prepare_revision_walk(&revs);
|
||||||
|
while ((commit = get_revision(&revs)) != NULL) {
|
||||||
|
/* ignore merges */
|
||||||
|
if (commit->parents && commit->parents->next)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
commit_list_insert(commit, &list);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (list) {
|
||||||
|
unsigned char sha1[20];
|
||||||
|
char sign = '+';
|
||||||
|
|
||||||
|
commit = list->item;
|
||||||
|
if (!get_patch_id(commit, &patch_id_opts, sha1) &&
|
||||||
|
lookup_object(sha1))
|
||||||
|
sign = '-';
|
||||||
|
|
||||||
|
if (verbose) {
|
||||||
|
static char buf[16384];
|
||||||
|
pretty_print_commit(CMIT_FMT_ONELINE, commit, ~0,
|
||||||
|
buf, sizeof(buf), 0, NULL, NULL, 0);
|
||||||
|
printf("%c %s %s\n", sign,
|
||||||
|
sha1_to_hex(commit->object.sha1), buf);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%c %s\n", sign,
|
||||||
|
sha1_to_hex(commit->object.sha1));
|
||||||
|
}
|
||||||
|
|
||||||
|
list = list->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -21,6 +21,7 @@ extern int cmd_branch(int argc, const char **argv, const char *prefix);
|
|||||||
extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
|
extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
|
extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
|
extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
|
||||||
|
extern int cmd_cherry(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
|
extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
|
extern int cmd_count_objects(int argc, const char **argv, const char *prefix);
|
||||||
extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
|
extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
|
||||||
|
2
diff.h
2
diff.h
@ -102,6 +102,8 @@ extern int diff_tree(struct tree_desc *t1, struct tree_desc *t2,
|
|||||||
const char *base, struct diff_options *opt);
|
const char *base, struct diff_options *opt);
|
||||||
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
|
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
|
||||||
const char *base, struct diff_options *opt);
|
const char *base, struct diff_options *opt);
|
||||||
|
extern int diff_root_tree_sha1(const unsigned char *new, const char *base,
|
||||||
|
struct diff_options *opt);
|
||||||
|
|
||||||
struct combine_diff_path {
|
struct combine_diff_path {
|
||||||
struct combine_diff_path *next;
|
struct combine_diff_path *next;
|
||||||
|
1
git.c
1
git.c
@ -226,6 +226,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
|
|||||||
{ "cat-file", cmd_cat_file, RUN_SETUP },
|
{ "cat-file", cmd_cat_file, RUN_SETUP },
|
||||||
{ "checkout-index", cmd_checkout_index, RUN_SETUP },
|
{ "checkout-index", cmd_checkout_index, RUN_SETUP },
|
||||||
{ "check-ref-format", cmd_check_ref_format },
|
{ "check-ref-format", cmd_check_ref_format },
|
||||||
|
{ "cherry", cmd_cherry, RUN_SETUP },
|
||||||
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
|
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
|
||||||
{ "count-objects", cmd_count_objects, RUN_SETUP },
|
{ "count-objects", cmd_count_objects, RUN_SETUP },
|
||||||
{ "diff", cmd_diff, RUN_SETUP | USE_PAGER },
|
{ "diff", cmd_diff, RUN_SETUP | USE_PAGER },
|
||||||
|
26
log-tree.c
26
log-tree.c
@ -252,26 +252,6 @@ int log_tree_diff_flush(struct rev_info *opt)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int diff_root_tree(struct rev_info *opt,
|
|
||||||
const unsigned char *new, const char *base)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
void *tree;
|
|
||||||
struct tree_desc empty, real;
|
|
||||||
|
|
||||||
tree = read_object_with_reference(new, tree_type, &real.size, NULL);
|
|
||||||
if (!tree)
|
|
||||||
die("unable to read root tree (%s)", sha1_to_hex(new));
|
|
||||||
real.buf = tree;
|
|
||||||
|
|
||||||
empty.buf = "";
|
|
||||||
empty.size = 0;
|
|
||||||
retval = diff_tree(&empty, &real, base, &opt->diffopt);
|
|
||||||
free(tree);
|
|
||||||
log_tree_diff_flush(opt);
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int do_diff_combined(struct rev_info *opt, struct commit *commit)
|
static int do_diff_combined(struct rev_info *opt, struct commit *commit)
|
||||||
{
|
{
|
||||||
unsigned const char *sha1 = commit->object.sha1;
|
unsigned const char *sha1 = commit->object.sha1;
|
||||||
@ -297,8 +277,10 @@ static int log_tree_diff(struct rev_info *opt, struct commit *commit, struct log
|
|||||||
/* Root commit? */
|
/* Root commit? */
|
||||||
parents = commit->parents;
|
parents = commit->parents;
|
||||||
if (!parents) {
|
if (!parents) {
|
||||||
if (opt->show_root_diff)
|
if (opt->show_root_diff) {
|
||||||
diff_root_tree(opt, sha1, "");
|
diff_root_tree_sha1(sha1, "", &opt->diffopt);
|
||||||
|
log_tree_diff_flush(opt);
|
||||||
|
}
|
||||||
return !opt->loginfo;
|
return !opt->loginfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
tree-diff.c
18
tree-diff.c
@ -215,6 +215,24 @@ int diff_tree_sha1(const unsigned char *old, const unsigned char *new, const cha
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int diff_root_tree_sha1(const unsigned char *new, const char *base, struct diff_options *opt)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
void *tree;
|
||||||
|
struct tree_desc empty, real;
|
||||||
|
|
||||||
|
tree = read_object_with_reference(new, tree_type, &real.size, NULL);
|
||||||
|
if (!tree)
|
||||||
|
die("unable to read root tree (%s)", sha1_to_hex(new));
|
||||||
|
real.buf = tree;
|
||||||
|
|
||||||
|
empty.size = 0;
|
||||||
|
empty.buf = "";
|
||||||
|
retval = diff_tree(&empty, &real, base, opt);
|
||||||
|
free(tree);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static int count_paths(const char **paths)
|
static int count_paths(const char **paths)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user