Git development
 help / color / mirror / Atom feed
* Re: [Census] So who uses git?
From: Andreas Ericsson @ 2006-02-02 14:59 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Pitre, Linus Torvalds, git, Joel Becker
In-Reply-To: <7v8xsu7kys.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> 
> I do not particularly have much preference among --also,
> --with-index, or --incremental, but:
> 
>  - 'with-index' is precise but might be too technical;
>  - 'incremental' is not really incremental -- you can use it
>    only once.
> 
> Because you do not have to say "git commit --also" without paths
> (which _is_ awkward) to get the traditional behaviour, maybe it
> is a good name for that flag (it is also the shortest).
> 

Except that -a, which is the logical shorthand, is already taken. How 
about --include (or --include-index, or --index) and -i? commit being a 
fairly commonly used command, I think it's safe to assume that most 
people will read the man-page or the help output if there's something 
they don't undetstand.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* [PATCH] get_sha1_1: allow octopus^12 to be properly parsed.
From: Junio C Hamano @ 2006-02-03  7:48 UTC (permalink / raw)
  To: git; +Cc: linux
In-Reply-To: <7vbqxpj6qs.fsf@assigned-by-dhcp.cox.net>

We probably thought anybody who does more than 9 parents in an
Octopus is insane when this was initially done, but there is no
inherent reason to limit the number of independent topic
branches that happen to mature at the same time.

Our commit-tree allows up to 16 already, so at least we should
prepare to handle what we can produce, if only to be consistent.

Signed-off-by: Junio C Hamano <junkio@cox.net>

---

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

 > That reminds me of another practical limit I've known but did
 > nothing about for quite some time (you may not even remember
 > doing that parser anymore).  This does not work for Len's merge:
 >
 > 	$ git rev-parse --verify funmerge^10
 >
 > You could do a 16-way merge but 12-way is already hitting
 > usability limit, depending on what you would want to do with
 > them.  For example, you cannot easily decompose the topic
 > branches out of that merge, like this:
 >
 > 	$ git checkout -b redo-3549 funmerge^2     ;# works
 >       $ git checkout -b redo-pnpacpi funmerge^12 ;# doesn't

 sha1_name.c |   39 ++++++++++++++++-----------------------
 1 files changed, 16 insertions(+), 23 deletions(-)

6c7e009d38da459545bd2eed63e7624f81cea90f
diff --git a/sha1_name.c b/sha1_name.c
index ba0747c..fa85d8a 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -388,43 +388,36 @@ static int peel_onion(const char *name, 
 
 static int get_sha1_1(const char *name, int len, unsigned char *sha1)
 {
-	int parent, ret;
+	int ret, has_suffix;
 	const char *cp;
 
-	/* foo^[0-9] or foo^ (== foo^1); we do not do more than 9 parents. */
-	if (len > 2 && name[len-2] == '^' &&
-	    name[len-1] >= '0' && name[len-1] <= '9') {
-		parent = name[len-1] - '0';
-		len -= 2;
-	}
-	else if (len > 1 && name[len-1] == '^') {
-		parent = 1;
-		len--;
-	} else
-		parent = -1;
-
-	if (parent >= 0)
-		return get_parent(name, len, sha1, parent);
-
 	/* "name~3" is "name^^^",
-	 * "name~12" is "name^^^^^^^^^^^^", and
 	 * "name~" and "name~0" are name -- not "name^0"!
+	 * "name^" is not "name^0"; it is "name^1".
 	 */
-	parent = 0;
+	has_suffix = 0;
 	for (cp = name + len - 1; name <= cp; cp--) {
 		int ch = *cp;
 		if ('0' <= ch && ch <= '9')
 			continue;
-		if (ch != '~')
-			parent = -1;
+		if (ch == '~' || ch == '^')
+			has_suffix = ch;
 		break;
 	}
-	if (!parent && *cp == '~') {
+
+	if (has_suffix) {
+		int num = 0;
 		int len1 = cp - name;
 		cp++;
 		while (cp < name + len)
-			parent = parent * 10 + *cp++ - '0';
-		return get_nth_ancestor(name, len1, sha1, parent);
+			num = num * 10 + *cp++ - '0';
+		if (has_suffix == '^') {
+			if (!num && len1 == len - 1)
+				num = 1;
+			return get_parent(name, len1, sha1, num);
+		}
+		/* else if (has_suffix == '~') -- goes without saying */
+		return get_nth_ancestor(name, len1, sha1, num);
 	}
 
 	ret = peel_onion(name, len, sha1);
-- 
1.1.6.gb1a9

^ permalink raw reply related

* Re: The merge from hell...
From: linux @ 2006-02-03  6:41 UTC (permalink / raw)
  To: git

While we're stress-testing the ystem, does anyone feel like fixing
git-rev-parse 9fdb62af92c741addbea15545f214a6e89460865^10 ?

The following is my attempt, but it doesn't seem sufficient...

$ ~/git/git-rev-parse 9fdb62af92c741addbea15545f214a6e89460865^{1,2,3,4,5,6,7,8,9,10,11,12}
3ee68c4af3fd7228c1be63254b9f884614f9ebb2
876c184b31dc73cc3f38c5b86dee55d091a56769
729b4d4ce1982c52040bbf22d6711cdf8db07ad8
cf82478840188f8c8494c1d7a668a8ae170d0e07
dacd9b80355525be0e3c519687868410e304ad1c
63c94b68ec30847a6e2b36651703f41066f91480
35f652b5ef4ef145ac5514f6302b3f4cebfbbad4
1a38416cea8ac801ae8f261074721f35317613dc
4a90c7e86202f46fa9af011bdbcdf36e355d1721
fatal: '9fdb62af92c741addbea15545f214a6e89460865^10': No such file or directory

(Placed in the public domain; go nuts.)

diff --git a/sha1_name.c b/sha1_name.c
index ba0747c..adf49d2 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -388,52 +388,33 @@ static int peel_onion(const char *name, 
 
 static int get_sha1_1(const char *name, int len, unsigned char *sha1)
 {
-	int parent, ret;
-	const char *cp;
-
-	/* foo^[0-9] or foo^ (== foo^1); we do not do more than 9 parents. */
-	if (len > 2 && name[len-2] == '^' &&
-	    name[len-1] >= '0' && name[len-1] <= '9') {
-		parent = name[len-1] - '0';
-		len -= 2;
-	}
-	else if (len > 1 && name[len-1] == '^') {
-		parent = 1;
-		len--;
-	} else
-		parent = -1;
-
-	if (parent >= 0)
-		return get_parent(name, len, sha1, parent);
-
-	/* "name~3" is "name^^^",
-	 * "name~12" is "name^^^^^^^^^^^^", and
-	 * "name~" and "name~0" are name -- not "name^0"!
-	 */
-	parent = 0;
-	for (cp = name + len - 1; name <= cp; cp--) {
-		int ch = *cp;
-		if ('0' <= ch && ch <= '9')
-			continue;
-		if (ch != '~')
-			parent = -1;
-		break;
+	int parent = 0, pow10 = 1;
+	const char *cp = name + len;
+	char ch = 0;	/* In case len == 0 */
+
+	/* Parse trailing number and check for ^5 or ~5 */
+	while (cp > name && (ch = *--cp) >= '0' && ch <= '9') {
+		parent += ch - '0' * pow10;
+		pow10 *= 10;
 	}
-	if (!parent && *cp == '~') {
-		int len1 = cp - name;
-		cp++;
-		while (cp < name + len)
-			parent = parent * 10 + *cp++ - '0';
-		return get_nth_ancestor(name, len1, sha1, parent);
+
+	/* Handle foo^[0-9]* case */
+	if (ch == '^') {
+		/* foo^ means foo^1, first parent */
+		if (cp + 1 == name)
+			parent = 1;
+		return get_parent(name, cp - name, sha1, parent);
 	}
+	/* Handle foo~[0-9]* case.  name~ = name~0 = name (not name^0!) */
+	if (ch == '~')
+		return get_nth_ancestor(name, cp - name, sha1, parent);
 
-	ret = peel_onion(name, len, sha1);
-	if (!ret)
+	if (!peel_onion(name, len, sha1))
 		return 0;
 
-	ret = get_sha1_basic(name, len, sha1);
-	if (!ret)
+	if (!get_sha1_basic(name, len, sha1))
 		return 0;
+
 	return get_short_sha1(name, len, sha1, 0);
 }
 

^ permalink raw reply related

* Re: The merge from hell...
From: Junio C Hamano @ 2006-02-03  6:33 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Brown, Len, Git Mailing List, Paul Mackerras, Marco Costalba,
	Aneesh Kumar
In-Reply-To: <Pine.LNX.4.64.0602022210540.3462@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> On Fri, 3 Feb 2006, Brown, Len wrote:
>>
>> In the back of my head I was worried about using plain
>> numbers when I saw somebody refer to "shorthand SHA1".
>> Hopefully this is an idle worry and it is not possible
>> for the tool to confuse a numeric branch name with a SHA1 id.
>
> It _is_ possible, but the rule is that references will be resolved first. 

I have to admit that I had this broken for a while.  The
breakage was when you have the same numeric branch name _and_
tagname, then ref resolution was skipped and short SHA1 was
taken.  It _might_ have bitten somebody in real life until I
fixed it.  But I believe this is fixed now.

> It's pretty unlikely, of course. But it's one reason to try to avoid using 
> ref names that are numeric.

Or even non numeric ones, like "deadbeef".

^ permalink raw reply

* Re: The merge from hell...
From: Junio C Hamano @ 2006-02-03  6:28 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Brown, Len, Git Mailing List, Paul Mackerras, Marco Costalba,
	Aneesh Kumar
In-Reply-To: <Pine.LNX.4.64.0602022139190.3462@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> The 12-way merge was a bit over the top, but it worked. I'd suggest not 
> beign quite _that_ aggressive in the future, though, but it's not a big 
> deal.

Heh, I was quietly planning to raise the limit, or lift it
altogether ;-).

I find Len's explanation that those topics cooked independently
and happened to mature at about the same time an excellent
excuse to record this as an Octopus, and with that usage there
is no inherent reason, other than making the diff completely
unreadable, to limit the number of parents.  But I tend to agree
that the current 16 is a sane limit in practice.

That reminds me of another practical limit I've known but did
nothing about for quite some time (you may not even remember
doing that parser anymore).  This does not work for Len's merge:

	$ git rev-parse --verify funmerge^10

You could do a 16-way merge but 12-way is already hitting
usability limit, depending on what you would want to do with
them.  For example, you cannot easily decompose the topic
branches out of that merge, like this:

	$ git checkout -b redo-3549 funmerge^2     ;# works
        $ git checkout -b redo-pnpacpi funmerge^12 ;# doesn't

> One thing I'd ask for: would it be possible to have more descriptive 
> branch names than just numbers? Even if you want to track it by bugzilla 
> entry number, how about calling it "bugzilla-12345" instead? 

When kernel people (not just Len) talk about a "bugzilla ID",
does that ID always come from the same namespace, or do some
subsystems have their own bugzilla?

^ permalink raw reply

* RE: The merge from hell...
From: Linus Torvalds @ 2006-02-03  6:16 UTC (permalink / raw)
  To: Brown, Len
  Cc: Junio C Hamano, Git Mailing List, Paul Mackerras, Marco Costalba,
	Aneesh Kumar
In-Reply-To: <F7DC2337C7631D4386A2DF6E8FB22B3005EFE838@hdsmsx401.amr.corp.intel.com>



On Fri, 3 Feb 2006, Brown, Len wrote:
>
> In the back of my head I was worried about using plain
> numbers when I saw somebody refer to "shorthand SHA1".
> Hopefully this is an idle worry and it is not possible
> for the tool to confuse a numeric branch name with a SHA1 id.

It _is_ possible, but the rule is that references will be resolved first. 

If you mis-type a reference and it could be construed as a short hex SHA1 
ID (it needs to have more than 5 characters in it to trigger, though), the 
auto-completion of SHA1 ID's could bite you, though.

It's pretty unlikely, of course. But it's one reason to try to avoid using 
ref names that are numeric.

		Linus

^ permalink raw reply

* RE: The merge from hell...
From: Brown, Len @ 2006-02-03  6:04 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Junio C Hamano, Git Mailing List, Paul Mackerras, Marco Costalba,
	Aneesh Kumar

>The 12-way merge was a bit over the top, but it worked. I'd 
>suggest not being quite _that_ aggressive in the future,
>though, but it's not a big deal.

I favor "assertive" over "aggressive" --
I assert that the tools I use must work as advertised;-)

> #define MAXPARENT (16)

How about setting this #define to the number
that you're comfortable with?  Then folks like me --
who wouldn't dream of checking code into Linux with a hopped-up git --
will simply obey the limit that comes with the tool?

>One thing I'd ask for: would it be possible to have more descriptive 
>branch names than just numbers? Even if you want to track it 
>by bugzilla entry number, how about calling it "bugzilla-12345" instead? 

bugzilla-#### -- no problem -- will do.

thanks,
-Len

ps. 
In the back of my head I was worried about using plain
numbers when I saw somebody refer to "shorthand SHA1".
Hopefully this is an idle worry and it is not possible
for the tool to confuse a numeric branch name with a SHA1 id.

^ permalink raw reply

* [Attn - repository browser authors] diff-tree combined format.
From: Junio C Hamano @ 2006-02-03  5:49 UTC (permalink / raw)
  To: Paul Mackerras, Marco Costalba, Aneesh Kumar, Kay Sievers; +Cc: git
In-Reply-To: <7v64nxmhqn.fsf@assigned-by-dhcp.cox.net>

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

> Before setting the output format in stone by having gitk
> interpret it, I'd like to do a quick sanity-check poll.

My current thinking is:

    (1) keep the index line, but format it like this:

	index d36904c,376f0fa..4fa6c16

	That is, parents separated with comma, double dots and
	the result.

    (2) match line numbers in the hunk header to normal diff's
        order:

	@@@ -1,87 -1,3 +1,93 @@@

	That is, counts for parents prefixed with '-', and
	the count for result prefixed with '+'.

If somebody has a strong feeling against the above please raise
your hand.

I said "poll" but I mistakenly dropped all the important /
affected people from the CC list, so in case you missed it, here
is a reproduction.  I think gitweb could also use combined diff
so I added Kay to the list.

> Len's merge is a bit too wide, so I'll use GIT 1.0.0 commit as
> an example.  Here is what I have right now.
>
>         $ git diff-tree --cc v1.0.0 -- debian/changelog | head -n 15
>         c2f3bf071ee90b01f2d629921bb04c4f798f02fa
>         diff --cc debian/changelog
>         index d36904c..376f0fa->4fa6c16
>         @@@ +1,93 -1,87 -1,3 @@@
>         ++git-core (1.0.0-0) unstable; urgency=low
>         ++
>         ++  * GIT 1.0.0
>         ++
>         ++ -- Junio C Hamano <junkio@cox.net>  Wed, 21 Dec 2005...
>         ++
>          +git-core (0.99.9n-0) unstable; urgency=low
>          +
>          +  * GIT 0.99.9n aka 1.0rc6
>          +
>          + -- Junio C Hamano <junkio@cox.net>  Wed, 14 Dec 2005...
>
> Two things to note.
>
>  * Somebody said he missed "index" lines.  There is one now, but
>    I am wondering if it might be just be an added noise.  It
>    gets absolutely horrible if you run diff-tree on Len's merge.
>    On the other hand, being able to cut&paste them to "git
>    cat-file blob" command line might be handy.
>
>    Do we want to keep it?
>
>    If we were to keep it, is the format OK?  It lists parent
>    blob names (double-dot separated), an arrow, and then result
>    blob name.  An alternative would be parent,parent..result,
>    like this:
>
>         index d36904c,376f0fa..4fa6c16
>
>    which might be more consistent with the normal ones.
>
>  * I show the line number from the result (+1,93) and then
>    parents' line numbers (-1,87 for the first parent, -1,3 for
>    the second parent).  To be consistent with the normal ones, I
>    am thinking it might be better to move the line number for
>    the result to the last.  One downside of that change is I
>    tend to use the line number of the result to look up the full
>    result more often than to use the line number of the parent,
>    and something like Len's merge would push the most important
>    line number off the edge of the screen.
>
>    Do we want to keep it the way it is, or do we want to do
>    this instead?
>
>         @@@ -1,87 -1,3 +1,93 @@@

To be complete, I'd also describe the rules for combined diff
text here.

1. Unlike normal unidiff that has one column prefix, this has N
   column prefix for N parents (usually 2 -- your branch and the
   other branch that is merged into it -- but more for an
   Octopus).  Column 1 talks about the first parent, column 2
   about the second, etc.

2. The hunk header starts and ends with N+1 (usually 2+1=3, more
   for an Octopus) '@' characters.

3. The column prefix is one of the following two shapes and a
   half:

   * one or more minus '-' and whitespace in others: the line
     does not appear in the result, and parents with '-' has
     it.

   * one or more plus '+' and whitespace in others: the line
     appears in the result, and parents without '+' has it.

   * all whitespace: the line appears in the result and all
     parents have it (this is a special case of the above).

^ permalink raw reply

* RE: The merge from hell...
From: Linus Torvalds @ 2006-02-03  5:45 UTC (permalink / raw)
  To: Brown, Len
  Cc: Junio C Hamano, Git Mailing List, Paul Mackerras, Marco Costalba,
	Aneesh Kumar
In-Reply-To: <F7DC2337C7631D4386A2DF6E8FB22B3005EFE7FF@hdsmsx401.amr.corp.intel.com>



On Thu, 2 Feb 2006, Brown, Len wrote:
> 
> I can do 16 next time, or 22, or none

Actually, you can't do 22:

	/*
	 * Having more than two parents is not strange at all, and this is
	 * how multi-way merges are represented.
	 */
	#define MAXPARENT (16)

(commit-tree.c).

Now, admittedly you should literally need no more than to change that 
#define and recompile, but at least by default, git-write-tree won't 
accept more than 16 parents.

The 12-way merge was a bit over the top, but it worked. I'd suggest not 
beign quite _that_ aggressive in the future, though, but it's not a big 
deal.

One thing I'd ask for: would it be possible to have more descriptive 
branch names than just numbers? Even if you want to track it by bugzilla 
entry number, how about calling it "bugzilla-12345" instead? 

I can make the educated guess that it's the bugzilla.kernel.org tracking 
number, but still.. I think it would make the changelog more readable and 
understandable to outsiders.

		Linus

^ permalink raw reply

* Re: [PATCH] combine-diff: add safety check to --cc.
From: Junio C Hamano @ 2006-02-03  5:28 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0602021454060.21884@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> And now when I look at Len's "Merge from hell", not only does it take less 
> than 2 seconds for git-diff-tree to calculate, it looks correct too. At 
> least I don't see anything that I consider extraneous, although it might, 
> of course, have removed too much, and I'd not notice.

I've run "diff -u0" between -c output and --cc output and what
was dropped looked sane.

^ permalink raw reply

* Re: gitview 0.3
From: Junio C Hamano @ 2006-02-03  5:03 UTC (permalink / raw)
  To: Aneesh Kumar; +Cc: git
In-Reply-To: <cc723f590602020803u72bdff2ek95fba2ea30970170@mail.gmail.com>

Aneesh Kumar <aneesh.kumar@gmail.com> writes:

> ... Can you get the gitview added git repository so that next
> time onwards i need to send only the diff.

We _could_ make a contrib/gitview directory to keep it there,
and as somebody else comes up with a new interesting git
application, add a new directory in contrib/ to expand that
area.

But personally I am not enthused about keeping other peoples'
projects in git.git tree [*1*].  I'd rather see you start your
own public repository, propagate your changes from there, and
run it as your own project.

Even though it is currently a single file 'project', you will
want to add more stuff, maybe splitting the code to use your own
*.py module to import into the main program, and add *.c files
to interface with the lower level and Makefile to describe the
build rules once we start libifying git.  I suspect we are all
better off if we keep separate projects separate in the long
run.

Somebody (I think it was Sean Estabrooks but I may be mistaken)
once offered to host git projects at a site he controls.  I
wonder if you can get him interested...


[Footnote]

*1* I was not too happy to see gitk merged in with "the coolest
merge ever" myself, but that was done before my time.  "Not too
happy" does not necessarily mean I object to it.  All things
considered I think it was a good thing: (1) as a showcase of how
cool a merge can be, it was a good demonstration; (2) coming
with a repository browser usable out-of-box with minimum
dependencies was a good thing (tcl/tk is pretty much available
universally for easy install); (3) it is a good example program
of how a repository browser can be done.

^ permalink raw reply

* RE: The merge from hell...
From: Brown, Len @ 2006-02-03  4:20 UTC (permalink / raw)
  To: Linus Torvalds, Junio C Hamano
  Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar

 
>Thank Len. He may have done it as a way to avoid having extra merges, 
>since I complained about those last time ;)

Seems I'm batting 1000 for entertainment value
over my last two kernel patch pushes:-)

The previous one I took abuse for unwittingly cluttering
history with "extra" merges.  The thread went on
and on, but buried in there were some interesting
observations on work flow, and somebody
asserted that the "cleanest" way to cherry pick
the topic branches onto the release branch was
with a multi-branch merge.

As git merge seemed to advertise support for it w/o
me needing to learn a new command, I tried it out
and it seemed to work fine -- including a nice colorful
diagram in gitk:-)

I can do 16 next time, or 22, or none -- or you can have
git merge under the covers do this via iteration instead
of all at once -- that's up to you guys.  My topic branches
tend to be disjoint topics with little expected overlap;
so grabbing a bunch of them when they're fully "cooked"
in -mm and plunking them down in one merge is actually
an example of history matching reality.

cheers,
-Len

^ permalink raw reply

* gitview
From: Aneesh Kumar @ 2006-02-03  3:58 UTC (permalink / raw)
  To: Junio C Hamano, Git Mailing List

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

Hi Junio,

I am attaching below the new gitview file which contain some copyright
and author changes. The changelog is also attached.

-aneesh

[-- Attachment #2: gitview --]
[-- Type: application/octet-stream, Size: 25142 bytes --]

#! /usr/bin/env python

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

""" gitview
GUI browser for git repository 
This program is based on bzrk by Scott James Remnant <scott@ubuntu.com>
"""
__copyright__ = "Copyright (C) 2006 Hewlett-Packard Development Company, L.P."
__author__    = "Aneesh Kumar K.V <aneesh.kumar@hp.com>"


import sys
import os
import gtk
import pygtk
import pango
import re
import time
import gobject
import cairo
import math
import string

try:
    import gtksourceview
    have_gtksourceview = True
except ImportError:
    have_gtksourceview = False
    print "Running without gtksourceview module"

re_ident = re.compile('(author|committer) (?P<ident>.*) (?P<epoch>\d+) (?P<tz>[+-]\d{4})')

def list_to_string(args, skip):
	count = len(args)
	i = skip
	str_arg=" "
	while (i < count ):
		str_arg = str_arg + args[i]
		str_arg = str_arg + " "
		i = i+1

	return str_arg

def show_date(epoch, tz):
	secs = float(epoch)
	tzsecs = float(tz[1:3]) * 3600
	tzsecs += float(tz[3:5]) * 60
	if (tz[0] == "+"):
		secs += tzsecs
	else:
		secs -= tzsecs

	return time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(secs))
		

class CellRendererGraph(gtk.GenericCellRenderer):
	"""Cell renderer for directed graph.

	This module contains the implementation of a custom GtkCellRenderer that
	draws part of the directed graph based on the lines suggested by the code
	in graph.py.

	Because we're shiny, we use Cairo to do this, and because we're naughty
	we cheat and draw over the bits of the TreeViewColumn that are supposed to
	just be for the background.

	Properties:
	node              (column, colour) tuple to draw revision node,
	in_lines          (start, end, colour) tuple list to draw inward lines,
	out_lines         (start, end, colour) tuple list to draw outward lines.
	"""

	__gproperties__ = {
	"node":         ( gobject.TYPE_PYOBJECT, "node",
			  "revision node instruction",
			  gobject.PARAM_WRITABLE
			),
	"in-lines":     ( gobject.TYPE_PYOBJECT, "in-lines",
			  "instructions to draw lines into the cell",
			  gobject.PARAM_WRITABLE
			),
	"out-lines":    ( gobject.TYPE_PYOBJECT, "out-lines",
			  "instructions to draw lines out of the cell",
			  gobject.PARAM_WRITABLE
			),
	}

	def do_set_property(self, property, value):
		"""Set properties from GObject properties."""
		if property.name == "node":
			self.node = value
		elif property.name == "in-lines":
			self.in_lines = value
		elif property.name == "out-lines":
			self.out_lines = value
		else:
			raise AttributeError, "no such property: '%s'" % property.name

	def box_size(self, widget):
		"""Calculate box size based on widget's font.

		Cache this as it's probably expensive to get.  It ensures that we
		draw the graph at least as large as the text.
		"""
		try:
			return self._box_size
		except AttributeError:
			pango_ctx = widget.get_pango_context()
			font_desc = widget.get_style().font_desc
			metrics = pango_ctx.get_metrics(font_desc)

			ascent = pango.PIXELS(metrics.get_ascent())
			descent = pango.PIXELS(metrics.get_descent())

			self._box_size = ascent + descent + 6
			return self._box_size

	def set_colour(self, ctx, colour, bg, fg):
		"""Set the context source colour.

		Picks a distinct colour based on an internal wheel; the bg
		parameter provides the value that should be assigned to the 'zero'
		colours and the fg parameter provides the multiplier that should be
		applied to the foreground colours.
		"""
		colours = [
		    ( 1.0, 0.0, 0.0 ),
		    ( 1.0, 1.0, 0.0 ),
		    ( 0.0, 1.0, 0.0 ),
		    ( 0.0, 1.0, 1.0 ),
		    ( 0.0, 0.0, 1.0 ),
		    ( 1.0, 0.0, 1.0 ),
		    ]

		colour %= len(colours)
		red   = (colours[colour][0] * fg) or bg
		green = (colours[colour][1] * fg) or bg
		blue  = (colours[colour][2] * fg) or bg

		ctx.set_source_rgb(red, green, blue)

	def on_get_size(self, widget, cell_area):
		"""Return the size we need for this cell.

		Each cell is drawn individually and is only as wide as it needs
		to be, we let the TreeViewColumn take care of making them all
		line up.
		"""
		box_size = self.box_size(widget)

		cols = self.node[0]
		for start, end, colour in self.in_lines + self.out_lines:
			cols = max(cols, start, end)

		width = box_size * (cols + 1)
		height = box_size

		# FIXME I have no idea how to use cell_area properly
		return (0, 0, width, height)

	def on_render(self, window, widget, bg_area, cell_area, exp_area, flags):
		"""Render an individual cell.

		Draws the cell contents using cairo, taking care to clip what we
		do to within the background area so we don't draw over other cells.
		Note that we're a bit naughty there and should really be drawing
		in the cell_area (or even the exposed area), but we explicitly don't
		want any gutter.

		We try and be a little clever, if the line we need to draw is going
		to cross other columns we actually draw it as in the .---' style
		instead of a pure diagonal ... this reduces confusion by an
		incredible amount.
		"""
		ctx = window.cairo_create()
		ctx.rectangle(bg_area.x, bg_area.y, bg_area.width, bg_area.height)
		ctx.clip()

		box_size = self.box_size(widget)

		ctx.set_line_width(box_size / 8)
		ctx.set_line_cap(cairo.LINE_CAP_SQUARE)

		# Draw lines into the cell
		for start, end, colour in self.in_lines:
			ctx.move_to(cell_area.x + box_size * start + box_size / 2,
					bg_area.y - bg_area.height / 2)

			if start - end > 1:
				ctx.line_to(cell_area.x + box_size * start, bg_area.y)
				ctx.line_to(cell_area.x + box_size * end + box_size, bg_area.y)
			elif start - end < -1:
				ctx.line_to(cell_area.x + box_size * start + box_size,
						bg_area.y)
				ctx.line_to(cell_area.x + box_size * end, bg_area.y)

		    	ctx.line_to(cell_area.x + box_size * end + box_size / 2,
					bg_area.y + bg_area.height / 2)

			self.set_colour(ctx, colour, 0.0, 0.65)
			ctx.stroke()

		# Draw lines out of the cell
		for start, end, colour in self.out_lines:
			ctx.move_to(cell_area.x + box_size * start + box_size / 2,
					bg_area.y + bg_area.height / 2)

			if start - end > 1:
				ctx.line_to(cell_area.x + box_size * start,
						bg_area.y + bg_area.height)
				ctx.line_to(cell_area.x + box_size * end + box_size,
						bg_area.y + bg_area.height)
			elif start - end < -1:
				ctx.line_to(cell_area.x + box_size * start + box_size,
						bg_area.y + bg_area.height)
				ctx.line_to(cell_area.x + box_size * end,
						bg_area.y + bg_area.height)

			ctx.line_to(cell_area.x + box_size * end + box_size / 2,
					bg_area.y + bg_area.height / 2 + bg_area.height)

			self.set_colour(ctx, colour, 0.0, 0.65)
			ctx.stroke()

		# Draw the revision node in the right column
		(column, colour) = self.node
		ctx.arc(cell_area.x + box_size * column + box_size / 2,
				cell_area.y + cell_area.height / 2,
				box_size / 4, 0, 2 * math.pi)

		self.set_colour(ctx, colour, 0.0, 0.5)
		ctx.stroke_preserve()

		self.set_colour(ctx, colour, 0.5, 1.0)
		ctx.fill()

class Commit:
	""" This represent a commit object obtained after parsing the git-rev-list 
	output """

	children_sha1 = {}

	def __init__(self, commit_lines):
		self.message 		= ""
		self.author		= ""
		self.date 		= ""
		self.committer 		= ""
		self.commit_date 	= ""
		self.commit_sha1	= ""
		self.parent_sha1	= [ ]
		self.parse_commit(commit_lines)


	def parse_commit(self, commit_lines):

		# First line is the sha1 lines
		line = string.strip(commit_lines[0])
		sha1 = re.split(" ", line)
		self.commit_sha1 = sha1[0]
		self.parent_sha1 = sha1[1:]

		#build the child list
		for parent_id in self.parent_sha1:
			try:
				Commit.children_sha1[parent_id].append(self.commit_sha1)
			except KeyError:
				Commit.children_sha1[parent_id] = [self.commit_sha1]

		# IF we don't have parent
		if (len(self.parent_sha1) == 0):
			self.parent_sha1 = [0]

		for line in commit_lines[1:]:
			m = re.match("^ ", line)
			if (m != None):
				# First line of the commit message used for short log
				if self.message == "":
					self.message = string.strip(line)
				continue

			m = re.match("tree", line)
			if (m != None):
				continue

			m = re.match("parent", line)
			if (m != None):
				continue

			m = re_ident.match(line)
			if (m != None):
				date = show_date(m.group('epoch'), m.group('tz'))
				if m.group(1) == "author":
       					self.author = m.group('ident')
       					self.date = date
				elif m.group(1) == "committer":
       					self.committer = m.group('ident')
       					self.commit_date = date

				continue

	def get_message(self, with_diff=0):
		if (with_diff == 1):
			message = self.diff_tree()
		else:
			fp = os.popen("git cat-file commit " + self.commit_sha1)
			message = fp.read()
			fp.close()

		return message

	def diff_tree(self):
		fp = os.popen("git diff-tree --pretty --cc  -v -p " + " " + self.commit_sha1)
		diff = fp.read()
		fp.close()
		if (diff == ""):
			# After optimization in case of merge commits if don't
			# have any diffs. Just show the commit message
			diff = self.get_message(0)

		return diff

class DiffWindow:
	"""Diff window.
	This object represents and manages a single window containing the
	differences between two revisions on a branch.
	"""

	def __init__(self):
		self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
		self.window.set_border_width(0)
		self.window.set_title("Git repository browser diff window")

		# Use two thirds of the screen by default
		screen = self.window.get_screen()
		monitor = screen.get_monitor_geometry(0)
		width = int(monitor.width * 0.66)
		height = int(monitor.height * 0.66)
		self.window.set_default_size(width, height)

		self.construct()

	def construct(self):
		"""Construct the window contents."""
		hbox = gtk.HBox(spacing=6)
		hbox.set_border_width(12)
		self.window.add(hbox)
		hbox.show()

		scrollwin = gtk.ScrolledWindow()
		scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		scrollwin.set_shadow_type(gtk.SHADOW_IN)
		hbox.pack_start(scrollwin, expand=True, fill=True)
		scrollwin.show()

		if have_gtksourceview:
			self.buffer = gtksourceview.SourceBuffer()
			slm = gtksourceview.SourceLanguagesManager()
			gsl = slm.get_language_from_mime_type("text/x-patch")
			self.buffer.set_highlight(True)
			self.buffer.set_language(gsl)
			sourceview = gtksourceview.SourceView(self.buffer)
		else:
			self.buffer = gtk.TextBuffer()
			sourceview = gtk.TextView(self.buffer)

		sourceview.set_editable(False)
		sourceview.modify_font(pango.FontDescription("Monospace"))
		scrollwin.add(sourceview)
		sourceview.show()


	def set_diff(self, commit_sha1, parent_sha1):
		"""Set the differences showed by this window.
		Compares the two trees and populates the window with the
		differences.
		"""
		# Diff with the first commit or the last commit shows nothing
		if (commit_sha1 == 0 or parent_sha1 == 0 ):
			return 

		fp = os.popen("git diff-tree -p " + parent_sha1 + " " + commit_sha1)
		self.buffer.set_text(fp.read())
		fp.close()
		self.window.show()


class GitView:
	""" This is the main class
	"""

	def __init__(self, with_diff=0):
		self.with_diff = with_diff
        	self.window =  	gtk.Window(gtk.WINDOW_TOPLEVEL)
        	self.window.set_border_width(0)
		self.window.set_title("Git repository browser")


        	# Use three-quarters of the screen by default
        	screen = self.window.get_screen()
        	monitor = screen.get_monitor_geometry(0)
        	width = int(monitor.width * 0.75)
        	height = int(monitor.height * 0.75)
        	self.window.set_default_size(width, height)

        	# FIXME AndyFitz!
        	icon = self.window.render_icon(gtk.STOCK_INDEX, gtk.ICON_SIZE_BUTTON)
        	self.window.set_icon(icon)

        	self.accel_group = gtk.AccelGroup()
        	self.window.add_accel_group(self.accel_group)

        	self.construct()


	def construct(self):
		"""Construct the window contents."""
		paned = gtk.VPaned()
		paned.pack1(self.construct_top(), resize=False, shrink=True)
		paned.pack2(self.construct_bottom(), resize=False, shrink=True)
		self.window.add(paned)
		paned.show()

	def construct_top(self):
		"""Construct the top-half of the window."""
		vbox = gtk.VBox(spacing=6)
		vbox.set_border_width(12)
		vbox.show()

		scrollwin = gtk.ScrolledWindow()
		scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
		scrollwin.set_shadow_type(gtk.SHADOW_IN)
		vbox.pack_start(scrollwin, expand=True, fill=True)
		scrollwin.show()

		self.treeview = gtk.TreeView()
		self.treeview.set_rules_hint(True)
		self.treeview.set_search_column(4)
		self.treeview.connect("cursor-changed", self._treeview_cursor_cb)
		scrollwin.add(self.treeview)
		self.treeview.show()

		cell = CellRendererGraph()
		column = gtk.TreeViewColumn()
		column.set_resizable(False)
		column.pack_start(cell, expand=False)
		column.add_attribute(cell, "node", 1)
		column.add_attribute(cell, "in-lines", 2)
		column.add_attribute(cell, "out-lines", 3)
		self.treeview.append_column(column)

		cell = gtk.CellRendererText()
		cell.set_property("width-chars", 65)
		cell.set_property("ellipsize", pango.ELLIPSIZE_END)
		column = gtk.TreeViewColumn("Message")
		column.set_resizable(True)
		column.pack_start(cell, expand=True)
		column.add_attribute(cell, "text", 4)
		self.treeview.append_column(column)

		cell = gtk.CellRendererText()
		cell.set_property("width-chars", 40)
		cell.set_property("ellipsize", pango.ELLIPSIZE_END)
		column = gtk.TreeViewColumn("Author")
		column.set_resizable(True)
		column.pack_start(cell, expand=True)
		column.add_attribute(cell, "text", 5)
		self.treeview.append_column(column)

		cell = gtk.CellRendererText()
		cell.set_property("ellipsize", pango.ELLIPSIZE_END)
		column = gtk.TreeViewColumn("Date")
		column.set_resizable(True)
		column.pack_start(cell, expand=True)
		column.add_attribute(cell, "text", 6)
		self.treeview.append_column(column)

		return vbox


	def construct_bottom(self):
		"""Construct the bottom half of the window."""
		vbox = gtk.VBox(False, spacing=6)
		vbox.set_border_width(12)
		(width, height) = self.window.get_size()
		vbox.set_size_request(width, int(height / 2.5))
		vbox.show()

		self.table = gtk.Table(rows=4, columns=4)
		self.table.set_row_spacings(6)
		self.table.set_col_spacings(6)
		vbox.pack_start(self.table, expand=False, fill=True)
		self.table.show()

		align = gtk.Alignment(0.0, 0.5)
		label = gtk.Label()
		label.set_markup("<b>Revision:</b>")
		align.add(label)
		self.table.attach(align, 0, 1, 0, 1, gtk.FILL, gtk.FILL)
		label.show()
		align.show()

		align = gtk.Alignment(0.0, 0.5)
		self.revid_label = gtk.Label()
		self.revid_label.set_selectable(True)
		align.add(self.revid_label)
		self.table.attach(align, 1, 2, 0, 1, gtk.EXPAND | gtk.FILL, gtk.FILL)
		self.revid_label.show()
		align.show()

		align = gtk.Alignment(0.0, 0.5)
		label = gtk.Label()
		label.set_markup("<b>Committer:</b>")
		align.add(label)
		self.table.attach(align, 0, 1, 1, 2, gtk.FILL, gtk.FILL)
		label.show()
		align.show()

		align = gtk.Alignment(0.0, 0.5)
		self.committer_label = gtk.Label()
		self.committer_label.set_selectable(True)
		align.add(self.committer_label)
		self.table.attach(align, 1, 2, 1, 2, gtk.EXPAND | gtk.FILL, gtk.FILL)
		self.committer_label.show()
		align.show()

		align = gtk.Alignment(0.0, 0.5)
		label = gtk.Label()
		label.set_markup("<b>Timestamp:</b>")
		align.add(label)
		self.table.attach(align, 0, 1, 2, 3, gtk.FILL, gtk.FILL)
		label.show()
		align.show()

		align = gtk.Alignment(0.0, 0.5)
		self.timestamp_label = gtk.Label()
		self.timestamp_label.set_selectable(True)
		align.add(self.timestamp_label)
		self.table.attach(align, 1, 2, 2, 3, gtk.EXPAND | gtk.FILL, gtk.FILL)
		self.timestamp_label.show()
		align.show()

		align = gtk.Alignment(0.0, 0.5)
		label = gtk.Label()
		label.set_markup("<b>Parents:</b>")
		align.add(label)
		self.table.attach(align, 0, 1, 3, 4, gtk.FILL, gtk.FILL)
		label.show()
		align.show()
		self.parents_widgets = []

		align = gtk.Alignment(0.0, 0.5)
		label = gtk.Label()
		label.set_markup("<b>Children:</b>")
		align.add(label)
		self.table.attach(align, 2, 3, 3, 4, gtk.FILL, gtk.FILL)
		label.show()
		align.show()
		self.children_widgets = []

		scrollwin = gtk.ScrolledWindow()
		scrollwin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
		scrollwin.set_shadow_type(gtk.SHADOW_IN)
		vbox.pack_start(scrollwin, expand=True, fill=True)
		scrollwin.show()

		if have_gtksourceview:
			self.message_buffer = gtksourceview.SourceBuffer()
			slm = gtksourceview.SourceLanguagesManager()
			gsl = slm.get_language_from_mime_type("text/x-patch")
			self.message_buffer.set_highlight(True)
			self.message_buffer.set_language(gsl)
			sourceview = gtksourceview.SourceView(self.message_buffer)
		else:
			self.message_buffer = gtk.TextBuffer()
			sourceview = gtk.TextView(self.message_buffer)

		sourceview.set_editable(False)
		sourceview.modify_font(pango.FontDescription("Monospace"))
		scrollwin.add(sourceview)
		sourceview.show()

		return vbox

	def _treeview_cursor_cb(self, *args):
		"""Callback for when the treeview cursor changes."""
		(path, col) = self.treeview.get_cursor()
		commit = self.model[path][0]

		if commit.committer is not None:
			committer = commit.committer
			timestamp = commit.commit_date
			message   =  commit.get_message(self.with_diff)
			revid_label = commit.commit_sha1
		else:
    			committer = ""
    			timestamp = ""
    			message = ""
			revid_label = ""

		self.revid_label.set_text(revid_label)
		self.committer_label.set_text(committer)
		self.timestamp_label.set_text(timestamp)
		self.message_buffer.set_text(message)

		for widget in self.parents_widgets:
			self.table.remove(widget)

		self.parents_widgets = []
		self.table.resize(4 + len(commit.parent_sha1) - 1, 4)
		for idx, parent_id in enumerate(commit.parent_sha1):
			self.table.set_row_spacing(idx + 3, 0)

			align = gtk.Alignment(0.0, 0.0)
			self.parents_widgets.append(align)
			self.table.attach(align, 1, 2, idx + 3, idx + 4,
					gtk.EXPAND | gtk.FILL, gtk.FILL)
			align.show()

			hbox = gtk.HBox(False, 0)
			align.add(hbox)
			hbox.show()

			label = gtk.Label(parent_id)
			label.set_selectable(True)
			hbox.pack_start(label, expand=False, fill=True)
			label.show()

			image = gtk.Image()
			image.set_from_stock(gtk.STOCK_JUMP_TO, gtk.ICON_SIZE_MENU)
			image.show()

			button = gtk.Button()
			button.add(image)
			button.set_relief(gtk.RELIEF_NONE)
			button.connect("clicked", self._go_clicked_cb, parent_id)
			hbox.pack_start(button, expand=False, fill=True)
			button.show()

			image = gtk.Image()
			image.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
			image.show()

			button = gtk.Button()
			button.add(image)
			button.set_relief(gtk.RELIEF_NONE)
			button.set_sensitive(True)
			button.connect("clicked", self._show_clicked_cb,
					commit.commit_sha1, parent_id)
			hbox.pack_start(button, expand=False, fill=True)
			button.show()

		# Populate with child details
		for widget in self.children_widgets:
			self.table.remove(widget)

		self.children_widgets = []
		try:
			child_sha1 = Commit.children_sha1[commit.commit_sha1]
		except KeyError:
			# We don't have child
			child_sha1 = [ 0 ]

		if ( len(child_sha1) > len(commit.parent_sha1)):
			self.table.resize(4 + len(child_sha1) - 1, 4)

		for idx, child_id in enumerate(child_sha1):
			self.table.set_row_spacing(idx + 3, 0)

			align = gtk.Alignment(0.0, 0.0)
			self.children_widgets.append(align)
			self.table.attach(align, 3, 4, idx + 3, idx + 4,
					gtk.EXPAND | gtk.FILL, gtk.FILL)
			align.show()

			hbox = gtk.HBox(False, 0)
			align.add(hbox)
			hbox.show()

			label = gtk.Label(child_id)
			label.set_selectable(True)
			hbox.pack_start(label, expand=False, fill=True)
			label.show()

			image = gtk.Image()
			image.set_from_stock(gtk.STOCK_JUMP_TO, gtk.ICON_SIZE_MENU)
			image.show()

			button = gtk.Button()
			button.add(image)
			button.set_relief(gtk.RELIEF_NONE)
			button.connect("clicked", self._go_clicked_cb, child_id)
			hbox.pack_start(button, expand=False, fill=True)
			button.show()

			image = gtk.Image()
			image.set_from_stock(gtk.STOCK_FIND, gtk.ICON_SIZE_MENU)
			image.show()

			button = gtk.Button()
			button.add(image)
			button.set_relief(gtk.RELIEF_NONE)
			button.set_sensitive(True)
			button.connect("clicked", self._show_clicked_cb,
					child_id, commit.commit_sha1)
			hbox.pack_start(button, expand=False, fill=True)
			button.show()

	def _destroy_cb(self, widget):
		"""Callback for when a window we manage is destroyed."""
		self.quit()


	def quit(self):
		"""Stop the GTK+ main loop."""
		gtk.main_quit()

	def run(self, args):
		self.set_branch(args)
        	self.window.connect("destroy", self._destroy_cb)
		self.window.show()
		gtk.main()

	def set_branch(self, args):
		"""Fill in different windows with info from the reposiroty"""
		fp = os.popen("git rev-parse --sq --default HEAD " + list_to_string(args, 1))
		git_rev_list_cmd = fp.read()
		fp.close()
		fp = os.popen("git rev-list  --header --topo-order --parents " + git_rev_list_cmd)
		self.update_window(fp)

	def update_window(self, fp):
		commit_lines = []

		self.model = gtk.ListStore(gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT,
				gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT, str, str, str)

		# used for cursor positioning 
		self.index = {}

		self.colours = {}
		self.nodepos = {}
		self.incomplete_line = {}

		index = 0
		last_colour = 0
		last_nodepos = -1
		out_line = []	
		input_line = fp.readline()
		while (input_line != ""):
			# The commit header ends with '\0'
			# This NULL is immediately followed by the sha1 of the 
			# next commit
			if (input_line[0] != '\0'):
				commit_lines.append(input_line)
				input_line = fp.readline()
				continue;

			commit = Commit(commit_lines)
			if (commit != None ):
				(out_line, last_colour, last_nodepos) = self.draw_graph(commit,
										index, out_line,
										last_colour,
										last_nodepos)
				self.index[commit.commit_sha1] = index
				index += 1

			# Skip the '\0
			commit_lines = []
			commit_lines.append(input_line[1:])
			input_line = fp.readline()

		fp.close()

		self.treeview.set_model(self.model)
		self.treeview.show()

	def draw_graph(self, commit, index, out_line, last_colour, last_nodepos):
		in_line=[]

		#   |   -> outline
		#   X
		#   |\  <- inline 

		# Reset nodepostion
		if (last_nodepos > 5):
			last_nodepos = 0

		# Add the incomplete lines of the last cell in this 
		for sha1 in self.incomplete_line.keys():
			if ( sha1 != commit.commit_sha1):
				for pos in self.incomplete_line[sha1]:
					in_line.append((pos, pos, self.colours[sha1]))
			else:
				del self.incomplete_line[sha1]

		try:
			colour = self.colours[commit.commit_sha1]
		except KeyError:
			last_colour +=1
			self.colours[commit.commit_sha1] = last_colour
			colour =  last_colour
		try:
			node_pos = self.nodepos[commit.commit_sha1]
		except KeyError:
			last_nodepos +=1
			self.nodepos[commit.commit_sha1] = last_nodepos
			node_pos = last_nodepos

		#The first parent always continue on the same line
		try:
			# check we alreay have the value
			tmp_node_pos = self.nodepos[commit.parent_sha1[0]]
		except KeyError:
			self.colours[commit.parent_sha1[0]] = colour
			self.nodepos[commit.parent_sha1[0]] = node_pos

		in_line.append((node_pos, self.nodepos[commit.parent_sha1[0]],
					self.colours[commit.parent_sha1[0]]))

		self.add_incomplete_line(commit.parent_sha1[0], index+1)

		if (len(commit.parent_sha1) > 1):
			for parent_id in commit.parent_sha1[1:]:
				try:
					tmp_node_pos = self.nodepos[parent_id]
				except KeyError:
					last_colour += 1;
					self.colours[parent_id] = last_colour
					last_nodepos +=1
					self.nodepos[parent_id] = last_nodepos

				in_line.append((node_pos, self.nodepos[parent_id],
							self.colours[parent_id]))
				self.add_incomplete_line(parent_id, index+1)

		node = (node_pos, colour) 

		self.model.append([commit, node, out_line, in_line,
				commit.message, commit.author, commit.date]) 

		return (in_line, last_colour, last_nodepos)

	def add_incomplete_line(self, sha1, index):
		try:
			self.incomplete_line[sha1].append(self.nodepos[sha1])
		except KeyError:
			self.incomplete_line[sha1] = [self.nodepos[sha1]]


	def _go_clicked_cb(self, widget, revid):
		"""Callback for when the go button for a parent is clicked."""
		try:
			self.treeview.set_cursor(self.index[revid])
		except KeyError:
			print "Revision %s not present in the list" % revid
			# revid == 0 is the parent of the first commit
			if (revid != 0 ):
				print "Try running gitview without any options"

		self.treeview.grab_focus()

	def _show_clicked_cb(self, widget,  commit_sha1, parent_sha1):
		"""Callback for when the show button for a parent is clicked."""
		window = DiffWindow()
		window.set_diff(commit_sha1, parent_sha1)
		self.treeview.grab_focus()

if __name__ == "__main__":
	without_diff = 0

	if (len(sys.argv) > 1 ):
		if (sys.argv[1] == "--without-diff"):
			without_diff = 1

	view = GitView( without_diff != 1)
	view.run(sys.argv[without_diff:])



[-- Attachment #3: gitview.log --]
[-- Type: text/x-log, Size: 1519 bytes --]

commit 14d7d1b8955346a93155f64a3cc51e3b9c419d1d
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Fri Feb 3 09:15:47 2006 +0530

    update copyright and author information

commit 7336d07153635e096b02b282add0c5e07ea6e7e2
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Thu Feb 2 21:51:11 2006 +0530

    [PATCH] display time using timezone information
    From Jonas Fonseca 	<fonseca@diku.dk>

commit 42ddafa3829e5af32093a97566ee195d61b052c0
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Thu Feb 2 16:51:03 2006 +0530

    Better layout with VPaned window
    use diff-tree with --cc option
    Make --with-diff the default and instead have option --without-diff

commit c51f615ffd6f4e591378c514f9cac079ac071231
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Thu Feb 2 12:29:12 2006 +0530

    [PATCH] Use "diff-tree -c" to display merges a bit more readably.
    
    From Junio C Hamano

commit 7235517a31aafc0577a22d806df295a211d14e72
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Thu Feb 2 09:23:28 2006 +0530

    with --with-diff option get the commit message and  code diff using single command.

commit 780c770895fed16a9ea160c1c9919a9291406229
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Wed Feb 1 19:06:48 2006 +0530

    Rearrange the code

commit 5597d066f68e20349d0fd6a1d038aac59866e727
Author: Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Date:   Wed Feb 1 16:41:14 2006 +0530

    Add support for displaying the diff in  the main window.


^ permalink raw reply

* Re: [PATCH] combine-diff: add safety check to --cc.
From: Linus Torvalds @ 2006-02-03  1:05 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v64nxmhqn.fsf@assigned-by-dhcp.cox.net>



On Thu, 2 Feb 2006, Junio C Hamano wrote:
> 
> Two seconds?  You must be using CPUs/disks/memory that are lot
> faster than what I use (the kernel.org machine available to me
> seems to do it at around 3.5 wallclock seconds).  Envy, envy,...

That's not even the fastest machine I have.

However, a lot of it may be due to packing. Packed repositories tend to be 
a lot faster, and this was fully packed.

> Two things to note.
> 
>  * Somebody said he missed "index" lines.  There is one now, but
>    I am wondering if it might be just be an added noise.  It
>    gets absolutely horrible if you run diff-tree on Len's merge.
>    On the other hand, being able to cut&paste them to "git
>    cat-file blob" command line might be handy.
> 
>    Do we want to keep it?

I don't mind it, I have no strong opinions.

>  * I show the line number from the result (+1,93) and then
>    parents' line numbers (-1,87 for the first parent, -1,3 for
>    the second parent).  To be consistent with the normal ones, I
>    am thinking it might be better to move the line number for
>    the result to the last.

I think you're right. The "far off to the right" case is the unusual case, 
I think, and consistency is more important.

But it's certainly not a huge deal for me either.

		Linus

^ permalink raw reply

* Re: [PATCH] combine-diff: add safety check to --cc.
From: Junio C Hamano @ 2006-02-03  0:02 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0602021454060.21884@g5.osdl.org>

Linus Torvalds <torvalds@osdl.org> writes:

> Ok, my testing shows that this is all wonderful.

Thanks for the compliment.

> And now when I look at Len's "Merge from hell", not only does it take less 
> than 2 seconds for git-diff-tree to calculate, it looks correct too. At 
> least I don't see anything that I consider extraneous, although it might, 
> of course, have removed too much, and I'd not notice.

Two seconds?  You must be using CPUs/disks/memory that are lot
faster than what I use (the kernel.org machine available to me
seems to do it at around 3.5 wallclock seconds).  Envy, envy,...

I've done a couple of fixups and added one missing feature and
have pushed it out in 'pu' after some final testing.  The
missing feature was line numbers from each parent.  I could not
count them right for a long time for some unknown silliness.

Before setting the output format in stone by having gitk
interpret it, I'd like to do a quick sanity-check poll.

Len's merge is a bit too wide, so I'll use GIT 1.0.0 commit as
an example.  Here is what I have right now.

        $ git diff-tree --cc v1.0.0 -- debian/changelog | head -n 15
        c2f3bf071ee90b01f2d629921bb04c4f798f02fa
        diff --cc debian/changelog
        index d36904c..376f0fa->4fa6c16
        @@@ +1,93 -1,87 -1,3 @@@
        ++git-core (1.0.0-0) unstable; urgency=low
        ++
        ++  * GIT 1.0.0
        ++
        ++ -- Junio C Hamano <junkio@cox.net>  Wed, 21 Dec 2005...
        ++
         +git-core (0.99.9n-0) unstable; urgency=low
         +
         +  * GIT 0.99.9n aka 1.0rc6
         +
         + -- Junio C Hamano <junkio@cox.net>  Wed, 14 Dec 2005...

Two things to note.

 * Somebody said he missed "index" lines.  There is one now, but
   I am wondering if it might be just be an added noise.  It
   gets absolutely horrible if you run diff-tree on Len's merge.
   On the other hand, being able to cut&paste them to "git
   cat-file blob" command line might be handy.

   Do we want to keep it?

   If we were to keep it, is the format OK?  It lists parent
   blob names (double-dot separated), an arrow, and then result
   blob name.  An alternative would be parent,parent..result,
   like this:

        index d36904c,376f0fa..4fa6c16

   which might be more consistent with the normal ones.

 * I show the line number from the result (+1,93) and then
   parents' line numbers (-1,87 for the first parent, -1,3 for
   the second parent).  To be consistent with the normal ones, I
   am thinking it might be better to move the line number for
   the result to the last.  One downside of that change is I
   tend to use the line number of the result to look up the full
   result more often than to use the line number of the parent,
   and something like Len's merge would push the most important
   line number off the edge of the screen.

   Do we want to keep it the way it is, or do we want to do
   this instead?

        @@@ -1,87 -1,3 +1,93 @@@

^ permalink raw reply

* Re: [PATCH] combine-diff: add safety check to --cc.
From: Linus Torvalds @ 2006-02-02 23:03 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Git Mailing List, Paul Mackerras, Marco Costalba, Aneesh Kumar,
	Len Brown
In-Reply-To: <7vvevyrtn9.fsf_-_@assigned-by-dhcp.cox.net>



On Thu, 2 Feb 2006, Junio C Hamano wrote:
>
> The earlier change implemented "only two version" check but
> without checking if the change rewrites from all the parents.
> This implements a check to make sure that a change introduced
> by the merge from all the parents is caught to be interesting.

Ok, my testing shows that this is all wonderful.

In fact, git-diff-tree now gets the subtle cases right for things that 
"gitk" for some reason gets wrong. I haven't figured out what's wrong with 
gitk, but I don't think it's even worth it: it would be better to just 
teach gitk to use git-diff-tree --cc.

And now when I look at Len's "Merge from hell", not only does it take less 
than 2 seconds for git-diff-tree to calculate, it looks correct too. At 
least I don't see anything that I consider extraneous, although it might, 
of course, have removed too much, and I'd not notice. But it looks great 
(well, as great as it can look without colorization and/or years of 
experience with it - multi-way diffs really aren't very readable ;)

Paul, I'm not able to do something like this in tcl/tk, but could you look 
at trying to make gitk use "git-rev-list --cc" for the colorization?

			Linus

^ permalink raw reply

* Re: Question around git-shell usage in Everyday Git
From: Alan Chandler @ 2006-02-02 21:23 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano
In-Reply-To: <7vbqxqxqk7.fsf@assigned-by-dhcp.cox.net>

On Thursday 02 February 2006 05:44, Junio C Hamano wrote:
...
>
> So in short, I am mildly negative about this.  If I were doing
> this kind of thing I'd have one unix UID and one directory per
> one physical user.  What is the real reason (other than "I just
> do not want to" feeling) you want to have smaller number of home
> directories than you have users?

You are right.  I don't know whether you can tell, but I wrote my last note at 
just gone 5:00am my time this moring  after getting up to go an catch a 
flight to Germany for the day.  I spent the flight and the wait for the 
flight back going over the options in my mind and I NOW think it better to 
have proper home directories.

I do have to say, my motivation originally was more about not announcing to 
the world the internal structure of my filesystem rather than the limitation 
around creating lots of home directories, but part of the reasoning to myself 
today was that that probably doesn't really matter.

-- 
Alan Chandler
http://www.chandlerfamily.org.uk
Open Source. It's the difference between trust and antitrust.

^ permalink raw reply

* Re: [PATCH] Shallow clone: low level machinery.
From: Junio C Hamano @ 2006-02-02 19:31 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.63.0602021932450.16426@wbgn013.biozentrum.uni-wuerzburg.de>

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

> Scenario: I have cvsimported a project. Using a graft, I told git that a 
> certain commit is indeed a merge between two branches. That is, in 
> addition to the parent the commit objects tells us about, it has another 
> parent which was tip of another branch.
>
> How would this graft be interpreted by the server we want to pull from? As 
> if we had cut off the history. Which we did not. In effect, we could be 
> sent many, many objects we already have.

I thought the protocol is sending the full graft file both ways.
The uploader says "here are the grafts I have and use", and the
downloader modifies it and sends back what grafts it wants to
be used during the common revision discovery (aka building
rev-list parameters).  The most important modification during
this exchange is to cauterize the history at --since=v2.6.14
commit (or tag).

The uploader may not have the fake parent you grafted onto a
commit.  You may have a graft entry that says commit W has X, Y
and Z as its parents, when its real parent is only X.  Y may be
some other commit in the project (i.e. the other end knows about
it but it is not a real parent of W), and Z may be from a
development track that the uploader has not even heard of.  You
may say a commit V does not have parent but that commit itself
is from a separate development track the uploader does not know
about.

The uploader, however, should be able to at least honour, modulo
implementation bugs ;-), "X and Y are both parents of W" part.
Just ignoring V and Z and keeping usable part of information
would be a reasonable fallback position [*1*].  And that should
not result in a "many objects" situation when the downloader
says "Now I happen to have W, do not send things reachable from
it".  The uploader side should be able to omit what are
reachable from X or Y even though it cannot exclude things
reachable from Z.  Because the uploader does not even have Z,
there is no reason to worry about things reachable from Z being
sent unnecessarily to the downloader.

At least that was the intention.  "graft" messages are not about
sending "here are the cut-off points"; it is to agree on the
graft information both ends use during the common revision
computation.  The experimental code does not treat cut-offs any
differently other grafts.


[Footnote]

*1* we might want to enhance the "shallow" protocol further to
do this exchange slightly differently.  The downloader first
sends its grafts (which may contain parents or graft/cutoff
points that uploader does not have), and the uploader adjusts
the received grafts for commits like V and parents like Z and
then add its own grafts.  The result is sent back to the
downloader and that becomes the common set of grafts in effect
during the common revision discovery.  This would contain
commits and parents that the downloader does not yet have but
that is not a problem for common revision discovery.  After the
transfer is done, the downloader would adjust its "graft" file
if it made a new shallow clone, but otherwise it should not use
the information it received from the uploader, because things
like V and Z are not in this list.  I _think_ it would suffice
to look at each graft entry and to add that entry locally if it
talks about a commit the downloader does not have in its graft
file.

^ permalink raw reply

* Re: problem compiling tonights Git
From: dave morgan @ 2006-02-02 18:58 UTC (permalink / raw)
  To: git
In-Reply-To: <i6k4u1p8jnuq0anj0v59bep2r6itnqk2ru@4ax.com>

On Thu, 02 Feb 2006 18:41:30 +0000, dave morgan <morgad@eclipse.co.uk>
wrote:

>Debian/testing system, 2.6.15 Kernel, AMD Athlon CPU @ 1Ghz, 512Mb RAM

[snip]

I did another 'make' and it worked the 2nd time ...

I assume it must be local problem with XMMS, X or Gnome

Sorry for the noise

best regards
Dave

^ permalink raw reply

* Re: [PATCH] Shallow clone: low level machinery.
From: Johannes Schindelin @ 2006-02-02 18:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vr76m36ge.fsf@assigned-by-dhcp.cox.net>

Hi,

On Wed, 1 Feb 2006, Junio C Hamano wrote:

> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > I think it would be trivial: just resolve ~A to the tree A points to:
> 
> <tired> Hmph.  I thought you meant "have-only A" to mean similar
> to "have A" but additionally "do not assume I have things behind
> A", and are going to extend rev-list to support ~A syntax to do
> that.  I am a bit surprised to see your "rev-list ~A" is to
> include A, not exclude A and not what are behind A.  Where is
> the connection between this and "have-only A"?  </tired> ;-)

<tired> My patch was wrong. You'd have to introduce a new flag saying: 
Traverse this commit, but mark its parents as uninteresting. </tired>

> > Now, is it possible that a fetch does something unintended, when there are 
> > grafts which are not cutoffs? I don't know yet, but I think so.
> 
> I think we are disagreeing, so "not Exactly".  I meant "grafts
> are grafts, there is no cutoffs, they are also just grafts".  So
> the answer to your question is "it does not matter".

Scenario: I have cvsimported a project. Using a graft, I told git that a 
certain commit is indeed a merge between two branches. That is, in 
addition to the parent the commit objects tells us about, it has another 
parent which was tip of another branch.

How would this graft be interpreted by the server we want to pull from? As 
if we had cut off the history. Which we did not. In effect, we could be 
sent many, many objects we already have.

Ciao,
Dscho

^ permalink raw reply

* problem compiling tonights Git
From: dave morgan @ 2006-02-02 18:41 UTC (permalink / raw)
  To: git

Debian/testing system, 2.6.15 Kernel, AMD Athlon CPU @ 1Ghz, 512Mb RAM
(some of the following lines re-wrapped by my mailer)

david@tower2:~/git$ cg-update -v
Fetching head...
Fetching objects...
progress: 28 objects, 107898 bytes
Fetching tags...
Tree change:
8233340ce6eb700eb2cd9c0fef4d1705997c499b:823bcd6edc7f7330714486b228b052953c2f4229

Applying changes...
Fast-forwarding 8233340ce6eb700eb2cd9c0fef4d1705997c499b ->
823bcd6edc7f7330714486b228b052953c2f4229
        on top of 8233340ce6eb700eb2cd9c0fef4d1705997c499b...
:100644 100644 243f967... 36363bd... M  combine-diff.c
:100644 100644 8ae6dbc... ec51e7d... M  diff.c
:100755 100755 6e3a44a... b6799d8... M  git-svnimport.perl
:100644 100644 92326f9... 97ce13c... M  http-fetch.c
:100644 100644 ad0eafe... f92b960... M  index.c
:100644 100644 1bc1887... a554e07... M  rev-list.c
:100644 100644 a84a04f... afec98d... M  update-index.c
david@tower2:~/git$ make install
GIT_VERSION = 1.1.6.g823b
gcc -o index.o -c -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>' index.c
gcc -o diff.o -c -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  diff.c
gcc -o combine-diff.o -c -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'
combine-diff.c
ar rcs libgit.a blob.o commit.o connect.o count-delta.o csum-file.o
date.o diff-delta.o entry.o exec_cmd.o ident.o index.o object.o
pack-check.o patch-delta.o path.o pkt-line.o quote.o read-cache.o
refs.o run-command.o server-info.o setup.o sha1_file.o sha1_name.o
strbuf.o tag.o tree.o usage.o config.o environment.o ctype.o copy.o
fetch-clone.o diff.o diffcore-break.o diffcore-order.o
diffcore-pathspec.o diffcore-pickaxe.o diffcore-rename.o tree-diff.o
combine-diff.o epoch.o
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-apply apply.o
libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-cat-file
cat-file.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o
git-checkout-index  checkout-index.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-clone-pack
clone-pack.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-commit-tree
commit-tree.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o
git-convert-objects  convert-objects.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-diff-files
diff-files.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-diff-index
diff-index.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-diff-stages
diff-stages.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-diff-tree
diff-tree.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-fetch-pack
fetch-pack.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-fsck-objects
fsck-objects.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-hash-object
hash-object.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-index-pack
index-pack.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-init-db
init-db.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-local-fetch
local-fetch.o fetch.o libgit.a -lz  -lcrypto
gcc -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'  -o git-ls-files
ls-files.o libgit.a -lz  -lcrypto
collect2: ld terminated with signal 11 [Segmentation fault]
make: *** [git-ls-files] Error 1


david@tower2:~/git$ ld --version
GNU ld version 2.16.91 20051214 Debian GNU/Linux
Copyright 2005 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms
of
the GNU General Public License.  This program has absolutely no
warranty.


is this a problem with git-ls-files, or my toolchain?

best regards
Dave

^ permalink raw reply

* gitk changing line color for no reason after merge
From: Pavel Roskin @ 2006-02-02 17:21 UTC (permalink / raw)
  To: Paul Mackerras, git

Hello, Paul!

I have noticed that gitk changes the line color at a commit following a
merge (i.e. a commit with many parents).  I made this screenshot to
demonstrate the problem:

http://red-bean.com/proski/gitk/gitk.png

If you follow the leftmost line, you'll see how green becomes red, gray
becomes brown and red becomes blue.

I think it would be much better if line colors only change at
non-trivial nodes, i.e. those with more than one child or parent.

The fix is trivial:

diff --git a/gitk b/gitk
index f12b3ce..14ff570 100755
--- a/gitk
+++ b/gitk
@@ -770,7 +770,7 @@ proc assigncolor {id} {
 
     if [info exists colormap($id)] return
     set ncolors [llength $colors]
-    if {$nparents($id) <= 1 && $nchildren($id) == 1} {
+    if {$nchildren($id) == 1} {
 	set child [lindex $children($id) 0]
 	if {[info exists colormap($child)]
 	    && $nparents($child) == 1} {


I checked the history of gitk and could trace this code back to the
first version of gitk in the git repository.  Maybe it was intended this
way, but I think it would be better to fix it.

-- 
Regards,
Pavel Roskin

^ permalink raw reply related

* [PATCH 1/2] Provide a more meaningful initial "From " line when using --compose in git-send-email.
From: Ryan Anderson @ 2006-02-02 16:56 UTC (permalink / raw)
  To: git; +Cc: Ryan Anderson
In-Reply-To: <11388993661745-git-send-email-ryan@michonline.com>

git-send-email, when used with --compose, provided the user with a mbox-format
file to edit.  Some users, however, were confused by the leading, blank, "From
" line, so this change puts the value that will appear on the From: line of the
actual email on this line, along with a note that the line is ignored.

Signed-off-by: Ryan Anderson <ryan@michonline.com>

---

 git-send-email.perl |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

c6b0c22e482aa6fe314e4be077d705c98fee7bf2
diff --git a/git-send-email.perl b/git-send-email.perl
index ec1428d..51b7513 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -125,7 +125,7 @@ if ($compose) {
 	# effort to have it be unique
 	open(C,">",$compose_filename)
 		or die "Failed to open for writing $compose_filename: $!";
-	print C "From \n";
+	print C "From $from # This line is ignored.\n";
 	printf C "Subject: %s\n\n", $initial_subject;
 	printf C <<EOT;
 GIT: Please enter your email below.
-- 
1.1.4.g3dcbd

^ permalink raw reply related

* [PATCH 0/2] Small updates to git-send-email
From: Ryan Anderson @ 2006-02-02 16:56 UTC (permalink / raw)
  To: git

These updates fix some usability issues raised by Octavian in #git.

Thanks for the feedback!

-- 
Ryan Anderson
  sometimes Pug Majere

^ permalink raw reply

* [PATCH 2/2] git-send-email: Add --quiet to reduce some of the chatter when sending emails.
From: Ryan Anderson @ 2006-02-02 16:56 UTC (permalink / raw)
  To: git; +Cc: Ryan Anderson
In-Reply-To: <11388993663675-git-send-email-ryan@michonline.com>

Signed-off-by: Ryan Anderson <ryan@michonline.com>

---

 git-send-email.perl |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

3dcbd6298dc6fb4a903404cb9c47e3690bf2e01a
diff --git a/git-send-email.perl b/git-send-email.perl
index 51b7513..ca1fa37 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -34,7 +34,7 @@ my $compose_filename = ".msg.$$";
 my (@to,@cc,$initial_reply_to,$initial_subject,@files,$from,$compose);
 
 # Behavior modification variables
-my ($chain_reply_to, $smtp_server) = (1, "localhost");
+my ($chain_reply_to, $smtp_server, $quiet) = (1, "localhost", 0);
 
 # Example reply to:
 #$initial_reply_to = ''; #<20050203173208.GA23964@foobar.com>';
@@ -51,6 +51,7 @@ my $rc = GetOptions("from=s" => \$from,
 		    "chain-reply-to!" => \$chain_reply_to,
 		    "smtp-server=s" => \$smtp_server,
 		    "compose" => \$compose,
+		    "quiet" => \$quiet,
 	 );
 
 # Now, let's fill any that aren't set in with defaults:
@@ -267,8 +268,10 @@ sub send_message
 
 	sendmail(%mail) or die $Mail::Sendmail::error;
 
-	print "OK. Log says:\n", $Mail::Sendmail::log;
-	print "\n\n"
+	unless ($quiet) {
+		print "OK. Log says:\n", $Mail::Sendmail::log;
+		print "\n\n"
+	}
 }
 
 
-- 
1.1.4.g3dcbd

^ permalink raw reply related


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