1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-11-01 14:57:52 +01:00

Built-in cherry

This replaces the shell script git-cherry with a version written in C.

The behaviour of the new version differs from the original in two
points: it has no long help any more, and it is handling the (optional)
third parameter a bit differently.  Basically, it does the equivalent
of

   ours=`git-rev-list $ours ^$limit ^$upstream`

instead of

   ours=`git-rev-list $ours ^$limit`

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
Rene Scharfe 2006-10-24 01:01:57 +02:00 committed by Junio C Hamano
parent 1259404c7e
commit e827633a5d
5 changed files with 110 additions and 93 deletions

View file

@ -157,7 +157,7 @@ BASIC_LDFLAGS =
SCRIPT_SH = \
git-bisect.sh git-branch.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-ls-remote.sh \
git-merge-one-file.sh git-parse-remote.sh \
@ -210,7 +210,7 @@ PROGRAMS = \
EXTRA_PROGRAMS =
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 \
$(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS))

View file

@ -437,3 +437,109 @@ int cmd_format_patch(int argc, const char **argv, const char *prefix)
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;
}

View file

@ -19,6 +19,7 @@ extern int cmd_archive(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_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_count_objects(int argc, const char **argv, const char *prefix);
extern int cmd_diff_files(int argc, const char **argv, const char *prefix);

View file

@ -1,91 +0,0 @@
#!/bin/sh
#
# Copyright (c) 2005 Junio C Hamano.
#
USAGE='[-v] <upstream> [<head>] [<limit>]'
LONG_USAGE=' __*__*__*__*__> <upstream>
/
fork-point
\__+__+__+__+__+__+__+__> <head>
Each commit between the fork-point (or <limit> if given) and <head> is
examined, and compared against the change each commit between the
fork-point and <upstream> introduces. If the change seems to be in
the upstream, it is shown on the standard output with prefix "+".
Otherwise it is shown with prefix "-".'
. git-sh-setup
case "$1" in -v) verbose=t; shift ;; esac
case "$#,$1" in
1,*..*)
upstream=$(expr "z$1" : 'z\(.*\)\.\.') ours=$(expr "z$1" : '.*\.\.\(.*\)$')
set x "$upstream" "$ours"
shift ;;
esac
case "$#" in
1) upstream=`git-rev-parse --verify "$1"` &&
ours=`git-rev-parse --verify HEAD` || exit
limit="$upstream"
;;
2) upstream=`git-rev-parse --verify "$1"` &&
ours=`git-rev-parse --verify "$2"` || exit
limit="$upstream"
;;
3) upstream=`git-rev-parse --verify "$1"` &&
ours=`git-rev-parse --verify "$2"` &&
limit=`git-rev-parse --verify "$3"` || exit
;;
*) usage ;;
esac
# Note that these list commits in reverse order;
# not that the order in inup matters...
inup=`git-rev-list ^$ours $upstream` &&
ours=`git-rev-list $ours ^$limit` || exit
tmp=.cherry-tmp$$
patch=$tmp-patch
mkdir $patch
trap "rm -rf $tmp-*" 0 1 2 3 15
for c in $inup
do
git-diff-tree -p $c
done | git-patch-id |
while read id name
do
echo $name >>$patch/$id
done
LF='
'
O=
for c in $ours
do
set x `git-diff-tree -p $c | git-patch-id`
if test "$2" != ""
then
if test -f "$patch/$2"
then
sign=-
else
sign=+
fi
case "$verbose" in
t)
c=$(git-rev-list --pretty=oneline --max-count=1 $c)
esac
case "$O" in
'') O="$sign $c" ;;
*) O="$sign $c$LF$O" ;;
esac
fi
done
case "$O" in
'') ;;
*) echo "$O" ;;
esac

1
git.c
View file

@ -224,6 +224,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
{ "cat-file", cmd_cat_file, RUN_SETUP },
{ "checkout-index", cmd_checkout_index, RUN_SETUP },
{ "check-ref-format", cmd_check_ref_format },
{ "cherry", cmd_cherry, RUN_SETUP },
{ "commit-tree", cmd_commit_tree, RUN_SETUP },
{ "count-objects", cmd_count_objects, RUN_SETUP },
{ "diff", cmd_diff, RUN_SETUP | USE_PAGER },