Git development
 help / color / mirror / Atom feed
* Re: [RFC] git integrated bugtracking
From: Guilhem Bonnefille @ 2007-06-12  8:54 UTC (permalink / raw)
  To: Git List
In-Reply-To: <1181587892.3380.37.camel@ld0161-tx32>

Hi,

This subject is quite interesting. I read that one of the main
expected goal of integrating SCM and BT is to help release manager in
its task.

In my point of view, we have to keep in mind that it's not because a
commit solved a problem, that all the following commits will always
solve the problem. Development ALWAYS suffers regression. The really
way to avoid this is to have an organisation of code that allows
automatic tests. So it needs something greater than the SCM: you have
to be organized for this.

One interesting project to have a look for is aegis (
http://aegis.sourceforge.net/ ).
It proposes a sort of SCM, that integrates process to ensure quality
of code. One of them is that the /SCM/ will control the non regression
before commiting.

I hope these informations will help defining how we can design a
system that integrates SCM and BT in a distributed manner.
-- 
Guilhem BONNEFILLE
-=- #UIN: 15146515 JID: guyou@im.apinc.org MSN: guilhem_bonnefille@hotmail.com
-=- mailto:guilhem.bonnefille@gmail.com
-=- http://nathguil.free.fr/

^ permalink raw reply

* Re: git-svn set-tree bug
From: Eric Wong @ 2007-06-12  8:39 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Joakim Tjernlund, Steven Grimm, git
In-Reply-To: <7v1wghlj7j.fsf@assigned-by-dhcp.pobox.com>

Junio C Hamano <gitster@pobox.com> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> > If dcommit detects a merge commit when doing rev-list When looking at
> > commit objects, is it safe to assume that the first parent is always the
> > "mainline" and that parents after it are the ones to merge from?
> >
> > So if I saw:
> >
> > commit $X
> > parent $A
> > parent $B
> >
> > I'd basically do:
> >   reset --hard $A
> >   merge --squash $B
> >
> > And resulting in $C which would have the same tree as $X,
> > then, when dcommit-ting, $D would be created with two parents:
> >   $D~1 (svn), $B (git), but not $A
> 
> I am not sure what you mean by "mainline", but I assume that you
> mean "SVN is the main and we are tracking it while taking
> advantage of more efficient and merge-capable git in guerrilla
> fashion".  Because the tip of the current branch is what the
> user is pushing back to SVN via dcommit, I would say it is safe
> to assume that the first parent of such a merge is the line that
> corresponds to the SVN branch you are keeping track.

Yes, "mainline" meaning the history that would be committed to SVN if
history were linear.

I've gotten the following patch working for Joakim's second test script
(with dcommit before merge).  However, without the dcommit before merge
in the first test script, git-svn has trouble figuring out which history
to follow.  It'll take more work to figure out what to do in this
situation, and how to deal with more complex history...

Subject: git-svn: Allow dcommit to handle certain single-parent merge commits

This only works if a merge is the first commit to be committed
in a chain of commits.
---
 git-svn.perl |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 0ae8d70..6b3e021 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -403,6 +403,9 @@ sub cmd_dcommit {
 			                svn_path => '');
 			if (!SVN::Git::Editor->new(\%ed_opts)->apply_diff) {
 				print "No changes\n$d~1 == $d\n";
+			} elsif (my $merge_parent = verify_ref("$d^2")) {
+				$gs->{inject_parents}->{$last_rev} =
+				                                 $merge_parent;
 			}
 		}
 	}
-- 
Eric Wong

^ permalink raw reply related

* Re: [PATCH 5/5] Add gitmodules(5)
From: Lars Hjemli @ 2007-06-12  8:27 UTC (permalink / raw)
  To: skimo; +Cc: Frank Lichtenheld, Junio C Hamano, git
In-Reply-To: <20070612080402.GQ955MdfPADPa@greensroom.kotnet.org>

On 6/12/07, Sven Verdoolaege <skimo@kotnet.org> wrote:
> On Tue, Jun 12, 2007 at 09:05:21AM +0200, Lars Hjemli wrote:
> > +The file contains one subsection per submodule, and the subsection value
> > +is the name of the submodule. Each submodule section also contains the
> > +following required keys:
>
> Your only argument for making them required was that Junio thought that
> not having them might be ambiguous, but he doesn't think so anymore.

Well, I actually also had an argument about being strict in the
beginning and possibly loosen the rules later on. Anyways, I can do a
patch on top of this series (if/when it's accepted) and let Junio
decide to apply or drop the 'optional path' stuff.

>
> > +submodule.<name>.path::
> > +     Defines the path, relative to the top-level directory of the git
>
> Your previous patch had "_a_ path" instead of "_the_ path".
> I prefer the former since it allows a module to be checkoud out
> at multiple locations.

This is somewhat intentional. I want to move the submodule repos into
.git/submodules/$name/ (with working dir) and symlink this directory
when 'checking out' the submodule. This would be a simple solution for
the following problems:
  -keeping submodule modifications between checkouts
  -having submodules within submodules

Multiple checkout paths for a single submodule will bring havoc on
this plan, so I need to ask: what is the use-case for multiple
checkout paths?

-- 
larsh

^ permalink raw reply

* Re: git-svn set-tree bug
From: Lars Hjemli @ 2007-06-12  8:04 UTC (permalink / raw)
  To: Eric Wong; +Cc: Junio C Hamano, Joakim Tjernlund, Steven Grimm, git
In-Reply-To: <20070612072035.GA29385@muzzle>

On 6/12/07, Eric Wong <normalperson@yhbt.net> wrote:
> If dcommit detects a merge commit when doing rev-list When looking at
> commit objects, is it safe to assume that the first parent is always the
> "mainline" and that parents after it are the ones to merge from?
>
> So if I saw:
>
> commit $X
> parent $A
> parent $B
>
> I'd basically do:
>   reset --hard $A
>   merge --squash $B
>
> And resulting in $C which would have the same tree as $X,
> then, when dcommit-ting, $D would be created with two parents:
>   $D~1 (svn), $B (git), but not $A
>
> Rewritten history:
>   $A         =>  $D~1
>   $X         =>  $D (HEAD revision in SVN)
>
> $X and $A are now discarded and gc-able.
>
>
> Of course, since I already have the result of "merge --squash $B" in $X,
> I could just rewrite $X with a single parent (call it $X'), dcommit, and
> then give $D ($D~1 and $B) as parents.  Avoiding the nastiness of
> set-tree
>

Would it be possible to keep the 'local commit' $X and change the
mapping in .rev_db to point at $X instead of $D? This would of course
require a matching TREE-ID + noMetadata=1. I've been tempted to try to
implement this, but my perl-skills are sadly non-existent.

If this is possible it would make my day-job interaction with svn a
much more pleasant experience: push/pull between git repos would 'just
work' (without -f).

And if "follow left parent" also works out, I (and our
'releasemaster') can finally do all merging in git (without --squash)
and preserve the DAG. Ahh, that would be great...

--
larsh

^ permalink raw reply

* Re: [PATCH 5/5] Add gitmodules(5)
From: Sven Verdoolaege @ 2007-06-12  8:04 UTC (permalink / raw)
  To: Lars Hjemli; +Cc: Frank Lichtenheld, Junio C Hamano, git
In-Reply-To: <11816319211097-git-send-email-hjemli@gmail.com>

On Tue, Jun 12, 2007 at 09:05:21AM +0200, Lars Hjemli wrote:
> +The file contains one subsection per submodule, and the subsection value
> +is the name of the submodule. Each submodule section also contains the
> +following required keys:

Your only argument for making them required was that Junio thought that
not having them might be ambiguous, but he doesn't think so anymore.

> +submodule.<name>.path::
> +	Defines the path, relative to the top-level directory of the git

Your previous patch had "_a_ path" instead of "_the_ path".
I prefer the former since it allows a module to be checkoud out
at multiple locations.

skimo

^ permalink raw reply

* Re: git-svn set-tree bug
From: Junio C Hamano @ 2007-06-12  7:34 UTC (permalink / raw)
  To: Eric Wong; +Cc: Joakim Tjernlund, Steven Grimm, git
In-Reply-To: <20070612072035.GA29385@muzzle>

Eric Wong <normalperson@yhbt.net> writes:

> If dcommit detects a merge commit when doing rev-list When looking at
> commit objects, is it safe to assume that the first parent is always the
> "mainline" and that parents after it are the ones to merge from?
>
> So if I saw:
>
> commit $X
> parent $A
> parent $B
>
> I'd basically do:
>   reset --hard $A
>   merge --squash $B
>
> And resulting in $C which would have the same tree as $X,
> then, when dcommit-ting, $D would be created with two parents:
>   $D~1 (svn), $B (git), but not $A

I am not sure what you mean by "mainline", but I assume that you
mean "SVN is the main and we are tracking it while taking
advantage of more efficient and merge-capable git in guerrilla
fashion".  Because the tip of the current branch is what the
user is pushing back to SVN via dcommit, I would say it is safe
to assume that the first parent of such a merge is the line that
corresponds to the SVN branch you are keeping track.

^ permalink raw reply

* Re: git-svn set-tree bug
From: Eric Wong @ 2007-06-12  7:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Joakim Tjernlund, Steven Grimm, git
In-Reply-To: <7vir9vox5l.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> > Joakim Tjernlund <joakim.tjernlund@transmode.se> wrote:
> >> > -----Original Message-----
> >> > From: Steven Grimm [mailto:koreth@midwinter.com] 
> >> > Sent: den 11 juni 2007 01:37
> >> > To: Joakim Tjernlund
> >> > Cc: 'Eric Wong'; 'git'
> >> > Subject: Re: git-svn set-tree bug
> >> > 
> >> > Joakim Tjernlund wrote:
> >> > > Is there a way to tell set-tree to commit the whole "merge" branch
> >> > > as one svn commit?
> >> > > If I merge the latest kernel into my tree there will
> >> > > be a lot of commits that I don't want in svn.
> >> > >   
> >> > 
> >> > You want a "squash" merge. Something like this:
> >> > 
> >> > git checkout -b tempbranch origin/svn-branch-to-commit-merge-to
> >> > git merge --squash branch-with-commits-you-want-to-merge
> >> > git commit
> >> > git svn dcommit
> >> > 
> >> > The "merge" command will merge in the changes but will not commit 
> >> > anything; when you do the explicit "commit" command 
> >> > afterwards, you get 
> >> > the contents of the merge but from git's point of view it's just a 
> >> > regular commit so git-svn doesn't get confused.
> >> > 
> >> > After you do git svn dcommit, you may want to edit 
> >> > .git/info/grafts to 
> >> > tell git after the fact that this commit was a merge. It won't hurt 
> >> > git-svn at that point and it will mean you can do another merge later 
> >> > without git getting confused about what has already been merged.
> >> > 
> >> > Take a look at the script I posted a while back, which does something 
> >> > similar:
> >> > 
> >> > http://www.spinics.net/lists/git/msg29119.html
> >
> > I must have missed this message the first time around.
> >
> >> Hi Steven
> >> 
> >> That looks promising, especially Junos comment about making git-svn
> >> able to deal with merges. Eric, do you feel this is doable?
> >
> > Doable?  Yes.  However, I think using grafts is quite hackish and
> > unreliable[1].  I'd rather just have users using set-tree if
> > they want to deal with non-linear history in the first place.
> >
> > I'd personally avoid any sort of non-linear history when interacting
> > with SVN repositories, however.
> 
> I've been wondering if you can do a moral equilvalent of the
> graft trick but without using graft inside dcommit.  Perform a
> merge --squash of the other branch (call the tip commit $B),
> then dcommit on the git side as usual, and call it commit $C.
> Steven's procedure would do a graft trick here, but instead of
> doing that, rewrite $C to have the two parents.  Using the tree
> object of $C, create a new git commit $D that is a merge between
> the parent of $C (i.e. $C^) and the squashed branch tip $B.
> Replace the tip of the current branch (which is $C) with $D.
> Finally, replace the mapping between svn commit and git side
> recorded in the revdb (which currently says $C on the git side
> corresponds to the HEAD of SVN side) with this new commit $D.
> 
> Wouldn't that let the git side know what was merged into the
> branch, so that later merges on the git side would go smoothly?
> 
> Or am I grossly misunderstanding how dcommit, tracking of svn vs
> git commit mappings and the graft trick work?

Ok, it took me a few reads, but I think that'll work...

If dcommit detects a merge commit when doing rev-list When looking at
commit objects, is it safe to assume that the first parent is always the
"mainline" and that parents after it are the ones to merge from?

So if I saw:

commit $X
parent $A
parent $B

I'd basically do:
  reset --hard $A
  merge --squash $B

And resulting in $C which would have the same tree as $X,
then, when dcommit-ting, $D would be created with two parents:
  $D~1 (svn), $B (git), but not $A

Rewritten history:
  $A         =>  $D~1
  $X         =>  $D (HEAD revision in SVN)

$X and $A are now discarded and gc-able.


Of course, since I already have the result of "merge --squash $B" in $X,
I could just rewrite $X with a single parent (call it $X'), dcommit, and
then give $D ($D~1 and $B) as parents.  Avoiding the nastiness of
set-tree

-- 
Eric Wong

^ permalink raw reply

* Re: [PATCH 1/3] refactor dir_add_name
From: Junio C Hamano @ 2007-06-12  7:13 UTC (permalink / raw)
  To: Jeff King; +Cc: Jonas Fonseca, git
In-Reply-To: <20070611194651.GA15309@coredump.intra.peff.net>

Jeff King <peff@peff.net> writes:

> ... But we could do something like
> (totally untested):
>
> #define alloc_grow(x, nr, alloc) \
>   alloc_grow_helper(&(x), nr, &(alloc), sizeof(*(x)))
>
> inline
> void alloc_grow_helper(void **x, int nr, int *alloc, int size)
> {
>   if (nr >= *alloc) {
>     *alloc = alloc_nr(*alloc);
>     *x = xrealloc(*x, *alloc * size);
>   }
> }
>
> Horribly ugly (I'm seeing stars!) but probably a bit safer in the long
> run, and nobody needs to look at it most of the time. :)
>
> What do you think?

That looks ugly and also I am curious what the generated
assembly would look like.  Hopefully the compiler is clever
enough to generate the same code, but I dunno.

Unless somebody else more versed with C preprocessor tricks
comes along and offers a better advice, I would go with the
earlier simpler one with a big fat warning.  I however would
prefer all caps name for a magic macro like this, whose sole
point is a huge side effect.

Anyway, it appears that Jonas picked up your patch to polish up,
so I won't touch this series until that resurfaces.

^ permalink raw reply

* [PATCH 5/5] Add gitmodules(5)
From: Lars Hjemli @ 2007-06-12  7:05 UTC (permalink / raw)
  To: Frank Lichtenheld; +Cc: Junio C Hamano, git
In-Reply-To: <20070611225918.GD4323@planck.djpig.de>

This adds documentation for the .gitmodules file.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---

On 6/12/07, Frank Lichtenheld <frank@lichtenheld.de> wrote:
> On Mon, Jun 11, 2007 at 09:12:25PM +0200, Lars Hjemli wrote:
> > +Consider the following .gitmodules file:
> > +
> > +     [submodule 'libfoo']
> > +             path = include/foo
> > +             url = git://foo.com/git/lib.git
> > +
> > +     [submodule 'libbar']
> > +             path = include/bar
> > +             url = git://bar.com/git/lib.git
> > +
> 
> Still the wrong quotes.

Thanks for noticing


 Documentation/Makefile       |    2 +-
 Documentation/gitmodules.txt |   62 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletions(-)
 create mode 100644 Documentation/gitmodules.txt

diff --git a/Documentation/Makefile b/Documentation/Makefile
index 9cef480..2ad18e0 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -2,7 +2,7 @@ MAN1_TXT= \
 	$(filter-out $(addsuffix .txt, $(ARTICLES) $(SP_ARTICLES)), \
 		$(wildcard git-*.txt)) \
 	gitk.txt
-MAN5_TXT=gitattributes.txt gitignore.txt
+MAN5_TXT=gitattributes.txt gitignore.txt gitmodules.txt
 MAN7_TXT=git.txt
 
 DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT))
diff --git a/Documentation/gitmodules.txt b/Documentation/gitmodules.txt
new file mode 100644
index 0000000..6c7d9bf
--- /dev/null
+++ b/Documentation/gitmodules.txt
@@ -0,0 +1,62 @@
+gitmodules(5)
+=============
+
+NAME
+----
+gitmodules - defining submodule properties
+
+SYNOPSIS
+--------
+.gitmodules
+
+
+DESCRIPTION
+-----------
+
+The `.gitmodules` file, located in the top-level directory of a git
+working tree, is a text file with a syntax matching the requirements
+of gitlink:git-config[1].
+
+The file contains one subsection per submodule, and the subsection value
+is the name of the submodule. Each submodule section also contains the
+following required keys:
+
+submodule.<name>.path::
+	Defines the path, relative to the top-level directory of the git
+	working tree, where the submodule is expected to be checked out.
+	The path name must not end with a `/`. All submodule paths must
+	be unique within the .gitmodules file.
+
+submodule.<name>.url::
+	Defines an url from where the submodule repository can be cloned.
+
+
+EXAMPLES
+--------
+
+Consider the following .gitmodules file:
+
+	[submodule "libfoo"]
+		path = include/foo
+		url = git://foo.com/git/lib.git
+
+	[submodule "libbar"]
+		path = include/bar
+		url = git://bar.com/git/lib.git
+
+
+This defines two submodules, `libfoo` and `libbar`. These are expected to
+be checked out in the paths 'include/foo' and 'include/bar', and for both
+submodules an url is specified which can be used for cloning the submodules.
+
+SEE ALSO
+--------
+gitlink:git-submodule[1] gitlink:git-config[1]
+
+DOCUMENTATION
+-------------
+Documentation by Lars Hjemli <hjemli@gmail.com>
+
+GIT
+---
+Part of the gitlink:git[7] suite
-- 
1.5.2.1.914.gbd3a7

^ permalink raw reply related

* Re: Does anyone have any benchmarks against CVS?
From: Martin Langhoff @ 2007-06-12  6:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: linux@horizon.com, git
In-Reply-To: <7vlkeqnm96.fsf@assigned-by-dhcp.pobox.com>

On 6/12/07, Junio C Hamano <gitster@pobox.com> wrote:
> "Martin Langhoff" <martin.langhoff@gmail.com> writes:
>
> > It _will_ be a bit of an apple-to-oranges comparison, but you could
> > use a few large-ish projects that have a published GIT gateway.
> > ...
> >   - cvs status vs git status
>
> This _is_ apples and oranges.

_All_ of them are ;-)

git-log is _not_ the same as cvs log. And a clone is not the same as a
checkout, ever. Perhaps diff is the only reasonable comparison.

However, the benchmarks doco can show the comparative numbers and
explain how those are different. Which is a great alibi to explain why
almost all the git ops are insanely faster * and some of the
interesting concepts behind git.

* - except clone - but mention "--references" to speed it up)

> people seem to use "cvs -q update -n" often
> when they want to know "what's different between me and
> upstream"?

I'm one of those ;-)

>  - "git am a-dozen-of-mails" vs its cvs equivalent.
>  - "git rebase a-dozen-of-commits" vs its cvs equivalent.

Don't thing those exist.

cheers


martin

^ permalink raw reply

* Re: That improved git-gui blame viewer..
From: Junio C Hamano @ 2007-06-12  6:52 UTC (permalink / raw)
  To: Marco Costalba
  Cc: Junio C Hamano, Linus Torvalds, Shawn O. Pearce, Git Mailing List
In-Reply-To: <e5bfff550706112316j42c7c8e8uf8383de990ca9707@mail.gmail.com>

"Marco Costalba" <mcostalba@gmail.com> writes:

> On 6/11/07, Junio C Hamano <gitster@pobox.com> wrote:
>>
>> An option to re-blame starting from the parent commit of what is
>> currently blamed (i.e. "peel" one level) would certainly be
>> interesting but I do not think git-gui has it (yet).
>
> Not to advertise, but qgit has already that from ages.

Advertising is good.

> Annotate algorithm of qgit is little different in that it starts from
> the oldest revision that modified a file and goes to the latest. In
> this way we can have the whole file history annotated in one pass and
> very fast.

I am not sure about two things in this description.

 (1) Are you emulating CVS-like "a file has an identity, and we
     follow its changes" model?  How does it handle file split,
     merge, and code movement in general?

 (2) It is unclear why going from old to new has the advantage
     of being "one pass", implication of which is that the
     opposite direction needs to be done as more than one pass.
     Care to enlighten?

^ permalink raw reply

* Re: [PATCH 0/3] Support config-based names
From: Junio C Hamano @ 2007-06-12  6:44 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706120131010.5848@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> On Mon, 11 Jun 2007, Junio C Hamano wrote:
>
>> Daniel Barkalow <barkalow@iabervon.org> writes:
>
> What I'm worried about is whether we'll eventually want some sort of 
> function and an object with the same name, and then have to have a syntax 
> problem with legacy functions being confusing.

I would agree that I'd worry about that; we will eventually want
some sort of function that is user customizable from command
line, in the same sense as "@{any date specifier}" but possibly
stronger.  And at that point, even [] would get in the way of
that scriptable part.  I'd prefer to provide a set of well
defined and usable "atoms" and let the people script with them.

>> We need to see how useful this would be in practice; we would
>> not want to add new syntax without a set of convincing use
>> cases.  At this point, it still feels as if it is a feature that
>> was implemented only because it could, not because there was a
>> real need.
>
> I'd be a lot more reliable at using git if git-commit reported "git log 
> --pretty=oneline HEAD^{push}..HEAD" after each commit (if there is a 
> HEAD^{push}). I'm forever committing things and forgetting to push them 
> when I mean to.

First, I think 'push' is a misnomer for that purpose, as your
widely popular "pretend we immediately fetched back" topic made
remote tracking branches, which were originally associated more
strongly to 'fetch', associated equally well to 'push'.  You are
comparing what the remote counterpart of your current branch has
(or supposed to have) with what you built.  So I would have
called it 'remote'.

Second, more importantly, that functionality to do log or diff
would go to post commit hook script, and you shouldn't have to
have such a built-in "function" and new syntax to implement
that.  I think more generally useful would be a change to "git
remote" to teach what "git-parse-remote" historically has done,
so that scripts can ask things like:

 - what is the symbolic name of the remote associated with my
   current branch (i.e. branch.$current.remote)?

 - what is the url of the remote given its symbolic name
   (i.e. remote.$remote.url and URL: in .git/remotes/$remote)?

 - what branch at the remote would my current branch pushed to
   (i.e. $current mapped through remote.$remote.push and Push: in
   .git/remotes/$remote)?

 - what remote tracking branch I am using to track that branch
   (i.e. that remote branch mapped through remote.$remote.fetch
   and Pull: in .git/remotes/$remote)?

 - what remote branch do I usually merge into my current branch
   (i.e. branch.$current.merge or the "first refspec listed"
   fallback)?

and combinations of the above.  I would even prefer the
"combinations" to be performed by callers of "git remote", iow,
in your hook script, not as myriad of "git remote" options.

> I didn't have a particular need for ^{merge}, but I accidentally wrote it 
> first because I was confused as to what I wanted.

The last question above is there for completeness.  I think it
would also be a good thing to give to the user.

In other words, I think the questions I listed above are "atoms"
at more appropriate granularity to build flexible tools out of
in order to fit people's different workflow, and I think it is
way premature to embed only a selected-few combinations of them
into syntax sha1_name.c understands.

^ permalink raw reply

* Re: [PATCH] git-svn: use git-log rather than rev-list | xargs cat-file
From: Eric Wong @ 2007-06-12  6:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Sam Vilain, git
In-Reply-To: <7vhcpfrlk1.fsf@assigned-by-dhcp.pobox.com>

Junio C Hamano <gitster@pobox.com> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> > Sam Vilain <sam@vilain.net> wrote:
> >> This saves a bit of time when rebuilding the git-svn index.
> >
> > Does git-log still have the 16k buffer limit?  If so then we can't use
> > it because commit messages over 16k will be truncated and the git-svn-id
> > line will not show up.  Also, if that limit is removed I'd prefer to
> > just add --pretty=raw to rev-list because git-log is stil porcelain and
> > more likely to change.
> 
> How about this?  It passes the test suite, but other than that
> hasn't seen much test yet.  I tried to be careful, but sanity
> checking by extra sets of eyeballs would be needed.

The patch looks and runs alright to me, but then again I haven't looked
at the C portions of git in a while :x

I expected the malloc/free overhead to be much greater, but it's hardly
noticeable (nor measureable with /usr/bin/time or bash built-in time).
There are just a handful more pagefaults measured with /usr/bin/time,
but the runtime performance is neck-and-neck with/without the patch.

Maybe glibc (2.3.6 on x86 Debian Etch) and Linux (2.6.18) are just doing
a very good job with memory allocation... I wonder how well it runs on
other platforms.

-- 
Eric Wong

^ permalink raw reply

* Re: That improved git-gui blame viewer..
From: Marco Costalba @ 2007-06-12  6:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, Shawn O. Pearce, Git Mailing List
In-Reply-To: <7vveduqxxr.fsf@assigned-by-dhcp.pobox.com>

On 6/11/07, Junio C Hamano <gitster@pobox.com> wrote:
>
> An option to re-blame starting from the parent commit of what is
> currently blamed (i.e. "peel" one level) would certainly be
> interesting but I do not think git-gui has it (yet).

Not to advertise, but qgit has already that from ages.

Annotate algorithm of qgit is little different in that it starts from
the oldest revision that modified a file and goes to the latest. In
this way we can have the whole file history annotated in one pass and
very fast.

Currently the slowest steps are, from fastest to slowest:

1 - annotating the files
2 - getting the file history
3 - getting the corrisponding patches (in case of long histories)


Thanks for your patience.
Marco

^ permalink raw reply

* Re: [PATCH 0/3] Support config-based names
From: Daniel Barkalow @ 2007-06-12  5:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbqfln3mf.fsf@assigned-by-dhcp.pobox.com>

On Mon, 11 Jun 2007, Junio C Hamano wrote:

> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > It can be useful to refer to commits in remotes based on their configured 
> > relationship to local branches. For example, "git log HEAD^[push]..HEAD" 
> > would, when pushing is set up, show what hasn't been pushed yet.
> 
> It's not like we will be adding 'push' objects and 'merge'
> objects, so I think HEAD^{push} (curly brace, not bracket) is
> good enough.

What I'm worried about is whether we'll eventually want some sort of 
function and an object with the same name, and then have to have a syntax 
problem with legacy functions being confusing.

> We need to see how useful this would be in practice; we would
> not want to add new syntax without a set of convincing use
> cases.  At this point, it still feels as if it is a feature that
> was implemented only because it could, not because there was a
> real need.

I'd be a lot more reliable at using git if git-commit reported "git log 
--pretty=oneline HEAD^{push}..HEAD" after each commit (if there is a 
HEAD^{push}). I'm forever committing things and forgetting to push them 
when I mean to. My original series actually ended with adding something to 
git-commit.sh, but I decided I didn't like the implementation of that 
actual patch.

I didn't have a particular need for ^{merge}, but I accidentally wrote it 
first because I was confused as to what I wanted. I think "git diff 
HEAD^{merge}" might be good for finding out what work you've done that 
hasn't gotten in yet.

Of course, for particular cases, it's just as easy to type the actual 
tracking branch name on the command line, but ^{push} and ^{merge} can be 
used genericly in scripts, because the same common or pattern works for 
any branch.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* [PATCH] Extend --pretty=oneline to cover the first paragraph, so that an ugly commit message like this can be handled sanely.
From: Junio C Hamano @ 2007-06-12  5:34 UTC (permalink / raw)
  To: git
In-Reply-To: <7vhcpfrlk1.fsf@assigned-by-dhcp.pobox.com>

Currently, --pretty=oneline and --pretty=email (hence
format-patch) take and use only the first line of the commit log
message.  This changes them to:

 - Take the first paragraph, where the definition of the first
   paragraph is "skip all blank lines from the beginning, and
   then grab everything up to the next empty line".

 - Replace all line breaks with a whitespace.

This change would not affect a well-behaved commit message that
adheres to the convention of "single line summary, a blank line,
and then body of message", as its first paragraph always
consists of a single line.  Commit messages from different
culture, such as the ones imported from CVS/SVN, can however get
chomped with the existing behaviour at the first linebreak in
the middle of sentence right now, which would become much easier
to see with this change.

The Subject: and --pretty=oneline output would become very long
and unsightly for non-conforming commits, but their messages are
already ugly anyway, and thischange at least avoids the loss of
information.

The Subject: line from a multi-line paragraph is folded using
RFC2822 line folding rules at the places where line breaks were
in the original.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 * This is on top of the previous "Lift 16kB limit" clean-up.
   I haven't checked what mailinfo does when it unfolds a folded
   Subject: line yet, but it may have to be updated to match
   this, so that "format-patch --stdout | am" behaves sanely on
   commits with multi-line first paragraph.

 commit.c |  396 +++++++++++++++++++++++++++++++++++++++++---------------------
 1 files changed, 262 insertions(+), 134 deletions(-)

diff --git a/commit.c b/commit.c
index d43a68e..e2fd9ba 100644
--- a/commit.c
+++ b/commit.c
@@ -529,6 +529,14 @@ static int add_rfc2047(char *buf, const char *line, int len,
 	return bp - buf;
 }
 
+static unsigned long bound_rfc2047(unsigned long len, const char *encoding)
+{
+	/* upper bound of q encoded string of length 'len' */
+	unsigned long elen = strlen(encoding);
+
+	return len * 3 + elen + 100;
+}
+
 static int add_user_info(const char *what, enum cmit_fmt fmt, char *buf,
 			 const char *line, enum date_mode dmode,
 			 const char *encoding)
@@ -922,6 +930,224 @@ static long format_commit_message(const struct commit *commit,
 	return strlen(*buf_p);
 }
 
+#define ALLOC_GROW(buf, space, need) \
+	do { \
+		if ((space) < (need)) { \
+			buf = xrealloc(buf, need); \
+			space = need; \
+		} \
+	} while (0)
+
+static void pp_header(enum cmit_fmt fmt,
+		      int abbrev,
+		      enum date_mode dmode,
+		      const char *encoding,
+		      const struct commit *commit,
+		      const char **msg_p,
+		      unsigned long *len_p,
+		      unsigned long *ofs_p,
+		      char **buf_p,
+		      unsigned long *space_p)
+{
+	int parents_shown = 0;
+
+	for (;;) {
+		const char *line = *msg_p;
+		char *dst;
+		int linelen = get_one_line(*msg_p, *len_p);
+		unsigned long len;
+
+		if (!linelen)
+			return;
+		*msg_p += linelen;
+		*len_p -= linelen;
+
+		if (linelen == 1)
+			/* End of header */
+			return;
+
+		ALLOC_GROW(*buf_p, *space_p, linelen + *ofs_p + 20);
+		dst = *buf_p + *ofs_p;
+
+		if (fmt == CMIT_FMT_RAW) {
+			memcpy(dst, line, linelen);
+			*ofs_p += linelen;
+			continue;
+		}
+
+		if (!memcmp(line, "parent ", 7)) {
+			if (linelen != 48)
+				die("bad parent line in commit");
+			continue;
+		}
+
+		if (!parents_shown) {
+			struct commit_list *parent;
+			int num;
+			for (parent = commit->parents, num = 0;
+			     parent;
+			     parent = parent->next, num++)
+				;
+			/* with enough slop */
+			num = *ofs_p + num * 50 + 20;
+			ALLOC_GROW(*buf_p, *space_p, num);
+			dst = *buf_p + *ofs_p;
+			*ofs_p += add_merge_info(fmt, dst, commit, abbrev);
+			parents_shown = 1;
+		}
+
+		/*
+		 * MEDIUM == DEFAULT shows only author with dates.
+		 * FULL shows both authors but not dates.
+		 * FULLER shows both authors and dates.
+		 */
+		if (!memcmp(line, "author ", 7)) {
+			len = linelen;
+			if (fmt == CMIT_FMT_EMAIL)
+				len = bound_rfc2047(linelen, encoding);
+			ALLOC_GROW(*buf_p, *space_p, *ofs_p + len);
+			dst = *buf_p + *ofs_p;
+			*ofs_p += add_user_info("Author", fmt, dst,
+						line + 7, dmode, encoding);
+		}
+
+		if (!memcmp(line, "committer ", 10) &&
+		    (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER)) {
+			len = linelen;
+			if (fmt == CMIT_FMT_EMAIL)
+				len = bound_rfc2047(linelen, encoding);
+			ALLOC_GROW(*buf_p, *space_p, *ofs_p + len);
+			dst = *buf_p + *ofs_p;
+			*ofs_p += add_user_info("Commit", fmt, dst,
+						line + 10, dmode, encoding);
+		}
+	}
+}
+
+static void pp_title_line(enum cmit_fmt fmt,
+			  const char **msg_p,
+			  unsigned long *len_p,
+			  unsigned long *ofs_p,
+			  char **buf_p,
+			  unsigned long *space_p,
+			  int indent,
+			  const char *subject,
+			  const char *after_subject,
+			  const char *encoding,
+			  int plain_non_ascii)
+{
+	char *title;
+	unsigned long title_alloc, title_len;
+	unsigned long len;
+
+	title_len = 0;
+	title_alloc = 80;
+	title = xmalloc(title_alloc);
+	for (;;) {
+		const char *line = *msg_p;
+		int linelen = get_one_line(line, *len_p);
+		*msg_p += linelen;
+		*len_p -= linelen;
+
+		if (!linelen || is_empty_line(line, &linelen))
+			break;
+
+		if (title_alloc <= title_len + linelen + 2) {
+			title_alloc = title_len + linelen + 80;
+			title = xrealloc(title, title_alloc);
+		}
+		len = 0;
+		if (title_len) {
+			if (fmt == CMIT_FMT_EMAIL) {
+				len++;
+				title[title_len++] = '\n';
+			}
+			len++;
+			title[title_len++] = ' ';
+		}
+		memcpy(title + title_len, line, linelen);
+		title_len += linelen;
+	}
+
+	/* Enough slop for the MIME header and rfc2047 */
+	len = bound_rfc2047(title_len, encoding)+ 1000;
+	if (subject)
+		len += strlen(subject);
+	if (after_subject)
+		len += strlen(after_subject);
+	if (encoding)
+		len += strlen(encoding);
+	ALLOC_GROW(*buf_p, *space_p, title_len + *ofs_p + len);
+
+	if (subject) {
+		len = strlen(subject);
+		memcpy(*buf_p + *ofs_p, subject, len);
+		*ofs_p += len;
+		*ofs_p += add_rfc2047(*buf_p + *ofs_p,
+				      title, title_len, encoding);
+	} else {
+		memcpy(*buf_p + *ofs_p, title, title_len);
+		*ofs_p += title_len;
+	}
+	(*buf_p)[(*ofs_p)++] = '\n';
+	if (plain_non_ascii) {
+		const char *header_fmt =
+			"MIME-Version: 1.0\n"
+			"Content-Type: text/plain; charset=%s\n"
+			"Content-Transfer-Encoding: 8bit\n";
+		*ofs_p += snprintf(*buf_p + *ofs_p,
+				   *space_p - *ofs_p,
+				   header_fmt, encoding);
+	}
+	if (after_subject) {
+		len = strlen(after_subject);
+		memcpy(*buf_p + *ofs_p, after_subject, len);
+		*ofs_p += len;
+	}
+	free(title);
+	if (fmt == CMIT_FMT_EMAIL) {
+		ALLOC_GROW(*buf_p, *space_p, *ofs_p + 20);
+		(*buf_p)[(*ofs_p)++] = '\n';
+	}
+}
+
+static void pp_remainder(enum cmit_fmt fmt,
+			 const char **msg_p,
+			 unsigned long *len_p,
+			 unsigned long *ofs_p,
+			 char **buf_p,
+			 unsigned long *space_p,
+			 int indent)
+{
+	int first = 1;
+	for (;;) {
+		const char *line = *msg_p;
+		int linelen = get_one_line(line, *len_p);
+		*msg_p += linelen;
+		*len_p -= linelen;
+
+		if (!linelen)
+			break;
+
+		if (is_empty_line(line, &linelen)) {
+			if (first)
+				continue;
+			if (fmt == CMIT_FMT_SHORT)
+				break;
+		}
+		first = 0;
+
+		ALLOC_GROW(*buf_p, *space_p, *ofs_p + linelen + indent + 20);
+		if (indent) {
+			memset(*buf_p + *ofs_p, ' ', indent);
+			*ofs_p += indent;
+		}
+		memcpy(*buf_p + *ofs_p, line, linelen);
+		*ofs_p += linelen;
+		(*buf_p)[(*ofs_p)++] = '\n';
+	}
+}
+
 unsigned long pretty_print_commit(enum cmit_fmt fmt,
 				  const struct commit *commit,
 				  unsigned long len,
@@ -930,16 +1156,14 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 				  const char *after_subject,
 				  enum date_mode dmode)
 {
-	int hdr = 1, body = 0, seen_title = 0;
 	unsigned long offset = 0;
+	unsigned long beginning_of_body;
 	int indent = 4;
-	int parents_shown = 0;
 	const char *msg = commit->buffer;
 	int plain_non_ascii = 0;
 	char *reencoded;
 	const char *encoding;
 	char *buf;
-	unsigned long space, slop;
 
 	if (fmt == CMIT_FMT_USERFORMAT)
 		return format_commit_message(commit, msg, buf_p, space_p);
@@ -950,8 +1174,10 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 	if (!encoding)
 		encoding = "utf-8";
 	reencoded = logmsg_reencode(commit, encoding);
-	if (reencoded)
+	if (reencoded) {
 		msg = reencoded;
+		len = strlen(reencoded);
+	}
 
 	if (fmt == CMIT_FMT_ONELINE || fmt == CMIT_FMT_EMAIL)
 		indent = 0;
@@ -982,155 +1208,57 @@ unsigned long pretty_print_commit(enum cmit_fmt fmt,
 		}
 	}
 
-	space = *space_p;
-	buf = *buf_p;
-
-	/*
-	 * We do not want to repeatedly realloc below, so
-	 * preallocate with enough slop to hold MIME headers,
-	 * "Subject: " prefix, etc.
-	 */
-	slop = 1000;
-	if (subject)
-		slop += strlen(subject);
-	if (after_subject)
-		slop += strlen(after_subject);
-	if (space < strlen(msg) + slop) {
-		space = strlen(msg) + slop;
-		buf = xrealloc(buf, space);
-		*space_p = space;
-		*buf_p = buf;
+	pp_header(fmt, abbrev, dmode, encoding,
+		  commit, &msg, &len,
+		  &offset, buf_p, space_p);
+	if (fmt != CMIT_FMT_ONELINE && !subject) {
+		ALLOC_GROW(*buf_p, *space_p, offset + 20);
+		(*buf_p)[offset++] = '\n';
 	}
 
+	/* Skip excess blank lines at the beginning of body, if any... */
 	for (;;) {
-		const char *line = msg;
 		int linelen = get_one_line(msg, len);
-
+		int ll = linelen;
 		if (!linelen)
 			break;
-
-		/* 20 would cover indent and leave us some slop */
-		if (offset + linelen + 20 > space) {
-			space = offset + linelen + 20;
-			buf = xrealloc(buf, space);
-			*buf_p = buf;
-			*space_p = space;
-		}
-
+		if (!is_empty_line(msg, &ll))
+			break;
 		msg += linelen;
 		len -= linelen;
-		if (hdr) {
-			if (linelen == 1) {
-				hdr = 0;
-				if ((fmt != CMIT_FMT_ONELINE) && !subject)
-					buf[offset++] = '\n';
-				continue;
-			}
-			if (fmt == CMIT_FMT_RAW) {
-				memcpy(buf + offset, line, linelen);
-				offset += linelen;
-				continue;
-			}
-			if (!memcmp(line, "parent ", 7)) {
-				if (linelen != 48)
-					die("bad parent line in commit");
-				continue;
-			}
-
-			if (!parents_shown) {
-				offset += add_merge_info(fmt, buf + offset,
-							 commit, abbrev);
-				parents_shown = 1;
-				continue;
-			}
-			/*
-			 * MEDIUM == DEFAULT shows only author with dates.
-			 * FULL shows both authors but not dates.
-			 * FULLER shows both authors and dates.
-			 */
-			if (!memcmp(line, "author ", 7))
-				offset += add_user_info("Author", fmt,
-							buf + offset,
-							line + 7,
-							dmode,
-							encoding);
-			if (!memcmp(line, "committer ", 10) &&
-			    (fmt == CMIT_FMT_FULL || fmt == CMIT_FMT_FULLER))
-				offset += add_user_info("Commit", fmt,
-							buf + offset,
-							line + 10,
-							dmode,
-							encoding);
-			continue;
-		}
+	}
 
-		if (!subject)
-			body = 1;
+	/* These formats treat the title line specially. */
+	if (fmt == CMIT_FMT_ONELINE
+	    || fmt == CMIT_FMT_EMAIL)
+		pp_title_line(fmt, &msg, &len, &offset,
+			      buf_p, space_p, indent,
+			      subject, after_subject, encoding,
+			      plain_non_ascii);
 
-		if (is_empty_line(line, &linelen)) {
-			if (!seen_title)
-				continue;
-			if (!body)
-				continue;
-			if (subject)
-				continue;
-			if (fmt == CMIT_FMT_SHORT)
-				break;
-		}
+	beginning_of_body = offset;
+	if (fmt != CMIT_FMT_ONELINE)
+		pp_remainder(fmt, &msg, &len, &offset,
+			     buf_p, space_p, indent);
 
-		seen_title = 1;
-		if (subject) {
-			int slen = strlen(subject);
-			memcpy(buf + offset, subject, slen);
-			offset += slen;
-			offset += add_rfc2047(buf + offset, line, linelen,
-					      encoding);
-		}
-		else {
-			memset(buf + offset, ' ', indent);
-			memcpy(buf + offset + indent, line, linelen);
-			offset += linelen + indent;
-		}
-		buf[offset++] = '\n';
-		if (fmt == CMIT_FMT_ONELINE)
-			break;
-		if (subject && plain_non_ascii) {
-			int sz;
-			char header[512];
-			const char *header_fmt =
-				"MIME-Version: 1.0\n"
-				"Content-Type: text/plain; charset=%s\n"
-				"Content-Transfer-Encoding: 8bit\n";
-			sz = snprintf(header, sizeof(header), header_fmt,
-				      encoding);
-			if (sizeof(header) < sz)
-				die("Encoding name %s too long", encoding);
-			memcpy(buf + offset, header, sz);
-			offset += sz;
-		}
-		if (after_subject) {
-			int slen = strlen(after_subject);
-			if (slen > space - offset - 1)
-				slen = space - offset - 1;
-			memcpy(buf + offset, after_subject, slen);
-			offset += slen;
-			after_subject = NULL;
-		}
-		subject = NULL;
-	}
-	while (offset && isspace(buf[offset-1]))
+	while (offset && isspace((*buf_p)[offset-1]))
 		offset--;
+
+	ALLOC_GROW(*buf_p, *space_p, offset + 20);
+	buf = *buf_p;
+
 	/* Make sure there is an EOLN for the non-oneline case */
 	if (fmt != CMIT_FMT_ONELINE)
 		buf[offset++] = '\n';
+
 	/*
-	 * make sure there is another EOLN to separate the headers from whatever
-	 * body the caller appends if we haven't already written a body
+	 * The caller may append additional body text in e-mail
+	 * format.  Make sure we did not strip the blank line
+	 * between the header and the body.
 	 */
-	if (fmt == CMIT_FMT_EMAIL && !body)
+	if (fmt == CMIT_FMT_EMAIL && offset <= beginning_of_body)
 		buf[offset++] = '\n';
 	buf[offset] = '\0';
-
 	free(reencoded);
 	return offset;
 }
-- 
1.5.2.1.1021.g1c0b0

^ permalink raw reply related

* Re: [PATCH] Unquote From line from patch before comparing with given from address.
From: Junio C Hamano @ 2007-06-12  5:28 UTC (permalink / raw)
  To: Kristian Høgsberg; +Cc: git
In-Reply-To: <11815814802456-git-send-email-krh@redhat.com>

Thanks.

That has been longstanding, and I hinted how that can be fixed a
couple of times on the list, and was waiting for somebody for
whom fixing it would make a difference to fix it, while sort of
pretending to be lazy.

Happy to see finally somebody stepped forward ;-).

^ permalink raw reply

* Re: [PATCH 0/3] Support config-based names
From: Junio C Hamano @ 2007-06-12  5:28 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706112244210.5848@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> writes:

> It can be useful to refer to commits in remotes based on their configured 
> relationship to local branches. For example, "git log HEAD^[push]..HEAD" 
> would, when pushing is set up, show what hasn't been pushed yet.

It's not like we will be adding 'push' objects and 'merge'
objects, so I think HEAD^{push} (curly brace, not bracket) is
good enough.

We need to see how useful this would be in practice; we would
not want to add new syntax without a set of convincing use
cases.  At this point, it still feels as if it is a feature that
was implemented only because it could, not because there was a
real need.

^ permalink raw reply

* Re: Please remerge git-gui.git into git.git
From: Junio C Hamano @ 2007-06-12  5:25 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: git
In-Reply-To: <20070612022747.GP6073@spearce.org>

"Shawn O. Pearce" <spearce@spearce.org> writes:

> I'll be happy when the subproject support is mature enough that
> git-gui can be unmerged from git.git, and we can instead just point
> git.git at the git-gui project.  But I still think its a good idea to
> distribute git-gui as part of the release tarball for core Git; users
> have come to expect they can find a stable version of git-gui there,
> much as they also expect to find a reasonably stable version of gitk.

Of course.  

That would require git-tar-tree to learn --recurse-into-subprojects
option ;-)  Hint, hint...

^ permalink raw reply

* Re: [RFC] Teach diff to imply --find-copies-harder upon -C -C
From: Junio C Hamano @ 2007-06-12  5:05 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706112109180.4059@racer.site>

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

> earlier, a second "-C" on the command line had no effect. But since I use 
> "--find-copies-harder" quite a bit, and it is so long to type, and I am
> an inherently lazy person, I'd like the second "-C" to be a shortcut for 
> "--find-copies-harder".

Sounds good and consistent with what we do in git-blame.

^ permalink raw reply

* Re: [PATCH 0/3] Support config-based names
From: Daniel Barkalow @ 2007-06-12  4:13 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Junio C Hamano, git
In-Reply-To: <20070612033134.GS6073@spearce.org>

On Mon, 11 Jun 2007, Shawn O. Pearce wrote:

> Daniel Barkalow <barkalow@iabervon.org> wrote:
> > It can be useful to refer to commits in remotes based on their configured 
> > relationship to local branches. For example, "git log HEAD^[push]..HEAD" 
> > would, when pushing is set up, show what hasn't been pushed yet.
> 
> Interesting.
> 
> What about `git diff master^[push]@{3.days.ago}^{tree} master` ?
> 
> Can anyone even understand that?  Can Git even understand it?
> As I follow your code I don't think it would, as the ^[push]
> operator seems like it needs to be on the very end of the string,
> and it assumes everything to the left of the ^[ is the branch name.

Ah, but the code actually peels off parts and parses the part under, so 
HEAD^[push]^{tree} actually works. However, it doesn't treat HEAD^[push] 
as an alias for a branch, so it doesn't find the reflog.

> So I also couldn't phrase that as:
> 
>   git diff master@{3.days.ago}^[push]^{tree} master
> 
> More interesting is just what do you want going on here with the
> reflog query and the ^[push] query.  Should the reflog operator apply
> before the ^[push] translation, or after?  Or should it depend on
> the order of them in the statement?  I can see where you would want
> to look at your local tracking branch for the current branch 3 days
> ago, which might be "HEAD^[push]@{3.days.ago}".  But I'm not really
> sure what the meaning of "HEAD@{3.days.ago}^[push]" is.  Is that
> the branch that HEAD was on 3 days ago's push branch?  Huh?  ;-)

Whatever that means, I bet we don't track the necessary information. I 
think ^[push] only applies to ref names. But it should probably resolve as 
a ref name itself, so that HEAD^[push]@{3.days.ago} would work. Not sure 
how to write the code for that, though.

> In general it seems our "operators" are ^{foo} or @{foo}, so I wonder
> why not ^{push}.  push is not a valid object type, and probably
> never will be, so peeling the onion back to get to what ^{push}
> means (even though its not an object type) is probably OK.

^{push} and ^{merge} are certainly possible, if the namespace of object 
types and the namespace of functions aren't going to overlap. I wasn't 
sure if this would be true in general with future additions to both 
namespaces.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [PATCH 0/3] Support config-based names
From: Shawn O. Pearce @ 2007-06-12  3:31 UTC (permalink / raw)
  To: Daniel Barkalow; +Cc: Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.64.0706112244210.5848@iabervon.org>

Daniel Barkalow <barkalow@iabervon.org> wrote:
> It can be useful to refer to commits in remotes based on their configured 
> relationship to local branches. For example, "git log HEAD^[push]..HEAD" 
> would, when pushing is set up, show what hasn't been pushed yet.

Interesting.

What about `git diff master^[push]@{3.days.ago}^{tree} master` ?

Can anyone even understand that?  Can Git even understand it?
As I follow your code I don't think it would, as the ^[push]
operator seems like it needs to be on the very end of the string,
and it assumes everything to the left of the ^[ is the branch name.
So I also couldn't phrase that as:

  git diff master@{3.days.ago}^[push]^{tree} master

More interesting is just what do you want going on here with the
reflog query and the ^[push] query.  Should the reflog operator apply
before the ^[push] translation, or after?  Or should it depend on
the order of them in the statement?  I can see where you would want
to look at your local tracking branch for the current branch 3 days
ago, which might be "HEAD^[push]@{3.days.ago}".  But I'm not really
sure what the meaning of "HEAD@{3.days.ago}^[push]" is.  Is that
the branch that HEAD was on 3 days ago's push branch?  Huh?  ;-)

Food for thought.

In general it seems our "operators" are ^{foo} or @{foo}, so I wonder
why not ^{push}.  push is not a valid object type, and probably
never will be, so peeling the onion back to get to what ^{push}
means (even though its not an object type) is probably OK.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] Port git-tag.sh to C.
From: Daniel Barkalow @ 2007-06-12  3:28 UTC (permalink / raw)
  To: Carlos Rica; +Cc: =?X-UNKNOWN?Q?Kristian_H=F8gsberg?=, git, Julian Phillips
In-Reply-To: <1b46aba20706081858u7f18d9b2o5602db43d396c19@mail.gmail.com>

On Sat, 9 Jun 2007, Carlos Rica wrote:

> Feel free to choose the script which you need to get replaced first,
> or, depending on your urgency, you could ask me for one of them and I
> would try to concentrate my efforts on it. Why do you started with
> git-tag? For me, it was enough easy to begin with, perhaps you could
> have other reasons.

Incidentally, I have been working on fetch, based on Julian Phillips's 
version. I'm trying to split out the "how do I communicate with remote 
repositories" code, and use it for pushing and ls-remote as well as fetch. 
I've got a bunch of not-for-official-history development that you should 
look at if you try any of the remote-repository-access scripts.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* [PATCH 3/3] Support branch^[merge] and branch^[push]
From: Daniel Barkalow @ 2007-06-12  3:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

For a branch name, support getting related refs based on configuration.

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 sha1_name.c |   50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/sha1_name.c b/sha1_name.c
index 7df01af..dc5da7a 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -5,6 +5,7 @@
 #include "blob.h"
 #include "tree-walk.h"
 #include "refs.h"
+#include "remote.h"
 
 static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
 {
@@ -511,6 +512,51 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
 	return 0;
 }
 
+static int lookup_specials(const char *name, int len, unsigned char *sha1)
+{
+	const char *sp;
+
+	if (len < 5 || name[len - 1] != ']')
+		return -1;
+
+	for (sp = name + len - 1; name <= sp; sp--) {
+		int ch = *sp;
+		if (ch == '[' && name < sp && sp[-1] == '^')
+			break;
+	}
+
+	if (sp <= name)
+		return -1;
+
+	sp++; /* beginning of special name */
+	if (!strncmp("merge]", sp, 6)) {
+		char *word = xstrndup(name, sp - name - 2);
+		struct branch *branch = branch_get(word);
+		free(word);
+		if (branch && branch->merge) {
+			return get_sha1(branch->merge->dst, sha1);
+		}
+	} else if (!strncmp("push]", sp, 5)) {
+		char *word = xstrndup(name, sp - name - 2);
+		struct branch *branch = branch_get(word);
+		struct refspec remote;
+		struct refspec local;
+
+		if (!branch || !branch->remote)
+			return -1;
+
+		remote.src = branch->refname;
+		if (remote_find_push(branch->remote, &remote))
+			return -1;
+
+		local.src = remote.dst;
+		if (remote_find_tracking(branch->remote, &local))
+			return -1;
+		return get_sha1(local.dst, sha1);
+	}
+	return -1;
+}
+
 static int get_describe_name(const char *name, int len, unsigned char *sha1)
 {
 	const char *cp;
@@ -565,6 +611,10 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1)
 		return get_nth_ancestor(name, len1, sha1, num);
 	}
 
+	ret = lookup_specials(name, len, sha1);
+	if (!ret)
+		return 0;
+
 	ret = peel_onion(name, len, sha1);
 	if (!ret)
 		return 0;
-- 
1.5.2.901.g27ad4-dirty

^ permalink raw reply related

* [PATCH 1/3] Parse and report branch configuration along with remote configuration.
From: Daniel Barkalow @ 2007-06-12  3:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Signed-off-by: Daniel Barkalow <barkalow@iabervon.org>
---
 remote.c |   92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 remote.h |   13 +++++++++
 2 files changed, 94 insertions(+), 11 deletions(-)

diff --git a/remote.c b/remote.c
index d904616..1fbceeb 100644
--- a/remote.c
+++ b/remote.c
@@ -5,6 +5,12 @@
 static struct remote **remotes;
 static int allocated_remotes;
 
+static struct branch **branches;
+static int allocated_branches;
+
+static struct branch *current_branch;
+static const char *default_remote_name;
+
 #define BUF_SIZE (2048)
 static char buffer[BUF_SIZE];
 
@@ -67,6 +73,45 @@ static struct remote *make_remote(const char *name, int len)
 	return remotes[empty];
 }
 
+static struct branch *make_branch(const char *name, int len)
+{
+	int i, empty = -1;
+	char *refname;
+
+	for (i = 0; i < allocated_branches; i++) {
+		if (!branches[i]) {
+			if (empty < 0)
+				empty = i;
+		} else {
+			if (len ? (!strncmp(name, branches[i]->name, len) &&
+				   !branches[i]->name[len]) :
+			    !strcmp(name, branches[i]->name))
+				return branches[i];
+		}
+	}
+
+	if (empty < 0) {
+		empty = allocated_branches;
+		allocated_branches += allocated_branches ? allocated_branches : 1;
+		branches = xrealloc(branches,
+				   sizeof(*branches) * allocated_branches);
+		memset(branches + empty, 0,
+		       (allocated_branches - empty) * sizeof(*branches));
+	}
+	branches[empty] = xcalloc(1, sizeof(struct branch));
+	if (len)
+		branches[empty]->name = xstrndup(name, len);
+	else
+		branches[empty]->name = xstrdup(name);
+	refname = malloc(strlen(name) + strlen("refs/heads/") + 1);
+	strcpy(refname, "refs/heads/");
+	strcpy(refname + strlen("refs/heads/"),
+	       branches[empty]->name);
+	branches[empty]->refname = refname;
+
+	return branches[empty];
+}
+
 static void read_remotes_file(struct remote *remote)
 {
 	FILE *f = fopen(git_path("remotes/%s", remote->name), "r");
@@ -144,20 +189,25 @@ static void read_branches_file(struct remote *remote)
 	add_uri(remote, p);
 }
 
-static char *default_remote_name = NULL;
-static const char *current_branch = NULL;
-static int current_branch_len = 0;
-
 static int handle_config(const char *key, const char *value)
 {
 	const char *name;
 	const char *subkey;
 	struct remote *remote;
-	if (!prefixcmp(key, "branch.") && current_branch &&
-	    !strncmp(key + 7, current_branch, current_branch_len) &&
-	    !strcmp(key + 7 + current_branch_len, ".remote")) {
-		free(default_remote_name);
-		default_remote_name = xstrdup(value);
+	struct branch *branch;
+	if (!prefixcmp(key, "branch.")) {
+		name = key + 7;
+		subkey = strrchr(name, '.');
+		branch = make_branch(name, subkey - name);
+		if (!value)
+			return 0;
+		if (!strcmp(subkey, ".remote")) {
+			branch->remote_name = xstrdup(value);
+			if (branch == current_branch)
+				default_remote_name = branch->remote_name;
+		} else if (!strcmp(subkey, ".merge"))
+			branch->merge_name = xstrdup(value);
+		return 0;
 	}
 	if (prefixcmp(key,  "remote."))
 		return 0;
@@ -212,8 +262,8 @@ static void read_config(void)
 	head_ref = resolve_ref("HEAD", sha1, 0, &flag);
 	if (head_ref && (flag & REF_ISSYMREF) &&
 	    !prefixcmp(head_ref, "refs/heads/")) {
-		current_branch = head_ref + strlen("refs/heads/");
-		current_branch_len = strlen(current_branch);
+		current_branch =
+			make_branch(head_ref + strlen("refs/heads/"), 0);
 	}
 	git_config(handle_config);
 }
@@ -551,3 +601,23 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
 	}
 	return 0;
 }
+
+struct branch *branch_get(const char *name)
+{
+	struct branch *ret;
+
+	read_config();
+	if (!name || !strcmp(name, "HEAD"))
+		ret = current_branch;
+	else
+		ret = make_branch(name, 0);
+	if (ret->remote_name) {
+		ret->remote = remote_get(ret->remote_name);
+		if (ret->merge_name) {
+			ret->merge = malloc(sizeof(*ret->merge));
+			ret->merge->src = ret->merge_name;
+			remote_find_tracking(ret->remote, ret->merge);
+		}
+	}
+	return ret;
+}
diff --git a/remote.h b/remote.h
index 01dbcef..14615e8 100644
--- a/remote.h
+++ b/remote.h
@@ -38,4 +38,17 @@ int match_refs(struct ref *src, struct ref *dst, struct ref ***dst_tail,
  */
 int remote_find_tracking(struct remote *remote, struct refspec *refspec);
 
+struct branch {
+	const char *name;
+	const char *refname;
+
+	const char *remote_name;
+	struct remote *remote;
+
+	const char *merge_name;
+	struct refspec *merge;
+};
+
+struct branch *branch_get(const char *name);
+
 #endif
-- 
1.5.2.901.g27ad4-dirty

^ 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