git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Christian Couder <chriscool@tuxfamily.org>
Date
Aug 28, 2009, 04:47 UTC
Message-ID
<20090828044746.4307.88742.chriscool@tuxfamily.org>
In-Reply-To
<20090828043913.4307.34708.chriscool@tuxfamily.org>
From: Stephan Beyer <s-beyer@gmx.net>

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@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>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 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
Previous: Christian CouderNext: Eric Raible
Message 5 of 17 in “complete reroll of my "port rebase -i to C" series”
  1. 00/15 complete reroll of my "port rebase -i to C" seriesChristian Couder, Aug 28, 2009
  2. 01/15 sequencer: add "builtin-sequencer--helper.c"Christian Couder, Aug 28, 2009
  3. 02/15 sequencer: add "make_patch" function to save a patchChristian Couder, Aug 28, 2009
  4. 03/15 rebase -i: use "git sequencer--helper --make-patch"Christian Couder, Aug 28, 2009
  5. 04/15 sequencer: add "reset_almost_hard()" and related functionsChristian Couder, Aug 28, 2009
  6. Eric RaibleAug 28, 2009
  7. 05/15 sequencer: add "--reset-hard" option to "git sequencer--helper"Christian Couder, Aug 28, 2009
  8. 06/15 rebase -i: use "git sequencer--helper --reset-hard"Christian Couder, Aug 28, 2009
  9. 07/15 sequencer: add "do_fast_forward()" to perform a fast forwardChristian Couder, Aug 28, 2009
  10. 08/15 sequencer: add "--fast-forward" option to "git sequencer--helper"Christian Couder, Aug 28, 2009
  11. 09/15 sequencer: let "git sequencer--helper" callers set "allow_dirty"Christian Couder, Aug 28, 2009
  12. 10/15 rebase -i: use "git sequencer--helper --fast-forward"Christian Couder, Aug 28, 2009
  13. 11/15 revert: libify cherry-pick and revert functionnalityChristian Couder, Aug 28, 2009
  14. 12/15 pick: libify "pick_help_msg()"Christian Couder, Aug 28, 2009
  15. 13/15 sequencer: add "do_commit()" and related functions working on "next_commit"Christian Couder, Aug 28, 2009
  16. 14/15 sequencer: add "--cherry-pick" option to "git sequencer--helper"Christian Couder, Aug 28, 2009
  17. 15/15 rebase -i: use "git sequencer--helper --cherry-pick"Christian Couder, Aug 28, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.