git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] git-rerere.txt: Mention rr-cache directory
@ 2008-07-09  0:17 Stephan Beyer
  2008-07-09  0:25 ` Johannes Schindelin
  0 siblings, 1 reply; 11+ messages in thread
From: Stephan Beyer @ 2008-07-09  0:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Stephan Beyer

If a user reads the rerere documentation, he or she is not told to
create the $GIT_DIR/rr-cache directory to be able to use git-rerere.
This patch adds such a remark.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
 Documentation/git-rerere.txt |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index 678bfd3..667505c 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -23,8 +23,8 @@ initial manual merge, and later by noticing the same automerge
 results and applying the previously recorded hand resolution.
 
 [NOTE]
-You need to set the configuration variable rerere.enabled to
-enable this command.
+You need to set the configuration variable `rerere.enabled` and create
+the `rr-cache` directory under `$GIT_DIR` to enable this command.
 
 
 COMMANDS
@@ -170,8 +170,8 @@ As a convenience measure, 'git-merge' automatically invokes
 records it if it is a new conflict, or reuses the earlier hand
 resolve when it is not.  'git-commit' also invokes 'git-rerere'
 when recording a merge result.  What this means is that you do
-not have to do anything special yourself (Note: you still have
-to set the config variable rerere.enabled to enable this command).
+not have to do anything special yourself, except making sure
+that `rerere.enabled` is set and `$GIT_DIR/rr-cache` exists.
 
 In our example, when you did the test merge, the manual
 resolution is recorded, and it will be reused when you do the
-- 
1.5.6.2.574.gd4568

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
  2008-07-09  0:17 [PATCH] git-rerere.txt: Mention rr-cache directory Stephan Beyer
@ 2008-07-09  0:25 ` Johannes Schindelin
  2008-07-09  0:38   ` Johannes Schindelin
  0 siblings, 1 reply; 11+ messages in thread
From: Johannes Schindelin @ 2008-07-09  0:25 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: Junio C Hamano, git

Hi,

On Wed, 9 Jul 2008, Stephan Beyer wrote:

> If a user reads the rerere documentation, he or she is not told to 
> create the $GIT_DIR/rr-cache directory to be able to use git-rerere. 

Is it?  The config setting is not enough?  Then that is a bug, and should 
not be blessed by a bug in the documentation.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
  2008-07-09  0:25 ` Johannes Schindelin
@ 2008-07-09  0:38   ` Johannes Schindelin
  2008-07-09  1:09     ` Junio C Hamano
                       ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Johannes Schindelin @ 2008-07-09  0:38 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: Junio C Hamano, git

Hi,

On Wed, 9 Jul 2008, Johannes Schindelin wrote:

> On Wed, 9 Jul 2008, Stephan Beyer wrote:
> 
> > If a user reads the rerere documentation, he or she is not told to 
> > create the $GIT_DIR/rr-cache directory to be able to use git-rerere. 
> 
> Is it?  The config setting is not enough?  Then that is a bug, and should 
> not be blessed by a bug in the documentation.

Okay, I took a look:

-- snip --
static int is_rerere_enabled(void)
{
        struct stat st;
        const char *rr_cache;
        int rr_cache_exists;

        if (!rerere_enabled)
                return 0;

        rr_cache = git_path("rr-cache");
        rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
        if (rerere_enabled < 0)
                return rr_cache_exists;

        if (!rr_cache_exists &&
            (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
                die("Could not create directory %s", rr_cache);
        return 1;
}
-- snap --

As you can see, in the case rerere_enabled < 0 (i.e. the config did not 
say anything about rerere), it is assumed enabled _exactly_ when 
.git/rr_cache/ exists.

But if it is > 0, the directory is created.

Of course, this only holds true when the config is read, i.e. when 
setup_rerere() was called in time.  Which is the case when you call 
rerere() (as is done both from cmd_rerere() as well as cmd_commit()).

Of course, I haven't tested it.  Other than running the test script, that 
is.

So care to elaborate what is going wrong?

BTW I think it is a horrible thing that rerere() is declared in commit.h 
(a libgit header), but implemented in builtin-rerere.c, which is not part 
of libgit.a.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
  2008-07-09  0:38   ` Johannes Schindelin
@ 2008-07-09  1:09     ` Junio C Hamano
  2008-07-09  9:21     ` Stephan Beyer
  2008-07-09 10:18     ` [PATCH] rerere: Separate libgit and builtin functions Stephan Beyer
  2 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2008-07-09  1:09 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Stephan Beyer, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Of course, this only holds true when the config is read, i.e. when 
> setup_rerere() was called in time.  Which is the case when you call 
> rerere() (as is done both from cmd_rerere() as well as cmd_commit()).
>
> Of course, I haven't tested it.  Other than running the test script, that 
> is.
>
> So care to elaborate what is going wrong?

Very interesting question indeed.

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] git-rerere.txt: Mention rr-cache directory
  2008-07-09  0:38   ` Johannes Schindelin
  2008-07-09  1:09     ` Junio C Hamano
@ 2008-07-09  9:21     ` Stephan Beyer
  2008-07-09 10:18     ` [PATCH] rerere: Separate libgit and builtin functions Stephan Beyer
  2 siblings, 0 replies; 11+ messages in thread
From: Stephan Beyer @ 2008-07-09  9:21 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git

Hi,

On Wed, Jul 09, Johannes Schindelin wrote:
> On Wed, 9 Jul 2008, Johannes Schindelin wrote:
> > On Wed, 9 Jul 2008, Stephan Beyer wrote:
> > 
> > > If a user reads the rerere documentation, he or she is not told to 
> > > create the $GIT_DIR/rr-cache directory to be able to use git-rerere. 
> > 
> > Is it?  The config setting is not enough?  Then that is a bug, and should 
> > not be blessed by a bug in the documentation.

I don't know if this is exactly a bug, at least config.txt says:

rerere.enabled::
	Activate recording of resolved conflicts, so that identical
	conflict hunks can be resolved automatically, should they
	be encountered again.  linkgit:git-rerere[1] command is by
	default enabled if you create `rr-cache` directory under
	`$GIT_DIR`, but can be disabled by setting this option to false.

So according to *that* documentation it is right, according to the
git-rerere.txt documentation it was wrong, and according to the
source it is...
> -- snip --
> static int is_rerere_enabled(void)
> {
>         struct stat st;
>         const char *rr_cache;
>         int rr_cache_exists;
> 
>         if (!rerere_enabled)
>                 return 0;
> 
>         rr_cache = git_path("rr-cache");
>         rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
>         if (rerere_enabled < 0)
>                 return rr_cache_exists;
> 
>         if (!rr_cache_exists &&
>             (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
>                 die("Could not create directory %s", rr_cache);
>         return 1;
> }
> -- snap --
> 
> As you can see, in the case rerere_enabled < 0 (i.e. the config did not 
> say anything about rerere), it is assumed enabled _exactly_ when 
> .git/rr_cache/ exists.
> 
> But if it is > 0, the directory is created.

Yes.
There is also an important part in the file:
-- snip --
/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
static int rerere_enabled = -1;
-- snap --

So this means it's the following behavior:
 - rerere_enabled < 0: enable, iff rr-cache exists
 - rerere_enabled ==0: disable
 - rerere_enabled > 0: enable and create rr-cache if it does not exist

So this is my fault, sorry :) Both documentations (config.txt and
git-rerere.txt) are right.
It was not explicitly enabled on this one machine which lead me to the
wrong assumption. I should sync my ~/.gitconfig more often ;)

Sorry for that,
  Stephan

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH] rerere: Separate libgit and builtin functions
  2008-07-09  0:38   ` Johannes Schindelin
  2008-07-09  1:09     ` Junio C Hamano
  2008-07-09  9:21     ` Stephan Beyer
@ 2008-07-09 10:18     ` Stephan Beyer
  2008-07-09 11:55       ` Johannes Schindelin
  2008-07-09 12:03       ` [PATCH] " Johannes Schindelin
  2 siblings, 2 replies; 11+ messages in thread
From: Stephan Beyer @ 2008-07-09 10:18 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, Junio C Hamano, Stephan Beyer

This patch moves rerere()-related functions into a newly created
rerere.c file.  Also setup_rerere() is moved into rerere.c to decrease
code duplications for rerere.c and builtin-rerere.c.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---

> BTW I think it is a horrible thing that rerere() is declared in commit.h
> (a libgit header), but implemented in builtin-rerere.c, which is not part
> of libgit.a.

Ok, I give it a try.

 Makefile                     |    2 +
 builtin-rerere.c             |  324 +++---------------------------------------
 builtin-rerere.c => rerere.c |  133 +-----------------
 rerere.h                     |    9 ++
 4 files changed, 32 insertions(+), 436 deletions(-)
 copy builtin-rerere.c => rerere.c (66%)
 create mode 100644 rerere.h

diff --git a/Makefile b/Makefile
index bddd1a7..4e23c29 100644
--- a/Makefile
+++ b/Makefile
@@ -363,6 +363,7 @@ LIB_H += quote.h
 LIB_H += reflog-walk.h
 LIB_H += refs.h
 LIB_H += remote.h
+LIB_H += rerere.h
 LIB_H += revision.h
 LIB_H += run-command.h
 LIB_H += sha1-lookup.h
@@ -447,6 +448,7 @@ LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
 LIB_OBJS += remote.o
+LIB_OBJS += rerere.o
 LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
 LIB_OBJS += server-info.o
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 85222d9..669a963 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -1,6 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
 #include "path-list.h"
+#include "rerere.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 
@@ -13,183 +14,11 @@ static const char git_rerere_usage[] =
 static int cutoff_noresolve = 15;
 static int cutoff_resolve = 60;
 
-/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
-static int rerere_enabled = -1;
-
-static char *merge_rr_path;
-
 static const char *rr_path(const char *name, const char *file)
 {
 	return git_path("rr-cache/%s/%s", name, file);
 }
 
-static void read_rr(struct path_list *rr)
-{
-	unsigned char sha1[20];
-	char buf[PATH_MAX];
-	FILE *in = fopen(merge_rr_path, "r");
-	if (!in)
-		return;
-	while (fread(buf, 40, 1, in) == 1) {
-		int i;
-		char *name;
-		if (get_sha1_hex(buf, sha1))
-			die("corrupt MERGE_RR");
-		buf[40] = '\0';
-		name = xstrdup(buf);
-		if (fgetc(in) != '\t')
-			die("corrupt MERGE_RR");
-		for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
-			; /* do nothing */
-		if (i == sizeof(buf))
-			die("filename too long");
-		path_list_insert(buf, rr)->util = name;
-	}
-	fclose(in);
-}
-
-static struct lock_file write_lock;
-
-static int write_rr(struct path_list *rr, int out_fd)
-{
-	int i;
-	for (i = 0; i < rr->nr; i++) {
-		const char *path = rr->items[i].path;
-		int length = strlen(path) + 1;
-		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
-		    write_in_full(out_fd, "\t", 1) != 1 ||
-		    write_in_full(out_fd, path, length) != length)
-			die("unable to write rerere record");
-	}
-	if (commit_lock_file(&write_lock) != 0)
-		die("unable to write rerere record");
-	return 0;
-}
-
-static int handle_file(const char *path,
-	 unsigned char *sha1, const char *output)
-{
-	SHA_CTX ctx;
-	char buf[1024];
-	int hunk = 0, hunk_no = 0;
-	struct strbuf one, two;
-	FILE *f = fopen(path, "r");
-	FILE *out = NULL;
-
-	if (!f)
-		return error("Could not open %s", path);
-
-	if (output) {
-		out = fopen(output, "w");
-		if (!out) {
-			fclose(f);
-			return error("Could not write %s", output);
-		}
-	}
-
-	if (sha1)
-		SHA1_Init(&ctx);
-
-	strbuf_init(&one, 0);
-	strbuf_init(&two,  0);
-	while (fgets(buf, sizeof(buf), f)) {
-		if (!prefixcmp(buf, "<<<<<<< "))
-			hunk = 1;
-		else if (!prefixcmp(buf, "======="))
-			hunk = 2;
-		else if (!prefixcmp(buf, ">>>>>>> ")) {
-			int cmp = strbuf_cmp(&one, &two);
-
-			hunk_no++;
-			hunk = 0;
-			if (cmp > 0) {
-				strbuf_swap(&one, &two);
-			}
-			if (out) {
-				fputs("<<<<<<<\n", out);
-				fwrite(one.buf, one.len, 1, out);
-				fputs("=======\n", out);
-				fwrite(two.buf, two.len, 1, out);
-				fputs(">>>>>>>\n", out);
-			}
-			if (sha1) {
-				SHA1_Update(&ctx, one.buf ? one.buf : "",
-					    one.len + 1);
-				SHA1_Update(&ctx, two.buf ? two.buf : "",
-					    two.len + 1);
-			}
-			strbuf_reset(&one);
-			strbuf_reset(&two);
-		} else if (hunk == 1)
-			strbuf_addstr(&one, buf);
-		else if (hunk == 2)
-			strbuf_addstr(&two, buf);
-		else if (out)
-			fputs(buf, out);
-	}
-	strbuf_release(&one);
-	strbuf_release(&two);
-
-	fclose(f);
-	if (out)
-		fclose(out);
-	if (sha1)
-		SHA1_Final(sha1, &ctx);
-	return hunk_no;
-}
-
-static int find_conflict(struct path_list *conflict)
-{
-	int i;
-	if (read_cache() < 0)
-		return error("Could not read index");
-	for (i = 0; i+1 < active_nr; i++) {
-		struct cache_entry *e2 = active_cache[i];
-		struct cache_entry *e3 = active_cache[i+1];
-		if (ce_stage(e2) == 2 &&
-		    ce_stage(e3) == 3 &&
-		    ce_same_name(e2, e3) &&
-		    S_ISREG(e2->ce_mode) &&
-		    S_ISREG(e3->ce_mode)) {
-			path_list_insert((const char *)e2->name, conflict);
-			i++; /* skip over both #2 and #3 */
-		}
-	}
-	return 0;
-}
-
-static int merge(const char *name, const char *path)
-{
-	int ret;
-	mmfile_t cur, base, other;
-	mmbuffer_t result = {NULL, 0};
-	xpparam_t xpp = {XDF_NEED_MINIMAL};
-
-	if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0)
-		return 1;
-
-	if (read_mmfile(&cur, rr_path(name, "thisimage")) ||
-			read_mmfile(&base, rr_path(name, "preimage")) ||
-			read_mmfile(&other, rr_path(name, "postimage")))
-		return 1;
-	ret = xdl_merge(&base, &cur, "", &other, "",
-			&xpp, XDL_MERGE_ZEALOUS, &result);
-	if (!ret) {
-		FILE *f = fopen(path, "w");
-		if (!f)
-			return error("Could not write to %s", path);
-		fwrite(result.ptr, result.size, 1, f);
-		fclose(f);
-	}
-
-	free(cur.ptr);
-	free(base.ptr);
-	free(other.ptr);
-	free(result.ptr);
-
-	return ret;
-}
-
 static void unlink_rr_item(const char *name)
 {
 	unlink(rr_path(name, "thisimage"));
@@ -198,6 +27,17 @@ static void unlink_rr_item(const char *name)
 	rmdir(git_path("rr-cache/%s", name));
 }
 
+static int git_rerere_gc_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "gc.rerereresolved"))
+		cutoff_resolve = git_config_int(var, value);
+	else if (!strcmp(var, "gc.rerereunresolved"))
+		cutoff_noresolve = git_config_int(var, value);
+	else
+		return git_default_config(var, value, cb);
+	return 0;
+}
+
 static void garbage_collect(struct path_list *rr)
 {
 	struct path_list to_remove = { NULL, 0, 0, 1 };
@@ -207,6 +47,7 @@ static void garbage_collect(struct path_list *rr)
 	int len, i, cutoff;
 	time_t now = time(NULL), then;
 
+	git_config(git_rerere_gc_config, NULL);
 	strlcpy(buf, git_path("rr-cache"), sizeof(buf));
 	len = strlen(buf);
 	dir = opendir(buf);
@@ -267,148 +108,19 @@ static int diff_two(const char *file1, const char *label1,
 	return 0;
 }
 
-static int do_plain_rerere(struct path_list *rr, int fd)
-{
-	struct path_list conflict = { NULL, 0, 0, 1 };
-	int i;
-
-	find_conflict(&conflict);
-
-	/*
-	 * MERGE_RR records paths with conflicts immediately after merge
-	 * failed.  Some of the conflicted paths might have been hand resolved
-	 * in the working tree since then, but the initial run would catch all
-	 * and register their preimages.
-	 */
-
-	for (i = 0; i < conflict.nr; i++) {
-		const char *path = conflict.items[i].path;
-		if (!path_list_has_path(rr, path)) {
-			unsigned char sha1[20];
-			char *hex;
-			int ret;
-			ret = handle_file(path, sha1, NULL);
-			if (ret < 1)
-				continue;
-			hex = xstrdup(sha1_to_hex(sha1));
-			path_list_insert(path, rr)->util = hex;
-			if (mkdir(git_path("rr-cache/%s", hex), 0755))
-				continue;;
-			handle_file(path, NULL, rr_path(hex, "preimage"));
-			fprintf(stderr, "Recorded preimage for '%s'\n", path);
-		}
-	}
-
-	/*
-	 * Now some of the paths that had conflicts earlier might have been
-	 * hand resolved.  Others may be similar to a conflict already that
-	 * was resolved before.
-	 */
-
-	for (i = 0; i < rr->nr; i++) {
-		struct stat st;
-		int ret;
-		const char *path = rr->items[i].path;
-		const char *name = (const char *)rr->items[i].util;
-
-		if (!stat(rr_path(name, "preimage"), &st) &&
-				!stat(rr_path(name, "postimage"), &st)) {
-			if (!merge(name, path)) {
-				fprintf(stderr, "Resolved '%s' using "
-						"previous resolution.\n", path);
-				goto tail_optimization;
-			}
-		}
-
-		/* Let's see if we have resolved it. */
-		ret = handle_file(path, NULL, NULL);
-		if (ret)
-			continue;
-
-		fprintf(stderr, "Recorded resolution for '%s'.\n", path);
-		copy_file(rr_path(name, "postimage"), path, 0666);
-tail_optimization:
-		if (i < rr->nr - 1)
-			memmove(rr->items + i,
-				rr->items + i + 1,
-				sizeof(rr->items[0]) * (rr->nr - i - 1));
-		rr->nr--;
-		i--;
-	}
-
-	return write_rr(rr, fd);
-}
-
-static int git_rerere_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "gc.rerereresolved"))
-		cutoff_resolve = git_config_int(var, value);
-	else if (!strcmp(var, "gc.rerereunresolved"))
-		cutoff_noresolve = git_config_int(var, value);
-	else if (!strcmp(var, "rerere.enabled"))
-		rerere_enabled = git_config_bool(var, value);
-	else
-		return git_default_config(var, value, cb);
-	return 0;
-}
-
-static int is_rerere_enabled(void)
-{
-	struct stat st;
-	const char *rr_cache;
-	int rr_cache_exists;
-
-	if (!rerere_enabled)
-		return 0;
-
-	rr_cache = git_path("rr-cache");
-	rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
-	if (rerere_enabled < 0)
-		return rr_cache_exists;
-
-	if (!rr_cache_exists &&
-	    (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
-		die("Could not create directory %s", rr_cache);
-	return 1;
-}
-
-static int setup_rerere(struct path_list *merge_rr)
-{
-	int fd;
-
-	git_config(git_rerere_config, NULL);
-	if (!is_rerere_enabled())
-		return -1;
-
-	merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR"));
-	fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
-	read_rr(merge_rr);
-	return fd;
-}
-
-int rerere(void)
-{
-	struct path_list merge_rr = { NULL, 0, 0, 1 };
-	int fd;
-
-	fd = setup_rerere(&merge_rr);
-	if (fd < 0)
-		return 0;
-	return do_plain_rerere(&merge_rr, fd);
-}
-
 int cmd_rerere(int argc, const char **argv, const char *prefix)
 {
 	struct path_list merge_rr = { NULL, 0, 0, 1 };
 	int i, fd;
 
+	if (argc < 2)
+		return rerere();
+
 	fd = setup_rerere(&merge_rr);
 	if (fd < 0)
 		return 0;
 
-	if (argc < 2)
-		return do_plain_rerere(&merge_rr, fd);
-	else if (!strcmp(argv[1], "clear")) {
+	if (!strcmp(argv[1], "clear")) {
 		for (i = 0; i < merge_rr.nr; i++) {
 			struct stat st;
 			const char *name = (const char *)merge_rr.items[i].util;
@@ -417,7 +129,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
 					stat(rr_path(name, "postimage"), &st))
 				unlink_rr_item(name);
 		}
-		unlink(merge_rr_path);
+		unlink(git_path("rr-cache/MERGE_RR"));
 	} else if (!strcmp(argv[1], "gc"))
 		garbage_collect(&merge_rr);
 	else if (!strcmp(argv[1], "status"))
diff --git a/builtin-rerere.c b/rerere.c
similarity index 66%
copy from builtin-rerere.c
copy to rerere.c
index 85222d9..5c22bed 100644
--- a/builtin-rerere.c
+++ b/rerere.c
@@ -1,18 +1,11 @@
-#include "builtin.h"
 #include "cache.h"
 #include "path-list.h"
+#include "rerere.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 
 #include <time.h>
 
-static const char git_rerere_usage[] =
-"git-rerere [clear | status | diff | gc]";
-
-/* these values are days */
-static int cutoff_noresolve = 15;
-static int cutoff_resolve = 60;
-
 /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
 static int rerere_enabled = -1;
 
@@ -190,83 +183,6 @@ static int merge(const char *name, const char *path)
 	return ret;
 }
 
-static void unlink_rr_item(const char *name)
-{
-	unlink(rr_path(name, "thisimage"));
-	unlink(rr_path(name, "preimage"));
-	unlink(rr_path(name, "postimage"));
-	rmdir(git_path("rr-cache/%s", name));
-}
-
-static void garbage_collect(struct path_list *rr)
-{
-	struct path_list to_remove = { NULL, 0, 0, 1 };
-	char buf[1024];
-	DIR *dir;
-	struct dirent *e;
-	int len, i, cutoff;
-	time_t now = time(NULL), then;
-
-	strlcpy(buf, git_path("rr-cache"), sizeof(buf));
-	len = strlen(buf);
-	dir = opendir(buf);
-	strcpy(buf + len++, "/");
-	while ((e = readdir(dir))) {
-		const char *name = e->d_name;
-		struct stat st;
-		if (name[0] == '.' && (name[1] == '\0' ||
-					(name[1] == '.' && name[2] == '\0')))
-			continue;
-		i = snprintf(buf + len, sizeof(buf) - len, "%s", name);
-		strlcpy(buf + len + i, "/preimage", sizeof(buf) - len - i);
-		if (stat(buf, &st))
-			continue;
-		then = st.st_mtime;
-		strlcpy(buf + len + i, "/postimage", sizeof(buf) - len - i);
-		cutoff = stat(buf, &st) ? cutoff_noresolve : cutoff_resolve;
-		if (then < now - cutoff * 86400) {
-			buf[len + i] = '\0';
-			path_list_insert(xstrdup(name), &to_remove);
-		}
-	}
-	for (i = 0; i < to_remove.nr; i++)
-		unlink_rr_item(to_remove.items[i].path);
-	path_list_clear(&to_remove, 0);
-}
-
-static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
-{
-	int i;
-	for (i = 0; i < nbuf; i++)
-		if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
-			return -1;
-	return 0;
-}
-
-static int diff_two(const char *file1, const char *label1,
-		const char *file2, const char *label2)
-{
-	xpparam_t xpp;
-	xdemitconf_t xecfg;
-	xdemitcb_t ecb;
-	mmfile_t minus, plus;
-
-	if (read_mmfile(&minus, file1) || read_mmfile(&plus, file2))
-		return 1;
-
-	printf("--- a/%s\n+++ b/%s\n", label1, label2);
-	fflush(stdout);
-	xpp.flags = XDF_NEED_MINIMAL;
-	memset(&xecfg, 0, sizeof(xecfg));
-	xecfg.ctxlen = 3;
-	ecb.outf = outf;
-	xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
-
-	free(minus.ptr);
-	free(plus.ptr);
-	return 0;
-}
-
 static int do_plain_rerere(struct path_list *rr, int fd)
 {
 	struct path_list conflict = { NULL, 0, 0, 1 };
@@ -341,11 +257,7 @@ tail_optimization:
 
 static int git_rerere_config(const char *var, const char *value, void *cb)
 {
-	if (!strcmp(var, "gc.rerereresolved"))
-		cutoff_resolve = git_config_int(var, value);
-	else if (!strcmp(var, "gc.rerereunresolved"))
-		cutoff_noresolve = git_config_int(var, value);
-	else if (!strcmp(var, "rerere.enabled"))
+	if (!strcmp(var, "rerere.enabled"))
 		rerere_enabled = git_config_bool(var, value);
 	else
 		return git_default_config(var, value, cb);
@@ -372,7 +284,7 @@ static int is_rerere_enabled(void)
 	return 1;
 }
 
-static int setup_rerere(struct path_list *merge_rr)
+int setup_rerere(struct path_list *merge_rr)
 {
 	int fd;
 
@@ -396,42 +308,3 @@ int rerere(void)
 		return 0;
 	return do_plain_rerere(&merge_rr, fd);
 }
-
-int cmd_rerere(int argc, const char **argv, const char *prefix)
-{
-	struct path_list merge_rr = { NULL, 0, 0, 1 };
-	int i, fd;
-
-	fd = setup_rerere(&merge_rr);
-	if (fd < 0)
-		return 0;
-
-	if (argc < 2)
-		return do_plain_rerere(&merge_rr, fd);
-	else if (!strcmp(argv[1], "clear")) {
-		for (i = 0; i < merge_rr.nr; i++) {
-			struct stat st;
-			const char *name = (const char *)merge_rr.items[i].util;
-			if (!stat(git_path("rr-cache/%s", name), &st) &&
-					S_ISDIR(st.st_mode) &&
-					stat(rr_path(name, "postimage"), &st))
-				unlink_rr_item(name);
-		}
-		unlink(merge_rr_path);
-	} else if (!strcmp(argv[1], "gc"))
-		garbage_collect(&merge_rr);
-	else if (!strcmp(argv[1], "status"))
-		for (i = 0; i < merge_rr.nr; i++)
-			printf("%s\n", merge_rr.items[i].path);
-	else if (!strcmp(argv[1], "diff"))
-		for (i = 0; i < merge_rr.nr; i++) {
-			const char *path = merge_rr.items[i].path;
-			const char *name = (const char *)merge_rr.items[i].util;
-			diff_two(rr_path(name, "preimage"), path, path, path);
-		}
-	else
-		usage(git_rerere_usage);
-
-	path_list_clear(&merge_rr, 1);
-	return 0;
-}
diff --git a/rerere.h b/rerere.h
new file mode 100644
index 0000000..35b0fa8
--- /dev/null
+++ b/rerere.h
@@ -0,0 +1,9 @@
+#ifndef RERERE_H
+#define RERERE_H
+
+#include "path-list.h"
+
+extern int setup_rerere(struct path_list *);
+extern int rerere(void);
+
+#endif
-- 
1.5.6.2.574.gd4568

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] rerere: Separate libgit and builtin functions
  2008-07-09 10:18     ` [PATCH] rerere: Separate libgit and builtin functions Stephan Beyer
@ 2008-07-09 11:55       ` Johannes Schindelin
  2008-07-09 12:00         ` Stephan Beyer
  2008-07-09 12:03       ` [PATCH] " Johannes Schindelin
  1 sibling, 1 reply; 11+ messages in thread
From: Johannes Schindelin @ 2008-07-09 11:55 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: git, Junio C Hamano

Hi,

On Wed, 9 Jul 2008, Stephan Beyer wrote:

> This patch moves rerere()-related functions into a newly created 
> rerere.c file.  Also setup_rerere() is moved into rerere.c to decrease 
> code duplications for rerere.c and builtin-rerere.c.

It is not moved to decrease code duplication, but because it is needed by 
rerere().

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] rerere: Separate libgit and builtin functions
  2008-07-09 11:55       ` Johannes Schindelin
@ 2008-07-09 12:00         ` Stephan Beyer
  2008-07-09 12:58           ` [PATCHv2] " Stephan Beyer
  0 siblings, 1 reply; 11+ messages in thread
From: Stephan Beyer @ 2008-07-09 12:00 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, Junio C Hamano

> > This patch moves rerere()-related functions into a newly created 
> > rerere.c file.  Also setup_rerere() is moved into rerere.c to decrease 
> > code duplications for rerere.c and builtin-rerere.c.
> 
> It is not moved to decrease code duplication, but because it is needed by 
> rerere().

Right.

And btw the patch seems to be broken. (At least I can't apply it
here...)   Sorry :( Usually I test applying before sending but this time
lunch was eliciting.

Well, I'm going to fix that.

-- 
Stephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] rerere: Separate libgit and builtin functions
  2008-07-09 10:18     ` [PATCH] rerere: Separate libgit and builtin functions Stephan Beyer
  2008-07-09 11:55       ` Johannes Schindelin
@ 2008-07-09 12:03       ` Johannes Schindelin
  2008-07-09 18:25         ` Junio C Hamano
  1 sibling, 1 reply; 11+ messages in thread
From: Johannes Schindelin @ 2008-07-09 12:03 UTC (permalink / raw)
  To: Stephan Beyer; +Cc: git, Junio C Hamano

Hi,

On Wed, 9 Jul 2008, Stephan Beyer wrote:

>  Makefile                     |    2 +
>  builtin-rerere.c             |  324 +++---------------------------------------
>  builtin-rerere.c => rerere.c |  133 +-----------------
>  rerere.h                     |    9 ++
>  4 files changed, 32 insertions(+), 436 deletions(-)

Heh, that sounds nice!  Deleting way more lines than adding!  :-)

>  copy builtin-rerere.c => rerere.c (66%)

Oh, well :-)

> diff --git a/builtin-rerere.c b/rerere.c
> similarity index 66%
> copy from builtin-rerere.c
> copy to rerere.c
> index 85222d9..5c22bed 100644
> --- a/builtin-rerere.c
> +++ b/rerere.c
> @@ -1,18 +1,11 @@
> -#include "builtin.h"
>  #include "cache.h"
>  #include "path-list.h"
> +#include "rerere.h"
>  #include "xdiff/xdiff.h"
>  #include "xdiff-interface.h"
>  
>  #include <time.h>

No longer necessary, is it?

> diff --git a/rerere.h b/rerere.h
> new file mode 100644
> index 0000000..35b0fa8
> --- /dev/null
> +++ b/rerere.h
> @@ -0,0 +1,9 @@
> +#ifndef RERERE_H
> +#define RERERE_H
> +
> +#include "path-list.h"
> +
> +extern int setup_rerere(struct path_list *);

Why?

Ah, it is needed for "gc".  Maybe this needs documentation, since it cause 
some minutes of head scratching with yours truly.

Ciao,
Dscho

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCHv2] rerere: Separate libgit and builtin functions
  2008-07-09 12:00         ` Stephan Beyer
@ 2008-07-09 12:58           ` Stephan Beyer
  0 siblings, 0 replies; 11+ messages in thread
From: Stephan Beyer @ 2008-07-09 12:58 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git, Stephan Beyer

This patch moves rerere()-related functions into a newly created
rerere.c file.
The setup_rerere() function is needed by both rerere() and cmd_rerere(),
so this function is moved to rerere.c and declared non-static (and "extern")
in newly created rerere.h file.

Signed-off-by: Stephan Beyer <s-beyer@gmx.net>
---
Hi again,

so now it should apply cleanly.
Seems that I had not built the topic branch of the former patch
on top of the latest master by accident.

Regards,
  Stephan

 Makefile                     |    2 +
 builtin-commit.c             |    1 +
 builtin-rerere.c             |  362 ++---------------------------------------
 commit.h                     |    1 -
 builtin-rerere.c => rerere.c |  129 +---------------
 rerere.h                     |    9 +
 6 files changed, 33 insertions(+), 471 deletions(-)
 copy builtin-rerere.c => rerere.c (71%)
 create mode 100644 rerere.h

diff --git a/Makefile b/Makefile
index 4796565..de15163 100644
--- a/Makefile
+++ b/Makefile
@@ -363,6 +363,7 @@ LIB_H += quote.h
 LIB_H += reflog-walk.h
 LIB_H += refs.h
 LIB_H += remote.h
+LIB_H += rerere.h
 LIB_H += revision.h
 LIB_H += run-command.h
 LIB_H += sha1-lookup.h
@@ -447,6 +448,7 @@ LIB_OBJS += read-cache.o
 LIB_OBJS += reflog-walk.o
 LIB_OBJS += refs.o
 LIB_OBJS += remote.o
+LIB_OBJS += rerere.o
 LIB_OBJS += revision.o
 LIB_OBJS += run-command.o
 LIB_OBJS += server-info.o
diff --git a/builtin-commit.c b/builtin-commit.c
index 745c11e..bdc83df 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -22,6 +22,7 @@
 #include "utf8.h"
 #include "parse-options.h"
 #include "path-list.h"
+#include "rerere.h"
 #include "unpack-trees.h"
 
 static const char * const builtin_commit_usage[] = {
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 839b26e..5d40e16 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -1,11 +1,10 @@
 #include "builtin.h"
 #include "cache.h"
 #include "path-list.h"
+#include "rerere.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 
-#include <time.h>
-
 static const char git_rerere_usage[] =
 "git-rerere [clear | status | diff | gc]";
 
@@ -13,14 +12,6 @@ static const char git_rerere_usage[] =
 static int cutoff_noresolve = 15;
 static int cutoff_resolve = 60;
 
-/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
-static int rerere_enabled = -1;
-
-/* automatically update cleanly resolved paths to the index */
-static int rerere_autoupdate;
-
-static char *merge_rr_path;
-
 static const char *rr_path(const char *name, const char *file)
 {
 	return git_path("rr-cache/%s/%s", name, file);
@@ -38,179 +29,6 @@ static int has_resolution(const char *name)
 	return !stat(rr_path(name, "postimage"), &st);
 }
 
-static void read_rr(struct path_list *rr)
-{
-	unsigned char sha1[20];
-	char buf[PATH_MAX];
-	FILE *in = fopen(merge_rr_path, "r");
-	if (!in)
-		return;
-	while (fread(buf, 40, 1, in) == 1) {
-		int i;
-		char *name;
-		if (get_sha1_hex(buf, sha1))
-			die("corrupt MERGE_RR");
-		buf[40] = '\0';
-		name = xstrdup(buf);
-		if (fgetc(in) != '\t')
-			die("corrupt MERGE_RR");
-		for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
-			; /* do nothing */
-		if (i == sizeof(buf))
-			die("filename too long");
-		path_list_insert(buf, rr)->util = name;
-	}
-	fclose(in);
-}
-
-static struct lock_file write_lock;
-
-static int write_rr(struct path_list *rr, int out_fd)
-{
-	int i;
-	for (i = 0; i < rr->nr; i++) {
-		const char *path;
-		int length;
-		if (!rr->items[i].util)
-			continue;
-		path = rr->items[i].path;
-		length = strlen(path) + 1;
-		if (write_in_full(out_fd, rr->items[i].util, 40) != 40 ||
-		    write_in_full(out_fd, "\t", 1) != 1 ||
-		    write_in_full(out_fd, path, length) != length)
-			die("unable to write rerere record");
-	}
-	if (commit_lock_file(&write_lock) != 0)
-		die("unable to write rerere record");
-	return 0;
-}
-
-static int handle_file(const char *path,
-	 unsigned char *sha1, const char *output)
-{
-	SHA_CTX ctx;
-	char buf[1024];
-	int hunk = 0, hunk_no = 0;
-	struct strbuf one, two;
-	FILE *f = fopen(path, "r");
-	FILE *out = NULL;
-
-	if (!f)
-		return error("Could not open %s", path);
-
-	if (output) {
-		out = fopen(output, "w");
-		if (!out) {
-			fclose(f);
-			return error("Could not write %s", output);
-		}
-	}
-
-	if (sha1)
-		SHA1_Init(&ctx);
-
-	strbuf_init(&one, 0);
-	strbuf_init(&two,  0);
-	while (fgets(buf, sizeof(buf), f)) {
-		if (!prefixcmp(buf, "<<<<<<< "))
-			hunk = 1;
-		else if (!prefixcmp(buf, "======="))
-			hunk = 2;
-		else if (!prefixcmp(buf, ">>>>>>> ")) {
-			if (strbuf_cmp(&one, &two) > 0)
-				strbuf_swap(&one, &two);
-			hunk_no++;
-			hunk = 0;
-			if (out) {
-				fputs("<<<<<<<\n", out);
-				fwrite(one.buf, one.len, 1, out);
-				fputs("=======\n", out);
-				fwrite(two.buf, two.len, 1, out);
-				fputs(">>>>>>>\n", out);
-			}
-			if (sha1) {
-				SHA1_Update(&ctx, one.buf ? one.buf : "",
-					    one.len + 1);
-				SHA1_Update(&ctx, two.buf ? two.buf : "",
-					    two.len + 1);
-			}
-			strbuf_reset(&one);
-			strbuf_reset(&two);
-		} else if (hunk == 1)
-			strbuf_addstr(&one, buf);
-		else if (hunk == 2)
-			strbuf_addstr(&two, buf);
-		else if (out)
-			fputs(buf, out);
-	}
-	strbuf_release(&one);
-	strbuf_release(&two);
-
-	fclose(f);
-	if (out)
-		fclose(out);
-	if (sha1)
-		SHA1_Final(sha1, &ctx);
-	if (hunk) {
-		if (output)
-			unlink(output);
-		return error("Could not parse conflict hunks in %s", path);
-	}
-	return hunk_no;
-}
-
-static int find_conflict(struct path_list *conflict)
-{
-	int i;
-	if (read_cache() < 0)
-		return error("Could not read index");
-	for (i = 0; i+1 < active_nr; i++) {
-		struct cache_entry *e2 = active_cache[i];
-		struct cache_entry *e3 = active_cache[i+1];
-		if (ce_stage(e2) == 2 &&
-		    ce_stage(e3) == 3 &&
-		    ce_same_name(e2, e3) &&
-		    S_ISREG(e2->ce_mode) &&
-		    S_ISREG(e3->ce_mode)) {
-			path_list_insert((const char *)e2->name, conflict);
-			i++; /* skip over both #2 and #3 */
-		}
-	}
-	return 0;
-}
-
-static int merge(const char *name, const char *path)
-{
-	int ret;
-	mmfile_t cur, base, other;
-	mmbuffer_t result = {NULL, 0};
-	xpparam_t xpp = {XDF_NEED_MINIMAL};
-
-	if (handle_file(path, NULL, rr_path(name, "thisimage")) < 0)
-		return 1;
-
-	if (read_mmfile(&cur, rr_path(name, "thisimage")) ||
-			read_mmfile(&base, rr_path(name, "preimage")) ||
-			read_mmfile(&other, rr_path(name, "postimage")))
-		return 1;
-	ret = xdl_merge(&base, &cur, "", &other, "",
-			&xpp, XDL_MERGE_ZEALOUS, &result);
-	if (!ret) {
-		FILE *f = fopen(path, "w");
-		if (!f)
-			return error("Could not write to %s", path);
-		fwrite(result.ptr, result.size, 1, f);
-		fclose(f);
-	}
-
-	free(cur.ptr);
-	free(base.ptr);
-	free(other.ptr);
-	free(result.ptr);
-
-	return ret;
-}
-
 static void unlink_rr_item(const char *name)
 {
 	unlink(rr_path(name, "thisimage"));
@@ -219,6 +37,17 @@ static void unlink_rr_item(const char *name)
 	rmdir(git_path("rr-cache/%s", name));
 }
 
+static int git_rerere_gc_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "gc.rerereresolved"))
+		cutoff_resolve = git_config_int(var, value);
+	else if (!strcmp(var, "gc.rerereunresolved"))
+		cutoff_noresolve = git_config_int(var, value);
+	else
+		return git_default_config(var, value, cb);
+	return 0;
+}
+
 static void garbage_collect(struct path_list *rr)
 {
 	struct path_list to_remove = { NULL, 0, 0, 1 };
@@ -227,6 +56,7 @@ static void garbage_collect(struct path_list *rr)
 	int i, cutoff;
 	time_t now = time(NULL), then;
 
+	git_config(git_rerere_gc_config, NULL);
 	dir = opendir(git_path("rr-cache"));
 	while ((e = readdir(dir))) {
 		const char *name = e->d_name;
@@ -279,181 +109,25 @@ static int diff_two(const char *file1, const char *label1,
 	return 0;
 }
 
-static struct lock_file index_lock;
-
-static int update_paths(struct path_list *update)
-{
-	int i;
-	int fd = hold_locked_index(&index_lock, 0);
-	int status = 0;
-
-	if (fd < 0)
-		return -1;
-
-	for (i = 0; i < update->nr; i++) {
-		struct path_list_item *item = &update->items[i];
-		if (add_file_to_cache(item->path, ADD_CACHE_IGNORE_ERRORS))
-			status = -1;
-	}
-
-	if (!status && active_cache_changed) {
-		if (write_cache(fd, active_cache, active_nr) ||
-		    commit_locked_index(&index_lock))
-			die("Unable to write new index file");
-	} else if (fd >= 0)
-		rollback_lock_file(&index_lock);
-	return status;
-}
-
-static int do_plain_rerere(struct path_list *rr, int fd)
-{
-	struct path_list conflict = { NULL, 0, 0, 1 };
-	struct path_list update = { NULL, 0, 0, 1 };
-	int i;
-
-	find_conflict(&conflict);
-
-	/*
-	 * MERGE_RR records paths with conflicts immediately after merge
-	 * failed.  Some of the conflicted paths might have been hand resolved
-	 * in the working tree since then, but the initial run would catch all
-	 * and register their preimages.
-	 */
-
-	for (i = 0; i < conflict.nr; i++) {
-		const char *path = conflict.items[i].path;
-		if (!path_list_has_path(rr, path)) {
-			unsigned char sha1[20];
-			char *hex;
-			int ret;
-			ret = handle_file(path, sha1, NULL);
-			if (ret < 1)
-				continue;
-			hex = xstrdup(sha1_to_hex(sha1));
-			path_list_insert(path, rr)->util = hex;
-			if (mkdir(git_path("rr-cache/%s", hex), 0755))
-				continue;;
-			handle_file(path, NULL, rr_path(hex, "preimage"));
-			fprintf(stderr, "Recorded preimage for '%s'\n", path);
-		}
-	}
-
-	/*
-	 * Now some of the paths that had conflicts earlier might have been
-	 * hand resolved.  Others may be similar to a conflict already that
-	 * was resolved before.
-	 */
-
-	for (i = 0; i < rr->nr; i++) {
-		int ret;
-		const char *path = rr->items[i].path;
-		const char *name = (const char *)rr->items[i].util;
-
-		if (has_resolution(name)) {
-			if (!merge(name, path)) {
-				fprintf(stderr, "Resolved '%s' using "
-						"previous resolution.\n", path);
-				if (rerere_autoupdate)
-					path_list_insert(path, &update);
-				goto mark_resolved;
-			}
-		}
-
-		/* Let's see if we have resolved it. */
-		ret = handle_file(path, NULL, NULL);
-		if (ret)
-			continue;
-
-		fprintf(stderr, "Recorded resolution for '%s'.\n", path);
-		copy_file(rr_path(name, "postimage"), path, 0666);
-	mark_resolved:
-		rr->items[i].util = NULL;
-	}
-
-	if (update.nr)
-		update_paths(&update);
-
-	return write_rr(rr, fd);
-}
-
-static int git_rerere_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "gc.rerereresolved"))
-		cutoff_resolve = git_config_int(var, value);
-	else if (!strcmp(var, "gc.rerereunresolved"))
-		cutoff_noresolve = git_config_int(var, value);
-	else if (!strcmp(var, "rerere.enabled"))
-		rerere_enabled = git_config_bool(var, value);
-	else if (!strcmp(var, "rerere.autoupdate"))
-		rerere_autoupdate = git_config_bool(var, value);
-	else
-		return git_default_config(var, value, cb);
-	return 0;
-}
-
-static int is_rerere_enabled(void)
-{
-	struct stat st;
-	const char *rr_cache;
-	int rr_cache_exists;
-
-	if (!rerere_enabled)
-		return 0;
-
-	rr_cache = git_path("rr-cache");
-	rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
-	if (rerere_enabled < 0)
-		return rr_cache_exists;
-
-	if (!rr_cache_exists &&
-	    (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
-		die("Could not create directory %s", rr_cache);
-	return 1;
-}
-
-static int setup_rerere(struct path_list *merge_rr)
-{
-	int fd;
-
-	git_config(git_rerere_config, NULL);
-	if (!is_rerere_enabled())
-		return -1;
-
-	merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR"));
-	fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
-	read_rr(merge_rr);
-	return fd;
-}
-
-int rerere(void)
-{
-	struct path_list merge_rr = { NULL, 0, 0, 1 };
-	int fd;
-
-	fd = setup_rerere(&merge_rr);
-	if (fd < 0)
-		return 0;
-	return do_plain_rerere(&merge_rr, fd);
-}
-
 int cmd_rerere(int argc, const char **argv, const char *prefix)
 {
 	struct path_list merge_rr = { NULL, 0, 0, 1 };
 	int i, fd;
 
+	if (argc < 2)
+		return rerere();
+
 	fd = setup_rerere(&merge_rr);
 	if (fd < 0)
 		return 0;
 
-	if (argc < 2)
-		return do_plain_rerere(&merge_rr, fd);
-	else if (!strcmp(argv[1], "clear")) {
+	if (!strcmp(argv[1], "clear")) {
 		for (i = 0; i < merge_rr.nr; i++) {
 			const char *name = (const char *)merge_rr.items[i].util;
 			if (!has_resolution(name))
 				unlink_rr_item(name);
 		}
-		unlink(merge_rr_path);
+		unlink(git_path("rr-cache/MERGE_RR"));
 	} else if (!strcmp(argv[1], "gc"))
 		garbage_collect(&merge_rr);
 	else if (!strcmp(argv[1], "status"))
diff --git a/commit.h b/commit.h
index 2d94d41..fda7ad0 100644
--- a/commit.h
+++ b/commit.h
@@ -131,7 +131,6 @@ extern struct commit_list *get_shallow_commits(struct object_array *heads,
 int in_merge_bases(struct commit *, struct commit **, int);
 
 extern int interactive_add(int argc, const char **argv, const char *prefix);
-extern int rerere(void);
 
 static inline int single_parent(struct commit *commit)
 {
diff --git a/builtin-rerere.c b/rerere.c
similarity index 71%
copy from builtin-rerere.c
copy to rerere.c
index 839b26e..bbd8c00 100644
--- a/builtin-rerere.c
+++ b/rerere.c
@@ -1,18 +1,9 @@
-#include "builtin.h"
 #include "cache.h"
 #include "path-list.h"
+#include "rerere.h"
 #include "xdiff/xdiff.h"
 #include "xdiff-interface.h"
 
-#include <time.h>
-
-static const char git_rerere_usage[] =
-"git-rerere [clear | status | diff | gc]";
-
-/* these values are days */
-static int cutoff_noresolve = 15;
-static int cutoff_resolve = 60;
-
 /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
 static int rerere_enabled = -1;
 
@@ -26,12 +17,6 @@ static const char *rr_path(const char *name, const char *file)
 	return git_path("rr-cache/%s/%s", name, file);
 }
 
-static time_t rerere_created_at(const char *name)
-{
-	struct stat st;
-	return stat(rr_path(name, "preimage"), &st) ? (time_t) 0 : st.st_mtime;
-}
-
 static int has_resolution(const char *name)
 {
 	struct stat st;
@@ -211,74 +196,6 @@ static int merge(const char *name, const char *path)
 	return ret;
 }
 
-static void unlink_rr_item(const char *name)
-{
-	unlink(rr_path(name, "thisimage"));
-	unlink(rr_path(name, "preimage"));
-	unlink(rr_path(name, "postimage"));
-	rmdir(git_path("rr-cache/%s", name));
-}
-
-static void garbage_collect(struct path_list *rr)
-{
-	struct path_list to_remove = { NULL, 0, 0, 1 };
-	DIR *dir;
-	struct dirent *e;
-	int i, cutoff;
-	time_t now = time(NULL), then;
-
-	dir = opendir(git_path("rr-cache"));
-	while ((e = readdir(dir))) {
-		const char *name = e->d_name;
-		if (name[0] == '.' &&
-		    (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
-			continue;
-		then = rerere_created_at(name);
-		if (!then)
-			continue;
-		cutoff = (has_resolution(name)
-			  ? cutoff_resolve : cutoff_noresolve);
-		if (then < now - cutoff * 86400)
-			path_list_append(name, &to_remove);
-	}
-	for (i = 0; i < to_remove.nr; i++)
-		unlink_rr_item(to_remove.items[i].path);
-	path_list_clear(&to_remove, 0);
-}
-
-static int outf(void *dummy, mmbuffer_t *ptr, int nbuf)
-{
-	int i;
-	for (i = 0; i < nbuf; i++)
-		if (write_in_full(1, ptr[i].ptr, ptr[i].size) != ptr[i].size)
-			return -1;
-	return 0;
-}
-
-static int diff_two(const char *file1, const char *label1,
-		const char *file2, const char *label2)
-{
-	xpparam_t xpp;
-	xdemitconf_t xecfg;
-	xdemitcb_t ecb;
-	mmfile_t minus, plus;
-
-	if (read_mmfile(&minus, file1) || read_mmfile(&plus, file2))
-		return 1;
-
-	printf("--- a/%s\n+++ b/%s\n", label1, label2);
-	fflush(stdout);
-	xpp.flags = XDF_NEED_MINIMAL;
-	memset(&xecfg, 0, sizeof(xecfg));
-	xecfg.ctxlen = 3;
-	ecb.outf = outf;
-	xdi_diff(&minus, &plus, &xpp, &xecfg, &ecb);
-
-	free(minus.ptr);
-	free(plus.ptr);
-	return 0;
-}
-
 static struct lock_file index_lock;
 
 static int update_paths(struct path_list *update)
@@ -378,11 +295,7 @@ static int do_plain_rerere(struct path_list *rr, int fd)
 
 static int git_rerere_config(const char *var, const char *value, void *cb)
 {
-	if (!strcmp(var, "gc.rerereresolved"))
-		cutoff_resolve = git_config_int(var, value);
-	else if (!strcmp(var, "gc.rerereunresolved"))
-		cutoff_noresolve = git_config_int(var, value);
-	else if (!strcmp(var, "rerere.enabled"))
+	if (!strcmp(var, "rerere.enabled"))
 		rerere_enabled = git_config_bool(var, value);
 	else if (!strcmp(var, "rerere.autoupdate"))
 		rerere_autoupdate = git_config_bool(var, value);
@@ -411,7 +324,7 @@ static int is_rerere_enabled(void)
 	return 1;
 }
 
-static int setup_rerere(struct path_list *merge_rr)
+int setup_rerere(struct path_list *merge_rr)
 {
 	int fd;
 
@@ -435,39 +348,3 @@ int rerere(void)
 		return 0;
 	return do_plain_rerere(&merge_rr, fd);
 }
-
-int cmd_rerere(int argc, const char **argv, const char *prefix)
-{
-	struct path_list merge_rr = { NULL, 0, 0, 1 };
-	int i, fd;
-
-	fd = setup_rerere(&merge_rr);
-	if (fd < 0)
-		return 0;
-
-	if (argc < 2)
-		return do_plain_rerere(&merge_rr, fd);
-	else if (!strcmp(argv[1], "clear")) {
-		for (i = 0; i < merge_rr.nr; i++) {
-			const char *name = (const char *)merge_rr.items[i].util;
-			if (!has_resolution(name))
-				unlink_rr_item(name);
-		}
-		unlink(merge_rr_path);
-	} else if (!strcmp(argv[1], "gc"))
-		garbage_collect(&merge_rr);
-	else if (!strcmp(argv[1], "status"))
-		for (i = 0; i < merge_rr.nr; i++)
-			printf("%s\n", merge_rr.items[i].path);
-	else if (!strcmp(argv[1], "diff"))
-		for (i = 0; i < merge_rr.nr; i++) {
-			const char *path = merge_rr.items[i].path;
-			const char *name = (const char *)merge_rr.items[i].util;
-			diff_two(rr_path(name, "preimage"), path, path, path);
-		}
-	else
-		usage(git_rerere_usage);
-
-	path_list_clear(&merge_rr, 1);
-	return 0;
-}
diff --git a/rerere.h b/rerere.h
new file mode 100644
index 0000000..35b0fa8
--- /dev/null
+++ b/rerere.h
@@ -0,0 +1,9 @@
+#ifndef RERERE_H
+#define RERERE_H
+
+#include "path-list.h"
+
+extern int setup_rerere(struct path_list *);
+extern int rerere(void);
+
+#endif
-- 
1.5.6

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] rerere: Separate libgit and builtin functions
  2008-07-09 12:03       ` [PATCH] " Johannes Schindelin
@ 2008-07-09 18:25         ` Junio C Hamano
  0 siblings, 0 replies; 11+ messages in thread
From: Junio C Hamano @ 2008-07-09 18:25 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Stephan Beyer, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> On Wed, 9 Jul 2008, Stephan Beyer wrote:
>
>>  Makefile                     |    2 +
>>  builtin-rerere.c             |  324 +++---------------------------------------
>>  builtin-rerere.c => rerere.c |  133 +-----------------
>>  rerere.h                     |    9 ++
>>  4 files changed, 32 insertions(+), 436 deletions(-)
>
> Heh, that sounds nice!  Deleting way more lines than adding!  :-)
>
>>  copy builtin-rerere.c => rerere.c (66%)
>
> Oh, well :-)

We may want to fix this, though.  I haven't verified by looking at the
diffstat summary code, but what I think is happening is that the bogus 436
is the result of counting the lines removed from builtin-rerere.c (that
lost many of its lines to rerere.c), and also counting the lines that were
remove from rerere.c pretending as if rerere.c had full contents of
builtin-rerere.c initially (i.e., counting the lines that were _not_ moved
to rerere.c).

It may just be the matter of subtracting the size of the preimage of
copied files (in this case, builtin-rerere.c that was used to initialize
rerere.c) from the grand total of deleted lines.  I dunno.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2008-07-09 18:26 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-09  0:17 [PATCH] git-rerere.txt: Mention rr-cache directory Stephan Beyer
2008-07-09  0:25 ` Johannes Schindelin
2008-07-09  0:38   ` Johannes Schindelin
2008-07-09  1:09     ` Junio C Hamano
2008-07-09  9:21     ` Stephan Beyer
2008-07-09 10:18     ` [PATCH] rerere: Separate libgit and builtin functions Stephan Beyer
2008-07-09 11:55       ` Johannes Schindelin
2008-07-09 12:00         ` Stephan Beyer
2008-07-09 12:58           ` [PATCHv2] " Stephan Beyer
2008-07-09 12:03       ` [PATCH] " Johannes Schindelin
2008-07-09 18:25         ` Junio C Hamano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).