Git development
 help / color / mirror / Atom feed
* cogito-0.10 broken for cg-commit < logmessagefile
From: Russell King @ 2005-06-08 13:46 UTC (permalink / raw)
  To: git

The command in the subject prepends the log message with a blank line.
This ain't good because it messes up commit messages as per Linus'
requirements (the first line must be a summary.)

Is this known about / has this been fixed in 0.11 ?

(It's presently a blocking bug...)

-- 
Russell King


^ permalink raw reply

* [PATCH] three --merge-order bug fixes
From: Jon Seymour @ 2005-06-08 14:37 UTC (permalink / raw)
  To: git; +Cc: torvalds, jon.seymour

[PATCH] three --merge-order bug fixes

This patch fixes three bugs in --merge-order support
    * mark_ancestors_uninteresting was unnecessarily exponential which 
      caused a problem when a commit with no parents was merged near the 
      head of something like the linux kernel
    * removed a spurious statement from find_base which wasn't
      apparently causing problems now, but wasn't correct either.
    * removed an unnecessarily strict check from find_base_for_list
      that causes a problem if git-rev-list commit ^parent-of-commit 
      is specified.
    * added some unit tests which were accidentally omitted from
      original merge-order patch

The fix to mark_ancestors_uninteresting isn't an optimal fix - a full
graph scan will still be performed in this case even though it is
not strictly required. However, a full graph scan is linear 
and still no worse than git-rev-list HEAD which runs in less than 2
seconds on a warm cache.

Signed-off-by: Jon Seymour <jon.seymour@gmail.com>

Diverged from fcbfd5a6b2c87dc5ecd1d6c4e94c56eebf44c8ac by Linus Torvalds <torvalds@ppc970.osdl.org>
---
diff --git a/epoch.c b/epoch.c
--- a/epoch.c
+++ b/epoch.c
@@ -229,7 +229,7 @@ static int find_base_for_list(struct com
 
 		struct commit *item = list->item;
 
-		if (item->object.util || (item->object.flags & UNINTERESTING)) {
+		if (item->object.util) {
 			die("%s:%d:%s: logic error: this should not have happened - commit %s\n",
 			    __FILE__, __LINE__, __FUNCTION__, sha1_to_hex(item->object.sha1));
 		}
@@ -323,7 +323,6 @@ static int find_base(struct commit *head
 	struct commit_list *pending = NULL;
 	struct commit_list *next;
 
-	commit_list_insert(head, &pending);
 	for (next = head->parents; next; next = next->next) {
 		commit_list_insert(next->item, &pending);
 	}
@@ -418,8 +417,8 @@ static void mark_ancestors_uninteresting
 	int boundary = flags & BOUNDARY;
 	int uninteresting = flags & UNINTERESTING;
 
+	commit->object.flags |= UNINTERESTING;
 	if (uninteresting || boundary || !visited) {
-		commit->object.flags |= UNINTERESTING;
 		return;
 
 		// we only need to recurse if
diff --git a/t/t6001-rev-list-merge-order.sh b/t/t6001-rev-list-merge-order.sh
new file mode 100644
--- /dev/null
+++ b/t/t6001-rev-list-merge-order.sh
@@ -0,0 +1,175 @@
+#!/bin/sh
+#
+# Copyright (c) 2005 Jon Seymour
+#
+
+test_description='Test rev-list --merge-order
+'
+. ./test-lib.sh
+
+function do_commit
+{
+    git-commit-tree "$@" </dev/null
+}
+
+function check_adjacency
+{
+    read previous
+    echo "= $previous"
+    while read next
+    do
+        if ! (git-cat-file commit $previous | grep "^parent $next" >/dev/null)
+        then
+            echo "^ $next"
+        else
+            echo "| $next"
+        fi
+        previous=$next
+    done
+}
+
+function sed_script
+{
+   for c in root a0 a1 a2 a3 a4 b1 b2 b3 b4 c1 c2 c3 l0 l1 l2 l3 l4 l5
+   do
+       echo -n "s/${!c}/$c/;"
+   done
+}
+
+date >path0
+git-update-cache --add path0
+tree=$(git-write-tree)
+root=$(do_commit $tree 2>/dev/null)
+export GIT_COMMITTER_NAME=foobar  # to guarantee that the commit is different
+l0=$(do_commit $tree -p $root)
+l1=$(do_commit $tree -p $l0)
+l2=$(do_commit $tree -p $l1)
+a0=$(do_commit $tree -p $l2)
+a1=$(do_commit $tree -p $a0)
+export GIT_COMMITTER_NAME=foobar2 # to guarantee that the commit is different
+b1=$(do_commit $tree -p $a0)
+c1=$(do_commit $tree -p $b1)
+export GIT_COMMITTER_NAME=foobar3 # to guarantee that the commit is different
+b2=$(do_commit $tree -p $b1)
+b3=$(do_commit $tree -p $b2)
+c2=$(do_commit $tree -p $c1 -p $b2)
+c3=$(do_commit $tree -p $c2)
+a2=$(do_commit $tree -p $a1)
+a3=$(do_commit $tree -p $a2)
+b4=$(do_commit $tree -p $b3 -p $a3)
+a4=$(do_commit $tree -p $a3 -p $b4 -p $c3)
+l3=$(do_commit $tree -p $a4)
+l4=$(do_commit $tree -p $l3)
+l5=$(do_commit $tree -p $l4)
+echo $l5 > .git/HEAD
+
+git-rev-list --merge-order --show-breaks HEAD | sed "$(sed_script)" > actual-merge-order
+cat > expected-merge-order <<EOF
+= l5
+| l4
+| l3
+= a4
+| c3
+| c2
+| c1
+^ b4
+| b3
+| b2
+| b1
+^ a3
+| a2
+| a1
+= a0
+| l2
+| l1
+| l0
+= root
+EOF
+
+git-rev-list HEAD | check_adjacency | sed "$(sed_script)" > actual-default-order
+normal_adjacency_count=$(git-rev-list HEAD | check_adjacency | grep -c "\^" | tr -d ' ')
+merge_order_adjacency_count=$(git-rev-list --merge-order HEAD | check_adjacency | grep -c "\^" | tr -d ' ')
+
+test_expect_success 'Testing that the rev-list has correct number of entries' '[ $(git-rev-list HEAD | wc -l) -eq 19 ]'
+test_expect_success 'Testing that --merge-order produces the correct result' 'diff expected-merge-order actual-merge-order'
+test_expect_success 'Testing that --merge-order produces as many or fewer discontinuities' '[ $merge_order_adjacency_count -le $normal_adjacency_count ]'
+
+cat > expected-merge-order-1 <<EOF
+c3
+c2
+c1
+b3
+b2
+b1
+a3
+a2
+a1
+a0
+l2
+l1
+l0
+root
+EOF
+
+git-rev-list --merge-order $a3 $b3 $c3 | sed "$(sed_script)" > actual-merge-order-1
+test_expect_success 'Testing multiple heads' 'diff expected-merge-order-1 actual-merge-order-1'
+
+cat > expected-merge-order-2 <<EOF
+c3
+c2
+c1
+b3
+b2
+b1
+a3
+a2
+EOF
+
+git-rev-list --merge-order $a3 $b3 $c3 ^$a1 | sed "$(sed_script)" > actual-merge-order-2
+test_expect_success 'Testing stop' 'diff expected-merge-order-2 actual-merge-order-2'
+
+cat > expected-merge-order-3 <<EOF
+c3
+c2
+c1
+b3
+b2
+b1
+a3
+a2
+a1
+a0
+l2
+EOF
+
+git-rev-list --merge-order $a3 $b3 $c3 ^$l1 | sed "$(sed_script)" > actual-merge-order-3
+test_expect_success 'Testing stop in linear epoch' 'diff expected-merge-order-3 actual-merge-order-3'
+
+cat > expected-merge-order-4 <<EOF
+l5
+l4
+l3
+a4
+c3
+c2
+c1
+b4
+b3
+b2
+b1
+a3
+a2
+a1
+a0
+l2
+EOF
+
+git-rev-list --merge-order $l5 ^$l1 | sed "$(sed_script)" > actual-merge-order-4
+test_expect_success 'Testing start in linear epoch, stop after non-linear epoch' 'diff expected-merge-order-4 actual-merge-order-4'
+
+git-rev-list --merge-order $l5 $l5 ^$l1 2>/dev/null | sed "$(sed_script)" > actual-merge-order-5
+test_expect_success 'Testing duplicated start arguments' 'diff expected-merge-order-4 actual-merge-order-5'
+
+test_expect_success 'Testing exclusion near merge' 'git-rev-list --merge-order $a4 ^$c3 2>/dev/null'
+
+test_done

^ permalink raw reply

* Re: gitk-1.1 out
From: Linus Torvalds @ 2005-06-08 14:49 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <17053.35147.52729.794561@cargo.ozlabs.ibm.com>



On Wed, 1 Jun 2005, Paul Mackerras wrote:
> 
> * Commits that are pointed to by a tag in .git/refs/tags are now
>   marked with a little yellow "luggage label" shape attached to the
>   circle representing the commit.  The tag name is written on the
>   label.

Can you do the same for things in .git/refs/heads? Possibly using another 
color?

I realize that that may sound silly, but a tree that has many branches can 
validly be used with gitk with something like this:

	gitk $(ls .git/refs/heads)

and it results in gitk correctly showing all the different heads, but 
because they aren't marked in the output, it's almost impossible to 
understand what's up.

You can try it out with something like Jeff's tree at 

	rsync://rsync.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6.git/

if you want to, but the reason I noticed was that I was trying it out with
the result of "git cvsimport" in a tree that had branches. If it had had
flags for the branches, it would have been an _extremely_ nice
visualization tool, as it was it was just "cool, but I can't tell what
those different tips are" ;)

		Linus

^ permalink raw reply

* Re: [GIT PULL] ARM updates
From: Linus Torvalds @ 2005-06-08 15:15 UTC (permalink / raw)
  To: Russell King; +Cc: Andrew Morton, Git Mailing List
In-Reply-To: <20050608143549.GA7074@dyn-67.arm.linux.org.uk>



On Wed, 8 Jun 2005, Russell King wrote:
> 
> Please incorporate the latest ARM changes, which can be found at:
> 
> 	master.kernel.org:/home/rmk/linux-2.6-arm.git

Heh, this one showed a problem with some git-apply sanity checks (I use 
"git-apply --stat" to generate the diffstat). 

In particular:

> This will update the following files:
> 
>  arch/arm/mm/minicache.c                |   73 ------------------

You didn't actually delete the file, you made it be zero-sized. Which made 
the patch header be

  diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
  --- a/arch/arm/mm/minicache.c
  +++ b/arch/arm/mm/minicache.c
  @@ -1,73 +0,0 @@
  ...

and git-apply complains about the fact that the patch deletes the file,
but the file still exists (it can tell both from this: it sees that this
is not a "delete" event, since a "diff --git" would have had a "delete"
header line in it, but it also sees that it's a delete because the patch
has no result lines, ie the final "+0,0" means that there was nothing
left).

Now, git-apply shouldn't actually care _that_ deeply in general, but the 
reason I added that check was exactly because in Linux, I actually want 
zero-sized files to not exist, and it turns out that git-apply did catch 
it..

Anyway, I've made git-apply warn in a nice way (instead of claiming the 
patch is corrupt and exiting), but it did point out that you left 
minixache.c empty, not deleted.

In contrast, the "copypage-xscale.S" file really _was_ deleted by your 
changes, not just made empty.

Russell, do you know why you sometimes generate empty files, and sometimes 
delete them? If you use "patch", add the "-E" flag to it..

		Linus

^ permalink raw reply

* Re: git-rev-list --merge-order hangs
From: Radoslaw Szkodzinski @ 2005-06-08 15:28 UTC (permalink / raw)
  To: jon; +Cc: git
In-Reply-To: <2cfc4032050608020215152887@mail.gmail.com>

Jon Seymour wrote:

>Actually, one case that I may not have considered properly is a commit
>near the head that has no parents.
>
>      git-rev-list --parents v2.6.12-rc6-astorm1 ^v2.6.12-rc6
>
>should tell you if this case exists. Ideally such a case should not
>occur, but that isn't a logical certainity, so I should handle it
>better than I currently do.
>
>Please let me know if this may explain your case. 
>  
>
This just threw tons of SHA1 hashes at me without complaining.
I've also tried git-rev-list HEAD >/dev/null without any chage whatsoever.

The tree is not secret, You can try (very slow) rsync at:
rsync://astralstorm.servegame.com/linux-2.6-astorm

Just update latest linux-2.6 with it to save time.
(mine is up to commit 1d6757fbff5bc86e94e59ab0d7bdd7e71351d839)

AstralStorm

^ permalink raw reply

* Re: [PATCH] three --merge-order bug fixes
From: Radoslaw Szkodzinski @ 2005-06-08 16:04 UTC (permalink / raw)
  To: Jon Seymour; +Cc: git, torvalds
In-Reply-To: <20050608143741.30382.qmail@blackcubes.dyndns.org>

Jon Seymour wrote:

>[PATCH] three --merge-order bug fixes
>  
>
The patch fixes the problem I reported. Well done.
Please apply.

AstralStorm

^ permalink raw reply

* Re: cogito-0.10 broken for cg-commit < logmessagefile
From: Catalin Marinas @ 2005-06-08 16:28 UTC (permalink / raw)
  To: git
In-Reply-To: <20050608144632.A28042@flint.arm.linux.org.uk>

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

Russell King <rmk@arm.linux.org.uk> wrote:
> The command in the subject prepends the log message with a blank line.
> This ain't good because it messes up commit messages as per Linus'
> requirements (the first line must be a summary.)

The patch below should fix the problem. There is no point in writing
the status information in a file which is read from stdin.

-- 
Catalin


[-- Attachment #2: cogito-stdin.diff --]
[-- Type: text/plain, Size: 410 bytes --]

Fix the log file when read from stdin

Log messages read from stdin shouldn't have additional lines.

Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

diff --git a/cg-commit b/cg-commit
--- a/cg-commit
+++ b/cg-commit
@@ -215,7 +215,7 @@ if tty -s; then
 		fi
 	fi
 else
-	cat >>$LOGMSG2
+	cat >$LOGMSG2
 fi
 # Remove heading and trailing blank lines.
 grep -v ^CG: $LOGMSG2 | git-stripspace >$LOGMSG

^ permalink raw reply

* [WITHDRAW PATCH] Add support for --wrt-author, --author and --exclude-author switches to git-rev-list
From: Jon Seymour @ 2005-06-08 16:36 UTC (permalink / raw)
  To: git; +Cc: Linus Torvalds
In-Reply-To: <2cfc40320506080414303d6d7b@mail.gmail.com>

G'day Linus,

I'd like to  withdraw this patch until the --merge-order bug fix of my
earlier post is applied. The patch as it stands won't operate
correctly once that fix is applied, so I'll have to modify it. Also, I
want to rename the --exclude-author switch to --prune-at-author.

Regards,

jon.

^ permalink raw reply

* Re: Upstream merging and conflicts (was Re: Using cvs2git to track an external CVS project)
From: Linus Torvalds @ 2005-06-08 15:59 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Git Mailing List
In-Reply-To: <46a038f9050602135971ece082@mail.gmail.com>



On Fri, 3 Jun 2005, Martin Langhoff wrote:
> 
> I understand this is architected to _not_ support cherry picking in
> the darcs/arch sense and I think it's a good idea. But it seems than
> any non-trivial merge ends up being a completely manual process.

Yes, and right now that "manual" part is actualyl fairly high. I'll fix 
that thing up (today, I hope), making nontrivial merges much easier.

> So it seems to me that git is well suited for a set of closely related
> HEADs that are very aggressive in synching with each other. Synching
> work is pushed out to the peripheral branches -- a design decision I
> agree with -- but there's very little support to help me keep a
> peripheral branch in sync.

Well, there's asome support for keeping a peripheral branch in sync, but
part of it ends up having to try to just merge into it from the main
branch every once in a while.

It all really boils down to "merge often, merge small". Git encourages 
that behaviour. Git concentrates on trivial merges, because the git 
philosophy is that if you let two trees diverge too much, your problems 
are not with the merge, but with other things.

NOTE! This does _not_ mean that you can't do big changes. You can very
much do a branch that does _huge_ changes, and as long as that branch
keeps merging with the original, it should work out reasonably well. Every
merge "re-bases" the work, so you'll never have to merge old changes. You
may end up with a fair number of manual things to fix up each time (and
see my comment on the manual fixup problems right now), but at least the 
thing should hopefully be incremental.

But yeah, if you actually do major re-organization, then the system
absolutely needs tons more smarts in the automated parts, since right now
it has no automated merging for renames etc things (things it _could_
detect, but doesn't do). There's really several layers of merging you can
automate, and git right now only automates the very very lowest stuff.

In other words, it should be possible to make git do pretty well even for
complex branches, but no, right now the automated parts don't even try.  
And it's still _all_ geared towards development that ends up being merged
reasonably often - you can merge in one direction for a while to keep the
pain incremental, but yes, you do need to merge the other way
_eventually_.

> The assumption that those peripheral branches must be short-lived and
> discardable is valid for a limited set of cases -- very circumscribed
> to short-term dev work. As soon as a dev branch has to run a little
> longer, it cannot afford to not sync with the HEAD. Particularly, it
> cannot skip a _single_ patch coming from HEAD.

It's true that you can't skip patches, since a merge is always 
all-or-nothing, and the global history really requires that (in a very 
fundamental way). However, you _can_ merge from the HEAD, and then say 
"that patch is no longer relevant in this tree", and remove it. Then 
you'll never need to worry about that patch any more, because you've 
merged it and in your merged result, it no longer exists).

That said, I don't claim that this is what you always want to do. In fact,
we have this exact issue in the kernel, and I think it's a great thing to
use a combination of a patch-based system _and_ git. You use git for the
"core", you use the patch-based system for the more fluid stuff. In the
case of the kernel, the patch-based system that seems to be used the most
is "quilt", but that's a detail. The big issue is that git is simply part 
of a bigger process:

> I use peripheral branches to track versions of code in production,
> that may have different sets of patches applied. For that purpose,
> patch-based SCMs are quite helpful (you can ask what patch is applied
> where), but as Linus pointed out, they don't actually help convergence
> at all. Git pulls towards convergence like a demon AFAICS -- yet some
> primitive patch trading smarts would save a lot of effort at the
> borders of the dev network.

Yes. I think this is fundamental. "git" needs to converge. It's how git
works. git also "crystallizes" the history and makes it unbreakable.  
Both of these things are _wonderful_ for what they mean, but both of these
fundamental issues are _horrible_ for other reasons.

So it's not a one-size-fits-all. git is designed to work around the kind
of stuff I do - my job in many ways is exactly to "crystallize" the work
that happens around me. I'm the ugly speck of dirt around which a
beautiful snowflake forms.

But to get the pieces that crystallize to form, you need all those unruly 
patches floating around freely as a gas, and feeding the crystallization 
process. And git is not suitable _at_all_ for that phase.

So I don't think that you should necessarily think of git as "the" souce
control management in the big picture. It's how you handle _one_ phase of
development, and the constraints it puts on that phase are both wonderful
and horrible, and thus you really should see the git phase as being the
solid core, but no more.

So git (apart from the use of "ephemeral branches for testing") is _not_ 
very conductive to wild development. I think git is actually a wonderful 
way of doing the wild development too, but only in a microscopic sense: 
you can use git either for the "big picture" crystal, or you can use git 
for the "I want to keep track of what I did" on a small scale, but then in 
between those things you'd need to have a patch-manager or something.

In other words, I'd expect that a _lot_ of git usage is of the type:
 - clone a throw-away tree from the standard repositories
 - do random things in it, merge with the standard repo every once in a 
   while. This is the "little picture".
 - export the result as a patch when you're happy with it, and use 
   somethign else to keep track of the patch until it can be merged into 
   the "big picture".

So I don't think any development effort that is big enough necessarily 
wants to use git as the _only_ way of doing development and merging stuff. 
The kernel certainly does not. Not now, and not in the long run.

(We know about the long run, because these issues were largely trye of BK
too, although BK handled especially metadata merges much much better. But
even with BK, we always ended up having 50% or more of the actual
development end results going around as patches, and BK was really the way
to crystallize the end result. It shouldn't come as a surprise that git
does the same - git was designed not so much as a technical BK
replacement, but as a replacement for that _process_ we had for BK).

Final note: I do believe that the kernel is kind of strange. I doubt
anybody else ended up using BK the way we did, and I suspect _most_ BK
users used BK as a better CVS, where BK was the primary - and only - thing
that kept track of patches.

Whether the kernel model is applicable to anything else, I dunno. 

		Linus

^ permalink raw reply

* Re: [GIT PULL] ARM updates
From: Russell King @ 2005-06-08 16:06 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Andrew Morton, Git Mailing List
In-Reply-To: <Pine.LNX.4.58.0506080802150.2286@ppc970.osdl.org>

On Wed, Jun 08, 2005 at 08:15:09AM -0700, Linus Torvalds wrote:
> 
> 
> On Wed, 8 Jun 2005, Russell King wrote:
> > 
> > Please incorporate the latest ARM changes, which can be found at:
> > 
> > 	master.kernel.org:/home/rmk/linux-2.6-arm.git
> 
> Heh, this one showed a problem with some git-apply sanity checks (I use 
> "git-apply --stat" to generate the diffstat). 
> 
> In particular:
> 
> > This will update the following files:
> > 
> >  arch/arm/mm/minicache.c                |   73 ------------------
> 
> You didn't actually delete the file, you made it be zero-sized. Which made 
> the patch header be
> 
>   diff --git a/arch/arm/mm/minicache.c b/arch/arm/mm/minicache.c
>   --- a/arch/arm/mm/minicache.c
>   +++ b/arch/arm/mm/minicache.c
>   @@ -1,73 +0,0 @@
>   ...
> 
> and git-apply complains about the fact that the patch deletes the file,
> but the file still exists (it can tell both from this: it sees that this
> is not a "delete" event, since a "diff --git" would have had a "delete"
> header line in it, but it also sees that it's a delete because the patch
> has no result lines, ie the final "+0,0" means that there was nothing
> left).

Hey, it's my first time at using git directly rather than the currently
broken cogito - I had to do everything manually.  See my last message
to the git mailing list.

> In contrast, the "copypage-xscale.S" file really _was_ deleted by your 
> changes, not just made empty.

That's because I remembered that one was deleted.  This change was
something which had been lingering for about a week while someone
tested it, so of course I'd forget what was created and removed by
it.

-- 
Russell King


^ permalink raw reply

* [RFC] rename/rename conflicts: do they matter?
From: Junio C Hamano @ 2005-06-08 17:21 UTC (permalink / raw)
  To: git

I was reviewing git-merge-one-file-script, and started
thinking...

It currently has a logic that says if both branches deleted the
same file, instead of taking that as a concensus to remove it,
it refuses to merge the path.  The error message states "This is a
potential rename conflict." as the rationale for doing so.  It
is trying to be careful about one branch renaming the file to
something while the other renaming it to something else.

However, it happily deletes "deleted in one and unchanged in the
other".  If we are so careful about "rename/rename conflicts", I
would think it would make more sense to be careful to consider
the possibility that one branch renamed this file, thereby
creating a copy at another path, while the other branch kept it
intact (the other side of this operation is "added in one"), but
we do not seem to bother worrying about it.  If we try to be
anal about this, then even a simple "added in one" case could
trigger "copy/copy" conflict.

My current thinking is that the current logic for "both delete"
is too anal, and we should treat this case just like other
"concensus" cases; simply removing the path in this case would
be better.


^ permalink raw reply

* Re: cogito-0.10 broken for cg-commit < logmessagefile
From: Petr Baudis @ 2005-06-08 18:17 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <tnxhdg8g6e1.fsf@arm.com>

Dear diary, on Wed, Jun 08, 2005 at 06:28:22PM CEST, I got a letter
where Catalin Marinas <catalin.marinas@arm.com> told me that...
> Russell King <rmk@arm.linux.org.uk> wrote:
> > The command in the subject prepends the log message with a blank line.
> > This ain't good because it messes up commit messages as per Linus'
> > requirements (the first line must be a summary.)
> 
> The patch below should fix the problem. There is no point in writing
> the status information in a file which is read from stdin.

Oh, yes. Thanks, applied.

FYI, I plan to release 0.11.2 this evening. I'll try to go through some
more queued patches before and update cg-log to fully use git-rev-list.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: git/cogito usage scenarios for CVS refugee
From: Petr Baudis @ 2005-06-08 18:34 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Git Mailing List
In-Reply-To: <46a038f9050608025152af4163@mail.gmail.com>

Dear diary, on Wed, Jun 08, 2005 at 11:51:17AM CEST, I got a letter
where Martin Langhoff <martin.langhoff@gmail.com> told me that...
> Trying to get my head around what usage patterns the git
> infrastructure supports. I'm interested in exploring more git-centric
> approaches...
> 
> For a project that uses CVS with a classic HEAD and FOO_15_STABLE
> approach, where FOO_15_STABLE gets only fixes -- how do I manage HEAD
> and XX_STABLE where some patches that work well in HEAD I may decide
> to merge into XX_STABLE, and some security patch may be applied first
> to XX_STABLE and then to HEAD? I can apply the patch on both branches
> -- yep. But does git help me in keeping track of what's been merged?
> 
> Does git help in any way to keep track of patches across 2.6.11.12 and
> 2.6.12rc5 ?
> 
> In a git-based project, one developer is about to merge from someone
> else's tree, are there any tools to review the patchlog that is about
> to be applied (or replayed?) against his tree? Is there any way to say
> "of the 20 commits that I'm about to merge, hold off 2" other than
> letting git apply them ... and backing them out right next?

The answer for all those questions is that git has no support for
cherrypicking (that sucks, but is hard to fix right now). git does ok
as long as one branch is superset of the other, but it does not help you
otherwise.

> And generally, is there any long-lived branch support? If I am to run
> a "local branch" of the Linux kernel, does git help me at all?

I don't understand what do you mean. How does a long-lived branch differ
from a short-lived one and what support would you expect/like?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [PATCH] git-diff-cache: handle pathspec beginning with a dash
From: Petr Baudis @ 2005-06-08 18:47 UTC (permalink / raw)
  To: Jonas Fonseca, torvalds; +Cc: git
In-Reply-To: <20050606212700.GA3498@diku.dk>

Dear diary, on Mon, Jun 06, 2005 at 11:27:00PM CEST, I got a letter
where Jonas Fonseca <fonseca@diku.dk> told me that...
> Parse everything after '--' as tree name or pathspec.
> 
> Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

Thanks, applied to git-pb. Linus, any particular reason for holding this
off?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: Problem with Cogito repository?
From: Petr Baudis @ 2005-06-08 18:49 UTC (permalink / raw)
  To: Philip Pokorny; +Cc: Git Mailing List
In-Reply-To: <42A3E858.7070809@mindspring.com>

Dear diary, on Mon, Jun 06, 2005 at 08:08:24AM CEST, I got a letter
where Philip Pokorny <ppokorny@mindspring.com> told me that...
> I've just updated my tree with cg-pull from 
> rsync://rsync.kernel.org/pub/scm/cogito/cogito.git
> 
> There seems to be a problem with the repository object for tag 
> "pull_from_pasky"

Indeed, unbelievable. I've deleted it several times but somehow it
always pops up again. Yes, its contents is nonsensical as it points to
the history at some point before the hashing changes. Please just delete
it.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [PATCH] Anal retentive 'const unsigned char *sha1'
From: Petr Baudis @ 2005-06-08 18:52 UTC (permalink / raw)
  To: torvalds; +Cc: Jason McMullan, git
In-Reply-To: <20050603150539.GA3239@jmcmullan.timesys>

Dear diary, on Fri, Jun 03, 2005 at 05:05:39PM CEST, I got a letter
where Jason McMullan <jason.mcmullan@timesys.com> told me that...
> Anal Retentive: make 'sha1' parameters const where possible
> 
> Signed-off-by: Jason McMullan <jason.mcmullan@timesys.com>

This seems as a generally Good Thing (tm). const is nice, isn't it?
Any particular reason for not applying it?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [PATCH] simple one-liner for README file
From: Petr Baudis @ 2005-06-08 18:53 UTC (permalink / raw)
  To: Konstantin Antselovich; +Cc: git
In-Reply-To: <42A03D84.4020601@antselovich.com>

Dear diary, on Fri, Jun 03, 2005 at 01:22:44PM CEST, I got a letter
where Konstantin Antselovich <konstantin@antselovich.com> told me that...
> Hi Petr,

Hello,

> I noticed a very small error in README file.
> I'm not sure if I should submit is as a patch, as
> it's just a change to one line.  (but I attached a patch anyways)

thanks, fixed.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [RFC] Removing git-*.html references from manpages
From: Petr Baudis @ 2005-06-08 18:59 UTC (permalink / raw)
  To: Jonas Fonseca; +Cc: David Greaves, git
In-Reply-To: <20050527225850.GA25491@diku.dk>

Dear diary, on Sat, May 28, 2005 at 12:58:50AM CEST, I got a letter
where Jonas Fonseca <fonseca@diku.dk> told me that...
> Hello,

Hi,

> What do you think?

so, what do people think? It sounds as a good thing, but I miss any
discussion. I assume that means everyone likes it? ;-)

> --- a/Documentation/git.txt  (mode:100644)
> +++ b/Documentation/git.txt  (mode:100644)
> @@ -39,34 +39,34 @@
>  
>  Manipulation commands
>  ~~~~~~~~~~~~~~~~~~~~~
> -link:git-checkout-cache.html[git-checkout-cache]::
> +gitlink:git-checkout-cache.html[git-checkout-cache]::
>  	Copy files from the cache to the working directory

So wasn't the point that this would rather be

	+gitlink:git-checkout-cache::

than to what you change it to now?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [RFC] Removing git-*.html references from manpages
From: David Greaves @ 2005-06-08 19:24 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Jonas Fonseca, git
In-Reply-To: <20050608185914.GJ982@pasky.ji.cz>

Petr Baudis wrote:

>Dear diary, on Sat, May 28, 2005 at 12:58:50AM CEST, I got a letter
>where Jonas Fonseca <fonseca@diku.dk> told me that...
>  
>
>>Hello,
>>    
>>
>
>Hi,
>
>  
>
>>What do you think?
>>    
>>
>
>so, what do people think? It sounds as a good thing, but I miss any
>discussion. I assume that means everyone likes it? ;-)
>  
>

I certainly like it :)

Although I'm moving house at the moment so I'm somewhat behind...

David

^ permalink raw reply

* Re: [PATCH] git-diff-cache: handle pathspec beginning with a dash
From: Linus Torvalds @ 2005-06-08 20:00 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Jonas Fonseca, git
In-Reply-To: <20050608184709.GE982@pasky.ji.cz>



On Wed, 8 Jun 2005, Petr Baudis wrote:
>
> Dear diary, on Mon, Jun 06, 2005 at 11:27:00PM CEST, I got a letter
> where Jonas Fonseca <fonseca@diku.dk> told me that...
> > Parse everything after '--' as tree name or pathspec.
> > 
> > Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
> 
> Thanks, applied to git-pb. Linus, any particular reason for holding this
> off?

It seems to have gone only to the mailing list. I only glance through the 
lists, and assume that if somebody wants me to apply a patch, they'll cc 
me personally too..

		Linus

^ permalink raw reply

* Re: [PATCH] git-diff-cache: handle pathspec beginning with a dash
From: Petr Baudis @ 2005-06-08 20:06 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Jonas Fonseca, git
In-Reply-To: <Pine.LNX.4.58.0506081259580.2286@ppc970.osdl.org>

Dear diary, on Wed, Jun 08, 2005 at 10:00:48PM CEST, I got a letter
where Linus Torvalds <torvalds@osdl.org> told me that...
> 
> 
> On Wed, 8 Jun 2005, Petr Baudis wrote:
> >
> > Dear diary, on Mon, Jun 06, 2005 at 11:27:00PM CEST, I got a letter
> > where Jonas Fonseca <fonseca@diku.dk> told me that...
> > > Parse everything after '--' as tree name or pathspec.
> > > 
> > > Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
> > 
> > Thanks, applied to git-pb. Linus, any particular reason for holding this
> > off?
> 
> It seems to have gone only to the mailing list. I only glance through the 
> lists, and assume that if somebody wants me to apply a patch, they'll cc 
> me personally too..

I see. Jonas mentioned on IRC that he forgot to Cc' you. I'm usually
going through everything on the mailing list, so if some patch stays out
for few days I'll start nagging. ;-)

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ permalink raw reply

* Re: [PATCH] git-diff-cache: handle pathspec beginning with a dash
From: Linus Torvalds @ 2005-06-08 20:13 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Jonas Fonseca, git
In-Reply-To: <20050608200612.GM982@pasky.ji.cz>



On Wed, 8 Jun 2005, Petr Baudis wrote:
> 
> I see. Jonas mentioned on IRC that he forgot to Cc' you. I'm usually
> going through everything on the mailing list, so if some patch stays out
> for few days I'll start nagging. ;-)

Even better, just forward it to me with the original author as "From:" at
the top of the email, and an added sign-off by you, and it will show which
path it took.

I took the two patches you pointed out from the mailing list, so they're 
in my archives now.

		Linus

^ permalink raw reply

* Re: git/cogito usage scenarios for CVS refugee
From: Martin Langhoff @ 2005-06-08 20:26 UTC (permalink / raw)
  To: Petr Baudis; +Cc: Git Mailing List
In-Reply-To: <20050608183414.GD982@pasky.ji.cz>

On 6/9/05, Petr Baudis <pasky@ucw.cz> wrote:
> The answer for all those questions is that git has no support for
> cherrypicking (that sucks, but is hard to fix right now). git does ok
> as long as one branch is superset of the other, but it does not help you
> otherwise.

Agreed -- there's no support for cherry picking. Is there some
git-specific strategy perhaps?

For example, when using cvs, which doesn't support cherry picking
either, people running "stable" branches use a "merged" tag that they
move around to indicate how far the bugfixes on the stable branch have
been merged into head. It doesn't allow cherry picking, but it works
and it is a valuable (if hackish) practice.

> > And generally, is there any long-lived branch support? If I am to run
> > a "local branch" of the Linux kernel, does git help me at all?
> 
> I don't understand what do you mean. How does a long-lived branch differ
> from a short-lived one and what support would you expect/like?

Something along the lines of what I've mention above. I mean, not
literally moving a tag around, but to have some basic suport to
identify what the merge status is. As soon as we are one commit out of
sync, git stops being useful.

It doesn't need to happen inside git actually -- perhaps there is just
enough support to add an identifier in each commit msg, so we could
have ancillary scripts that perform some simple patch tracking for
simple scenarios.

When an automatic merge succeeds, does git bring in the commitmsg and
a unique identifier of the commit?

cheers,


martin

^ permalink raw reply

* [PATCH] Many new features for cg-diff and cg-log
From: Dan Holmsand @ 2005-06-08 20:28 UTC (permalink / raw)
  To: git; +Cc: Petr Baudis
In-Reply-To: <20050608181747.GA982@pasky.ji.cz>

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

Petr Baudis wrote:
> FYI, I plan to release 0.11.2 this evening. I'll try to go through some
> more queued patches before and update cg-log to fully use git-rev-list.

In that case, you might want to have a look at this patch. I've been 
tinkering with cg-log and cg-diff for some time, and just about got 
ready to send you a patch.

Sorry about the monster patch, but I wanted to get it to you quickly...

...

[PATCH] Many new features for cg-diff and cg-log

Both cg-diff and cg-log get:

- A common infrastructure for option parsing, that allows for 
combinations of options like all getopt-using programs. So you can say:

cg-log -cfm
cg-diff foo --color
cg-log -sfrlinus foobar

At the same time, you get decent error reporting on illegal options.

- A common infrastructure for colorization. cg-log and cg-diff share 
setup, and sed scripts for colorization.

- diffstat (or rather, git-apply --stat) support.

- Support for the new -M, -C and -B switches to the git-diff-* brothers.

- Automatic search in less, so you can jump to the next commit/diff 
chunk by "n".

- Automatic color if the COGITO_AUTO_COLOR environment variable is set.

- "Smart pager" support - less isn't invoked unless there's actually 
some output. This is useful is COGITO_AUTO_COLOR is set.

cg-log also gets:

- Vast speedup. It uses git-rev-list and git-diff-tree to do most of the 
heavy lifting.

- A new default "-f" format, that allows deletions, renames etc. to be 
shown (the old format is still available as -F). Deletions and new files 
are color-coded.

- Diff output. cg-log -p shows diff output between commits. Colorized as 
in cg-diff.

- New, more compact summary, that's readable on 80-column terminals. By
default, sha1's are hidden, and the date is more compact (and readable). 
It can also be combined with the other options: for example "cg-log -sf" 
gives a nice overview of commits and the files they touch.

- Slightly new behaviour, thanks to use of git-diff-tree: when you use 
any of the options that shows differences between revisions, or that 
gives a subset of revisions, merge commits are hidden by default. They 
are visible if the "-a/--all" option is given.

- The default log format is also shorter. The full version is available 
with "-v". An even shorter format is available with "-q".

- Selection of ranges by date or maximum number of commits to show.

[-- Attachment #2: log-diff.patch.txt --]
[-- Type: text/plain, Size: 25800 bytes --]

 cg-Xlib |   83 +++++++++
 cg-diff |  220 +++++++++++--------------
 cg-log  |  556 ++++++++++++++++++++++++++++++++++++++++-----------------------
 3 files changed, 534 insertions(+), 325 deletions(-)

diff --git a/cg-Xlib b/cg-Xlib
--- a/cg-Xlib
+++ b/cg-Xlib
@@ -119,11 +119,94 @@ print_help () {
 }
 
 for option in "$@"; do
+	[ "$option" = -- ] && break
 	if [ "$option" = "-h" -o "$option" = "--help" ]; then
 		print_help ${_cg_cmd##cg-}
 	fi
 done
 
+# option parsing
+
+ARGS=("$@")
+ARGPOS=0
+
+optshift() {
+	unset ARGS[$ARGPOS]
+	ARGS=("${ARGS[@]}")
+	[ -z "$1" -o -n "${ARGS[$ARGPOS]}" ] || 
+	die "option \`$1' requires an argument"
+}
+
+optfail() {
+	die "unrecognized option \`${ARGS[$ARGPOS]}'"
+}
+
+optconflict() {
+	die "conflicting option \`$CUROPT'"
+}
+
+optparse() {
+	unset OPTARG
+	[ -z "$1" ] && case ${ARGS[$ARGPOS]} in
+	--)	optshift; return 1 ;;
+	-*)	return 0 ;;
+	*)	while (( ${#ARGS[@]} > ++ARGPOS )); do
+			[[ "${ARGS[$ARGPOS]}" == -- ]] && return 1
+			[[ "${ARGS[$ARGPOS]}" == -* ]] && return 0
+		done; return 1 ;;
+	esac
+
+	CUROPT=${ARGS[$ARGPOS]}
+	local match=${1%=} minmatch=${2:-1} opt=$CUROPT o=$CUROPT val
+	[[ $1 == *= ]] && val=$match
+	case $match in
+	--*)	[ "$val" ] && o=${o%%=*}
+		[ ${#o} -ge $((2 + $minmatch)) -a \
+			"${match:0:${#o}}" = "$o" ] || return 1
+		[[ -n "$val" && "$opt" == *=?* ]] && ARGS[$ARGPOS]=${opt#*=} ||
+		optshift $val ;;
+	-?)	[[ $o == $match* ]] || return 1
+		[[ $o != -?-* || -n "$val" ]] || optfail
+		ARGS[$ARGPOS]=${o#$match}
+		[ "${ARGS[$ARGPOS]}" ] && 
+		{ [ "$val" ] || ARGS[$ARGPOS]=-${ARGS[$ARGPOS]}; } || 
+		optshift $val ;;
+	*)	die "optparse cannot handle $1" ;;
+	esac
+	[ -z "$val" ] || { OPTARG=${ARGS[$ARGPOS]}; optshift; } 
+}
+
+maybe_less() {
+	# Invoke $PAGER if there is any output
+	local line
+	if read -r line; then
+		( echo "$line"; cat ) | LESS="-R $LESS" ${PAGER:-less}
+	fi
+}
+
+setup_colors()
+{
+	local C="header=32:author=36:signoff=33:committer=35:files=34"
+	C="$C:commit=34:date=32:trim=35"
+	C="$C:diffhdr=34:diffhdradd=32:diffadd=32:diffhdrmod=35"
+	C="$C:diffmod=35:diffhdrrem=31:diffrem=31:diffhunk=36"
+	C="$C:diffctx=34:diffcctx=33:default=0"
+	[ -n "$COGITO_COLORS" ] && C="$C:$COGITO_COLORS"
+
+	C=${C//=/=\'$'\e'[}
+	C=col${C//:/m\'; col}m\'
+	#coldefault=$(tput op)
+	eval $C
+
+	color_rules="
+s,^+++.*,$coldiffhdradd&$coldefault,
+s,^---.*,$coldiffhdrrem&$coldefault,
+s,^[+].*,$coldiffadd&$coldefault,
+s,^[-].*,$coldiffrem&$coldefault,
+s,^\\(@@.*@@\\)\\(.*\\),$coldiffhunk\\1$coldiffctx\\2$coldefault,
+s,^=*$',$coldiffhdr&$coldefault,
+s,^\\(Index:\\|===\\|diff\\) .*,$coldiffhdr&$coldefault,"
+}
 
 # Check if we have something to work on, unless the script can do w/o it.
 if [ ! "$_git_repo_unneeded" ]; then
diff --git a/cg-diff b/cg-diff
--- a/cg-diff
+++ b/cg-diff
@@ -5,13 +5,16 @@
 #
 # Outputs a diff for converting the first tree to the second one.
 # By default compares the current working tree to the state at the
-# last commit. The output will automatically be displayed in a pager
-# unless it is piped to a program.
+# last commit.
 #
 # OPTIONS
 # -------
-# -c::
-#	Colorize the diff output
+# -c, --color::
+#	Colorize the diff output and use a pager for output (less by 
+#	default).
+#
+# -d, --diffstat::
+#	Show `diffstat' before diff.
 #
 # -p::
 #	Instead of one ID denotes a parent commit to the specified ID
@@ -24,152 +27,131 @@
 #	empty revision which means '-r rev:' compares between 'rev' and
 #	'HEAD', while '-r rev' compares between 'rev' and working tree.
 #
+# -R::
+#	Output diff in reverse.
+#
+# -M::
+#	Detect renames.
+#
+# -C::
+#	Detect copies (as well as renames).
+#
+# -B::
+#	Detect rewrites.
+#
 # -m::
 #	Base the diff at the merge base of the -r arguments (defaulting
-#	to master and origin).
+#	to HEAD and origin).
 #
 # ENVIRONMENT VARIABLES
 # ---------------------
 # PAGER::
 #	The pager to display log information in, defaults to `less`.
 #
-# PAGER_FLAGS::
-#	Flags to pass to the pager. By default `R` is added to the `LESS`
-#	environment variable to allow displaying of colorized output.
+# COGITO_AUTO_COLOR::
+#	If set, colorized output is used automatically on color-capable
+#	terminals.
 
-USAGE="cg-diff [-c] [-m] [-p] [-r FROM_ID[:TO_ID]] [FILE]..."
+USAGE="cg-diff [-c] [-m] [-p] [-r FROM_ID[:TO_ID] [FILE]..."
 
 . ${COGITO_LIB}cg-Xlib
 
 
-id1=" "
-id2=" "
-parent=
-opt_color=
-mergebase=
-
-# TODO: Make cg-log use this too.
-setup_colors()
-{
-	local C="diffhdr=1;36:diffhdradd=1;32:diffadd=32:diffhdrmod=1;35:diffmod=35:diffhdrrem=1;31:diffrem=31:diffhunk=36:diffctx=34:diffcctx=33:default=0"
-	[ -n "$COGITO_COLORS" ] && C="$C:$COGITO_COLORS"
-
-	C=${C//=/=\'$'\e'[}
-	C=col${C//:/m\'; col}m\'
-	#coldefault=$(tput op)
-	eval $C
+unset id1 id2 parent diffprog sedprog diffstat difftmp opt_color renames
+dtargs=()
+
+show_diffstat() {
+	[ -s "$difftmp" ] || return
+	git-apply --stat "$difftmp"
+	echo
+	cat "$difftmp"
 }
 
-while [ "$1" ]; do
-	case "$1" in
-	-c)
-		opt_color=1
-		setup_colors
-		;;
-	-p)
+while optparse; do
+	if optparse -p; then
 		parent=1
-		;;
-	-r)
-		shift
-		if echo "$1" | grep -q ':'; then
-			id2=$(echo "$1" | cut -d : -f 2)
-			[ "$id2" ] || log_end="HEAD"
-			id1=$(echo "$1" | cut -d : -f 1)
-		elif [ "$id1" = " " ]; then
-			id1="$1"
+	elif optparse -m; then
+		incoming=1
+	elif optparse -r=; then
+		if [ -z "${id1+set}" ]; then
+			id1=$OPTARG
+			if [[ "$id1" == *:* ]]; then
+				id2=${id1#*:}
+				id1=${id1%:*}
+			fi
 		else
-			id2="$1"
+			[ -z "${id2+set}" ] || die "too many revisions"
+			id2=$OPTARG
 		fi
-		;;
-	-m)
-		mergebase=1
-		;;
-	*)
-		break
-		;;
-	esac
-	shift
-done
-
-colorize() {
-	if [ "$opt_color" ]; then
-		gawk '
-		{ if (/^(Index:|diff --git) /)
-		    print "'$coldiffhdr'" $0 "'$coldefault'"
-		  else if (/^======*$/)
-		    print "'$coldiffhdr'" $0 "'$coldefault'"
-		  else if (/^\+\+\+/)
-		    print "'$coldiffhdradd'" $0 "'$coldefault'"
-		  else if (/^\*\*\*/)
-		    print "'$coldiffhdrmod'" $0 "'$coldefault'"
-		  else if (/^---/)
-		    print "'$coldiffhdrrem'" $0 "'$coldefault'"
-		  else if (/^(\+|new( file)? mode )/)
-		    print "'$coldiffadd'" $0 "'$coldefault'"
-		  else if (/^(-|(deleted file|old) mode )/)
-		    print "'$coldiffrem'" $0 "'$coldefault'"
-		  else if (/^!/)
-		    print "'$coldiffmod'" $0 "'$coldefault'"
-		  else if (/^@@ \-[0-9]+(,[0-9]+)? \+[0-9]+(,[0-9]+)? @@/)
-		    print gensub(/^(@@[^@]*@@)([ \t]*)(.*)/,
-		         "'$coldiffhunk'" "\\1" "'$coldefault'" \
-			 "\\2" \
-			 "'$coldiffctx'" "\\3" "'$coldefault'", "")
-		  else if (/^\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/)
-		    print "'$coldiffcctx'" $0 "'$coldefault'"
-		  else
-		    print
-		}'
+	elif optparse -c; then
+		opt_color=1
+	elif optparse -d || optparse --diffstat; then
+		diffstat=1
+	elif optparse -R; then
+		dtargs[${#dtargs[@]}]="-R"
+	elif optparse -M; then
+		[ "$renames" ] && optconflict
+		renames=1
+		dtargs[${#dtargs[@]}]="-M"
+	elif optparse -C; then
+		[ "$renames" ] && optconflict
+		renames=1
+		dtargs[${#dtargs[@]}]="-C"
+	elif optparse -B; then
+		dtargs[${#dtargs[@]}]="-B"
 	else
-		cat
+		optfail
 	fi
-}
+done
+
+[ -n "$COGITO_AUTO_COLOR" -a -t 1 ] && [ "$(tput setaf 1 2>/dev/null)" ] && 
+opt_color=1
+
+LESS=$'+/\013^@@.*@@|^diff.--git..*$'" $LESS"
+
+diffprog=git-diff-tree
 
 if [ "$parent" ]; then
+	[ -z "${id2+set}" ] || die "too many revisions"
 	id2="$id1"
 	id1=$(parent-id "$id2" | head -n 1) || exit 1
+elif [ "$incoming" ]; then
+	tmp=$id1
+	id1="$(commit-id "${id2:-HEAD}")" || exit 1
+	id2="$(commit-id "${tmp:-origin}")" || exit 1
+	id1="$(git-merge-base "$id1" "$id2")" || exit 1
 fi
 
-if [ "$mergebase" ]; then
-	[ "$id1" != " " ] || id1="master"
-	[ "$id2" != " " ] || id2="origin"
-	id1=$(git-merge-base $(commit-id "$id1") $(commit-id "$id2"))
-fi
-
-
-filter=$(mktemp -t gitdiff.XXXXXX)
-for file in "$@"; do
-	echo "$file" >>$filter
-done
-
-if [ "$id2" = " " ]; then
-	if [ "$id1" != " " ]; then
-		tree=$(tree-id "$id1") || exit 1
-	else
-		tree=$(tree-id) || exit 1
-	fi
+id1=$(tree-id "$id1") || exit 1
 
+if [ -z "${id2+set}" ]; then
 	# Ensure to only diff modified files
 	git-update-cache --refresh >/dev/null
-
-	# FIXME: Update ret based on what did we match. And take "$@"
-	# to account after all.
-	ret=
-	cat $filter | xargs git-diff-cache -r -p $tree | colorize | pager
-
-	rm $filter
-
-	[ "$ret" ] && die "no files matched"
-	exit $ret
+	diffprog=git-diff-cache
+else
+	id2=$(tree-id "$id2") || exit 1
 fi
 
-
-id1=$(tree-id "$id1") || exit 1
-id2=$(tree-id "$id2") || exit 1
-
 [ "$id1" = "$id2" ] && die "trying to diff $id1 against itself"
+diffopts=(-r -p "${dtargs[@]}" $id1 $id2 "${ARGS[@]}")
+
+if [ "$diffstat" ]; then
+	difftmp=$(mktemp -t cgdiff.XXXXXX) || exit 1
+	trap "rm '$difftmp'" SIGTERM EXIT
+	$diffprog "${diffopts[@]}" > $difftmp
 
-cat $filter | xargs git-diff-tree -r -p $id1 $id2 | colorize | pager
+	diffprog=show_diffstat
+	diffopts=
+fi
 
-rm $filter
-exit 0
+if [ "$opt_color" ]; then
+	setup_colors
+	sedprog="$color_rules"
+
+	[ "$diffstat" ] && sedprog="$sedprog
+s,^\\( [^ ].*\\)\\( |  *[0-9][0-9]* \\),$colfiles\\1$coldefault\\2,"
+
+	$diffprog "${diffopts[@]}" | sed -e "$sedprog" | maybe_less
+else
+	$diffprog "${diffopts[@]}"
+fi
diff --git a/cg-log b/cg-log
--- a/cg-log
+++ b/cg-log
@@ -3,6 +3,7 @@
 # Make a log of changes in a GIT branch.
 # Copyright (c) Petr Baudis, 2005.
 # Copyright (c) David Woodhouse, 2005.
+# Copyright (c) Dan Holmsand, 2005.
 #
 # Display log information for files or a range of commits. The output
 # will automatically be displayed in a pager unless it is piped to
@@ -13,7 +14,7 @@
 # Arguments not interpreted as options will be interpreted as filenames;
 # cg-log then displays only changes in those files.
 #
-# -c::
+# -c, --color::
 #	Colorize to the output. The used colors are listed below together
 #	with information about which log output (summary, full or both)
 #	they apply to:
@@ -26,8 +27,15 @@
 #		- `date`:	'green'		(summary)
 #		- `trim_mark`:	'magenta'	(summary)
 #
+# -d, --diffstat::
+#	Show `diffstat' for every commit.
+#
 # -f::
-#	List affected files. (No effect when passed along `-s`.)
+#	Show list of files modified in each commit.
+#
+# -F::
+#	Show ChangeLog-style list of modified files, instead of the
+#	default listing.
 #
 # -r FROM_ID[:TO_ID]::
 #	Limit the log information to a set of revisions using either
@@ -37,29 +45,63 @@
 #	to the initial commit is shown. If no revisions is specified,
 #	the log information starting from 'HEAD' will be shown.
 #
-# -m::
-#	End the log listing at the merge base of the -r arguments
-#	(defaulting to master and origin).
-#
-# -s::
+# -s, --summary::
 #	Show a one line summary for each log entry. The summary contains
 #	information about the commit date, the author, the first line
 #	of the commit log and the commit ID. Long author names and commit
 #	IDs are trimmed and marked with an ending tilde (~).
 #
-# -uUSERNAME::
-#	List only commits where author or committer contains 'USERNAME'.
-#	The search for 'USERNAME' is case-insensitive.
+# -p, --patches::
+#	Show diffs for files modified by each commit.
+#
+# -v, --verbose::
+#	Show committer, tree and parents for each commit.
+#
+# -a, --all::
+#	Show merge commits as well. By default merge commits are not
+#	shown if you use any of the options that show differences between
+#	commits, or that select some disjoint commits. (-u, -f, -d, etc.)
+#
+# -m::
+#	End the log listing at the merge base of the -r arguments
+#	(defaulting to master and origin).
+#
+# -u, --search=TEXT::
+#	List only commits where author, committer or commit message
+#	contains 'TEXT'. The search for 'TEXT' is case-insensitive.
+#
+# -S, --match=TEXT::
+#	Look for commits that introduces TEXT in a file.
+#
+# -M::
+#	Detect renames.
+#
+# -C::
+#	Detect copies (as well as renames).
+#
+# -B::
+#	Detect rewrites.
+#
+# -y, --max-age=DATE::
+#	Limit output to commits younger than DATE.
+#
+# -o, --min-age=DATE::
+#	Limit output to commits older than DATE.
+#
+# --max-count=N::
+#	Show at most N commits.
+#
+# --stdin::
+#	Show commits for sha1s read from stdin.
 #
 # ENVIRONMENT VARIABLES
 # ---------------------
 # PAGER::
 #	The pager to display log information in, defaults to `less`.
 #
-# PAGER_FLAGS::
-#	Flags to pass to the pager. By default `R` and `S` is added to the
-#	`LESS` environment variable to allow displaying of colorized output
-#	and to avoid long lines from wrapping when using `-s`.
+# COGITO_AUTO_COLOR::
+#	If set, colorized output is used automatically on color-capable
+#	terminals.
 #
 # EXAMPLE USAGE
 # -------------
@@ -75,212 +117,314 @@ USAGE="cg-log [-c] [-f] [-m] [-s] [-uUSE
 # at least somewhere it does. Bash is broken.
 trap exit SIGPIPE
 
-[ "$COLUMNS" ] || COLUMNS="$(tput cols)"
+# speed bash up on utf-8 locales
+LANG=C
 
-colheader=
-colauthor=
-colcommitter=
-colfiles=
-colsignoff=
-colcommit=
-coldate=
-coltrim=
-coldefault=
-
-list_files=
-log_start=
-log_end=
-summary=
-user=
-mergebase=
-files=()
-
-while [ "$1" ]; do
-	case "$1" in
-	-c)
-		# See terminfo(5), "Color Handling"
-		colheader="$(tput setaf 2)"    # Green
-		colauthor="$(tput setaf 6)"    # Cyan
-		colcommitter="$(tput setaf 5)" # Magenta
-		colfiles="$(tput setaf 4)"     # Blue
-		colsignoff="$(tput setaf 3)"   # Yellow
-
-		colcommit="$(tput setaf 4)"
-		coldate="$(tput setaf 2)"
-		coltrim="$(tput setaf 5)"
-
-		coldefault="$(tput op)"        # Restore default
-		;;
-	-f)
-		list_files=1
-		;;
-	-u*)
-		user="${1#-u}"
-		;;
-	-r)
-		shift
-		if echo "$1" | grep -q ':'; then
-			log_end=$(echo "$1" | cut -d : -f 2)
-			[ "$log_end" ] || log_end="HEAD"
-			log_start=$(echo "$1" | cut -d : -f 1)
-		elif [ -z "$log_start" ]; then
-			log_start="$1"
-		else
-			log_end="$1"
-		fi
-		;;
-	-m)
-		mergebase=1
-		;;
-	-s)
-		summary=1
-		;;
-	*)
-		files=("$@")
-		break
-		;;
-	esac
-	shift
-done
+unset id1 id2 user verbose filelist patches sedprog incoming pretty maxn
+unset diffstat stdin opt_color renames dtmode quiet summary longsummary files
+unset needparse
+filemode=-s
+dtargs=() rlargs=()
+
+revlist() {
+	if [ "$stdin" ]; then
+		# read sha1s from stdin. remove leading stuff from
+		# git-rev-tree output.
+		sed 's/^[0-9]* \([a-f0-9]\{40\}\)/\1/'
+	elif [ "$user" ]; then
+		git-rev-list --header "${rlargs[@]}" |
+		LANG=C grep -iz "$user" | tr '\n\0' '\t\n' | cut -f1
+	else
+		git-rev-list "${rlargs[@]}" "$@"
+	fi 
+}
 
-list_commit_files()
-{
-	tree1="$1"
-	tree2="$2"
-	line=
-	sep="    * $colfiles"
-	# List all files for for the initial commit
-	if [ -z $tree2 ]; then
-		list_cmd="git-ls-tree $tree1"
+dolog() {
+	if [ "$dtmode" = diff-tree ]; then
+		revlist | 
+		git-diff-tree --stdin -v -r $filemode "${dtargs[@]}" \
+			-- "${ARGS[@]}"
 	else
-		list_cmd="git-diff-tree -r $tree1 $tree2"
+		revlist --pretty${pretty+=}$pretty
 	fi
+}
+
+showstat() {
+	git-diff-tree -r -p "${dtargs[@]}" $1 $2 -- "${ARGS[@]}" | 
+		git-apply --stat 2>/dev/null
 	echo
-	$list_cmd | cut -f 2- | while read file; do
-		echo -n "$sep"
-		sep=", "
-		line="$line$sep$file"
-		if [ ${#line} -le 74 ]; then
-			echo -n "$file"
+}
+
+showfiles() {
+	local p=6 sep="    * $colfiles" IFS=$'\n' file end=":$coldefault"
+	[ "$summary" ] && { end="$coldefault"$'\n'; }
+	for i in $(git-diff-tree -m -r $1 $2); do
+		[[ "$i" == :* ]] || continue
+		i=${i##*$'\t'}
+		if (( (p += 2 + ${#i}) < 75 )); then
+			echo -n "$sep$i"
 		else
-			line="      $file"
-			echo "$coldefault"
-			echo -n "      $colfiles$file"
+			(( p = 6 + ${#i} ))
+			echo ",$coldefault"
+			echo -n "      $colfiles$i"
 		fi
+		sep=", "
 	done
-	echo "$coldefault:"
+	echo "$end"
+}
+
+todate() {
+	local secs=$1 tzhours=${2:0:3} tzmins=${2:0:1}${2:3} 
+	local format="+%a %b %-d %H:%M:%S %Y $2"
+	# bash doesn't like leading zeros
+	[ "${tzhours:1:1}" = 0 ] && tzhours=${2:0:1}${2:2:1}
+	secs=$((secs + tzhours * 3600 + tzmins * 60))
+	LANG=C date -ud "1970-01-01 UTC + $secs sec" "$format"
 }
 
-if [ "$mergebase" ]; then
-	[ "$log_start" ] || log_start="master"
-	[ "$log_end" ] || log_end="origin"
-	log_start=$(git-merge-base $(commit-id "$log_start") $(commit-id "$log_end"))
+toepoch() {
+	expr "$1" : "[0-9]*$" >/dev/null && echo "$1" ||
+	date -ud "$1" +%s || die "invalid date $1"
+}
+
+showsummary() {
+	local commit=$1 author=$2 date=$3 text=$4 da
+	author=${author#Author: }
+	author=${author% <*}
+	[ ${#author} -gt 14 ] && author=${author:0:13}$coltrim~
+	if [ -z "$longsummary" ]; then
+		commit=
+	elif [ "${COLUMNS:-0}" -le 90 ]; then
+		commit="$colcommit${commit:0:12}$coltrim~ "
+	else
+		commit="$colcommit$commit "
+	fi
+	# find suitable short date format, assumes date in "std linus format"
+	da=(${date#Date:})
+	local dyear=${da[4]}
+	if [ "$year" -ne "$dyear" ]; then
+		# year month day
+		date="${da[1]} ${da[2]} $dyear"
+	elif [ "$month" != "${da[1]}" -o "$day" -ne "${da[2]}" ]; then
+		# month day
+		date="${da[1]} ${da[2]}"
+	else
+		# time
+		date=${da[3]%:*}
+	fi
+	line=${line#    }
+	printf "%s$colauthor%-14s $coldate%-6s $coldefault%s\n" \
+		"$commit" "$author" "$date" "$line"
+}
+
+while optparse; do
+	if optparse -c || optparse --color; then
+		opt_color=1
+	elif optparse -f; then
+		[ "$patches" ] && optconflict
+		files=1
+		filemode=
+	elif optparse -F; then
+		filelist=1
+		dtmode=diff-tree
+	elif optparse -p || optparse --patches; then
+		[ "$files" ] && optconflict
+		patches=1
+		filemode=-p
+	elif optparse -d || optparse --diffstat; then
+		diffstat=1
+		dtmode=diff-tree
+	elif optparse -u= || optparse --search= 2; then
+		user=$OPTARG
+		dtmode=diff-tree
+	elif optparse -q || optparse --short; then
+		[ "$verbose$summary" ] && optconflict
+		quiet=1
+	elif optparse -v || optparse --verbose; then
+		[ "$quiet" ] && optconflict
+		verbose=1
+	elif optparse -s || optparse --summary 2; then
+		[ "$quiet" ] && optconflict
+		summary=1
+	elif optparse --stdin 2; then
+		stdin=1
+		dtmode=diff-tree
+	elif optparse -y= || optparse --max-age= 5; then
+		rlargs[${#rlargs[@]}]=--max-age=$(toepoch "$OPTARG") || exit 1
+	elif optparse -o= || optparse --min-age= 2; then
+		rlargs[${#rlargs[@]}]=--min-age=$(toepoch "$OPTARG") || exit 1
+	elif optparse --max-count= 5; then
+		maxn=$OPTARG
+	elif optparse -a || optparse --all; then
+		dtargs[${#dtargs[@]}]="-m"
+		dtargs[${#dtargs[@]}]="--root"
+	elif optparse -m || optparse --mergebase 2; then
+		incoming=1
+	elif optparse -S= || optparse --match= 3; then
+		dtargs[${#dtargs[@]}]="-S$OPTARG"
+	elif optparse -M; then
+		[ "$renames" ] && optconflict
+		[ "$patches" ] || filemode=
+		dtargs[${#dtargs[@]}]="-M"
+		renames=1
+	elif optparse -C; then
+		[ "$renames" ] && optconflict
+		[ "$patches" ] || filemode=
+		dtargs[${#dtargs[@]}]="-C"
+		renames=1
+	elif optparse -B; then
+		[ "$patches" ] || filemode=
+		dtargs[${#dtargs[@]}]="-B"
+	elif optparse -r= || optparse --revision=; then
+		if [ -z "${id1+set}" ]; then
+			id1=$OPTARG
+			if [[ "$id1" == *:* ]]; then
+				id2=${id1#*:}
+				id1=${id1%:*}
+			fi
+		else
+			[ -z "${id2+set}" ] || die "too many revisions"
+			id2=$OPTARG
+		fi
+	else
+		optfail
+	fi
+done
+
+[ -n "$COGITO_AUTO_COLOR" -a -t 1 ] && [ "$(tput setaf 1 2>/dev/null)" ] && 
+	opt_color=1
+
+LESS="-S $LESS"
+[ "$COLUMNS" ] || COLUMNS="$(tput cols)"
+
+if [ "$incoming" ]; then
+	id1="$(commit-id "${id1:-origin}")" || exit 1
+	id2="$(commit-id "${id2:-HEAD}")" || exit 1
+	id2="$(git-merge-base "$id1" "$id2")" || exit 1
 fi
 
-if [ "$log_end" ]; then
-	id1="$(commit-id "$log_start")" || exit 1
-	id2="$(commit-id "$log_end")" || exit 1
-	revls="git-rev-tree $id2 ^$id1"
-	revsort="sort -rn"
-	revfmt="git-rev-tree"
+id1=$(commit-id "$id1") || exit 1
+[ -z "${id2+set}" ] || id2=$(commit-id "$id2") || exit 1
+rlargs=( "${rlargs[@]}" $id1 ${id2+^}$id2 )
+
+if [ -n "${dtargs[*]}${ARGS[*]}" -o "$filemode" != -s -o "$dtmode" ]; then
+	dtmode=diff-tree
 else
-	id1="$(commit-id "$log_start")" || exit 1
-	revls="git-rev-list $id1"
-	revsort="cat"
-	revfmt="git-rev-list"
+	dtmode=commit
+	[ "$verbose" -a -z "$summary" ] && pretty=raw
+	[ "$quiet" ] && { pretty=short; quiet=; } 
 fi
 
-print_commit_log() {
-	commit="$1"
-	author=
-	committer=
-	tree=
-	parents=()
-
-	git-cat-file commit $commit | \
-		while read key rest; do
-			trap exit SIGPIPE
-			case "$key" in
-			"author")
-				author="$rest"
-				;;
-			"committer")
-				committer="$rest"
-				;;
-			"tree")
-				tree="$rest"
-				;;
-			"parent")
-				parents[${#parents[@]}]="$rest"
-				;;
-			"")
-				if [ "$files" ]; then
-					parent="${parents[0]}"
-					diff_ops=
-					[ "$parent" ] || diff_ops=--root
-					[ "$(git-diff-tree -r $diff_ops $commit $parent "${files[@]}")" ] || return 1
-				fi
-				if [ "$user" ]; then
-					echo -e "author $author\ncommitter $committer" \
-						| grep -qi "$user" || return
-				fi
-				if [ "$summary" ]; then
-					# Print summary
-					commit="${commit%:*}"
-					author="${author% <*}"
-					date=(${committer#*> })
-					date="$(showdate $date '+%F %H:%M')"
-					read title
-					if [ "${#author}" -gt 15 ]; then
-						author="${author:0:14}$coltrim~"
-					fi
-					if [ "${COLUMNS:-0}" -le 90 ]; then
-						commit="${commit:0:12}$coltrim~"
-					fi
-
-					printf "$colcommit%s $colauthor%-15s $coldate%s $coldefault%s\n" \
-						"${commit%:*}" "$author" "$date" "$title"
-					return
-				fi
-
-				echo ${colheader}commit ${commit%:*} $coldefault
-				echo ${colheader}tree $tree $coldefault
-
-				for parent in "${parents[@]}"; do
-					echo ${colheader}parent $parent $coldefault
-				done
-
-				date=(${author#*> })
-				pdate="$(showdate $date)"
-				[ "$pdate" ] && author="${author%> *}> $pdate"
-				echo ${colauthor}author $author $coldefault
-
-				date=(${committer#*> })
-				pdate="$(showdate $date)"
-				[ "$pdate" ] && committer="${committer%> *}> $pdate"
-				echo ${colcommitter}committer $committer $coldefault
-
-				if [ -n "$list_files" ]; then
-					list_commit_files "$tree" "${parents[0]}"
-				fi
-				echo; sed -re '
-					/ *Signed-off-by:.*/Is//'$colsignoff'&'$coldefault'/
-					/ *Acked-by:.*/Is//'$colsignoff'&'$coldefault'/
-					s/./    &/
-				'
-				;;
-			esac
-		done
-}
+if [ "$summary" ]; then
+	year=$(date +%Y)
+	month=$(LANG=C date +%b)
+	day=$(date +%d)
+	[ "$verbose" ] && { longsummary=1; verbose=; }
+fi
+
+if [ "$filelist$diffstat$summary" -o "$pretty" = raw -o $dtmode = diff-tree ]
+then
+	needparse=1
+else
+	[ "$maxn" ] && rlargs=(--max-count="$maxn" "${rlargs[@]}")
+fi
 
-$revls | $revsort | while read time commit parents; do
-	trap exit SIGPIPE
-	[ "$revfmt" = "git-rev-list" ] && commit="$time"
-	log="$(print_commit_log $commit)"
-	if [ "$log" ]; then
-		echo "$log"
-		[ "$summary" ] || echo
+if [ "$opt_color" ]; then
+	setup_colors
+
+	if [ ! "$summary" ]; then
+		LESS=$'+/\013^Commit:.[a-f0-9]*|^diff.--git..*$'" $LESS"
+		sedprog="
+s,^\\(Commit: [^ ]*\\)\\(.*\\),$colheader\\1$coldefault\\2,
+s,^Author:.*,$colauthor&$coldefault,
+s,^Date:.*,$colauthor&$coldefault,
+s,^Tree:.*,$colheader&$coldefault,
+s,^Parent:.*,$colheader&$coldefault,
+s,^Committer:.*,$colcommitter&$coldefault,
+s,^Commitdate:.*,$colcommitter&$coldefault,
+s,^    Signed-[Oo]ff[- ][Bb]y:.*,$colsignoff&$coldefault,
+s,^    Acked[- ][Bb]y:.*,$colsignoff&$coldefault,"
 	fi
-	# LESS="S" will prevent less to wrap too long titles to multiple lines;
-	# you can scroll horizontally.
-done | LESS="S$LESS" pager
+
+	[ "$patches" ] && sedprog="$sedprog;$color_rules"
+
+	[ "$diffstat" ] && sedprog="$sedprog
+s,^\\( [^ ].*\\)\\( |  *[0-9][0-9]* \\),$colfiles\\1$coldefault\\2,"
+fi
+
+if [ $dtmode = diff-tree -a -z "$filemode" ]; then
+	filediffstart=$'s,^:[0-9]* [^ ]* [^ ]* [^ ]* \('
+	filediffend=$'[^\t]*\)\t\(.*\)'
+	sedprog="$sedprog
+${filediffstart}[NCR]$filediffend,$coldiffadd\\1 \\2$coldefault,
+${filediffstart}D$filediffend,$coldiffrem\\1 \\2$coldefault,
+${filediffstart}.$filediffend,$colfiles\\1 \\2$coldefault,"
+fi
+
+if [ "$needparse" ]; then
+	# Slow version, parsing output from diff-tree or rev-list
+	unset commit showds from lineno line
+	n=0
+	dolog | ( trap exit SIGPIPE
+	while [ "$line" ] || IFS='' read -r line; do 
+	case $line in 
+		$dtmode\ *)
+		[ "$maxn" ] && (( ++n > maxn )) && exit
+		[ "$showds" ] && showstat $commit $from
+		line=${line#$dtmode } f="%s\n" showds=$diffstat lineno=0
+		commit=${line% (*} from=${line#*(from }; from=${from%)}
+		[ "$summary" ] && f= || echo "Commit: $line" ;;
+
+		Author:*) printf "$f" "$line"; author=$line ;;
+
+		Date:*) printf "$f" "$line"; date=$line ;;
+
+		author\ *)
+		line=${line#author }; author=${line% [0-9]*}; date=${line##*> }
+		if [ "$f" ]; then
+			printf "$f" "Author: $author"
+			[ "$quiet" ] || printf "$f" "Date:   $(todate $date)" 
+		elif [ "$summary" ]; then
+			date=$(todate $date)
+		fi ;;
+
+		committer\ *)
+		if [ "$verbose" ]; then
+			line=${line#committer }
+			echo "Committer:  ${line% [0-9]*}"
+			echo "Commitdate: $(todate ${line##*> })"
+		fi ;;
+
+		tree\ *) [ "$verbose" ] && echo "Tree: ${line#tree }" ;;
+
+		parent\ *) [ "$verbose" ] && echo "Parent: ${line#parent }" ;;
+
+		\ \ \ \ * | '')
+		if (( ++lineno == 2 )); then
+			[ "$summary" ] && 
+			showsummary $commit "$author" "$date" "$line"
+			[ "$filelist" ] && showfiles $commit $from
+			printf "$f" "$line"
+			[ "$quiet" ] && { f=; echo; }
+		else
+			printf "$f" "$line"
+		fi ;;
+
+		*)
+		[ "$showds" ] && { showstat $commit $from; showds=; }
+		printf "%s\n" "$line"
+		while IFS='' read -r line; do
+			case $line in $dtmode\ *) break ;; esac
+			printf "%s\n" "$line"
+		done
+		continue ;;
+	esac
+	line=
+	done
+	[ "$showds" ] && showstat $commit $from
+	) | LANG=C sed -e "$sedprog" | maybe_less
+else
+	# Fast version, using sed only.
+	sedprog="s,^$dtmode ,Commit: ,;$sedprog"
+	dolog | LANG=C sed -e "$sedprog" | maybe_less
+fi 

^ permalink raw reply

* Re: [PATCH] Many new features for cg-diff and cg-log
From: Petr Baudis @ 2005-06-08 20:40 UTC (permalink / raw)
  To: Dan Holmsand; +Cc: git
In-Reply-To: <42A754D5.10705@gmail.com>

Dear diary, on Wed, Jun 08, 2005 at 10:28:05PM CEST, I got a letter
where Dan Holmsand <holmsand@gmail.com> told me that...
> Petr Baudis wrote:
> >FYI, I plan to release 0.11.2 this evening. I'll try to go through some
> >more queued patches before and update cg-log to fully use git-rev-list.
> 
> In that case, you might want to have a look at this patch. I've been 
> tinkering with cg-log and cg-diff for some time, and just about got 
> ready to send you a patch.
> 
> Sorry about the monster patch, but I wanted to get it to you quickly...

Well, it can always go to 0.11.3 or something.  I probably wouldn't take
it to the tree just before release anyway even if you sent it split up,
since due to the size of the changes, it's bound to have some hidden
bugs. ;-)

> [PATCH] Many new features for cg-diff and cg-log

Ok, this is really too big. Could you please split it up some? Also,
I've been hacking on cg-log too (and will make it use git-diff-tree -v
yet this evening), so you'll need to update it to apply to the latest
version.

I like what's inside (at least from the description), though! (Well,
mostly. But I'll comment on specific patches. No major objections.)

> - Selection of ranges by date or maximum number of commits to show.

Ad date, isn't that already supported now? The -r arguments can be a
date. Ad maximum number of commits, what'd be its use?

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
C++: an octopus made by nailing extra legs onto a dog. -- Steve Taylor

^ 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