[PATCH v4 04/15] sequencer: add "reset_almost_hard()" and related functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Stephan Beyer <s-beyer@xxxxxxx>

This patch adds the "reset_almost_hard()" function, some related
static variables and the related following functions:

	- parse_and_init_tree_desc()
	- reset_index_file()
	- set_verbosity()

"reset_almost_hard()" can be used to do a "git reset --hard". It
should be faster as it calls "unpack_trees()" directly, and it can
optionnaly preserve changes in the work tree if the "allow_dirty"
global is set. Preserving changes in the work tree can be usefull
if for example you want to get rid of the last commit but keep
your current not yet commited work.

In this patch the "allow_dirty" global is not used but a following
patch will make it possible to set it, and in the end the code
should be simpler with a global.

The code comes as is from the sequencer GSoC project:

git://repo.or.cz/git/sbeyer.git

(at commit 5a78908b70ceb5a4ea9fd4b82f07ceba1f019079)

Mentored-by: Daniel Barkalow <barkalow@xxxxxxxxxxxx>
Mentored-by: Christian Couder <chriscool@xxxxxxxxxxxxx>
Signed-off-by: Stephan Beyer <s-beyer@xxxxxxx>
Signed-off-by: Christian Couder <chriscool@xxxxxxxxxxxxx>
Signed-off-by: Junio C Hamano <gitster@xxxxxxxxx>
---
 builtin-sequencer--helper.c |  107 +++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 107 insertions(+), 0 deletions(-)

diff --git a/builtin-sequencer--helper.c b/builtin-sequencer--helper.c
index 1dda525..a15139c 100644
--- a/builtin-sequencer--helper.c
+++ b/builtin-sequencer--helper.c
@@ -2,16 +2,108 @@
 #include "cache.h"
 #include "parse-options.h"
 #include "run-command.h"
+#include "refs.h"
+#include "diff.h"
+#include "unpack-trees.h"
 
 #define SEQ_DIR "rebase-merge"
 
 #define PATCH_FILE	git_path(SEQ_DIR "/patch")
 
+static char *reflog;
+
+static int allow_dirty = 0, verbosity = 1, advice = 1;
+
+static unsigned char head_sha1[20];
+
 static const char * const git_sequencer_helper_usage[] = {
 	"git sequencer--helper --make-patch <commit>",
 	NULL
 };
 
+static int parse_and_init_tree_desc(const unsigned char *sha1,
+				    struct tree_desc *desc)
+{
+	struct tree *tree = parse_tree_indirect(sha1);
+	if (!tree)
+		return 1;
+	init_tree_desc(desc, tree->buffer, tree->size);
+	return 0;
+}
+
+static int reset_index_file(const unsigned char *sha1, int update, int dirty)
+{
+	int nr = 1;
+	int newfd;
+	struct tree_desc desc[2];
+	struct unpack_trees_options opts;
+	struct lock_file *lock = xcalloc(1, sizeof(struct lock_file));
+
+	memset(&opts, 0, sizeof(opts));
+	opts.head_idx = 1;
+	opts.src_index = &the_index;
+	opts.dst_index = &the_index;
+	opts.reset = 1; /* ignore unmerged entries and overwrite wt files */
+	opts.merge = 1;
+	opts.fn = oneway_merge;
+	if (verbosity > 2)
+		opts.verbose_update = 1;
+	if (update) /* update working tree */
+		opts.update = 1;
+
+	newfd = hold_locked_index(lock, 1);
+
+	read_cache_unmerged();
+
+	if (dirty) {
+		if (get_sha1("HEAD", head_sha1))
+			return error("You do not have a valid HEAD.");
+		if (parse_and_init_tree_desc(head_sha1, desc))
+			return error("Failed to find tree of HEAD.");
+		nr++;
+		opts.fn = twoway_merge;
+	}
+
+	if (parse_and_init_tree_desc(sha1, desc + nr - 1))
+		return error("Failed to find tree of %s.", sha1_to_hex(sha1));
+	if (unpack_trees(nr, desc, &opts))
+		return -1;
+	if (write_cache(newfd, active_cache, active_nr) ||
+	    commit_locked_index(lock))
+		return error("Could not write new index file.");
+
+	return 0;
+}
+
+/*
+ * Realize reset --hard behavior.
+ * If allow_dirty is set and there is a dirty work tree,
+ * then the changes in the work tree are to be kept.
+ *
+ * This should be faster than calling "git reset --hard" because
+ * this calls "unpack_trees()" directly (instead of forking and
+ * execing "git read-tree").
+ *
+ * Unmerged entries in the index will be discarded.
+ *
+ * If allow_dirty is set and fast forwarding the work tree
+ * fails because it is dirty, then the work tree will not be
+ * updated.
+ *
+ * No need to read or discard the index before calling this
+ * function.
+ */
+static int reset_almost_hard(const unsigned char *sha)
+{
+	int err = allow_dirty ?
+		(reset_index_file(sha, 1, 1) || reset_index_file(sha, 0, 0)) :
+		reset_index_file(sha, 1, 0);
+	if (err)
+		return error("Could not reset index.");
+
+	return update_ref(reflog, "HEAD", sha, NULL, 0, MSG_ON_ERR);
+}
+
 /* Generate purely informational patch file */
 static void make_patch(struct commit *commit)
 {
@@ -78,6 +170,21 @@ static struct commit *get_commit(const char *arg)
 	return lookup_commit_reference(sha1);
 }
 
+static int set_verbosity(int verbose)
+{
+	char tmp[] = "0";
+	verbosity = verbose;
+	if (verbosity <= 0) {
+		verbosity = 0;
+		advice = 0;
+	} else if (verbosity > 5)
+		verbosity = 5;
+	/* Git does not run on EBCDIC, so we rely on ASCII: */
+	tmp[0] += verbosity;
+	setenv("GIT_MERGE_VERBOSITY", tmp, 1);
+	return 0;
+}
+
 int cmd_sequencer__helper(int argc, const char **argv, const char *prefix)
 {
 	char *commit = NULL;
-- 
1.6.4.271.ge010d


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]