* [PATCH 01/13] sequencer: add "do_fast_forward()" to perform a fast forward
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 02/13] sequencer: add "--fast-forward" option to "git sequencer--helper" Christian Couder
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
From: Stephan Beyer <s-beyer@gmx.net>
This code is taken from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
but the messages have been changed to be the same as those
displayed by git-rebase--interactive.sh.
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index be030bc..0cd7e98 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -171,6 +171,15 @@ static struct commit *get_commit(const char *arg)
return lookup_commit_reference(sha1);
}
+static int do_fast_forward(const unsigned char *sha)
+{
+ if (reset_almost_hard(sha))
+ return error("Cannot fast forward to %s", sha1_to_hex(sha));
+ if (verbosity > 1)
+ printf("Fast forward to %s\n", sha1_to_hex(sha));
+ return 0;
+}
+
static int set_verbosity(int verbose)
{
char tmp[] = "0";
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 02/13] sequencer: add "--fast-forward" option to "git sequencer--helper"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
2009-08-12 5:15 ` [PATCH 01/13] sequencer: add "do_fast_forward()" to perform a fast forward Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 03/13] sequencer: let "git sequencer--helper" callers set "allow_dirty" Christian Couder
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
This new option uses the "do_fast_forward()" function to perform
a fast forward.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 16 ++++++++++++----
1 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 0cd7e98..bd72f65 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -19,6 +19,7 @@ static unsigned char head_sha1[20];
static const char * const git_sequencer_helper_usage[] = {
"git sequencer--helper --make-patch <commit>",
"git sequencer--helper --reset-hard <commit> <reflog-msg> <verbosity>",
+ "git sequencer--helper --fast-forward <commit> <reflog-msg> <verbosity>",
NULL
};
@@ -218,11 +219,14 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
{
char *patch_commit = NULL;
char *reset_commit = NULL;
+ char *ff_commit = NULL;
struct option options[] = {
OPT_STRING(0, "make-patch", &patch_commit, "commit",
"create a patch from commit"),
OPT_STRING(0, "reset-hard", &reset_commit, "commit",
"reset to commit"),
+ OPT_STRING(0, "fast-forward", &ff_commit, "commit",
+ "fast forward to commit"),
OPT_END()
};
@@ -239,15 +243,16 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return 0;
}
- if (reset_commit) {
+ if (ff_commit || reset_commit) {
unsigned char sha1[20];
+ char *commit = ff_commit ? ff_commit : reset_commit;
if (argc != 2)
usage_with_options(git_sequencer_helper_usage,
options);
- if (get_sha1(reset_commit, sha1)) {
- error("Could not find '%s'", reset_commit);
+ if (get_sha1(commit, sha1)) {
+ error("Could not find '%s'", commit);
return 1;
}
@@ -258,7 +263,10 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return 1;
}
- return reset_almost_hard(sha1);
+ if (ff_commit)
+ return do_fast_forward(sha1);
+ else
+ return reset_almost_hard(sha1);
}
usage_with_options(git_sequencer_helper_usage, options);
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 03/13] sequencer: let "git sequencer--helper" callers set "allow_dirty"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
2009-08-12 5:15 ` [PATCH 01/13] sequencer: add "do_fast_forward()" to perform a fast forward Christian Couder
2009-08-12 5:15 ` [PATCH 02/13] sequencer: add "--fast-forward" option to "git sequencer--helper" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 04/13] rebase -i: use "git sequencer--helper --fast-forward" Christian Couder
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
This flag can be set when using --reset-hard or --fast-forward, and
in this case changes in the work tree will be kept.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index bd72f65..71a7fef 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -18,8 +18,10 @@ static unsigned char head_sha1[20];
static const char * const git_sequencer_helper_usage[] = {
"git sequencer--helper --make-patch <commit>",
- "git sequencer--helper --reset-hard <commit> <reflog-msg> <verbosity>",
- "git sequencer--helper --fast-forward <commit> <reflog-msg> <verbosity>",
+ "git sequencer--helper --reset-hard <commit> <reflog-msg> "
+ "<verbosity> [<allow-dirty>]",
+ "git sequencer--helper --fast-forward <commit> <reflog-msg> "
+ "<verbosity> [<allow-dirty>]",
NULL
};
@@ -247,7 +249,7 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
unsigned char sha1[20];
char *commit = ff_commit ? ff_commit : reset_commit;
- if (argc != 2)
+ if (argc != 2 && argc != 3)
usage_with_options(git_sequencer_helper_usage,
options);
@@ -263,6 +265,9 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return 1;
}
+ if (argc == 3 && *argv[2] && strcmp(argv[2], "0"))
+ allow_dirty = 1;
+
if (ff_commit)
return do_fast_forward(sha1);
else
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 04/13] rebase -i: use "git sequencer--helper --fast-forward"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (2 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 03/13] sequencer: let "git sequencer--helper" callers set "allow_dirty" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 05/13] revert: libify pick Christian Couder
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
when fast forwarding.
Note that in the first hunk of this patch, there was this line:
test "a$1" = a-n && output git reset --soft $current_sha1
but the test always failed.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-rebase--interactive.sh | 11 +++--------
1 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0041994..7651fd6 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -154,11 +154,8 @@ pick_one () {
die "Could not get the parent of $sha1"
current_sha1=$(git rev-parse --verify HEAD)
if test "$no_ff$current_sha1" = "$parent_sha1"; then
- git sequencer--helper --reset-hard $sha1 \
+ git sequencer--helper --fast-forward $sha1 \
"$GIT_REFLOG_ACTION" "$VERBOSE"
- test "a$1" = a-n && output git reset --soft $current_sha1
- sha1=$(git rev-parse --short $sha1)
- output warn Fast forward to $sha1
else
output git cherry-pick "$@"
fi
@@ -238,10 +235,8 @@ pick_one_preserving_merges () {
done
case $fast_forward in
t)
- output warn "Fast forward to $sha1"
- git sequencer--helper --reset-hard $sha1 \
- "$GIT_REFLOG_ACTION" "$VERBOSE" ||
- die "Cannot fast forward to $sha1"
+ git sequencer--helper --fast-forward $sha1 \
+ "$GIT_REFLOG_ACTION" "$VERBOSE" || exit
;;
f)
first_parent=$(expr "$new_parents" : ' \([^ ]*\)')
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 05/13] revert: libify pick
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (3 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 04/13] rebase -i: use "git sequencer--helper --fast-forward" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 06/13] pick: simplify "error(...)" followed by "return -1" Christian Couder
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
From: Stephan Beyer <s-beyer@gmx.net>
This commit is made of code from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
The goal of this commit is to abstract out pick functionnality
into a new pick() function made of code from "builtin-revert.c".
The new pick() function is in a new "pick.c" file with an
associated "pick.h".
"pick.h" and "pick.c" are strictly the same as on the sequencer repo,
but a few changes were needed on "builtin-revert.c" to keep it up to
date with changes on git.git.
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
Makefile | 2 +
builtin-revert.c | 272 +++++++++---------------------------------------------
pick.c | 229 +++++++++++++++++++++++++++++++++++++++++++++
pick.h | 13 +++
4 files changed, 288 insertions(+), 228 deletions(-)
create mode 100644 pick.c
create mode 100644 pick.h
diff --git a/Makefile b/Makefile
index 189aee5..03ddc59 100644
--- a/Makefile
+++ b/Makefile
@@ -444,6 +444,7 @@ LIB_H += pack-refs.h
LIB_H += pack-revindex.h
LIB_H += parse-options.h
LIB_H += patch-ids.h
+LIB_H += pick.h
LIB_H += pkt-line.h
LIB_H += progress.h
LIB_H += quote.h
@@ -532,6 +533,7 @@ LIB_OBJS += parse-options.o
LIB_OBJS += patch-delta.o
LIB_OBJS += patch-ids.o
LIB_OBJS += path.o
+LIB_OBJS += pick.o
LIB_OBJS += pkt-line.o
LIB_OBJS += preload-index.o
LIB_OBJS += pretty.o
diff --git a/builtin-revert.c b/builtin-revert.c
index 151aa6a..6dd29a3 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -1,18 +1,14 @@
#include "cache.h"
#include "builtin.h"
-#include "object.h"
#include "commit.h"
#include "tag.h"
-#include "wt-status.h"
-#include "run-command.h"
#include "exec_cmd.h"
#include "utf8.h"
#include "parse-options.h"
-#include "cache-tree.h"
#include "diff.h"
#include "revision.h"
#include "rerere.h"
-#include "merge-recursive.h"
+#include "pick.h"
/*
* This implements the builtins revert and cherry-pick.
@@ -35,25 +31,23 @@ static const char * const cherry_pick_usage[] = {
NULL
};
-static int edit, no_replay, no_commit, mainline, signoff;
-static enum { REVERT, CHERRY_PICK } action;
+static int edit, no_commit, mainline, signoff;
+static int flags;
static struct commit *commit;
-static const char *me;
-
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
static void parse_args(int argc, const char **argv)
{
const char * const * usage_str =
- action == REVERT ? revert_usage : cherry_pick_usage;
+ flags & PICK_REVERSE ? revert_usage : cherry_pick_usage;
unsigned char sha1[20];
const char *arg;
int noop;
struct option options[] = {
OPT_BOOLEAN('n', "no-commit", &no_commit, "don't automatically commit"),
OPT_BOOLEAN('e', "edit", &edit, "edit the commit message"),
- OPT_BOOLEAN('x', NULL, &no_replay, "append commit name when cherry-picking"),
+ OPT_BIT('x', NULL, &flags, "append commit name when cherry-picking", PICK_ADD_NOTE),
OPT_BOOLEAN('r', NULL, &noop, "no-op (backward compatibility)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
OPT_INTEGER('m', "mainline", &mainline, "parent number"),
@@ -77,42 +71,12 @@ static void parse_args(int argc, const char **argv)
die ("'%s' does not point to a commit", arg);
}
-static char *get_oneline(const char *message)
-{
- char *result;
- const char *p = message, *abbrev, *eol;
- int abbrev_len, oneline_len;
-
- if (!p)
- die ("Could not read commit message of %s",
- sha1_to_hex(commit->object.sha1));
- while (*p && (*p != '\n' || p[1] != '\n'))
- p++;
-
- if (*p) {
- p += 2;
- for (eol = p + 1; *eol && *eol != '\n'; eol++)
- ; /* do nothing */
- } else
- eol = p;
- abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
- abbrev_len = strlen(abbrev);
- oneline_len = eol - p;
- result = xmalloc(abbrev_len + 5 + oneline_len);
- memcpy(result, abbrev, abbrev_len);
- memcpy(result + abbrev_len, "... ", 4);
- memcpy(result + abbrev_len + 4, p, oneline_len);
- result[abbrev_len + 4 + oneline_len] = '\0';
- return result;
-}
-
static char *get_encoding(const char *message)
{
const char *p = message, *eol;
if (!p)
- die ("Could not read commit message of %s",
- sha1_to_hex(commit->object.sha1));
+ return NULL;
while (*p && *p != '\n') {
for (eol = p + 1; *eol && *eol != '\n'; eol++)
; /* do nothing */
@@ -128,30 +92,6 @@ static char *get_encoding(const char *message)
return NULL;
}
-static struct lock_file msg_file;
-static int msg_fd;
-
-static void add_to_msg(const char *string)
-{
- int len = strlen(string);
- if (write_in_full(msg_fd, string, len) < 0)
- die_errno ("Could not write to MERGE_MSG");
-}
-
-static void add_message_to_msg(const char *message)
-{
- const char *p = message;
- while (*p && (*p != '\n' || p[1] != '\n'))
- p++;
-
- if (!*p)
- add_to_msg(sha1_to_hex(commit->object.sha1));
-
- p += 2;
- add_to_msg(p);
- return;
-}
-
static void set_author_ident_env(const char *message)
{
const char *p = message;
@@ -214,7 +154,7 @@ static char *help_msg(const unsigned char *sha1)
"mark the corrected paths with 'git add <paths>' "
"or 'git rm <paths>' and commit the result.");
- if (action == CHERRY_PICK) {
+ if (!(flags & PICK_REVERSE)) {
sprintf(helpbuf + strlen(helpbuf),
"\nWhen commiting, use the option "
"'-c %s' to retain authorship and message.",
@@ -223,187 +163,68 @@ static char *help_msg(const unsigned char *sha1)
return helpbuf;
}
-static struct tree *empty_tree(void)
+static void write_message(struct strbuf *msgbuf, const char *filename)
{
- struct tree *tree = xcalloc(1, sizeof(struct tree));
-
- tree->object.parsed = 1;
- tree->object.type = OBJ_TREE;
- pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);
- return tree;
+ struct lock_file msg_file;
+ int msg_fd;
+ msg_fd = hold_lock_file_for_update(&msg_file, filename,
+ LOCK_DIE_ON_ERROR);
+ if (write_in_full(msg_fd, msgbuf->buf, msgbuf->len) < 0)
+ die_errno("Could not write to %s.", filename);
+ strbuf_release(msgbuf);
+ if (commit_lock_file(&msg_file) < 0)
+ die("Error wrapping up %s", filename);
}
static int revert_or_cherry_pick(int argc, const char **argv)
{
- unsigned char head[20];
- struct commit *base, *next, *parent;
- int i, index_fd, clean;
- char *oneline, *reencoded_message = NULL;
- const char *message, *encoding;
- char *defmsg = git_pathdup("MERGE_MSG");
- struct merge_options o;
- struct tree *result, *next_tree, *base_tree, *head_tree;
- static struct lock_file index_lock;
+ const char *me;
+ struct strbuf msgbuf;
+ char *reencoded_message = NULL;
+ const char *encoding;
+ int failed;
git_config(git_default_config, NULL);
- me = action == REVERT ? "revert" : "cherry-pick";
+ me = flags & PICK_REVERSE ? "revert" : "cherry-pick";
setenv(GIT_REFLOG_ACTION, me, 0);
parse_args(argc, argv);
- /* this is copied from the shell script, but it's never triggered... */
- if (action == REVERT && !no_replay)
- die("revert is incompatible with replay");
-
if (read_cache() < 0)
die("git %s: failed to read the index", me);
- if (no_commit) {
- /*
- * We do not intend to commit immediately. We just want to
- * merge the differences in, so let's compute the tree
- * that represents the "current" state for merge-recursive
- * to work on.
- */
- if (write_cache_as_tree(head, 0, NULL))
- die ("Your index file is unmerged.");
- } else {
- if (get_sha1("HEAD", head))
- die ("You do not have a valid HEAD");
- if (index_differs_from("HEAD", 0))
- die ("Dirty index: cannot %s", me);
- }
- discard_cache();
-
- index_fd = hold_locked_index(&index_lock, 1);
+ if (!no_commit && index_differs_from("HEAD", 0))
+ die ("Dirty index: cannot %s", me);
- if (!commit->parents) {
- if (action == REVERT)
- die ("Cannot revert a root commit");
- parent = NULL;
- }
- else if (commit->parents->next) {
- /* Reverting or cherry-picking a merge commit */
- int cnt;
- struct commit_list *p;
-
- if (!mainline)
- die("Commit %s is a merge but no -m option was given.",
- sha1_to_hex(commit->object.sha1));
-
- for (cnt = 1, p = commit->parents;
- cnt != mainline && p;
- cnt++)
- p = p->next;
- if (cnt != mainline || !p)
- die("Commit %s does not have parent %d",
- sha1_to_hex(commit->object.sha1), mainline);
- parent = p->item;
- } else if (0 < mainline)
- die("Mainline was specified but commit %s is not a merge.",
- sha1_to_hex(commit->object.sha1));
- else
- parent = commit->parents->item;
-
- if (!(message = commit->buffer))
- die ("Cannot get commit message for %s",
+ if (!commit->buffer)
+ return error("Cannot get commit message for %s",
sha1_to_hex(commit->object.sha1));
-
- if (parent && parse_commit(parent) < 0)
- die("%s: cannot parse parent commit %s",
- me, sha1_to_hex(parent->object.sha1));
-
- /*
- * "commit" is an existing commit. We would want to apply
- * the difference it introduces since its first parent "prev"
- * on top of the current HEAD if we are cherry-pick. Or the
- * reverse of it if we are revert.
- */
-
- msg_fd = hold_lock_file_for_update(&msg_file, defmsg,
- LOCK_DIE_ON_ERROR);
-
- encoding = get_encoding(message);
+ encoding = get_encoding(commit->buffer);
if (!encoding)
encoding = "UTF-8";
if (!git_commit_encoding)
git_commit_encoding = "UTF-8";
- if ((reencoded_message = reencode_string(message,
+ if ((reencoded_message = reencode_string(commit->buffer,
git_commit_encoding, encoding)))
- message = reencoded_message;
-
- oneline = get_oneline(message);
-
- if (action == REVERT) {
- char *oneline_body = strchr(oneline, ' ');
+ commit->buffer = reencoded_message;
- base = commit;
- next = parent;
- add_to_msg("Revert \"");
- add_to_msg(oneline_body + 1);
- add_to_msg("\"\n\nThis reverts commit ");
- add_to_msg(sha1_to_hex(commit->object.sha1));
-
- if (commit->parents->next) {
- add_to_msg(", reversing\nchanges made to ");
- add_to_msg(sha1_to_hex(parent->object.sha1));
- }
- add_to_msg(".\n");
- } else {
- base = parent;
- next = commit;
- set_author_ident_env(message);
- add_message_to_msg(message);
- if (no_replay) {
- add_to_msg("(cherry picked from commit ");
- add_to_msg(sha1_to_hex(commit->object.sha1));
- add_to_msg(")\n");
- }
- }
-
- read_cache();
- init_merge_options(&o);
- o.branch1 = "HEAD";
- o.branch2 = oneline;
-
- head_tree = parse_tree_indirect(head);
- next_tree = next ? next->tree : empty_tree();
- base_tree = base ? base->tree : empty_tree();
-
- clean = merge_trees(&o,
- head_tree,
- next_tree, base_tree, &result);
-
- if (active_cache_changed &&
- (write_cache(index_fd, active_cache, active_nr) ||
- commit_locked_index(&index_lock)))
- die("%s: Unable to write new index file", me);
- rollback_lock_file(&index_lock);
-
- if (!clean) {
- add_to_msg("\nConflicts:\n\n");
- for (i = 0; i < active_nr;) {
- struct cache_entry *ce = active_cache[i++];
- if (ce_stage(ce)) {
- add_to_msg("\t");
- add_to_msg(ce->name);
- add_to_msg("\n");
- while (i < active_nr && !strcmp(ce->name,
- active_cache[i]->name))
- i++;
- }
- }
- if (commit_lock_file(&msg_file) < 0)
- die ("Error wrapping up %s", defmsg);
+ failed = pick(commit, mainline, flags, &msgbuf);
+ if (failed < 0) {
+ exit(1);
+ } else if (failed > 0) {
fprintf(stderr, "Automatic %s failed.%s\n",
me, help_msg(commit->object.sha1));
+ write_message(&msgbuf, git_path("MERGE_MSG"));
rerere();
exit(1);
}
- if (commit_lock_file(&msg_file) < 0)
- die ("Error wrapping up %s", defmsg);
+ if (!(flags & PICK_REVERSE))
+ set_author_ident_env(commit->buffer);
+ free(reencoded_message);
+
fprintf(stderr, "Finished one %s.\n", me);
+ write_message(&msgbuf, git_path("MERGE_MSG"));
+
/*
- *
* If we are cherry-pick, and if the merge did not result in
* hand-editing, we will hit this commit and inherit the original
* author date and name.
@@ -421,14 +242,11 @@ static int revert_or_cherry_pick(int argc, const char **argv)
args[i++] = "-s";
if (!edit) {
args[i++] = "-F";
- args[i++] = defmsg;
+ args[i++] = git_path("MERGE_MSG");
}
args[i] = NULL;
return execv_git_cmd(args);
}
- free(reencoded_message);
- free(defmsg);
-
return 0;
}
@@ -436,14 +254,12 @@ int cmd_revert(int argc, const char **argv, const char *prefix)
{
if (isatty(0))
edit = 1;
- no_replay = 1;
- action = REVERT;
+ flags = PICK_REVERSE | PICK_ADD_NOTE;
return revert_or_cherry_pick(argc, argv);
}
int cmd_cherry_pick(int argc, const char **argv, const char *prefix)
{
- no_replay = 0;
- action = CHERRY_PICK;
+ flags = 0;
return revert_or_cherry_pick(argc, argv);
}
diff --git a/pick.c b/pick.c
new file mode 100644
index 0000000..77c7169
--- /dev/null
+++ b/pick.c
@@ -0,0 +1,229 @@
+#include "cache.h"
+#include "commit.h"
+#include "run-command.h"
+#include "cache-tree.h"
+#include "pick.h"
+#include "merge-recursive.h"
+
+static struct commit *commit;
+
+static char *get_oneline(const char *message)
+{
+ char *result;
+ const char *p = message, *abbrev, *eol;
+ int abbrev_len, oneline_len;
+
+ if (!p)
+ return NULL;
+ while (*p && (*p != '\n' || p[1] != '\n'))
+ p++;
+
+ if (*p) {
+ p += 2;
+ for (eol = p + 1; *eol && *eol != '\n'; eol++)
+ ; /* do nothing */
+ } else
+ eol = p;
+ abbrev = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
+ abbrev_len = strlen(abbrev);
+ oneline_len = eol - p;
+ result = xmalloc(abbrev_len + 5 + oneline_len);
+ memcpy(result, abbrev, abbrev_len);
+ memcpy(result + abbrev_len, "... ", 4);
+ memcpy(result + abbrev_len + 4, p, oneline_len);
+ result[abbrev_len + 4 + oneline_len] = '\0';
+ return result;
+}
+
+static void add_message_to_msg(struct strbuf *msg, const char *message)
+{
+ const char *p = message;
+ while (*p && (*p != '\n' || p[1] != '\n'))
+ p++;
+
+ if (!*p)
+ strbuf_addstr(msg, sha1_to_hex(commit->object.sha1));
+
+ p += 2;
+ strbuf_addstr(msg, p);
+ return;
+}
+
+static struct tree *empty_tree(void)
+{
+ struct tree *tree = xcalloc(1, sizeof(struct tree));
+
+ tree->object.parsed = 1;
+ tree->object.type = OBJ_TREE;
+ pretend_sha1_file(NULL, 0, OBJ_TREE, tree->object.sha1);
+ return tree;
+}
+
+/*
+ * Pick changes introduced by pick_commit into current working tree
+ * and index.
+ *
+ * Return 0 on success.
+ * Return negative value on error before picking,
+ * and a positive value after picking,
+ * and return 1 if and only if a conflict occurs but no other error.
+ */
+int pick(struct commit *pick_commit, int mainline, int flags,
+ struct strbuf *msg)
+{
+ unsigned char head[20];
+ struct commit *base, *next, *parent;
+ int i, index_fd, clean;
+ int ret = 0;
+ char *oneline;
+ const char *message;
+ struct merge_options o;
+ struct tree *result, *next_tree, *base_tree, *head_tree;
+ static struct lock_file index_lock;
+
+ strbuf_init(msg, 0);
+ commit = pick_commit;
+
+ if (flags & PICK_REVERSE) /* REVERSE implies ADD_NOTE */
+ flags |= PICK_ADD_NOTE;
+
+ /*
+ * We do not intend to commit immediately. We just want to
+ * merge the differences in, so let's compute the tree
+ * that represents the "current" state for merge-recursive
+ * to work on.
+ */
+ if (write_cache_as_tree(head, 0, NULL)) {
+ error("Your index file is unmerged.");
+ return -1;
+ }
+ discard_cache();
+
+ index_fd = hold_locked_index(&index_lock, 0);
+ if (index_fd < 0) {
+ error("Unable to create locked index: %s",
+ strerror(errno));
+ return -1;
+ }
+
+ if (!commit->parents) {
+ if (flags & PICK_REVERSE) {
+ error("Cannot revert a root commit");
+ return -1;
+ }
+ parent = NULL;
+ }
+ else if (commit->parents->next) {
+ /* Reverting or cherry-picking a merge commit */
+ int cnt;
+ struct commit_list *p;
+
+ if (!mainline) {
+ error("Commit %s is a merge but no mainline was given.",
+ sha1_to_hex(commit->object.sha1));
+ return -1;
+ }
+
+ for (cnt = 1, p = commit->parents;
+ cnt != mainline && p;
+ cnt++)
+ p = p->next;
+ if (cnt != mainline || !p) {
+ error("Commit %s does not have parent %d",
+ sha1_to_hex(commit->object.sha1), mainline);
+ return -1;
+ }
+ parent = p->item;
+ } else if (0 < mainline) {
+ error("Mainline was specified but commit %s is not a merge.",
+ sha1_to_hex(commit->object.sha1));
+ return -1;
+ } else
+ parent = commit->parents->item;
+
+ if (!(message = commit->buffer)) {
+ error("Cannot get commit message for %s",
+ sha1_to_hex(commit->object.sha1));
+ return -1;
+ }
+
+ if (parent && parse_commit(parent) < 0) {
+ error("Cannot parse parent commit %s",
+ sha1_to_hex(parent->object.sha1));
+ return -1;
+ }
+
+ oneline = get_oneline(message);
+
+ if (flags & PICK_REVERSE) {
+ char *oneline_body = strchr(oneline, ' ');
+
+ base = commit;
+ next = parent;
+ strbuf_addstr(msg, "Revert \"");
+ strbuf_addstr(msg, oneline_body + 1);
+ strbuf_addstr(msg, "\"\n\nThis reverts commit ");
+ strbuf_addstr(msg, sha1_to_hex(commit->object.sha1));
+
+ if (commit->parents->next) {
+ strbuf_addstr(msg, ", reversing\nchanges made to ");
+ strbuf_addstr(msg, sha1_to_hex(parent->object.sha1));
+ }
+ strbuf_addstr(msg, ".\n");
+ } else {
+ base = parent;
+ next = commit;
+ add_message_to_msg(msg, message);
+ if (flags & PICK_ADD_NOTE) {
+ strbuf_addstr(msg, "(cherry picked from commit ");
+ strbuf_addstr(msg, sha1_to_hex(commit->object.sha1));
+ strbuf_addstr(msg, ")\n");
+ }
+ }
+
+ read_cache();
+ init_merge_options(&o);
+ o.branch1 = "HEAD";
+ o.branch2 = oneline;
+
+ head_tree = parse_tree_indirect(head);
+ next_tree = next ? next->tree : empty_tree();
+ base_tree = base ? base->tree : empty_tree();
+
+ clean = merge_trees(&o,
+ head_tree,
+ next_tree, base_tree, &result);
+
+ if (active_cache_changed &&
+ (write_cache(index_fd, active_cache, active_nr) ||
+ commit_locked_index(&index_lock))) {
+ error("Unable to write new index file");
+ return 2;
+ }
+ rollback_lock_file(&index_lock);
+
+ if (!clean) {
+ strbuf_addstr(msg, "\nConflicts:\n\n");
+ for (i = 0; i < active_nr;) {
+ struct cache_entry *ce = active_cache[i++];
+ if (ce_stage(ce)) {
+ strbuf_addstr(msg, "\t");
+ strbuf_addstr(msg, ce->name);
+ strbuf_addstr(msg, "\n");
+ while (i < active_nr && !strcmp(ce->name,
+ active_cache[i]->name))
+ i++;
+ }
+ }
+ ret = 1;
+ }
+ free(oneline);
+
+ discard_cache();
+ if (read_cache() < 0) {
+ error("Cannot read the index");
+ return 2;
+ }
+
+ return ret;
+}
diff --git a/pick.h b/pick.h
new file mode 100644
index 0000000..7eb0d3a
--- /dev/null
+++ b/pick.h
@@ -0,0 +1,13 @@
+#ifndef PICK_H
+#define PICK_H
+
+#include "commit.h"
+
+/* Pick flags: */
+#define PICK_REVERSE 1 /* pick the reverse changes ("revert") */
+#define PICK_ADD_NOTE 2 /* add note about original commit (unless conflict) */
+/* We don't need a PICK_QUIET. This is done by
+ * setenv("GIT_MERGE_VERBOSITY", "0", 1); */
+extern int pick(struct commit *pick_commit, int mainline, int flags, struct strbuf *msg);
+
+#endif
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 06/13] pick: simplify "error(...)" followed by "return -1"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (4 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 05/13] revert: libify pick Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 07/13] pick: rename "pick()" to "pick_commit()" Christian Couder
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
into "return error(...)", as suggested by Junio.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
pick.c | 62 ++++++++++++++++++++++++--------------------------------------
1 files changed, 24 insertions(+), 38 deletions(-)
diff --git a/pick.c b/pick.c
index 77c7169..6fea39c 100644
--- a/pick.c
+++ b/pick.c
@@ -93,24 +93,18 @@ int pick(struct commit *pick_commit, int mainline, int flags,
* that represents the "current" state for merge-recursive
* to work on.
*/
- if (write_cache_as_tree(head, 0, NULL)) {
- error("Your index file is unmerged.");
- return -1;
- }
+ if (write_cache_as_tree(head, 0, NULL))
+ return error("Your index file is unmerged.");
discard_cache();
index_fd = hold_locked_index(&index_lock, 0);
- if (index_fd < 0) {
- error("Unable to create locked index: %s",
- strerror(errno));
- return -1;
- }
+ if (index_fd < 0)
+ return error("Unable to create locked index: %s",
+ strerror(errno));
if (!commit->parents) {
- if (flags & PICK_REVERSE) {
- error("Cannot revert a root commit");
- return -1;
- }
+ if (flags & PICK_REVERSE)
+ return error("Cannot revert a root commit");
parent = NULL;
}
else if (commit->parents->next) {
@@ -118,40 +112,32 @@ int pick(struct commit *pick_commit, int mainline, int flags,
int cnt;
struct commit_list *p;
- if (!mainline) {
- error("Commit %s is a merge but no mainline was given.",
- sha1_to_hex(commit->object.sha1));
- return -1;
- }
+ if (!mainline)
+ return error("Commit %s is a merge but no mainline was given.",
+ sha1_to_hex(commit->object.sha1));
for (cnt = 1, p = commit->parents;
cnt != mainline && p;
cnt++)
p = p->next;
- if (cnt != mainline || !p) {
- error("Commit %s does not have parent %d",
- sha1_to_hex(commit->object.sha1), mainline);
- return -1;
- }
+ if (cnt != mainline || !p)
+ return error("Commit %s does not have parent %d",
+ sha1_to_hex(commit->object.sha1),
+ mainline);
parent = p->item;
- } else if (0 < mainline) {
- error("Mainline was specified but commit %s is not a merge.",
- sha1_to_hex(commit->object.sha1));
- return -1;
- } else
+ } else if (0 < mainline)
+ return error("Mainline was specified but commit %s is not a merge.",
+ sha1_to_hex(commit->object.sha1));
+ else
parent = commit->parents->item;
- if (!(message = commit->buffer)) {
- error("Cannot get commit message for %s",
- sha1_to_hex(commit->object.sha1));
- return -1;
- }
+ if (!(message = commit->buffer))
+ return error("Cannot get commit message for %s",
+ sha1_to_hex(commit->object.sha1));
- if (parent && parse_commit(parent) < 0) {
- error("Cannot parse parent commit %s",
- sha1_to_hex(parent->object.sha1));
- return -1;
- }
+ if (parent && parse_commit(parent) < 0)
+ return error("Cannot parse parent commit %s",
+ sha1_to_hex(parent->object.sha1));
oneline = get_oneline(message);
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 07/13] pick: rename "pick()" to "pick_commit()"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (5 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 06/13] pick: simplify "error(...)" followed by "return -1" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 08/13] pick: remove useless PICK_REVERSE => PICK_ADD_NOTE code Christian Couder
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-revert.c | 2 +-
pick.c | 8 ++++----
pick.h | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/builtin-revert.c b/builtin-revert.c
index 6dd29a3..4797ac5 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -206,7 +206,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
git_commit_encoding, encoding)))
commit->buffer = reencoded_message;
- failed = pick(commit, mainline, flags, &msgbuf);
+ failed = pick_commit(commit, mainline, flags, &msgbuf);
if (failed < 0) {
exit(1);
} else if (failed > 0) {
diff --git a/pick.c b/pick.c
index 6fea39c..13bf793 100644
--- a/pick.c
+++ b/pick.c
@@ -60,16 +60,16 @@ static struct tree *empty_tree(void)
}
/*
- * Pick changes introduced by pick_commit into current working tree
- * and index.
+ * Pick changes introduced by "commit" argument into current working
+ * tree and index.
*
* Return 0 on success.
* Return negative value on error before picking,
* and a positive value after picking,
* and return 1 if and only if a conflict occurs but no other error.
*/
-int pick(struct commit *pick_commit, int mainline, int flags,
- struct strbuf *msg)
+int pick_commit(struct commit *pick_commit, int mainline, int flags,
+ struct strbuf *msg)
{
unsigned char head[20];
struct commit *base, *next, *parent;
diff --git a/pick.h b/pick.h
index 7eb0d3a..7a74ad8 100644
--- a/pick.h
+++ b/pick.h
@@ -8,6 +8,6 @@
#define PICK_ADD_NOTE 2 /* add note about original commit (unless conflict) */
/* We don't need a PICK_QUIET. This is done by
* setenv("GIT_MERGE_VERBOSITY", "0", 1); */
-extern int pick(struct commit *pick_commit, int mainline, int flags, struct strbuf *msg);
+extern int pick_commit(struct commit *commit, int mainline, int flags, struct strbuf *msg);
#endif
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 08/13] pick: remove useless PICK_REVERSE => PICK_ADD_NOTE code
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (6 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 07/13] pick: rename "pick()" to "pick_commit()" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 09/13] pick: simplify bogus comment about commiting immediately Christian Couder
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
Useless of the removed code was found by Junio.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
pick.c | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/pick.c b/pick.c
index 13bf793..a6b1d6f 100644
--- a/pick.c
+++ b/pick.c
@@ -84,9 +84,6 @@ int pick_commit(struct commit *pick_commit, int mainline, int flags,
strbuf_init(msg, 0);
commit = pick_commit;
- if (flags & PICK_REVERSE) /* REVERSE implies ADD_NOTE */
- flags |= PICK_ADD_NOTE;
-
/*
* We do not intend to commit immediately. We just want to
* merge the differences in, so let's compute the tree
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 09/13] pick: simplify bogus comment about commiting immediately
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (7 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 08/13] pick: remove useless PICK_REVERSE => PICK_ADD_NOTE code Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 10/13] pick: libify "pick_help_msg()" Christian Couder
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
as suggested by Junio.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
pick.c | 6 ++----
1 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/pick.c b/pick.c
index a6b1d6f..058b877 100644
--- a/pick.c
+++ b/pick.c
@@ -85,10 +85,8 @@ int pick_commit(struct commit *pick_commit, int mainline, int flags,
commit = pick_commit;
/*
- * We do not intend to commit immediately. We just want to
- * merge the differences in, so let's compute the tree
- * that represents the "current" state for merge-recursive
- * to work on.
+ * Let's compute the tree that represents the "current" state
+ * for merge-recursive to work on.
*/
if (write_cache_as_tree(head, 0, NULL))
return error("Your index file is unmerged.");
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 10/13] pick: libify "pick_help_msg()"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (8 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 09/13] pick: simplify bogus comment about commiting immediately Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 11/13] sequencer: add "do_commit()" and related functions Christian Couder
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
This function gives an help message when pick or revert failed.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-revert.c | 23 +----------------------
pick.c | 22 ++++++++++++++++++++++
pick.h | 1 +
3 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/builtin-revert.c b/builtin-revert.c
index 4797ac5..e5250bd 100644
--- a/builtin-revert.c
+++ b/builtin-revert.c
@@ -142,27 +142,6 @@ static void set_author_ident_env(const char *message)
sha1_to_hex(commit->object.sha1));
}
-static char *help_msg(const unsigned char *sha1)
-{
- static char helpbuf[1024];
- char *msg = getenv("GIT_CHERRY_PICK_HELP");
-
- if (msg)
- return msg;
-
- strcpy(helpbuf, " After resolving the conflicts,\n"
- "mark the corrected paths with 'git add <paths>' "
- "or 'git rm <paths>' and commit the result.");
-
- if (!(flags & PICK_REVERSE)) {
- sprintf(helpbuf + strlen(helpbuf),
- "\nWhen commiting, use the option "
- "'-c %s' to retain authorship and message.",
- find_unique_abbrev(sha1, DEFAULT_ABBREV));
- }
- return helpbuf;
-}
-
static void write_message(struct strbuf *msgbuf, const char *filename)
{
struct lock_file msg_file;
@@ -211,7 +190,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)
exit(1);
} else if (failed > 0) {
fprintf(stderr, "Automatic %s failed.%s\n",
- me, help_msg(commit->object.sha1));
+ me, pick_help_msg(commit->object.sha1, flags));
write_message(&msgbuf, git_path("MERGE_MSG"));
rerere();
exit(1);
diff --git a/pick.c b/pick.c
index 058b877..4f882bb 100644
--- a/pick.c
+++ b/pick.c
@@ -208,3 +208,25 @@ int pick_commit(struct commit *pick_commit, int mainline, int flags,
return ret;
}
+
+char *pick_help_msg(const unsigned char *sha1, int flags)
+{
+ static char helpbuf[1024];
+ char *msg = getenv("GIT_CHERRY_PICK_HELP");
+
+ if (msg)
+ return msg;
+
+ strcpy(helpbuf, " After resolving the conflicts,\n"
+ "mark the corrected paths with 'git add <paths>' "
+ "or 'git rm <paths>' and commit the result.");
+
+ if (!(flags & PICK_REVERSE)) {
+ sprintf(helpbuf + strlen(helpbuf),
+ "\nWhen commiting, use the option "
+ "'-c %s' to retain authorship and message.",
+ find_unique_abbrev(sha1, DEFAULT_ABBREV));
+ }
+ return helpbuf;
+}
+
diff --git a/pick.h b/pick.h
index 7a74ad8..115541a 100644
--- a/pick.h
+++ b/pick.h
@@ -9,5 +9,6 @@
/* We don't need a PICK_QUIET. This is done by
* setenv("GIT_MERGE_VERBOSITY", "0", 1); */
extern int pick_commit(struct commit *commit, int mainline, int flags, struct strbuf *msg);
+extern char *pick_help_msg(const unsigned char *sha1, int flags);
#endif
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 11/13] sequencer: add "do_commit()" and related functions
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (9 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 10/13] pick: libify "pick_help_msg()" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 12/13] sequencer: add "--cherry-pick" option to "git sequencer--helper" Christian Couder
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
From: Stephan Beyer <s-beyer@gmx.net>
This patch adds some code that comes from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
It adds "struct commit_info", the "next_commit" static variable and
the following functions:
- do_commit()
- set_author_info()
- set_message_source()
- set_pick_subject()
- write_commit_summary_into()
This makes it possible to prepare and perform a commit.
Compared to the sequencer project, the only change is that "mark"
related (3 lines long) code has been removed from do_commit().
Mentored-by: Daniel Barkalow <barkalow@iabervon.org>
Mentored-by: Christian Couder <chriscool@tuxfamily.org>
Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 214 +++++++++++++++++++++++++++++++++++++++++++
1 files changed, 214 insertions(+), 0 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 71a7fef..61a8f2e 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -5,26 +5,69 @@
#include "refs.h"
#include "diff.h"
#include "unpack-trees.h"
+#include "string-list.h"
+#include "pick.h"
+#include "rerere.h"
+#include "dir.h"
+#include "cache-tree.h"
+#include "utf8.h"
#define SEQ_DIR "rebase-merge"
#define PATCH_FILE git_path(SEQ_DIR "/patch")
+#define MERGE_MSG git_path("MERGE_MSG")
+#define SQUASH_MSG git_path("SQUASH_MSG")
+
+/**********************************************************************
+ * Data structures
+ */
+
+struct user_info {
+ const char *name;
+ const char *mail;
+ const char *time; /* "<timestamp> <timezone>" */
+};
+
+struct commit_info {
+ struct user_info author; /* author info */
+ struct user_info committer; /* not used, but for easy extendability */
+ const char *encoding; /* encoding */
+ char *subject; /* basically the first line of the summary */
+ struct strbuf summary; /* the commit message */
+ char *source; /* source of the commit message, either
+ * "message", "merge", "squash" or a commit SHA1 */
+ char *patch; /* a patch */
+ struct string_list parents; /* list of parents' hex'ed sha1 ids */
+};
+
+/**********************************************************************
+ * Global variables
+ */
static char *reflog;
+static int squash_count = 0;
+
static int allow_dirty = 0, verbosity = 1, advice = 1;
static unsigned char head_sha1[20];
+static struct commit_info next_commit;
+
static const char * const git_sequencer_helper_usage[] = {
"git sequencer--helper --make-patch <commit>",
"git sequencer--helper --reset-hard <commit> <reflog-msg> "
"<verbosity> [<allow-dirty>]",
"git sequencer--helper --fast-forward <commit> <reflog-msg> "
"<verbosity> [<allow-dirty>]",
+ "git sequencer--helper --cherry-pick <commit> [<do-not-commit>]",
NULL
};
+/**********************************************************************
+ * Sequencer functions
+ */
+
static int parse_and_init_tree_desc(const unsigned char *sha1,
struct tree_desc *desc)
{
@@ -162,6 +205,157 @@ static void make_patch(struct commit *commit)
free(args);
}
+/* Commit current index with information next_commit onto parent_sha1. */
+static int do_commit(unsigned char *parent_sha1)
+{
+ int failed;
+ unsigned char tree_sha1[20];
+ unsigned char commit_sha1[20];
+ struct strbuf sbuf;
+ const char *reencoded = NULL;
+
+ if (squash_count) {
+ squash_count = 0;
+ if (file_exists(SQUASH_MSG))
+ unlink(SQUASH_MSG);
+ }
+
+ if (!index_differs_from("HEAD", 0) &&
+ !next_commit.parents.nr)
+ return error("No changes! Do you really want an empty commit?");
+
+ if (!next_commit.author.name || !next_commit.author.mail)
+ return error("Internal error: Author information not set properly.");
+
+ if (write_cache_as_tree(tree_sha1, 0, NULL))
+ return 1;
+
+ if (!next_commit.encoding)
+ next_commit.encoding = xstrdup("utf-8");
+ if (!git_commit_encoding)
+ git_commit_encoding = "utf-8";
+
+ strbuf_init(&sbuf, 8192); /* should avoid reallocs for the headers */
+ strbuf_addf(&sbuf, "tree %s\n", sha1_to_hex(tree_sha1));
+ if (parent_sha1)
+ strbuf_addf(&sbuf, "parent %s\n", sha1_to_hex(parent_sha1));
+ if (next_commit.parents.nr) {
+ int i;
+ for (i = 0; i < next_commit.parents.nr; ++i)
+ strbuf_addf(&sbuf, "parent %s\n",
+ next_commit.parents.items[i].string);
+ }
+ if (!next_commit.author.time) {
+ char time[50];
+ datestamp(time, sizeof(time));
+ next_commit.author.time = xstrdup(time);
+ }
+
+ stripspace(&next_commit.summary, 1);
+
+ /* if encodings differ, reencode whole buffer */
+ if (strcasecmp(git_commit_encoding, next_commit.encoding)) {
+ if ((reencoded = reencode_string(next_commit.author.name,
+ git_commit_encoding, next_commit.encoding))) {
+ free((void *)next_commit.author.name);
+ next_commit.author.name = reencoded;
+ }
+ if ((reencoded = reencode_string(next_commit.summary.buf,
+ git_commit_encoding, next_commit.encoding))) {
+ strbuf_reset(&next_commit.summary);
+ strbuf_addstr(&next_commit.summary, reencoded);
+ }
+ }
+ strbuf_addf(&sbuf, "author %s <%s> %s\n", next_commit.author.name,
+ next_commit.author.mail, next_commit.author.time);
+ strbuf_addf(&sbuf, "committer %s\n", git_committer_info(0));
+ if (!is_encoding_utf8(git_commit_encoding))
+ strbuf_addf(&sbuf, "encoding %s\n", git_commit_encoding);
+ strbuf_addch(&sbuf, '\n');
+ strbuf_addbuf(&sbuf, &next_commit.summary);
+ if (sbuf.buf[sbuf.len-1] != '\n')
+ strbuf_addch(&sbuf, '\n');
+
+ failed = write_sha1_file(sbuf.buf, sbuf.len, commit_type, commit_sha1);
+ strbuf_release(&sbuf);
+ if (failed)
+ return 1;
+
+ if (verbosity > 1)
+ printf("Created %scommit %s\n",
+ parent_sha1 || next_commit.parents.nr ? "" : "initial ",
+ sha1_to_hex(commit_sha1));
+
+ if (update_ref(reflog, "HEAD", commit_sha1, NULL, 0, 0))
+ return error("Could not update HEAD to %s.",
+ sha1_to_hex(commit_sha1));
+
+ return 0;
+}
+
+/*
+ * Fill next_commit.author according to ident.
+ * Ident may have one of the following forms:
+ * "name <e-mail> timestamp timezone\n..."
+ * "name <e-mail> timestamp timezone"
+ * "name <e-mail>"
+ */
+static void set_author_info(const char *ident)
+{
+ const char *tmp1 = strstr(ident, " <");
+ const char *tmp2;
+ char *data;
+ if (!tmp1)
+ return;
+ tmp2 = strstr(tmp1+2, ">");
+ if (!tmp2)
+ return;
+ if (tmp2[1] != 0 && tmp2[1] != ' ')
+ return;
+
+ data = xmalloc(strlen(ident)); /* a trivial upper bound */
+
+ snprintf(data, tmp1-ident+1, "%s", ident);
+ next_commit.author.name = xstrdup(data);
+ snprintf(data, tmp2-tmp1-1, "%s", tmp1+2);
+ next_commit.author.mail = xstrdup(data);
+
+ if (tmp2[1] == 0) {
+ free(data);
+ return;
+ }
+
+ tmp1 = strpbrk(tmp2+2, "\r\n");
+ if (!tmp1)
+ tmp1 = tmp2 + strlen(tmp2);
+
+ snprintf(data, tmp1-tmp2-1, "%s", tmp2+2);
+ next_commit.author.time = xstrdup(data);
+ free(data);
+}
+
+static void set_message_source(const char *source)
+{
+ if (next_commit.source)
+ free(next_commit.source);
+ next_commit.source = xstrdup(source);
+}
+
+/* Set subject, an information for the case of conflict */
+static void set_pick_subject(const char *hex, struct commit *commit)
+{
+ const char *tmp = strstr(commit->buffer, "\n\n");
+ if (tmp) {
+ const char *eol;
+ int len = strlen(hex);
+ tmp += 2;
+ eol = strchrnul(tmp, '\n');
+ next_commit.subject = xmalloc(eol - tmp + len + 5);
+ snprintf(next_commit.subject, eol - tmp + len + 5, "%s... %s",
+ hex, tmp);
+ }
+}
+
/* Return a commit object of "arg" */
static struct commit *get_commit(const char *arg)
{
@@ -198,6 +392,26 @@ static int set_verbosity(int verbose)
return 0;
}
+static int write_commit_summary_into(const char *filename)
+{
+ struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
+ int fd = hold_lock_file_for_update(lock, filename, 0);
+ if (fd < 0)
+ return error("Unable to create '%s.lock': %s", filename,
+ strerror(errno));
+ if (write_in_full(fd, next_commit.summary.buf,
+ next_commit.summary.len) < 0)
+ return error("Could not write to %s: %s",
+ filename, strerror(errno));
+ if (commit_lock_file(lock) < 0)
+ return error("Error wrapping up %s", filename);
+ return 0;
+}
+
+/**********************************************************************
+ * Builtin sequencer helper functions
+ */
+
/* v should be "" or "t" or "\d" */
static int parse_verbosity(const char *v)
{
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 12/13] sequencer: add "--cherry-pick" option to "git sequencer--helper"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (10 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 11/13] sequencer: add "do_commit()" and related functions Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 5:15 ` [PATCH 13/13] rebase -i: use "git sequencer--helper --cherry-pick" Christian Couder
2009-08-12 21:49 ` [PATCH 00/13] more changes to port rebase -i to C using sequencer code Junio C Hamano
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
From: Stephan Beyer <s-beyer@gmx.net>
This patch adds some code that comes from the sequencer GSoC project:
git://repo.or.cz/git/sbeyer.git
(commit e7b8dab0c2a73ade92017a52bb1405ea1534ef20)
Most of the code is taken from the insn_pick_act() function.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
builtin-sequencer--helper.c | 52 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 51 insertions(+), 1 deletions(-)
diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 61a8f2e..0f2255a 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -288,7 +288,7 @@ static int do_commit(unsigned char *parent_sha1)
if (update_ref(reflog, "HEAD", commit_sha1, NULL, 0, 0))
return error("Could not update HEAD to %s.",
- sha1_to_hex(commit_sha1));
+ sha1_to_hex(commit_sha1));
return 0;
}
@@ -436,6 +436,7 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
char *patch_commit = NULL;
char *reset_commit = NULL;
char *ff_commit = NULL;
+ char *cp_commit = NULL;
struct option options[] = {
OPT_STRING(0, "make-patch", &patch_commit, "commit",
"create a patch from commit"),
@@ -443,6 +444,8 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
"reset to commit"),
OPT_STRING(0, "fast-forward", &ff_commit, "commit",
"fast forward to commit"),
+ OPT_STRING(0, "cherry-pick", &cp_commit, "commit",
+ "cherry pick commit"),
OPT_END()
};
@@ -488,5 +491,52 @@ int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
return reset_almost_hard(sha1);
}
+ if (cp_commit) {
+ struct commit *commit;
+ int failed;
+ const char *author;
+ int no_commit = 0;
+
+ if (argc != 0 && argc != 1)
+ usage_with_options(git_sequencer_helper_usage,
+ options);
+
+ if (argc == 1 && *argv[0] && strcmp(argv[0], "0"))
+ no_commit = 1;
+
+ if (get_sha1("HEAD", head_sha1))
+ return error("You do not have a valid HEAD.");
+
+ commit = get_commit(cp_commit);
+ if (!commit)
+ return 1;
+
+ set_pick_subject(cp_commit, commit);
+
+ failed = pick_commit(commit, 0, 0, &next_commit.summary);
+
+ set_message_source(sha1_to_hex(commit->object.sha1));
+ author = strstr(commit->buffer, "\nauthor ");
+ if (author)
+ set_author_info(author + 8);
+
+ /* We do not want extra Conflicts: lines on cherry-pick,
+ so just take the old commit message. */
+ if (failed) {
+ strbuf_setlen(&next_commit.summary, 0);
+ strbuf_addstr(&next_commit.summary,
+ strstr(commit->buffer, "\n\n") + 2);
+ rerere();
+ make_patch(commit);
+ write_commit_summary_into(MERGE_MSG);
+ return error(pick_help_msg(commit->object.sha1, 0));
+ }
+
+ if (!no_commit && do_commit(head_sha1))
+ return error("Could not commit.");
+
+ return 0;
+ }
+
usage_with_options(git_sequencer_helper_usage, options);
}
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* [PATCH 13/13] rebase -i: use "git sequencer--helper --cherry-pick"
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (11 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 12/13] sequencer: add "--cherry-pick" option to "git sequencer--helper" Christian Couder
@ 2009-08-12 5:15 ` Christian Couder
2009-08-12 21:49 ` [PATCH 00/13] more changes to port rebase -i to C using sequencer code Junio C Hamano
13 siblings, 0 replies; 15+ messages in thread
From: Christian Couder @ 2009-08-12 5:15 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
instead of "git cherry-pick", as this will make it easier to
port "git-rebase--interactive.sh" to C.
Signed-off-by: Christian Couder <chriscool@tuxfamily.org>
---
git-rebase--interactive.sh | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 7651fd6..30af512 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -147,7 +147,7 @@ pick_one () {
pick_one_preserving_merges "$@" && return
if test ! -z "$REBASE_ROOT"
then
- output git cherry-pick "$@"
+ git sequencer--helper --cherry-pick $sha1 $no_ff
return
fi
parent_sha1=$(git rev-parse --verify $sha1^) ||
@@ -157,7 +157,7 @@ pick_one () {
git sequencer--helper --fast-forward $sha1 \
"$GIT_REFLOG_ACTION" "$VERBOSE"
else
- output git cherry-pick "$@"
+ git sequencer--helper --cherry-pick $sha1 $no_ff
fi
}
@@ -269,7 +269,9 @@ pick_one_preserving_merges () {
fi
;;
*)
- output git cherry-pick "$@" ||
+ no_commit=
+ test "a$1" = "a-n" && no_commit=t
+ git sequencer--helper --cherry-pick $sha1 $no_commit ||
die_with_patch $sha1 "Could not pick $sha1"
;;
esac
--
1.6.4.271.ge010d
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [PATCH 00/13] more changes to port rebase -i to C using sequencer code
2009-08-12 5:15 [PATCH 00/13] more changes to port rebase -i to C using sequencer code Christian Couder
` (12 preceding siblings ...)
2009-08-12 5:15 ` [PATCH 13/13] rebase -i: use "git sequencer--helper --cherry-pick" Christian Couder
@ 2009-08-12 21:49 ` Junio C Hamano
13 siblings, 0 replies; 15+ messages in thread
From: Junio C Hamano @ 2009-08-12 21:49 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski
Christian Couder <chriscool@tuxfamily.org> writes:
> These is just the current state of my work.
> Some patches have already been sent but are not yet in pu.
It seems that some later patches in the series are "oops, the earlier one
made mistakes and this patch fixes them". Could you fix them where they
were introduced?
^ permalink raw reply [flat|nested] 15+ messages in thread