Git development
 help / color / mirror / Atom feed
* What's cooking in git.git (topics)
From: Junio C Hamano @ 2006-12-20 21:21 UTC (permalink / raw)
  To: git; +Cc: Eric Wong, Jakub Narebski

Here are the topics that have been cooking.  Commits prefixed
with '-' are only in 'pu' while commits prefixed with '+' are
in 'next'.  The topics list the commits in reverse chronological
order.

* js/rerere (Wed Dec 20 17:39:41 2006 +0100) 3 commits
 - Make git-rerere a builtin
 - Add a test for git-rerere
 - move read_mmfile() into xdiff-interface

Rewrite of rerere in C by Johannes; this is supposed to contain
no feature change, and I should be able to merge it anytime when
it is shown to be correct.  We'll see.

* jc/skip-count (Tue Dec 19 18:25:32 2006 -0800) 1 commit
 + revision: --skip=<n>

This could help gitweb, but otherwise no strong reason to merge
to 'master' yet.

* jc/leftright (Tue Dec 19 02:28:16 2006 -0800) 4 commits
 + Revert "Make left-right automatic."
 + Make left-right automatic.
 + Teach all of log family --left-right output.
 + rev-list --left-right

Since I reverted the 'automatic' bits, this is ready to be
merged to 'master'.  Perhaps in v1.5.0.

* jc/fsck-reflog (Tue Dec 19 00:23:12 2006 -0800) 6 commits
 - git reflog expire
 - Move in_merge_bases() to commit.c
 - reflog: fix warning message.
 - Teach git-repack to preserve objects referred to by reflog
   entries.
 - Protect commits recorded in reflog from pruning.
 - add for_each_reflog_ent() iterator

Because reflogs are enabled by default in end user repositories
now, this series will be needed sooner or later.  The earlier
ones prevent commits lost by reset/rebase from getting pruned
while reflogs point at them, while the latter ones allow reflogs
to be pruned.  Earlier parts cannot be merged without the expiry
mechanism in the later ones, because doing so would mean crufts
will accumulate not just in reflogs but in object database,
without an easy way to prune them.

* jc/clone (Tue Dec 19 01:39:07 2006 +0100) 10 commits
 + Move "no merge candidate" warning into git-pull
 + Use preprocessor constants for environment variable names.
 + Do not create $GIT_DIR/remotes/ directory anymore.
 + Introduce GIT_TEMPLATE_DIR
 + Revert "fix testsuite: make sure they use templates freshly built
   from the source"
 + fix testsuite: make sure they use templates freshly built from the
   source
 + git-clone: lose the traditional 'no-separate-remote' layout
 + git-clone: lose the artificial "first" fetch refspec
 + git-pull: refuse default merge without branch.*.merge
 + git-clone: use wildcard specification for tracking branches

This is to conclude the move of the default repository layout
created by git-clone to separate-remote layout.  I think this is
ready and the next push would include this in the 'master'.

* jc/branch-remove-remote (Tue Dec 19 09:42:16 2006 +1100) 2 commits
 + git-branch -d: do not stop at the first failure.
 + Teach git-branch to delete tracking branches with -r -d

Will merge.

* jc/blame (Mon Dec 18 14:04:38 2006 -0800) 1 commit
 + blame: -b (blame.blankboundary) and --root (blame.showroot)

Will merge.

* jn/web (Sat Dec 16 17:12:55 2006 +0100) 1 commit
 - gitweb: Add some mod_perl specific support

On hold, Jakub's call.

* ew/svn-pm (Fri Dec 15 23:58:08 2006 -0800) 3 commits
 + git-svn: rename 'commit' command to 'set-tree'
 + git-svn: remove support for the svn command-line client
 + git-svn: convert to using Git.pm

I've heard a few comments that renaming 'commit' to 'set-tree'
are received favorably by users, so this might be ready to be
merged.  Eric's call, but I am not in the rush.

* jc/git-add--interactive (Wed Dec 20 13:06:46 2006 -0800) 3 commits
 . git-add: error out when given no arguments.
 + git-add --interactive: hunk splitting
 + git-add --interactive

This is a bit too young and I am not sure how useful it is in
practice.  I might cherry-pick its tip to 'master' first without
adding the --interactive bits.

* jc/explain (Mon Dec 4 19:35:04 2006 -0800) 1 commit
 - git-explain

Probably not in v1.5.0.

* jc/3way (Wed Nov 29 18:53:13 2006 -0800) 1 commit
 + git-merge: preserve and merge local changes when doing fast
   forward

Not in v1.5.0.

* js/shallow (Fri Nov 24 16:00:13 2006 +0100) 15 commits
 + fetch-pack: Do not fetch tags for shallow clones.
 + get_shallow_commits: Avoid memory leak if a commit has been
   reached already.
 + git-fetch: Reset shallow_depth before auto-following tags.
 + upload-pack: Check for NOT_SHALLOW flag before sending a shallow
   to the client.
 + fetch-pack: Properly remove the shallow file when it becomes
   empty.
 + shallow clone: unparse and reparse an unshallowed commit
 + Why didn't we mark want_obj as ~UNINTERESTING in the old code?
 + Why does it mean we do not have to register shallow if we have
   one?
 + We should make sure that the protocol is still extensible.
 + add tests for shallow stuff
 + Shallow clone: do not ignore shallowness when following tags
 + allow deepening of a shallow repository
 + allow cloning a repository "shallowly"
 + support fetching into a shallow repository
 + upload-pack: no longer call rev-list

Post v1.5.0.

* jc/web (Wed Nov 8 14:54:09 2006 -0800) 1 commit
 - gitweb: steal loadavg throttle from kernel.org
* jc/pickaxe (Sun Nov 5 11:52:43 2006 -0800) 1 commit
 - blame: --show-stats for easier optimization work.
* jc/diff (Mon Sep 25 23:03:34 2006 -0700) 1 commit
 - para-walk: walk n trees, index and working tree in parallel
* jc/diff-apply-patch (Fri Sep 22 16:17:58 2006 -0700) 1 commit
 + git-diff/git-apply: make diff output a bit friendlier to GNU patch
   (part 2)

The above four are on hold.

^ permalink raw reply

* Re: [PATCH] index-pack usage of mmap() is unacceptably slower on many OSes other than Linux
From: Linus Torvalds @ 2006-12-20 20:53 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff Garzik, Nicolas Pitre, Randal L. Schwartz, git
In-Reply-To: <7vbqlye2zz.fsf@assigned-by-dhcp.cox.net>



On Wed, 20 Dec 2006, Junio C Hamano wrote:
> 
> I needed to fix the changes to git-compat-util.h a bit from the
> version I sent earlier to make OpenBSD happy (sys/types.h there
> did not expose u_int unless _BSD_SOURCE was set, and
> netinet/in.h was duplicated by mistake).

Please don't use "u_int" in the first place. It's an abomination of a 
type. It should never be used.

There's simply no point. It's "unsigned int", and that doesn't need any 
header files at all.

I don't understand why people are lazy, and can't write "unsigned", but 
then introduce a type that requires you to have all kinds of magic. The 
lazyness just results in more work, and is totally nonportable.

So "u_int" (along with its idiotic brethren "u_long", "u_short" and 
"u_char") is just silly.

The only user in git seems to have been copied from a source that is 
insane. It does

	u_int words[NS_IN6ADDRSZ / NS_INT16SZ];

which is just insane. It actually seems to want to use "uint16_t", which 
at least would make sense, and be a type that has some _point_ to it.

So please change the "u_int" to either "unsigned int" or "uint16_t". 
Either is better.


^ permalink raw reply

* Patch: Support slashes in branches in git-cvsserver
From: Ron Parker @ 2006-12-20 20:55 UTC (permalink / raw)
  To: git

Here is a little patch to allow git-cvsserver to support fetching from
branches with slashes in their names like:

	topic/convert-to-xhtml

>From 1d22e18f46a82eab3fe6d467b2b87fe8203ebacc Mon Sep 17 00:00:00 2001
From: Ron Parker <ron.parker@mobot.org>
Date: Wed, 20 Dec 2006 14:48:31 -0600
Subject: [PATCH] Support slashes in branches in git-cvsserver

---
 git-cvsserver.perl |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 2a8447e..418c821 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -2087,7 +2087,9 @@ sub new
     die "Database dir '$self->{dbdir}' isn't a directory" unless
( defined($self->{dbdir}) and -d $self->{dbdir} );
 
     $self->{module} = $module;
-    $self->{file} = $self->{dbdir} . "/gitcvs.$module.sqlite";
+    my $mod = $module;
+    $mod =~ s/\//./g;
+    $self->{file} = $self->{dbdir} . "/gitcvs.$mod.sqlite";
 
     $self->{git_path} = $config . "/";
 
-- 
1.4.4.2.g8336


^ permalink raw reply related

* What's in git.git (stable), and Announcing GIT 1.4.4.3
From: Junio C Hamano @ 2006-12-20 20:48 UTC (permalink / raw)
  To: git; +Cc: linux-kernel

The latest maintenance release GIT 1.4.4.3 is available at the
usual places:

  http://www.kernel.org/pub/software/scm/git/

  git-1.4.4.3.tar.{gz,bz2}			(tarball)
  git-htmldocs-1.4.4.3.tar.{gz,bz2}		(preformatted docs)
  git-manpages-1.4.4.3.tar.{gz,bz2}		(preformatted docs)
  RPMS/$arch/git-*-1.4.4.3-1.$arch.rpm	(RPM)

This release contains merge-recursive corner case fix; it also
fixes git-cvsserver (when used with newer Perl) and Mac OS build
(when you use config.mak), among other things.

To let people who only follow the 'maint' releases know what's
happening in the larger picture...

We have just started talking about the next feature release
v1.5.0 on the 'master' branch side.  If we are lucky we could do
a -rc1 around Christmas, emperor's birthday in Japan, or perhaps
emperor's birthday in the Penguin land, but in any case the real
release is not expected to happen by mid January.

The new release will have many end-user level changes since the
last feature release v1.4.4, both at the UI level and at the
documentation level, based on previous discussions on the list.

It is strongly encouraged and very much appreciated to review
and to fill gaps you would find in today's 'master' and what's
cooking in 'next', if you were involved in the discussions
and/or if you are interested in the theme of v1.5.0: "usability
and teachability".

Thanks.

-jc.

----------------------------------------------------------------
* The 'maint' branch is at v1.4.4.3 and has these fixes since
  v1.4.4.2:

   Alex Riesen (1):
      Clarify fetch error for missing objects.

   Brian Gernhardt (1):
      Move Fink and Ports check to after config file

   Chris Wright (1):
      no need to install manpages as executable

   Eric Wong (2):
      git-svn: exit with status 1 for test failures
      git-svn: correctly display fatal() error messages

   Jim Meyering (1):
      Don't use memcpy when source and dest. buffers may overlap

   Junio C Hamano (1):
      GIT 1.4.4.3

   Martin Langhoff (1):
      cvsserver: Avoid miscounting bytes in Perl v5.8.x

   Shawn Pearce (2):
      Make sure the empty tree exists when needed in merge-recursive.
      Bypass expensive content comparsion during rename detection.

* The 'master' branch has these since the last announcement.
  They are NOT in 1.4.4.3.

   Aneesh Kumar K.V (1):
      Add config example with respect to branch

   Brian Gernhardt (2):
      Add documentation for show-branch --topics
      Remove COLLISION_CHECK from Makefile since it's not used.

   Eric Wong (1):
      git-cvsserver: fix breakage when calling git merge-file

   Jeff King (1):
      vim syntax: follow recent changes to commit template

   Junio C Hamano (8):
      parse-remote::expand_refs_wildcard()
      show-ref: fix --exclude-existing
      racy-git: documentation updates.
      rerere: fix breakage of resolving.
      fix populate-filespec
      config_rename_section: fix FILE* leak
      simplify inclusion of system header files.
      GIT 1.4.4.3

   Nicolas Pitre (4):
      make patch_delta() error cases a bit more verbose
      make git a bit less cryptic on fetch errors
      index-pack usage of mmap() is unacceptably slower on many OSes
         other than Linux
      clarify some error messages wrt unknown object types

   Robert Fitzsimons (1):
      gitweb: Show '...' links in "summary" view only if there are more items


^ permalink raw reply

* Re: [PATCH] index-pack usage of mmap() is unacceptably slower on many OSes other than Linux
From: Junio C Hamano @ 2006-12-20 20:17 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: Linus Torvalds, Nicolas Pitre, Randal L. Schwartz, git
In-Reply-To: <7v7iwnnzed.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> Linus Torvalds <torvalds@osdl.org> writes:
>
>> On Tue, 19 Dec 2006, Junio C Hamano wrote:
>>
>>> Jeff Garzik <jeff@garzik.org> writes:
>>> 
>>> > If you are going to do this, you have to audit -every- file, to make
>>> > sure git-compat-util.h is -always- the first header.
>>> 
>>> Will do.
>>
>> Well, since any cases where it isn't (and where we'd care) will  show up 
>> as just a compiler warning, I doubt we really even need to. We can fix 
>> things up as they get reported too..
>
> True, but I've done it already, so... 
>
> Test compile especially on non Linux boxes are appreciated (I'll
> do one on an OpenBSD bochs tomorrow myself anyway, though).

I've pushed the results out, along with the index-pack updates
from Linus/Nico.

I needed to fix the changes to git-compat-util.h a bit from the
version I sent earlier to make OpenBSD happy (sys/types.h there
did not expose u_int unless _BSD_SOURCE was set, and
netinet/in.h was duplicated by mistake).

^ permalink raw reply

* Re: Undocumented long options
From: Junio C Hamano @ 2006-12-20 20:06 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Jakub Narebski, git
In-Reply-To: <Pine.LNX.4.63.0612201716240.19693@wbgn013.biozentrum.uni-wuerzburg.de>

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

> On Wed, 20 Dec 2006, Jakub Narebski wrote:
>
>> Here is the list of undocumented long options I have found in git:
>> 
>>... a list omitted ...
>
> Matthew  24:46
>
> Hth,
> Dscho

Or perhaps a patch with Matthew 7:7?

^ permalink raw reply

* Re: [PATCH] revision: add --no-full-diff command line option
From: Junio C Hamano @ 2006-12-20 19:55 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20061220084107.GA6895@coredump.intra.peff.net>

Jeff King <peff@peff.net> writes:

> Signed-off-by: Jeff King <peff@peff.net>
> ---
> On Wed, Dec 20, 2006 at 12:14:14AM -0800, Junio C Hamano wrote:
>
>> > I use --full-diff all the time, so this should save some typing. I can't
>> > think of a time when I wouldn't want it on, but if there is, we probably
>> > need a --no-full-diff.
>> 
>> Absolutely.
>
> I took this to mean "absolutely we need --no-full-diff." :)

Modulo s/\.$/, if we were to do log.fulldiff/, yes.

> I note that --full-diff sets rev->diff = 1. The log.fulldiff config
> option does not, and nor does --no-full-diff unset it. However, I'm not
> sure it makes sense to set it. Doing "git-log --full-diff" outputs an
> extra line (separating the diff from the commit log) but since we
> haven't told it any type of diff to output, the diff is blank. And if we
> had told it a type, then that would have turned on rev->diff. So I don't
> see a point in setting it.

I need to think about this one.

^ permalink raw reply

* Re: [RFC/PATCH] Implement poor-man's submodule support in pre-commit hook
From: Junio C Hamano @ 2006-12-20 19:37 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git
In-Reply-To: <200612200901.30584.andyparkins@gmail.com>

Andy Parkins <andyparkins@gmail.com> writes:

> Problems:
>  - git-prune in the submodule could destroy supermodule-referenced
>    commits
>  - no checkout support
>  - no merge support (other than what git provides for the .gitmodule
>    file)
>  - no check for dirty submodule before commit
>
> Signed-off-by: Andy Parkins <andyparkins@gmail.com>

I do not think these are insurmountable.

As you fix them and enhance the support, I suspect you would
want a separate command to manage .gitmodule file and submodules
referenced by it.  I think it would be better to keep the patch
to the template to the minimum (for example, run "git submodule
update" if there is .gitmodules file at the toplevel), and
implement the body of the processing in "git-submodule.sh", or
something like that.

^ permalink raw reply

* Re: [PATCH 2/3] Add a test for git-rerere
From: Junio C Hamano @ 2006-12-20 18:37 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0612201737190.19693@wbgn013.biozentrum.uni-wuerzburg.de>

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

> +cat > a1 << EOF
> +Whether 'tis nobler in the mind to suffer
> +The slings and arrows of outrageous fortune,
> +Or to take arms against a sea of troubles,
> +And by opposing end them? To die: to sleep;
> +No more; and by a sleep to say we end
> +The heart-ache and the thousand natural shocks
> +That flesh is heir to, 'tis a consummation
> +Devoutly to be wish'd.
> +EOF

This is out of copyright protection long time ago, so it would
be fine to use in example ;-).

> +sha1=4f58849a60b4f969a2848966b6d02893b783e8fb
> +rr=.git/rr-cache/$sha1
> +test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
> +
> +test_expect_success 'no postimage or thisimage yet' \
> +	"test ! -f $rr/postimage -a ! -f $rr/thisimage"

I am worried that this test specifies the behaviour a bit too
precisely.  It is not t0000 basic where we want bit-for-bit
match with the expected result.  Wouldn't this test break when
you further improve xdl_merge, for example?

> +rm $rr/postimage
> +echo -ne "$sha1\ta1\0" > .git/rr-cache/MERGE_RR

Hmmmmmm.  I've stayed away from "echo -e" so far...

> +sha2=4000000000000000000000000000000000000000
> +rr2=.git/rr-cache/$sha2
> +mkdir $rr2
> +echo Hello > $rr2/preimage

Collisions are not so likely and perhaps we do not care.

> +case "$(date -d @11111111 +%s 2>/dev/null)" in
> +[1-9]*)
> +	# it is a recent GNU date. good.
> +	now=$(date +%s)
> +	let almost_15_days_ago=$now+60-15*86400
> +	let just_over_15_days_ago=$now-1-15*86400
> +	let almost_60_days_ago=$now+60-60*86400
> +	let just_over_60_days_ago=$now-1-60*86400

Hmmmmm.  I've stayed away from "let" so far as well...

^ permalink raw reply

* [PATCH] clarify some error messages wrt unknown object types
From: Nicolas Pitre @ 2006-12-20 18:34 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

If ever new object types are added for future extensions then better 
have current git version report them as "unknown" instead of 
"corrupted".

Signed-off-by: Nicolas Pitre <nico@cam.org>

---

diff --git a/index-pack.c b/index-pack.c
index 6d6c92b..35be3e9 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -268,7 +268,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
 	case OBJ_TAG:
 		break;
 	default:
-		bad_object(obj->offset, "bad object type %d", obj->type);
+		bad_object(obj->offset, "unknown object type %d", obj->type);
 	}
 	obj->hdr_size = consumed_bytes - obj->offset;
 
diff --git a/sha1_file.c b/sha1_file.c
index 63f416b..1c4df5b 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -1013,7 +1013,7 @@ void packed_object_info_detail(struct packed_git *p,
 	for (;;) {
 		switch (kind) {
 		default:
-			die("corrupted pack file %s containing object of kind %d",
+			die("pack %s contains unknown object type %d",
 			    p->pack_name, kind);
 		case OBJ_COMMIT:
 		case OBJ_TREE:
@@ -1063,7 +1063,7 @@ static int packed_object_info(struct packed_git *p, unsigned long offset,
 		strcpy(type, type_names[kind]);
 		break;
 	default:
-		die("corrupted pack file %s containing object of kind %d",
+		die("pack %s contains unknown object type %d",
 		    p->pack_name, kind);
 	}

^ permalink raw reply related

* Re: [PATCH] hooks/pre-commit: add example to add Signed-off-by line to message
From: Junio C Hamano @ 2006-12-20 17:44 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0612201835570.19693@wbgn013.biozentrum.uni-wuerzburg.de>

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

>> Why SQUASH_MSG?  Doesn't it confuse git-explain when it wants to
>> detect that you are in the middle of a squash merge?
>
> Yes, it confuses git-explain. Which did not existed when I concocted the 
> first (broken) version of this patch. There are only two ways to give 
> commit message templates AFAICT: misusing SQUASH_MSG and misusing 
> MERGE_MSG.

I wonder...

# An example hook script to check the commit log message.
# Called by git-commit with one argument, the name of the file
# that has the commit message.  The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit.  The hook is allowed to edit the commit message file.


^ permalink raw reply

* Re: [PATCH] hooks/pre-commit: add example to add Signed-off-by line to message
From: Johannes Schindelin @ 2006-12-20 17:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmz5ifpbv.fsf@assigned-by-dhcp.cox.net>

Hi,

On Wed, 20 Dec 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > Hi,
> >
> > On Wed, 20 Dec 2006, Andy Parkins wrote:
> >
> >> Signed-off-by: Andy Parkins <andyparkins@gmail.com>
> >
> > Acked-by: Johannes E. Schindelin <johannes.schindelin@gmx.de>
> >
> > Ciao,
> > Dscho
> 
> Why SQUASH_MSG?  Doesn't it confuse git-explain when it wants to
> detect that you are in the middle of a squash merge?

Yes, it confuses git-explain. Which did not existed when I concocted the 
first (broken) version of this patch. There are only two ways to give 
commit message templates AFAICT: misusing SQUASH_MSG and misusing 
MERGE_MSG.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH] hooks/pre-commit: add example to add Signed-off-by line to message
From: Junio C Hamano @ 2006-12-20 17:29 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.63.0612201717490.19693@wbgn013.biozentrum.uni-wuerzburg.de>

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

> Hi,
>
> On Wed, 20 Dec 2006, Andy Parkins wrote:
>
>> Signed-off-by: Andy Parkins <andyparkins@gmail.com>
>
> Acked-by: Johannes E. Schindelin <johannes.schindelin@gmx.de>
>
> Ciao,
> Dscho

Why SQUASH_MSG?  Doesn't it confuse git-explain when it wants to
detect that you are in the middle of a squash merge?

^ permalink raw reply

* [PATCH 3/3] Make git-rerere a builtin
From: Johannes Schindelin @ 2006-12-20 16:39 UTC (permalink / raw)
  To: git, junkio


The perl version used modules which are non-standard in some setups.
This patch brings the full power of rerere to a wider audience.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---

	If this is not liked, at least we have a test now. And I can use 
	it on all my machines.

 Makefile         |    2 +-
 builtin-rerere.c |  407 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 builtin.h        |    1 +
 git-rerere.perl  |  284 -------------------------------------
 git.c            |    1 +
 5 files changed, 410 insertions(+), 285 deletions(-)

diff --git a/Makefile b/Makefile
index 2c19c4d..6ce3ada 100644
--- a/Makefile
+++ b/Makefile
@@ -179,7 +179,6 @@ SCRIPT_SH = \
 SCRIPT_PERL = \
 	git-add--interactive.perl \
 	git-archimport.perl git-cvsimport.perl git-relink.perl \
-	git-rerere.perl \
 	git-cvsserver.perl \
 	git-svnimport.perl git-cvsexportcommit.perl \
 	git-send-email.perl git-svn.perl
@@ -294,6 +293,7 @@ BUILTIN_OBJS = \
 	builtin-push.o \
 	builtin-read-tree.o \
 	builtin-repo-config.o \
+	builtin-rerere.o \
 	builtin-rev-list.o \
 	builtin-rev-parse.o \
 	builtin-rm.o \
diff --git a/builtin-rerere.c b/builtin-rerere.c
new file mode 100644
index 0000000..191aeec
--- /dev/null
+++ b/builtin-rerere.c
@@ -0,0 +1,407 @@
+#include "cache.h"
+#include "path-list.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;
+
+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 = xstrdup(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;
+		write(out_fd, rr->items[i].util, 40);
+		write(out_fd, "\t", 1);
+		write(out_fd, path, strlen(path) + 1);
+	}
+	close(out_fd);
+	return commit_lock_file(&write_lock);
+}
+
+struct buffer {
+	char *ptr;
+	int nr, alloc;
+};
+
+static void append_line(struct buffer *buffer, const char *line)
+{
+	int len = strlen(line);
+
+	if (buffer->nr + len > buffer->alloc) {
+		buffer->alloc = alloc_nr(buffer->nr + len);
+		buffer->ptr = xrealloc(buffer->ptr, buffer->alloc);
+	}
+	memcpy(buffer->ptr + buffer->nr, line, len);
+	buffer->nr += len;
+}
+
+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 buffer minus = { NULL, 0, 0 }, plus = { NULL, 0, 0 };
+	struct buffer *one = &minus, *two = &plus;
+	FILE *f = fopen(path, "r");
+	FILE *out;
+
+	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);
+		}
+	} else
+		out = NULL;
+
+	if (sha1)
+		SHA1_Init(&ctx);
+
+	while (fgets(buf, sizeof(buf), f)) {
+		if (!strncmp("<<<<<<< ", buf, 8))
+			hunk = 1;
+		else if (!strncmp("=======", buf, 7))
+			hunk = 2;
+		else if (!strncmp(">>>>>>> ", buf, 8)) {
+			hunk_no++;
+			hunk = 0;
+			if (memcmp(one->ptr, two->ptr, one->nr < two->nr ?
+						one->nr : two->nr) > 0) {
+				struct buffer *swap = one;
+				one = two;
+				two = swap;
+			}
+			if (out) {
+				fputs("<<<<<<<\n", out);
+				fwrite(one->ptr, one->nr, 1, out);
+				fputs("=======\n", out);
+				fwrite(two->ptr, two->nr, 1, out);
+				fputs(">>>>>>>\n", out);
+			}
+			if (sha1) {
+				SHA1_Update(&ctx, one->ptr, one->nr);
+				SHA1_Update(&ctx, "\0", 1);
+				SHA1_Update(&ctx, two->ptr, two->nr);
+				SHA1_Update(&ctx, "\0", 1);
+			}
+		} else if (hunk == 1)
+			append_line(one, buf);
+		else if (hunk == 2)
+			append_line(two, buf);
+		else if (out)
+			fputs(buf, out);
+	}
+
+	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 + 2 < active_nr; i++) {
+		struct cache_entry *e1 = active_cache[i];
+		struct cache_entry *e2 = active_cache[i + 1];
+		struct cache_entry *e3 = active_cache[i + 2];
+		if (ce_stage(e1) == 1 && ce_stage(e2) == 2 &&
+				ce_stage(e3) == 3 && ce_same_name(e1, e2) &&
+				ce_same_name(e1, e3)) {
+			path_list_insert((const char *)e1->name, conflict);
+			i += 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"));
+	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++)
+		write(1, ptr[i].ptr, ptr[i].size);
+	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;
+	xecfg.ctxlen = 3;
+	xecfg.flags = 0;
+	ecb.outf = outf;
+	xdl_diff(&minus, &plus, &xpp, &xecfg, &ecb);
+
+	free(minus.ptr);
+	free(plus.ptr);
+	return 0;
+}
+
+static int copy_file(const char *src, const char *dest)
+{
+	FILE *in, *out;
+	char buffer[32768];
+	int count;
+
+	if (!(in = fopen(src, "r")))
+		return error("Could not open %s", src);
+	if (!(out = fopen(dest, "w")))
+		return error("Could not open %s", dest);
+	while ((count = fread(buffer, 1, sizeof(buffer), in)))
+		fwrite(buffer, 1, count, out);
+	fclose(in);
+	fclose(out);
+	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(path, rr_path(name, "postimage"));
+tail_optimization:
+		if (i < rr->nr - 1) {
+			memmove(rr->items + i,
+					rr->items + i + 1,
+					rr->nr - i - 1);
+		}
+		rr->nr--;
+		i--;
+	}
+
+	return write_rr(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 = -1;
+	struct stat st;
+
+	if (stat(git_path("rr-cache"), &st) || !S_ISDIR(st.st_mode))
+		return 0;
+
+	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);
+
+	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 (!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/builtin.h b/builtin.h
index 08519e7..8ffd8b2 100644
--- a/builtin.h
+++ b/builtin.h
@@ -52,6 +52,7 @@ extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
 extern int cmd_push(int argc, const char **argv, const char *prefix);
 extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_repo_config(int argc, const char **argv, const char *prefix);
+extern int cmd_rerere(int argc, const char **argv, const char *prefix);
 extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
 extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
 extern int cmd_rm(int argc, const char **argv, const char *prefix);
diff --git a/git-rerere.perl b/git-rerere.perl
deleted file mode 100755
index 4f69209..0000000
--- a/git-rerere.perl
+++ /dev/null
@@ -1,284 +0,0 @@
-#!/usr/bin/perl
-#
-# REuse REcorded REsolve.  This tool records a conflicted automerge
-# result and its hand resolution, and helps to resolve future
-# automerge that results in the same conflict.
-#
-# To enable this feature, create a directory 'rr-cache' under your
-# .git/ directory.
-
-use Digest;
-use File::Path;
-use File::Copy;
-
-my $git_dir = $::ENV{GIT_DIR} || ".git";
-my $rr_dir = "$git_dir/rr-cache";
-my $merge_rr = "$git_dir/rr-cache/MERGE_RR";
-
-my %merge_rr = ();
-
-sub read_rr {
-	if (!-f $merge_rr) {
-		%merge_rr = ();
-		return;
-	}
-	my $in;
-	local $/ = "\0";
-	open $in, "<$merge_rr" or die "$!: $merge_rr";
-	while (<$in>) {
-		chomp;
-		my ($name, $path) = /^([0-9a-f]{40})\t(.*)$/s;
-		$merge_rr{$path} = $name;
-	}
-	close $in;
-}
-
-sub write_rr {
-	my $out;
-	open $out, ">$merge_rr" or die "$!: $merge_rr";
-	for my $path (sort keys %merge_rr) {
-		my $name = $merge_rr{$path};
-		print $out "$name\t$path\0";
-	}
-	close $out;
-}
-
-sub compute_conflict_name {
-	my ($path) = @_;
-	my @side = ();
-	my $in;
-	open $in, "<$path"  or die "$!: $path";
-
-	my $sha1 = Digest->new("SHA-1");
-	my $hunk = 0;
-	while (<$in>) {
-		if (/^<<<<<<< .*/) {
-			$hunk++;
-			@side = ([], undef);
-		}
-		elsif (/^=======$/) {
-			$side[1] = [];
-		}
-		elsif (/^>>>>>>> .*/) {
-			my ($one, $two);
-			$one = join('', @{$side[0]});
-			$two = join('', @{$side[1]});
-			if ($two le $one) {
-				($one, $two) = ($two, $one);
-			}
-			$sha1->add($one);
-			$sha1->add("\0");
-			$sha1->add($two);
-			$sha1->add("\0");
-			@side = ();
-		}
-		elsif (@side == 0) {
-			next;
-		}
-		elsif (defined $side[1]) {
-			push @{$side[1]}, $_;
-		}
-		else {
-			push @{$side[0]}, $_;
-		}
-	}
-	close $in;
-	return ($sha1->hexdigest, $hunk);
-}
-
-sub record_preimage {
-	my ($path, $name) = @_;
-	my @side = ();
-	my ($in, $out);
-	open $in, "<$path"  or die "$!: $path";
-	open $out, ">$name" or die "$!: $name";
-
-	while (<$in>) {
-		if (/^<<<<<<< .*/) {
-			@side = ([], undef);
-		}
-		elsif (/^=======$/) {
-			$side[1] = [];
-		}
-		elsif (/^>>>>>>> .*/) {
-			my ($one, $two);
-			$one = join('', @{$side[0]});
-			$two = join('', @{$side[1]});
-			if ($two le $one) {
-				($one, $two) = ($two, $one);
-			}
-			print $out "<<<<<<<\n";
-			print $out $one;
-			print $out "=======\n";
-			print $out $two;
-			print $out ">>>>>>>\n";
-			@side = ();
-		}
-		elsif (@side == 0) {
-			print $out $_;
-		}
-		elsif (defined $side[1]) {
-			push @{$side[1]}, $_;
-		}
-		else {
-			push @{$side[0]}, $_;
-		}
-	}
-	close $out;
-	close $in;
-}
-
-sub find_conflict {
-	my $in;
-	local $/ = "\0";
-	my $pid = open($in, '-|');
-	die "$!" unless defined $pid;
-	if (!$pid) {
-		exec(qw(git ls-files -z -u)) or die "$!: ls-files";
-	}
-	my %path = ();
-	my @path = ();
-	while (<$in>) {
-		chomp;
-		my ($mode, $sha1, $stage, $path) =
-		    /^([0-7]+) ([0-9a-f]{40}) ([123])\t(.*)$/s;
-		$path{$path} |= (1 << $stage);
-	}
-	close $in;
-	while (my ($path, $status) = each %path) {
-		if ($status == 14) { push @path, $path; }
-	}
-	return @path;
-}
-
-sub merge {
-	my ($name, $path) = @_;
-	record_preimage($path, "$rr_dir/$name/thisimage");
-	unless (system('git', 'merge-file', map { "$rr_dir/$name/${_}image" }
-		       qw(this pre post))) {
-		my $in;
-		open $in, "<$rr_dir/$name/thisimage" or
-		    die "$!: $name/thisimage";
-		my $out;
-		open $out, ">$path" or die "$!: $path";
-		while (<$in>) { print $out $_; }
-		close $in;
-		close $out;
-		return 1;
-	}
-	return 0;
-}
-
-sub garbage_collect_rerere {
-	# We should allow specifying these from the command line and
-	# that is why the caller gives @ARGV to us, but I am lazy.
-
-	my $cutoff_noresolve = 15; # two weeks
-	my $cutoff_resolve = 60; # two months
-	my @to_remove;
-	while (<$rr_dir/*/preimage>) {
-		my ($dir) = /^(.*)\/preimage$/;
-		my $cutoff = ((-f "$dir/postimage")
-			      ? $cutoff_resolve
-			      : $cutoff_noresolve);
-		my $age = -M "$_";
-		if ($cutoff <= $age) {
-			push @to_remove, $dir;
-		}
-	}
-	if (@to_remove) {
-		rmtree(\@to_remove);
-	}
-}
-
--d "$rr_dir" || exit(0);
-
-read_rr();
-
-if (@ARGV) {
-	my $arg = shift @ARGV;
-	if ($arg eq 'clear') {
-		for my $path (keys %merge_rr) {
-			my $name = $merge_rr{$path};
-			if (-d "$rr_dir/$name" &&
-			    ! -f "$rr_dir/$name/postimage") {
-				rmtree(["$rr_dir/$name"]);
-			}
-		}
-		unlink $merge_rr;
-	}
-	elsif ($arg eq 'status') {
-		for my $path (keys %merge_rr) {
-			print $path, "\n";
-		}
-	}
-	elsif ($arg eq 'diff') {
-		for my $path (keys %merge_rr) {
-			my $name = $merge_rr{$path};
-			system('diff', ((@ARGV == 0) ? ('-u') : @ARGV),
-				'-L', "a/$path", '-L', "b/$path",
-				"$rr_dir/$name/preimage", $path);
-		}
-	}
-	elsif ($arg eq 'gc') {
-		garbage_collect_rerere(@ARGV);
-	}
-	else {
-		die "$0 unknown command: $arg\n";
-	}
-	exit 0;
-}
-
-my %conflict = map { $_ => 1 } find_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 my $path (keys %conflict) {
-	# This path has conflict.  If it is not recorded yet,
-	# record the pre-image.
-	if (!exists $merge_rr{$path}) {
-		my ($name, $hunk) = compute_conflict_name($path);
-		next unless ($hunk);
-		$merge_rr{$path} = $name;
-		if (! -d "$rr_dir/$name") {
-			mkpath("$rr_dir/$name", 0, 0777);
-			print STDERR "Recorded preimage for '$path'\n";
-			record_preimage($path, "$rr_dir/$name/preimage");
-		}
-	}
-}
-
-# 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 my $path (keys %merge_rr) {
-	my $name = $merge_rr{$path};
-
-	# We could resolve this automatically if we have images.
-	if (-f "$rr_dir/$name/preimage" &&
-	    -f "$rr_dir/$name/postimage") {
-		if (merge($name, $path)) {
-			print STDERR "Resolved '$path' using previous resolution.\n";
-			# Then we do not have to worry about this path
-			# anymore.
-			delete $merge_rr{$path};
-			next;
-		}
-	}
-
-	# Let's see if we have resolved it.
-	(undef, my $hunk) = compute_conflict_name($path);
-	next if ($hunk);
-
-	print STDERR "Recorded resolution for '$path'.\n";
-	copy($path, "$rr_dir/$name/postimage");
-	# And we do not have to worry about this path anymore.
-	delete $merge_rr{$path};
-}
-
-# Write out the rest.
-write_rr();
diff --git a/git.c b/git.c
index 016ee8a..202f25d 100644
--- a/git.c
+++ b/git.c
@@ -257,6 +257,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
 		{ "push", cmd_push, RUN_SETUP },
 		{ "read-tree", cmd_read_tree, RUN_SETUP },
 		{ "repo-config", cmd_repo_config },
+		{ "rerere", cmd_rerere, RUN_SETUP },
 		{ "rev-list", cmd_rev_list, RUN_SETUP },
 		{ "rev-parse", cmd_rev_parse, RUN_SETUP },
 		{ "rm", cmd_rm, RUN_SETUP },
-- 
1.4.4.2.g35224

^ permalink raw reply related

* [PATCH 2/3] Add a test for git-rerere
From: Johannes Schindelin @ 2006-12-20 16:37 UTC (permalink / raw)
  To: git, junkio


Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
 t/t4200-rerere.sh |  154 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
new file mode 100644
index 0000000..263c3d4
--- /dev/null
+++ b/t/t4200-rerere.sh
@@ -0,0 +1,154 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Johannes E. Schindelin
+#
+
+test_description='git-rerere
+'
+
+. ./test-lib.sh
+
+cat > a1 << EOF
+Whether 'tis nobler in the mind to suffer
+The slings and arrows of outrageous fortune,
+Or to take arms against a sea of troubles,
+And by opposing end them? To die: to sleep;
+No more; and by a sleep to say we end
+The heart-ache and the thousand natural shocks
+That flesh is heir to, 'tis a consummation
+Devoutly to be wish'd.
+EOF
+
+git add a1
+git commit -q -a -m initial
+
+git checkout -b first
+cat >> a1 << EOF
+To die, to sleep;
+To sleep: perchance to dream: ay, there's the rub;
+For in that sleep of death what dreams may come
+When we have shuffled off this mortal coil,
+Must give us pause: there's the respect
+That makes calamity of so long life;
+EOF
+git commit -q -a -m first
+
+git checkout -b second master
+git show first:a1 | sed 's/To die, t/To die! T/' > a1
+git commit -q -a -m second
+
+# activate rerere
+mkdir .git/rr-cache
+
+test_expect_failure 'conflicting merge' 'git pull . first'
+
+sha1=4f58849a60b4f969a2848966b6d02893b783e8fb
+rr=.git/rr-cache/$sha1
+test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
+
+test_expect_success 'no postimage or thisimage yet' \
+	"test ! -f $rr/postimage -a ! -f $rr/thisimage"
+
+git show first:a1 > a1
+
+cat > expect << EOF
+--- a/a1
++++ b/a1
+@@ -6,11 +6,7 @@
+ The heart-ache and the thousand natural shocks
+ That flesh is heir to, 'tis a consummation
+ Devoutly to be wish'd.
+-<<<<<<<
+-To die! To sleep;
+-=======
+ To die, to sleep;
+->>>>>>>
+ To sleep: perchance to dream: ay, there's the rub;
+ For in that sleep of death what dreams may come
+ When we have shuffled off this mortal coil,
+EOF
+
+git rerere diff > out
+
+test_expect_success 'rerere diff' 'diff -u expect out'
+
+cat > expect << EOF
+a1
+EOF
+
+git rerere status > out
+
+test_expect_success 'rerere status' 'diff -u expect out'
+
+test_expect_success 'commit succeeds' \
+	"git commit -q -a -m 'prefer first over second'"
+
+test_expect_success 'recorded postimage' "test -f $rr/postimage"
+
+git checkout -b third master
+git show second^:a1 | sed 's/To die: t/To die! T/' > a1
+git commit -q -a -m third
+
+test_expect_failure 'another conflicting merge' 'git pull . first'
+
+git show first:a1 | sed 's/To die: t/To die! T/' > expect
+test_expect_success 'rerere kicked in' "! grep ======= a1"
+
+test_expect_success 'rerere prefers first change' 'diff -u a1 expect'
+
+rm $rr/postimage
+echo -ne "$sha1\ta1\0" > .git/rr-cache/MERGE_RR
+
+test_expect_success 'rerere clear' 'git rerere clear'
+
+test_expect_success 'clear removed the directory' "test ! -d $rr"
+
+mkdir $rr
+echo Hello > $rr/preimage
+echo World > $rr/postimage
+
+sha2=4000000000000000000000000000000000000000
+rr2=.git/rr-cache/$sha2
+mkdir $rr2
+echo Hello > $rr2/preimage
+
+case "$(date -d @11111111 +%s 2>/dev/null)" in
+[1-9]*)
+	# it is a recent GNU date. good.
+	now=$(date +%s)
+	let almost_15_days_ago=$now+60-15*86400
+	let just_over_15_days_ago=$now-1-15*86400
+	let almost_60_days_ago=$now+60-60*86400
+	let just_over_60_days_ago=$now-1-60*86400
+	predate1="$(date -d "@$almost_60_days_ago" +%c)"
+	predate2="$(date -d "@$almost_15_days_ago" +%c)"
+	postdate1="$(date -d "@$just_over_60_days_ago" +%c)"
+	postdate2="$(date -d "@$just_over_15_days_ago" +%c)"
+	;;
+*)
+	# it is not GNU date. oh, well.
+	predate1="$(date)"
+	predate2="$(date)"
+	postdate1='1 Oct 2006 00:00:00'
+	postdate2='1 Dec 2006 00:00:00'
+esac
+
+touch -m -d "$predate1" $rr/preimage
+touch -m -d "$predate2" $rr2/preimage
+
+test_expect_success 'garbage collection (part1)' 'git rerere gc'
+
+test_expect_success 'young records still live' \
+	"test -f $rr/preimage -a -f $rr2/preimage"
+
+touch -m -d "$postdate1" $rr/preimage
+touch -m -d "$postdate2" $rr2/preimage
+
+test_expect_success 'garbage collection (part2)' 'git rerere gc'
+
+test_expect_success 'old records rest in peace' \
+	"test ! -f $rr/preimage -a ! -f $rr2/preimage"
+
+test_done
+
+
-- 
1.4.4.2.g35224

^ permalink raw reply related

* [PATCH 1/3] move read_mmfile() into xdiff-interface
From: Johannes Schindelin @ 2006-12-20 16:37 UTC (permalink / raw)
  To: git, junkio


read_file() was a useful function if you want to work with the xdiff stuff,
so it was renamed and put into a more central place.

Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
 builtin-merge-file.c |   20 ++------------------
 xdiff-interface.c    |   19 +++++++++++++++++++
 xdiff-interface.h    |    1 +
 3 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/builtin-merge-file.c b/builtin-merge-file.c
index 6c4c3a3..9135773 100644
--- a/builtin-merge-file.c
+++ b/builtin-merge-file.c
@@ -1,26 +1,10 @@
 #include "cache.h"
 #include "xdiff/xdiff.h"
+#include "xdiff-interface.h"
 
 static const char merge_file_usage[] =
 "git merge-file [-p | --stdout] [-q | --quiet] [-L name1 [-L orig [-L name2]]] file1 orig_file file2";
 
-static int read_file(mmfile_t *ptr, const char *filename)
-{
-	struct stat st;
-	FILE *f;
-
-	if (stat(filename, &st))
-		return error("Could not stat %s", filename);
-	if ((f = fopen(filename, "rb")) == NULL)
-		return error("Could not open %s", filename);
-	ptr->ptr = xmalloc(st.st_size);
-	if (fread(ptr->ptr, st.st_size, 1, f) != 1)
-		return error("Could not read %s", filename);
-	fclose(f);
-	ptr->size = st.st_size;
-	return 0;
-}
-
 int cmd_merge_file(int argc, char **argv, char **envp)
 {
 	char *names[3];
@@ -53,7 +37,7 @@ int cmd_merge_file(int argc, char **argv, char **envp)
 		names[i] = argv[i + 1];
 
 	for (i = 0; i < 3; i++)
-		if (read_file(mmfs + i, argv[i + 1]))
+		if (read_mmfile(mmfs + i, argv[i + 1]))
 			return -1;
 
 	ret = xdl_merge(mmfs + 1, mmfs + 0, names[0], mmfs + 2, names[2],
diff --git a/xdiff-interface.c b/xdiff-interface.c
index 08602f5..6c1f99b 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -102,3 +102,22 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf)
 	}
 	return 0;
 }
+
+int read_mmfile(mmfile_t *ptr, const char *filename)
+{
+	struct stat st;
+	FILE *f;
+
+	if (stat(filename, &st))
+		return error("Could not stat %s", filename);
+	if ((f = fopen(filename, "rb")) == NULL)
+		return error("Could not open %s", filename);
+	ptr->ptr = xmalloc(st.st_size);
+	if (fread(ptr->ptr, st.st_size, 1, f) != 1)
+		return error("Could not read %s", filename);
+	fclose(f);
+	ptr->size = st.st_size;
+	return 0;
+}
+
+
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 1346908..1918808 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -17,5 +17,6 @@ int xdiff_outf(void *priv_, mmbuffer_t *mb, int nbuf);
 int parse_hunk_header(char *line, int len,
 		      int *ob, int *on,
 		      int *nb, int *nn);
+int read_mmfile(mmfile_t *ptr, const char *filename);
 
 #endif
-- 
1.4.4.2.g35224

^ permalink raw reply related

* Re: [PATCH] hooks/pre-commit: add example to add Signed-off-by line to message
From: Johannes Schindelin @ 2006-12-20 16:18 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git
In-Reply-To: <200612201604.12498.andyparkins@gmail.com>

Hi,

On Wed, 20 Dec 2006, Andy Parkins wrote:

> Signed-off-by: Andy Parkins <andyparkins@gmail.com>

Acked-by: Johannes E. Schindelin <johannes.schindelin@gmx.de>

Ciao,
Dscho

^ permalink raw reply

* Re: Undocumented long options
From: Johannes Schindelin @ 2006-12-20 16:17 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git
In-Reply-To: <200612201707.00346.jnareb@gmail.com>

Hi,

On Wed, 20 Dec 2006, Jakub Narebski wrote:

> Here is the list of undocumented long options I have found in git:
> 
> * --abbrev-commit (in revision.c) - I'm not sure _where_ it should
>   be added, as it afects most visible I think git-log, git-show,
>   git-rev-list. Implies --abbrev.
> * --exclude-existing of git-show-ref; new option
> * --reflog of git-show-branch, similar to --no-name and --ahs1-name
>   options I think; new option
> * --timestamp option of git-rev-list. Bit strange, but perhaps useful.
>   I don't quite know what it does.
> * --full-history option of git-rev-list (--full-diff just got
>   documented). I think it would be nice to have described while at it
>   git history simplification, and how options like --full-history, path
>   limiter, --parents interacts with it.
> * --trivial option of git-read-tree. It looks like opposite of
>   (documented) --aggresive option, but source indicates that it might
>   be not exactly opposite.
> * --thin and --no-thin of send-pack. It is plumbing option, but even
>   plumbing should be documented. Not sure which commands are affected by
>   this.

Matthew  24:46

Hth,
Dscho

^ permalink raw reply

* Re: [RFC/PATCH] Implement poor-man's submodule support using commit hooks
From: Johannes Schindelin @ 2006-12-20 16:09 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git
In-Reply-To: <200612201440.41784.andyparkins@gmail.com>

Hi,

On Wed, 20 Dec 2006, Andy Parkins wrote:

>  Before now, I've replaced files in C by doing
> 
>  fd_old = open( "someexistingfile" );
>  unlink( "someexistingfile" );
>  fd_new = open( "someexistingfile" );

Lucky you! Obiously you are not stuck in the 10th circle called Windows.

Ciao,

^ permalink raw reply

* Undocumented long options
From: Jakub Narebski @ 2006-12-20 16:06 UTC (permalink / raw)
  To: git

Here is the list of undocumented long options I have found in git:

* --abbrev-commit (in revision.c) - I'm not sure _where_ it should
  be added, as it afects most visible I think git-log, git-show,
  git-rev-list. Implies --abbrev.
* --exclude-existing of git-show-ref; new option
* --reflog of git-show-branch, similar to --no-name and --ahs1-name
  options I think; new option
* --timestamp option of git-rev-list. Bit strange, but perhaps useful.
  I don't quite know what it does.
* --full-history option of git-rev-list (--full-diff just got
  documented). I think it would be nice to have described while at it
  git history simplification, and how options like --full-history, path
  limiter, --parents interacts with it.
* --trivial option of git-read-tree. It looks like opposite of
  (documented) --aggresive option, but source indicates that it might
  be not exactly opposite.
* --thin and --no-thin of send-pack. It is plumbing option, but even
  plumbing should be documented. Not sure which commands are affected by
  this.

-- 
Jakub Narebski

^ permalink raw reply

* [PATCH] hooks/pre-commit: add example to add Signed-off-by line to message
From: Andy Parkins @ 2006-12-20 16:04 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.63.0611291219190.30004@wbgn013.biozentrum.uni-wuerzburg.de>

Based on Johannes Schindelin's earlier patch to perform the same
function.

The call to git-sh-setup was causing "Not a git repository" errors after
the pre-commit script had run.  I removed the call and used
$(git-rev-parse --git-dir) instead, which seems to have fixed the
problem.

Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
 templates/hooks--pre-commit |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit
index 723a9ef..87d9ccc 100644
--- a/templates/hooks--pre-commit
+++ b/templates/hooks--pre-commit
@@ -7,6 +7,11 @@
 #
 # To enable this hook, make this file executable.
 
+# Uncomment the below to add a Signed-off-by line to the message.
+#git var GIT_AUTHOR_IDENT | \
+#sed -n "s/^\(.*\) [0-9]\+ [-+][0-9]\+$/Signed-off-by: \1/p" \
+# >> $(git-rev-parse --git-dir)/SQUASH_MSG
+
 # This is slightly modified from Andrew Morton's Perfect Patch.
 # Lines you introduce should not have trailing whitespace.
 # Also check for an indentation that has SP before a TAB.
-- 
1.4.4.2.g120e3

^ permalink raw reply related

* Re: [PATCH] hooks/pre-commit: add example to add Signed-off-by line to message
From: Andy Parkins @ 2006-12-20 15:54 UTC (permalink / raw)
  To: git
In-Reply-To: <Pine.LNX.4.63.0611291219190.30004@wbgn013.biozentrum.uni-wuerzburg.de>

On Wednesday 2006 November 29 11:20, Johannes Schindelin wrote:

> +# . git-sh-setup
> +# git var GIT_AUTHOR_IDENT | \
> +# sed -n "s/^\(.*\) [0-9]\+ [-+][0-9]\+$/Signed-off-by: \1/p" \
> +# > $GIT_DIR/SQUASH_MSG

I've been using this; and very useful it is too.  However, I just noticed that 
I was getting "Not a git repository" errors when I tried to commit in a 
subdirectory.  I traced the problem to my use of this fragment.  It seems 
that calling git-sh-setup inside the pre-commit hook was changing GIT_DIR 
(don't know why).  When I changed this to

git var GIT_AUTHOR_IDENT | \
sed -n "s/^\(.*\) [0-9]\+ [-+][0-9]\+$/Signed-off-by: \1/p" \
 >> $(git-rev-parse --git-dir)/SQUASH_MSG

It worked correctly again.


Andy


-- 
Dr Andy Parkins, M Eng (hons), MIEE

^ permalink raw reply

* Re: [RFC/PATCH] Implement poor-man's submodule support using  commit hooks
From: Randal L. Schwartz @ 2006-12-20 15:42 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git
In-Reply-To: <200612201440.41784.andyparkins@gmail.com>

>>>>> "Andy" == Andy Parkins <andyparkins@gmail.com> writes:

Andy>  fd_old = open( "someexistingfile" );
Andy>  unlink( "someexistingfile" );
Andy>  fd_new = open( "someexistingfile" );

This is dangerous if the process aborts suddenly.

Might be better to do this:

mumble_command < thefile > thefile.$$
mv thefile.$$ thefile

The second move will be atomic.  The only problem will be if the process
aborts, which will leave stale temp files around.

-- 
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn@stonehenge.com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.

^ permalink raw reply

* Re: [RFC/PATCH] Implement poor-man's submodule support using commit hooks
From: Martin Waitz @ 2006-12-20 15:44 UTC (permalink / raw)
  To: Andy Parkins; +Cc: git
In-Reply-To: <200612201435.49685.andyparkins@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 496 bytes --]

hoi :)

On Wed, Dec 20, 2006 at 02:35:48PM +0000, Andy Parkins wrote:
> I had a look at that; and my previous objection still applies: it blends two 
> repositories.  I'd rather they were separate.

yes, but one can see what is needed and where the real problems are.

And I really think we should only start adding submodule code to
mainline git when we are sure that we found an approach where we can see
that it works and that we don't have to change it later.

-- 
Martin Waitz

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: Corrupt pack file using older versions of git on a newer repo..
From: Nicolas Pitre @ 2006-12-20 15:30 UTC (permalink / raw)
  To: Sean; +Cc: git
In-Reply-To: <BAYC1-PASMTP11ADF6C984028A9DED853FAECF0@CEZ.ICE>

On Wed, 20 Dec 2006, Sean wrote:

> 
> This is probably expected behavior, but when bisecting another Git
> issue[1], i found that after a fresh clone of the git repository using
> 1.4.4.2 I got the following corrupt pack file when accessing that repo
> with an old version of git:
> 
> $ git --version
> git version 1.4.2
> 
> $ git log
> fatal: corrupted pack file .git/objects/pack/pack-d75f6a8307f8d8ce9727fe27107486839c54aef6.pack

To make that repository accessible with older git versions simply run 
git-repack -a -d using version 1.4.4.2.

The clone with version 1.4.4.2 added OBJ_OFS_DELTA objects to the pack 
which older git versions don't know about.  Those objects are used for 
pack transport when both ends know about them as they take less space.  
But the repack doesn't use them by default so a full repack will get rid 
of them automatically.



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox