Git development
 help / color / mirror / Atom feed
* Re: git-commit feature request: pass editor command line options
From: Jeff King @ 2009-10-14 21:12 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Miklos Vajna, Matthew Cline, git
In-Reply-To: <7vvdihdc4f.fsf@alter.siamese.dyndns.org>

On Wed, Oct 14, 2009 at 12:11:28PM -0700, Junio C Hamano wrote:

> > Hmm, what is the use-case when using an option --foo is useful when
> > creating a commit, but not useful when crating a tag?
> >
> > Apart from introducing inconsistency...
> 
> Not between commit and tag, but I can see you may want to auto-wrap for
> log message but forbid auto-wrap when editing rebase insn sheet during
> "rebase -i".

I think most people who want that just have their editor automagically
recognize the different situations based on the file name or contents. I
don't think the original author is wrong to want to be able to use
command-line options to do so, but if he is using a common editor like
vim or emacs, I think such autodetection has already been written.

-Peff

^ permalink raw reply

* Re: submodule-summary
From: Jens Lehmann @ 2009-10-14 21:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vfx9lbtpf.fsf_-_@alter.siamese.dyndns.org>

Junio C Hamano schrieb:
> Jens Lehmann <Jens.Lehmann@web.de> writes:
> 
>> Dscho condensed his initial patch with the interdiff you mentioned,
>> additionally silenced a compiler warning and activated --first-parent.
>> This follows as patch 1/4. Patches 2/4 to 4/4 contain my two bugfixes
>> and the testcase i copied from submodule summary while adapting it to
>> the changes of the output format.
> 
> I think 2 and 3 should be squashed into the first one.  I do not see any
> good reason for keeping initial "oops that was wrong" etched in stone,
> once the review process has revealed obvious bugs and reasonable fixes
> have been given to them.  If the original author re-spun a v2 patch, that
> is the normal thing that happens.

Right, will do.


> I am not happy with the option name --submodule-summary, by the way.
> Naming this option --submodule-summary shows the confusion between this
> series being the _latest_ great invention and this series being the _last_
> great invention.  I'd freely grant the former but would like to avoid the
> latter.
> 
> I have this nagging suspicion that we should leave the door open for later
> addition of --submodule=full that actually gives the patch text for the
> entire aggregated tree, perhaps recursively.  People may want to add even
> more other useful modes that we do not think of right now. It would be
> better to name this --submodule=shortlog or something.
> 
> If users like the shortlog mode (or the full mode) very much, perhaps the
> current default output, which shows the differences between two commit
> object names, can become a --submodule=summary (or --submodule=twoline)
> mode later, and the shortlog mode could become the default.

Good point. (Personally i like the options --submodule=shortlog and
--submodule=twoline. Because IMHO --submodule=summary could make
people expect similar output to git submodule summary, no?).

Thanks for your feedback, will send new patches soon.

^ permalink raw reply

* Re: git-commit feature request: pass editor command line options
From: Miklos Vajna @ 2009-10-14 22:12 UTC (permalink / raw)
  To: Matthew Cline; +Cc: git
In-Reply-To: <200910141303.01485.matt@nightrealms.com>

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

On Wed, Oct 14, 2009 at 01:03:01PM -0700, Matthew Cline <matt@nightrealms.com> wrote:
> On Wednesday 14 October 2009 10:23:38 am Miklos Vajna wrote:
> 
> > Hmm, what is the use-case when using an option --foo is useful when
> > creating a commit, but not useful when crating a tag?
> 
> In my case, it's using a commit template which starts with a comment, so I 
> want to move the cursor down to the line below the comment.

Then rebase, tag, add -e and even commit --amend would use core.editor,
while commit alone would use commit.editor, right?

A minor confusion would be that git commit --amend would not use
commit.editor. ;-)

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

^ permalink raw reply

* Re: [ANNOUNCE] GIT 1.6.5
From: Jakub Narebski @ 2009-10-14 22:11 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8wfi1fya.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> The latest feature release GIT 1.6.5 is available at the usual
> places:
> 
>   http://www.kernel.org/pub/software/scm/git/
> 
>   git-1.6.5.tar.{gz,bz2}			(source tarball)
>   git-htmldocs-1.6.5.tar.{gz,bz2}		(preformatted docs)
>   git-manpages-1.6.5.tar.{gz,bz2}		(preformatted docs)
> 
> The RPM binary packages for a few architectures are found in:
> 
>   RPMS/$arch/git-*-1.6.5-1.fc9.$arch.rpm	(RPM)
> 
> This cycle took a bit longer than I hoped, but here it is.  We already
> have some new features cooking in 'next', and I expect we may be able to
> have 1.6.6 by the end of the year.

Compiling git from source RPM git-1.6.5-1.fc9.src.rpm using

  $ rpmbuild --rebuild git-1.6.5-1.fc9.src.rpm

fails with the following error:

    SUBDIR perl
/usr/bin/perl Makefile.PL PREFIX='/usr'
Only one of PREFIX or INSTALL_BASE can be given.  Not both.
make[1]: *** [perl.mak] Error 2
make: *** [perl/perl.mak] Error 2
error: Bad exit status from /var/tmp/rpm-tmp.53174 (%build)

Compiling git from source with

 $ make prefix=/home/local/git \
        bindir=/home/local/git \
        gitexecdir=/home/local/git \
        template_dir=/home/local/git \
        GIT_PYTHON_DIR=/home/local/git 

gives the same error.

It might matter that I am using modern Perl way of installing Perl
modules locally, via local::lib, with ~/perl5/.modulebuildrc
containing 

  install  --install_base  /home/jnareb/perl5

and I have

  export MODULEBUILDRC="$HOME/perl5/.modulebuildrc"
  export PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"

Doing

 $ unset PERL_MM_OPT

before compiling (from SRPMS) made compilation pass this stage,
and finally succeed.

I guess that perl/Makefile (or rather the file that generates it)
should unset PERL_MM_OPT, or use INSTALL_BASE as DESTDIR rather
than fiddling with PREFIX.


But I am not a Perl hacker
------------------------------------------------------------
perl, v5.8.6
ExtUtils::MakeMaker 6.54 (local)
ExtUtils::MakeMaker 6.17 (global)

export MODULEBUILDRC="$HOME/perl5/.modulebuildrc"
export PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"
-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* [PATCH] git add -e documentation: rephrase note
From: Miklos Vajna @ 2009-10-14 22:26 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

The original note probably wanted to suggest "edit the patch with care",
but actually suggested just editing the first characters on certain
lines, which is a pretty bad suggestion.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 Documentation/git-add.txt |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 45ebf87..daa1add 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -86,9 +86,8 @@ OPTIONS
 	edit it.  After the editor was closed, adjust the hunk headers
 	and apply the patch to the index.
 +
-*NOTE*: Obviously, if you change anything else than the first character
-on lines beginning with a space or a minus, the patch will no longer
-apply.
+*NOTE*: Obviously, if you change the first characters of the lines or
+lines beginning with a space or a minus, the patch will no longer apply.
 
 -u::
 --update::
-- 
1.6.4

^ permalink raw reply related

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Junio C Hamano @ 2009-10-14 22:34 UTC (permalink / raw)
  To: Nicolas Pitre; +Cc: Daniel Barkalow, Jay Soffian, git
In-Reply-To: <alpine.LFD.2.00.0910141647390.20122@xanadu.home>

Nicolas Pitre <nico@fluxnic.net> writes:

> On Wed, 14 Oct 2009, Junio C Hamano wrote:
>
>> Nicolas Pitre <nico@fluxnic.net> writes:
>> 
>> > On Wed, 14 Oct 2009, Daniel Barkalow wrote:
>> >
>> >> On Wed, 14 Oct 2009, Jay Soffian wrote:
>> >> 
>> >> > $ git commit -m "blah"
>> >> > Cannot commit while not on any branch. Please use git commit -b <branch> to
>> >> > specify the name of a new branch to commit to, or use git commit -f to
>> >> > force a detached commit.
>> >> 
>> >> The difference is that some experienced users depend on being able to 
>> >> commit while not on a branch, and want to not get a warning for every 
>> >> commit while not on a branch.
>> >
>> > I assume that the -f would silence any warning?
>> 
>> It won't help to alleviate my irritation if I need to give -f to each and
>> every invocation of "git commit" while detached, though.
>
> Agreed.  Presumably some expert mode config would imply -f 
> automatically.

No, I do not want an expert mode.  I can probably live with "per session"
setting, that makes me decide to set or not set it when I detach, though.

^ permalink raw reply

* why no "ignore" command on git
From: Ralf Thielow @ 2009-10-14 22:35 UTC (permalink / raw)
  To: git

Hello,

why does git don't have an "ignore" command, to ignore some files or
directories all the time.
In many project file structures you have IDE specified project files
or directories which
should not be tracked on git. All the time git says that you can add
these files, this is not
usable if you want to add many files with the "git add ." command.
I read on some pages by a google search that you can create
a ".gitignore" directory or something like that. But you had to do
this manually.

why there is no "ignore" command on git?

best regards

Ralf

^ permalink raw reply

* Re: submodule-summary
From: Junio C Hamano @ 2009-10-14 22:42 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: Git Mailing List
In-Reply-To: <4AD6423D.10307@web.de>

Jens Lehmann <Jens.Lehmann@web.de> writes:

> Good point. (Personally i like the options --submodule=shortlog and
> --submodule=twoline. Because IMHO --submodule=summary could make
> people expect similar output to git submodule summary, no?).

Well, _that_ is something we could fix in "git submodule", isn't it?

Right now, the only way "git submodule" command can summarize the changes
is by showing a left-right shortlog, but it wouldn't be so inconceivable
that somebody may come up with different and equally useful way to show
them, e.g. diffstat, and at that point, we would probably want to have
"git submodule summary --stat" or "git submodule summary --shortlog" (and
the default being --shortlog).

I am _not_ married to the naming "shortlog", by the way, and shortlog is
rather a bad name for it.  Sorry for suggesting it; it is quite different
from the actual "git shortlog" command output (and no I am not suggesting
to make the output similar to shortlog), but rather is more similar to
"log --left-right --oneline".  But I think you got the point.

^ permalink raw reply

* Re: why no "ignore" command on git
From: Scott Wiersdorf @ 2009-10-14 23:02 UTC (permalink / raw)
  To: git
In-Reply-To: <42efdea40910141535g23a50b87p9b6c4a0fde7e842e@mail.gmail.com>

git does have a command to ignore files and directories: it's called
'emacs' (or 'vim' on some systems).

Seriously, the .gitignore file can contain a complex set of patterns
to ignore, and you can have .gitignore files at lower directories in a
hierarchy to override higher ones. This isn't something easily
contained in a simple command.

Scott


On Thu, Oct 15, 2009 at 12:35:23AM +0200, Ralf Thielow wrote:
> Hello,
> 
> why does git don't have an "ignore" command, to ignore some files or
> directories all the time.
> In many project file structures you have IDE specified project files
> or directories which
> should not be tracked on git. All the time git says that you can add
> these files, this is not
> usable if you want to add many files with the "git add ." command.
> I read on some pages by a google search that you can create
> a ".gitignore" directory or something like that. But you had to do
> this manually.
> 
> why there is no "ignore" command on git?
> 
> best regards
> 
> Ralf
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
Scott Wiersdorf
<scott@perlcode.org>

^ permalink raw reply

* Re: [PATCH] git add -e documentation: rephrase note
From: Jeff King @ 2009-10-14 23:04 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: Junio C Hamano, git
In-Reply-To: <20091014222628.GK6115@genesis.frugalware.org>

On Thu, Oct 15, 2009 at 12:26:28AM +0200, Miklos Vajna wrote:

> The original note probably wanted to suggest "edit the patch with care",
> but actually suggested just editing the first characters on certain
> lines, which is a pretty bad suggestion.

The intent of "-e" is to pick and choose lines of the diff to apply, or
even to munge the lines. So it is safe to:

  - remove lines with a '+' (don't stage the addition)

  - munge any lines with a '+' (stage modified contents)

  - add lines with a '+' (stage an addition)

  - convert lines with a ' ' to '-' (stage removal)

  - convert lines with a '-' to ' ' (don't stage removal)

It is a bad idea to:

  - delete '-' lines

  - delete ' ' lines

  - add ' ' or '-' line

  - munge the contents of ' ' or '-' lines

But that is just off the top of my head; perhaps others can come up with
corner cases where one of the safe things breaks.

> -*NOTE*: Obviously, if you change anything else than the first character
> -on lines beginning with a space or a minus, the patch will no longer
> -apply.
> +*NOTE*: Obviously, if you change the first characters of the lines or
> +lines beginning with a space or a minus, the patch will no longer apply.

So this is warning about changing or deleting ' ' or '-' lines, which is
good. But you can change the first characters of those lines, but only
by interchanging the two. So I think both the previous text and your
text don't cover all cases.

Maybe it makes sense instead to do a quick overview of what is OK and
what is not (like the list above).

-Peff

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Jeff King @ 2009-10-14 23:09 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Pitre, Daniel Barkalow, Jay Soffian, git
In-Reply-To: <7vws2xa9lu.fsf@alter.siamese.dyndns.org>

On Wed, Oct 14, 2009 at 03:34:05PM -0700, Junio C Hamano wrote:

> > Agreed.  Presumably some expert mode config would imply -f 
> > automatically.
> 
> No, I do not want an expert mode.  I can probably live with "per session"
> setting, that makes me decide to set or not set it when I detach, though.

That makes the most sense to me. If "git checkout" could write metadata
into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
could record an "ok to commit" bit. And could also be used to change it
after the fact. E.g.:

  $ git checkout --detach=commit origin/master
  $ git commit ;# should be ok

  $ git checkout --detach=examine origin/master
  $ git commit ;# complain
  $ git checkout --detach=commit HEAD
  $ git commit ;# ok

I guess something like "rebase" should detach with "ok to commit", since
it is planning on attaching the commits later. I'm not sure about "git
bisect". I guess probably it should be "not ok to commit" to be on the
safe side, and then somebody can "git checkout --detach=commit" if they
want to.

-Peff

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Nicolas Pitre @ 2009-10-14 23:34 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, Daniel Barkalow, Jay Soffian, git
In-Reply-To: <20091014230934.GC29664@coredump.intra.peff.net>

On Wed, 14 Oct 2009, Jeff King wrote:

> On Wed, Oct 14, 2009 at 03:34:05PM -0700, Junio C Hamano wrote:
> 
> > > Agreed.  Presumably some expert mode config would imply -f 
> > > automatically.
> > 
> > No, I do not want an expert mode.  I can probably live with "per session"
> > setting, that makes me decide to set or not set it when I detach, though.
> 
> That makes the most sense to me. If "git checkout" could write metadata
> into HEAD (or into DETACH_HEAD, as in Daniel's patch), then checkout
> could record an "ok to commit" bit. And could also be used to change it
> after the fact. E.g.:
> 
>   $ git checkout --detach=commit origin/master
>   $ git commit ;# should be ok
> 
>   $ git checkout --detach=examine origin/master
>   $ git commit ;# complain
>   $ git checkout --detach=commit HEAD
>   $ git commit ;# ok
> 
> I guess something like "rebase" should detach with "ok to commit", since
> it is planning on attaching the commits later. I'm not sure about "git
> bisect". I guess probably it should be "not ok to commit" to be on the
> safe side, and then somebody can "git checkout --detach=commit" if they
> want to.

Whatever is done about this... I'm afraid Git will end up less useful as 
operations that were possible before won't be anymore for "security's 
sake" unless some obnoxious override mode is involved.

Isn't the reflog already dealing with the security issue by making sure 
that nothing is "lost"?

Can't the user confusion be dealt with through some means other than 
making the tool less flexible?  I don't mind extra help message to be 
displayed after a headless commit is made for example.  But trying to 
make the tool more friendly should perhaps come from better education 
rather than added restrictions.

My thoughts only.


Nicolas

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Eric Raible @ 2009-10-14 23:52 UTC (permalink / raw)
  To: git
In-Reply-To: <7v7huxbtbk.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster <at> pobox.com> writes:

> It won't help to alleviate my irritation if I need to give -f to each and
> every invocation of "git commit" while detached, though.

I'm missing something fundamental here, I think.
I simply don't see the advantage of branching after committing
over branching before committing.

At worst, a temporary is cheap, eh?  So what is the value
of even allowing committing while HEAD is detached
(aside from the historical argument)?

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Junio C Hamano @ 2009-10-15  0:56 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Jeff King, Junio C Hamano, Daniel Barkalow, Jay Soffian, git
In-Reply-To: <alpine.LFD.2.00.0910141926170.20122@xanadu.home>

Nicolas Pitre <nico@fluxnic.net> writes:

> Can't the user confusion be dealt with through some means other than 
> making the tool less flexible?  I don't mind extra help message to be 
> displayed after a headless commit is made for example.  But trying to 
> make the tool more friendly should perhaps come from better education 
> rather than added restrictions.
>
> My thoughts only.

I actually share that but there apparently are people who have given up on
the education route.

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Jeff King @ 2009-10-15  1:47 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Nicolas Pitre, Daniel Barkalow, Jay Soffian, git
In-Reply-To: <7viqeha2zv.fsf@alter.siamese.dyndns.org>

On Wed, Oct 14, 2009 at 05:56:52PM -0700, Junio C Hamano wrote:

> Nicolas Pitre <nico@fluxnic.net> writes:
> 
> > Can't the user confusion be dealt with through some means other than 
> > making the tool less flexible?  I don't mind extra help message to be 
> > displayed after a headless commit is made for example.  But trying to 
> > make the tool more friendly should perhaps come from better education 
> > rather than added restrictions.
> >
> > My thoughts only.
> 
> I actually share that but there apparently are people who have given up on
> the education route.

I am personally undecided on this issue (my "this is the best option"
was the best of "a -f switch to commit, an 'expert' config option', or a
session-based option to commit").

But we really seem to have reached an impasse with how to proceed with
git ui.

People like Dscho are fed up with user complaints about parts of git
that can be unfriendly to new users. And I can understand that.  There
_is_ a perception that git is hard for beginners to use, and I don't
think that perception is entirely without merit. We expect the user to
understand the basic concepts of git, like history graphs, named refs
versus detached heads, tracking refs, the index, etc.

At the same time, I think that is what many of us _like_ about git. It
is based around simple and powerful concepts, and it doesn't get in your
way when you want to use those concepts in a powerful and flexible
manner. And I can understand resistance to making those features hard or
inconvenient to access; detached HEADs were invented for a reason, and
we want to use them.

So what is the right way to mediate between those desires? We have tried
or suggested several options, including:

  1. Educate users. Keep exposing them to the concepts, but make
     messages more clear. Improve documentation. This is largely the
     route taken with the index. Has it worked? I think there is still a
     perception among new users that the index is confusing.

  2. Use configuration options to differentiate behavior. This comes in
     the form of the sometimes-requested "expert/beginner mode" option.
     But it can also mean a config option for a specific behavior. The
     argument against it I have seen is that it can make git
     unpredictable for new versus old users. An old-timer helping a new
     person is more out-of-touch with what the new person's setup will
     do (which hurts when sitting at their terminal or when giving them
     advice online).

  3. Make a new porcelain interface that wraps the git plumbing. We have
     seen some examples of this. Obviously cogito was the first, and it
     has fallen by the wayside as people moved towards core git. That
     may be an artifact of its timing, though, as core git was a rapidly
     moving target, and power users wanted to use the new features. More
     recently we've had 'eg'. I don't know how many people are using it,
     but it is certainly not discussed on this list much. There are also
     GUIs wrapping git. I think these are subject to the same argument
     as (2), but even more so. An entirely new interface like 'eg' is
     really splitting the user base. As a git old-timer, I can keep up
     with what newbie options might impact git's behavior. But I haven't
     a clue how to do anything in 'eg'.

  4. Hide potentially dangerous behavior behind "-f" or similar options,
     or make it even more inaccessible. We have done this with some
     obviously dangerous cases, like "push -f" or "checkout -f", which
     can throw away data. But I think in cases where the behavior is
     simply confusing and not dangerous, we tend not to do this (at
     least I couldn't think of any examples off the top of my head). The
     obvious argument against it is that it inconveniences more
     experienced users. Dscho advocated "the good of the many" versus
     "the good of the few". And I can see some logic in that. At the
     same time, open source is about scratching itches. Is anyone really
     interested in doing something that makes our own itch worse?
     Everytime you use it, won't you be thinking about scratching?

So I don't know what the solution is. And maybe this is just useless
pontificating. But I feel like we have this discussion over and over,
every few months, about a different feature. I wish there were some way
to fix that.

Out of ideas,
-Peff

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Nicolas Pitre @ 2009-10-15  3:08 UTC (permalink / raw)
  To: Jeff King; +Cc: Junio C Hamano, Daniel Barkalow, Jay Soffian, git
In-Reply-To: <20091015014737.GA9923@coredump.intra.peff.net>

On Wed, 14 Oct 2009, Jeff King wrote:

> On Wed, Oct 14, 2009 at 05:56:52PM -0700, Junio C Hamano wrote:
> 
> > Nicolas Pitre <nico@fluxnic.net> writes:
> > 
> > > Can't the user confusion be dealt with through some means other than 
> > > making the tool less flexible?  I don't mind extra help message to be 
> > > displayed after a headless commit is made for example.  But trying to 
> > > make the tool more friendly should perhaps come from better education 
> > > rather than added restrictions.
> > >
> > > My thoughts only.
> > 
> > I actually share that but there apparently are people who have given up on
> > the education route.
> 
> I am personally undecided on this issue (my "this is the best option"
> was the best of "a -f switch to commit, an 'expert' config option', or a
> session-based option to commit").
> 
> But we really seem to have reached an impasse with how to proceed with
> git ui.
> 
> People like Dscho are fed up with user complaints about parts of git
> that can be unfriendly to new users. And I can understand that.

People like Dscho have to grow a thicker skin then.  There will _always_ 
be user complaints regardless of how balanced you try to make a UI.

> There _is_ a perception that git is hard for beginners to use, and I 
> don't think that perception is entirely without merit. We expect the 
> user to understand the basic concepts of git, like history graphs, 
> named refs versus detached heads, tracking refs, the index, etc.

Sure.  That's part of it, and beginners must get over with that 
perception.  Git is a professional tool and not a toy project anymore.  
Like any professional grade tool, there is a greater effort needed from 
beginners before being comfortable with the tool.

> At the same time, I think that is what many of us _like_ about git. It
> is based around simple and powerful concepts, and it doesn't get in your
> way when you want to use those concepts in a powerful and flexible
> manner. And I can understand resistance to making those features hard or
> inconvenient to access; detached HEADs were invented for a reason, and
> we want to use them.

Right.  Removing features That _are_ being used sounds a bit backward. 
Just because they happen to be confusing to beginners is not a good 
justification to remove/cripple them IMHO.

> So what is the right way to mediate between those desires? We have tried
> or suggested several options, including:
> 
>   1. Educate users. Keep exposing them to the concepts, but make
>      messages more clear. Improve documentation. This is largely the
>      route taken with the index. Has it worked? I think there is still a
>      perception among new users that the index is confusing.

Well, New users won't be new forever.  And Git is different from most 
other SCMs.  Eventually that difference is well understood by most 
not-so-new-anymore Git users.  Right now I have to deal with Perforce at 
$work and I find it _terribly_ confusing and obnoxious to use.  So it's 
only a question of getting used to something different.

IMHO this patch proposed by Daniel about the detached head is probably a 
good compromise.  It makes "confusing" operations more verbose to give 
new users a better feeling while keeping the flexibility intact.  And 
increased verbosity is less annoying than decreased flexibility.


Nicolas

^ permalink raw reply

* Re: Git: "No you can't handle my root!" (?)
From: Wesley J. Landaker @ 2009-10-15  3:02 UTC (permalink / raw)
  To: git
In-Reply-To: <1255383459.15646.10.camel@localhost>

On Monday 12 October 2009 15:37:39 Daniele Segato wrote:
> Il giorno lun, 12/10/2009 alle 01.28 -0400, sylvain@demarque.qc.ca ha
>
> scritto:
> > localhost / # git init
>
> I don't see the point of using git on the root directory :)

Just a comment: this might be of serious use in e.g. a chroot.

^ permalink raw reply

* [RFC PATCH v3 00/17] Return of smart HTTP
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git

This v3 series is a respin, and includes fixes to address reviewer
comments from v2.  The protocol specification is still omitted
from the series as I have not yet had a chance to merge reviewer
comments into the draft.

Major changes from v2:

  upload-pack:
  * multi_ack_2 renamed multi_ack_detailed

  helper:
  * options are now global
  * fetch is now a batch command (instead of fetch-multiple)
  * ftp:// no longer tries info/refs?service=git-upload-pack

  http-backend:
  * manual page
  * alternates files are now served as-is
  * uses proper QUERY_STRING parsing
  * GIT_COMMITTER_EMAIL set to REMOTE_USER, for receive-pack reflog
  * receive-pack defaults to *ON* if REMOTE_USER is set

This series is still lacking:

  * The HTTP protocol documentation
  * Tests for the smart http transport code (existing tests pass)

I don't want to rush reviews, but I'm fast running of time to work on
this series right now.  Next week I am offline for vacation... and
then its time for GitTogether '09.  I plan to work on tests for
this series and the HTTP spec document draft, but that's it until
after GitTogether '09.


These commits are also available at:

  git://repo.or.cz/git/fastimport.git v3-smart-http


Shawn O. Pearce (17):
  pkt-line: Add strbuf based functions
  pkt-line: Make packet_read_line easier to debug
  fetch-pack: Use a strbuf to compose the want list
  Move "get_ack()" back to fetch-pack
  Add multi_ack_detailed capability to fetch-pack/upload-pack
  remote-curl: Refactor walker initialization
  fetch: Allow transport -v -v -v to set verbosity to 3
  remote-helpers: Fetch more than one ref in a batch
  remote-helpers: Support custom transport options
  Move WebDAV HTTP push under remote-curl
  Git-aware CGI to provide dumb HTTP transport
  Add stateless RPC options to upload-pack, receive-pack
  Smart fetch and push over HTTP: server side
  Discover refs via smart HTTP server when available
  Smart push over HTTP: client side
  Smart fetch over HTTP: client side
  Smart HTTP fetch: gzip requests

 .gitignore                           |    1 +
 Documentation/config.txt             |    8 +
 Documentation/git-http-backend.txt   |  142 +++++++
 Documentation/git-remote-helpers.txt |   85 ++++-
 Makefile                             |    1 +
 builtin-fetch-pack.c                 |  210 ++++++++--
 builtin-fetch.c                      |    2 +-
 builtin-receive-pack.c               |   26 +-
 builtin-send-pack.c                  |  116 +++++-
 cache.h                              |    1 -
 commit.c                             |   10 +-
 commit.h                             |    2 +-
 connect.c                            |   21 -
 fetch-pack.h                         |    3 +-
 http-backend.c                       |  603 +++++++++++++++++++++++++++
 http-push.c                          |   43 ++-
 http.c                               |    9 +
 http.h                               |    1 +
 pkt-line.c                           |   86 ++++-
 pkt-line.h                           |    4 +
 remote-curl.c                        |  758 ++++++++++++++++++++++++++++++++--
 send-pack.h                          |    3 +-
 sideband.c                           |   11 +-
 transport-helper.c                   |  262 +++++++++++-
 transport.c                          |   32 +--
 transport.h                          |    2 +-
 upload-pack.c                        |   71 +++-
 27 files changed, 2296 insertions(+), 217 deletions(-)
 create mode 100644 Documentation/git-http-backend.txt
 create mode 100644 http-backend.c

^ permalink raw reply

* [RFC PATCH v3 02/17] pkt-line: Make packet_read_line easier to debug
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

When there is an error parsing the 4 byte length component we now
NUL terminate the string and display it as part of the die message,
this may hint as to what data was misunderstood by the application.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 pkt-line.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index bd603f8..893dd3c 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -124,12 +124,14 @@ static int packet_length(const char *linelen)
 int packet_read_line(int fd, char *buffer, unsigned size)
 {
 	int len;
-	char linelen[4];
+	char linelen[5];
 
 	safe_read(fd, linelen, 4);
 	len = packet_length(linelen);
-	if (len < 0)
-		die("protocol error: bad line length character");
+	if (len < 0) {
+		linelen[4] = '\0';
+		die("protocol error: bad line length character: %s", linelen);
+	}
 	if (!len)
 		return 0;
 	len -= 4;
-- 
1.6.5.52.g0ff2e

^ permalink raw reply related

* [RFC PATCH v3 01/17] pkt-line: Add strbuf based functions
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

These routines help to work with pkt-line values inside of a strbuf,
permitting simple formatting of buffered network messages.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 pkt-line.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 pkt-line.h |    4 +++
 2 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/pkt-line.c b/pkt-line.c
index b691abe..bd603f8 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -42,17 +42,19 @@ void packet_flush(int fd)
 	safe_write(fd, "0000", 4);
 }
 
+void packet_buf_flush(struct strbuf *buf)
+{
+	strbuf_add(buf, "0000", 4);
+}
+
 #define hex(a) (hexchar[(a) & 15])
-void packet_write(int fd, const char *fmt, ...)
+static char buffer[1000];
+static unsigned format_packet(const char *fmt, va_list args)
 {
-	static char buffer[1000];
 	static char hexchar[] = "0123456789abcdef";
-	va_list args;
 	unsigned n;
 
-	va_start(args, fmt);
 	n = vsnprintf(buffer + 4, sizeof(buffer) - 4, fmt, args);
-	va_end(args);
 	if (n >= sizeof(buffer)-4)
 		die("protocol error: impossibly long line");
 	n += 4;
@@ -60,9 +62,31 @@ void packet_write(int fd, const char *fmt, ...)
 	buffer[1] = hex(n >> 8);
 	buffer[2] = hex(n >> 4);
 	buffer[3] = hex(n);
+	return n;
+}
+
+void packet_write(int fd, const char *fmt, ...)
+{
+	va_list args;
+	unsigned n;
+
+	va_start(args, fmt);
+	n = format_packet(fmt, args);
+	va_end(args);
 	safe_write(fd, buffer, n);
 }
 
+void packet_buf_write(struct strbuf *buf, const char *fmt, ...)
+{
+	va_list args;
+	unsigned n;
+
+	va_start(args, fmt);
+	n = format_packet(fmt, args);
+	va_end(args);
+	strbuf_add(buf, buffer, n);
+}
+
 static void safe_read(int fd, void *buffer, unsigned size)
 {
 	ssize_t ret = read_in_full(fd, buffer, size);
@@ -72,15 +96,11 @@ static void safe_read(int fd, void *buffer, unsigned size)
 		die("The remote end hung up unexpectedly");
 }
 
-int packet_read_line(int fd, char *buffer, unsigned size)
+static int packet_length(const char *linelen)
 {
 	int n;
-	unsigned len;
-	char linelen[4];
-
-	safe_read(fd, linelen, 4);
+	int len = 0;
 
-	len = 0;
 	for (n = 0; n < 4; n++) {
 		unsigned char c = linelen[n];
 		len <<= 4;
@@ -96,8 +116,20 @@ int packet_read_line(int fd, char *buffer, unsigned size)
 			len += c - 'A' + 10;
 			continue;
 		}
-		die("protocol error: bad line length character");
+		return -1;
 	}
+	return len;
+}
+
+int packet_read_line(int fd, char *buffer, unsigned size)
+{
+	int len;
+	char linelen[4];
+
+	safe_read(fd, linelen, 4);
+	len = packet_length(linelen);
+	if (len < 0)
+		die("protocol error: bad line length character");
 	if (!len)
 		return 0;
 	len -= 4;
@@ -107,3 +139,31 @@ int packet_read_line(int fd, char *buffer, unsigned size)
 	buffer[len] = 0;
 	return len;
 }
+
+int packet_get_line(struct strbuf *out,
+	char **src_buf, size_t *src_len)
+{
+	int len;
+
+	if (*src_len < 4)
+		return -1;
+	len = packet_length(*src_buf);
+	if (len < 0)
+		return -1;
+	if (!len) {
+		*src_buf += 4;
+		*src_len -= 4;
+		return 0;
+	}
+	if (*src_len < len)
+		return -2;
+
+	*src_buf += 4;
+	*src_len -= 4;
+	len -= 4;
+
+	strbuf_add(out, *src_buf, len);
+	*src_buf += len;
+	*src_len -= len;
+	return len;
+}
diff --git a/pkt-line.h b/pkt-line.h
index 9df653f..1e5dcfe 100644
--- a/pkt-line.h
+++ b/pkt-line.h
@@ -2,14 +2,18 @@
 #define PKTLINE_H
 
 #include "git-compat-util.h"
+#include "strbuf.h"
 
 /*
  * Silly packetized line writing interface
  */
 void packet_flush(int fd);
 void packet_write(int fd, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
+void packet_buf_flush(struct strbuf *buf);
+void packet_buf_write(struct strbuf *buf, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
 
 int packet_read_line(int fd, char *buffer, unsigned size);
+int packet_get_line(struct strbuf *out, char **src_buf, size_t *src_len);
 ssize_t safe_write(int, const void *, ssize_t);
 
 #endif
-- 
1.6.5.52.g0ff2e

^ permalink raw reply related

* [RFC PATCH v3 03/17] fetch-pack: Use a strbuf to compose the want list
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

This change is being offered as a refactoring to make later
commits in the smart HTTP series easier.

By changing the enabled capabilities to be formatted in a strbuf
it is easier to add a new capability to the set of supported
capabilities.

By formatting the want portion of the request into a strbuf and
writing it as a whole block we can later decide to hold onto
the req_buf (instead of releasing it) to recycle in stateless
communications.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-fetch-pack.c |   52 ++++++++++++++++++++++++++++++++-----------------
 commit.c             |   10 +++-----
 commit.h             |    2 +-
 3 files changed, 39 insertions(+), 25 deletions(-)

diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 629735f..783c2b0 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -165,6 +165,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 	const unsigned char *sha1;
 	unsigned in_vain = 0;
 	int got_continue = 0;
+	struct strbuf req_buf = STRBUF_INIT;
 
 	if (marked)
 		for_each_ref(clear_marks, NULL);
@@ -175,6 +176,7 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 	fetching = 0;
 	for ( ; refs ; refs = refs->next) {
 		unsigned char *remote = refs->old_sha1;
+		const char *remote_hex;
 		struct object *o;
 
 		/*
@@ -192,27 +194,36 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 			continue;
 		}
 
-		if (!fetching)
-			packet_write(fd[1], "want %s%s%s%s%s%s%s%s\n",
-				     sha1_to_hex(remote),
-				     (multi_ack ? " multi_ack" : ""),
-				     (use_sideband == 2 ? " side-band-64k" : ""),
-				     (use_sideband == 1 ? " side-band" : ""),
-				     (args.use_thin_pack ? " thin-pack" : ""),
-				     (args.no_progress ? " no-progress" : ""),
-				     (args.include_tag ? " include-tag" : ""),
-				     (prefer_ofs_delta ? " ofs-delta" : ""));
-		else
-			packet_write(fd[1], "want %s\n", sha1_to_hex(remote));
+		remote_hex = sha1_to_hex(remote);
+		if (!fetching) {
+			struct strbuf c = STRBUF_INIT;
+			if (multi_ack)          strbuf_addstr(&c, " multi_ack");
+			if (use_sideband == 2)  strbuf_addstr(&c, " side-band-64k");
+			if (use_sideband == 1)  strbuf_addstr(&c, " side-band");
+			if (args.use_thin_pack) strbuf_addstr(&c, " thin-pack");
+			if (args.no_progress)   strbuf_addstr(&c, " no-progress");
+			if (args.include_tag)   strbuf_addstr(&c, " include-tag");
+			if (prefer_ofs_delta)   strbuf_addstr(&c, " ofs-delta");
+			packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf);
+			strbuf_release(&c);
+		} else
+			packet_buf_write(&req_buf, "want %s\n", remote_hex);
 		fetching++;
 	}
+
+	if (!fetching) {
+		strbuf_release(&req_buf);
+		packet_flush(fd[1]);
+		return 1;
+	}
+
 	if (is_repository_shallow())
-		write_shallow_commits(fd[1], 1);
+		write_shallow_commits(&req_buf, 1);
 	if (args.depth > 0)
-		packet_write(fd[1], "deepen %d", args.depth);
-	packet_flush(fd[1]);
-	if (!fetching)
-		return 1;
+		packet_buf_write(&req_buf, "deepen %d", args.depth);
+	packet_buf_flush(&req_buf);
+
+	safe_write(fd[1], req_buf.buf, req_buf.len);
 
 	if (args.depth > 0) {
 		char line[1024];
@@ -296,6 +307,8 @@ done:
 		multi_ack = 0;
 		flushes++;
 	}
+	strbuf_release(&req_buf);
+
 	while (flushes || multi_ack) {
 		int ack = get_ack(fd[0], result_sha1);
 		if (ack) {
@@ -809,6 +822,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
 
 	if (args.depth > 0) {
 		struct cache_time mtime;
+		struct strbuf sb = STRBUF_INIT;
 		char *shallow = git_path("shallow");
 		int fd;
 
@@ -826,12 +840,14 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args,
 
 		fd = hold_lock_file_for_update(&lock, shallow,
 					       LOCK_DIE_ON_ERROR);
-		if (!write_shallow_commits(fd, 0)) {
+		if (!write_shallow_commits(&sb, 0)
+		 || write_in_full(fd, sb.buf, sb.len) != sb.len) {
 			unlink_or_warn(shallow);
 			rollback_lock_file(&lock);
 		} else {
 			commit_lock_file(&lock);
 		}
+		strbuf_release(&sb);
 	}
 
 	reprepare_packed_git();
diff --git a/commit.c b/commit.c
index fedbd5e..471efb0 100644
--- a/commit.c
+++ b/commit.c
@@ -199,7 +199,7 @@ struct commit_graft *lookup_commit_graft(const unsigned char *sha1)
 	return commit_graft[pos];
 }
 
-int write_shallow_commits(int fd, int use_pack_protocol)
+int write_shallow_commits(struct strbuf *out, int use_pack_protocol)
 {
 	int i, count = 0;
 	for (i = 0; i < commit_graft_nr; i++)
@@ -208,12 +208,10 @@ int write_shallow_commits(int fd, int use_pack_protocol)
 				sha1_to_hex(commit_graft[i]->sha1);
 			count++;
 			if (use_pack_protocol)
-				packet_write(fd, "shallow %s", hex);
+				packet_buf_write(out, "shallow %s", hex);
 			else {
-				if (write_in_full(fd, hex,  40) != 40)
-					break;
-				if (write_str_in_full(fd, "\n") != 1)
-					break;
+				strbuf_addstr(out, hex);
+				strbuf_addch(out, '\n');
 			}
 		}
 	return count;
diff --git a/commit.h b/commit.h
index f4fc5c5..817c75c 100644
--- a/commit.h
+++ b/commit.h
@@ -131,7 +131,7 @@ extern struct commit_list *get_octopus_merge_bases(struct commit_list *in);
 
 extern int register_shallow(const unsigned char *sha1);
 extern int unregister_shallow(const unsigned char *sha1);
-extern int write_shallow_commits(int fd, int use_pack_protocol);
+extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol);
 extern int is_repository_shallow(void);
 extern struct commit_list *get_shallow_commits(struct object_array *heads,
 		int depth, int shallow_flag, int not_shallow_flag);
-- 
1.6.5.52.g0ff2e

^ permalink raw reply related

* [RFC PATCH v3 04/17] Move "get_ack()" back to fetch-pack
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

In 41cb7488 Linus moved this function to connect.c for reuse inside
of the git-clone-pack command.  That was 2005, but in 2006 Junio
retired git-clone-pack in commit efc7fa53.  Since then the only
caller has been fetch-pack.  Since this ACK/NAK exchange is only
used by the fetch-pack/upload-pack protocol we should keep move
it back to a private detail of fetch-pack.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-fetch-pack.c |   21 +++++++++++++++++++++
 cache.h              |    1 -
 connect.c            |   21 ---------------------
 3 files changed, 21 insertions(+), 22 deletions(-)

diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 783c2b0..7c09d46 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -157,6 +157,27 @@ static const unsigned char *get_rev(void)
 	return commit->object.sha1;
 }
 
+static int get_ack(int fd, unsigned char *result_sha1)
+{
+	static char line[1000];
+	int len = packet_read_line(fd, line, sizeof(line));
+
+	if (!len)
+		die("git fetch-pack: expected ACK/NAK, got EOF");
+	if (line[len-1] == '\n')
+		line[--len] = 0;
+	if (!strcmp(line, "NAK"))
+		return 0;
+	if (!prefixcmp(line, "ACK ")) {
+		if (!get_sha1_hex(line+4, result_sha1)) {
+			if (strstr(line+45, "continue"))
+				return 2;
+			return 1;
+		}
+	}
+	die("git fetch_pack: expected ACK/NAK, got '%s'", line);
+}
+
 static int find_common(int fd[2], unsigned char *result_sha1,
 		       struct ref *refs)
 {
diff --git a/cache.h b/cache.h
index a5eeead..4e283be 100644
--- a/cache.h
+++ b/cache.h
@@ -856,7 +856,6 @@ extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
 extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
 extern int finish_connect(struct child_process *conn);
 extern int path_match(const char *path, int nr, char **match);
-extern int get_ack(int fd, unsigned char *result_sha1);
 struct extra_have_objects {
 	int nr, alloc;
 	unsigned char (*array)[20];
diff --git a/connect.c b/connect.c
index 7945e38..839a103 100644
--- a/connect.c
+++ b/connect.c
@@ -107,27 +107,6 @@ int server_supports(const char *feature)
 		strstr(server_capabilities, feature) != NULL;
 }
 
-int get_ack(int fd, unsigned char *result_sha1)
-{
-	static char line[1000];
-	int len = packet_read_line(fd, line, sizeof(line));
-
-	if (!len)
-		die("git fetch-pack: expected ACK/NAK, got EOF");
-	if (line[len-1] == '\n')
-		line[--len] = 0;
-	if (!strcmp(line, "NAK"))
-		return 0;
-	if (!prefixcmp(line, "ACK ")) {
-		if (!get_sha1_hex(line+4, result_sha1)) {
-			if (strstr(line+45, "continue"))
-				return 2;
-			return 1;
-		}
-	}
-	die("git fetch_pack: expected ACK/NAK, got '%s'", line);
-}
-
 int path_match(const char *path, int nr, char **match)
 {
 	int i;
-- 
1.6.5.52.g0ff2e

^ permalink raw reply related

* [RFC PATCH v3 06/17] remote-curl: Refactor walker initialization
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git; +Cc: Daniel Barkalow
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

We will need the walker, url and remote in other functions as the
code grows larger to support smart HTTP.  Extract this out into a
set of globals we can easily reference once configured.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
CC: Daniel Barkalow <barkalow@iabervon.org>
---
 remote-curl.c |   24 ++++++++++++++----------
 1 files changed, 14 insertions(+), 10 deletions(-)

diff --git a/remote-curl.c b/remote-curl.c
index 2faf1c6..478f3ea 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -5,7 +5,17 @@
 #include "http.h"
 #include "exec_cmd.h"
 
-static struct ref *get_refs(struct walker *walker, const char *url)
+static struct remote *remote;
+static const char *url;
+static struct walker *walker;
+
+static void init_walker(void)
+{
+	if (!walker)
+		walker = get_http_walker(url, remote);
+}
+
+static struct ref *get_refs(void)
 {
 	struct strbuf buffer = STRBUF_INIT;
 	char *data, *start, *mid;
@@ -21,6 +31,7 @@ static struct ref *get_refs(struct walker *walker, const char *url)
 	refs_url = xmalloc(strlen(url) + 11);
 	sprintf(refs_url, "%s/info/refs", url);
 
+	init_walker();
 	http_ret = http_get_strbuf(refs_url, &buffer, HTTP_NO_CACHE);
 	switch (http_ret) {
 	case HTTP_OK:
@@ -78,10 +89,7 @@ static struct ref *get_refs(struct walker *walker, const char *url)
 
 int main(int argc, const char **argv)
 {
-	struct remote *remote;
 	struct strbuf buf = STRBUF_INIT;
-	const char *url;
-	struct walker *walker = NULL;
 
 	git_extract_argv0_path(argv[0]);
 	setup_git_directory();
@@ -103,8 +111,7 @@ int main(int argc, const char **argv)
 			break;
 		if (!prefixcmp(buf.buf, "fetch ")) {
 			char *obj = buf.buf + strlen("fetch ");
-			if (!walker)
-				walker = get_http_walker(url, remote);
+			init_walker();
 			walker->get_all = 1;
 			walker->get_tree = 1;
 			walker->get_history = 1;
@@ -115,11 +122,8 @@ int main(int argc, const char **argv)
 			printf("\n");
 			fflush(stdout);
 		} else if (!strcmp(buf.buf, "list")) {
-			struct ref *refs;
+			struct ref *refs = get_refs();
 			struct ref *posn;
-			if (!walker)
-				walker = get_http_walker(url, remote);
-			refs = get_refs(walker, url);
 			for (posn = refs; posn; posn = posn->next) {
 				if (posn->symref)
 					printf("@%s %s\n", posn->symref, posn->name);
-- 
1.6.5.52.g0ff2e

^ permalink raw reply related

* [RFC PATCH v3 05/17] Add multi_ack_detailed capability to fetch-pack/upload-pack
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

When multi_ack_detailed is enabled the ACK continue messages returned
by the remote upload-pack are broken out to describe the different
states within the peer.  This permits the client to better understand
the server's in-memory state.

The fetch-pack/upload-pack protocol now looks like:

NAK
---------------------------------
  Always sent in response to "done" if there was no common base
  selected from the "have" lines (or no have lines were sent).

  * no multi_ack or multi_ack_detailed:

    Sent when the client has sent a pkt-line flush ("0000") and
    the server has not yet found a common base object.

  * either multi_ack or multi_ack_detailed:

    Always sent in response to a pkt-line flush.

ACK %s
-----------------------------------
  * no multi_ack or multi_ack_detailed:

    Sent in response to "have" when the object exists on the remote
    side and is therefore an object in common between the peers.
    The argument is the SHA-1 of the common object.

  * either multi_ack or multi_ack_detailed:

    Sent in response to "done" if there are common objects.
    The argument is the last SHA-1 determined to be common.

ACK %s continue
-----------------------------------
  * multi_ack only:

    Sent in response to "have".

    The remote side wants the client to consider this object as
    common, and immediately stop transmitting additional "have"
    lines for objects that are reachable from it.  The reason
    the client should stop is not given, but is one of the two
    cases below available under multi_ack_detailed.

ACK %s common
-----------------------------------
  * multi_ack_detailed only:

    Sent in response to "have".  Both sides have this object.
    Like with "ACK %s continue" above the client should stop
    sending have lines reachable for objects from the argument.

ACK %s ready
-----------------------------------
  * multi_ack_detailed only:

    Sent in response to "have".

    The client should stop transmitting objects which are reachable
    from the argument, and send "done" soon to get the objects.

    If the remote side has the specified object, it should
    first send an "ACK %s common" message prior to sending
    "ACK %s ready".

    Clients may still submit additional "have" lines if there are
    more side branches for the client to explore that might be added
    to the common set and reduce the number of objects to transfer.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-fetch-pack.c |   41 ++++++++++++++++++++++++++++++++---------
 upload-pack.c        |   31 ++++++++++++++++++-------------
 2 files changed, 50 insertions(+), 22 deletions(-)

diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c
index 7c09d46..615f549 100644
--- a/builtin-fetch-pack.c
+++ b/builtin-fetch-pack.c
@@ -157,7 +157,15 @@ static const unsigned char *get_rev(void)
 	return commit->object.sha1;
 }
 
-static int get_ack(int fd, unsigned char *result_sha1)
+enum ack_type {
+	NAK = 0,
+	ACK,
+	ACK_continue,
+	ACK_common,
+	ACK_ready
+};
+
+static enum ack_type get_ack(int fd, unsigned char *result_sha1)
 {
 	static char line[1000];
 	int len = packet_read_line(fd, line, sizeof(line));
@@ -167,12 +175,16 @@ static int get_ack(int fd, unsigned char *result_sha1)
 	if (line[len-1] == '\n')
 		line[--len] = 0;
 	if (!strcmp(line, "NAK"))
-		return 0;
+		return NAK;
 	if (!prefixcmp(line, "ACK ")) {
 		if (!get_sha1_hex(line+4, result_sha1)) {
 			if (strstr(line+45, "continue"))
-				return 2;
-			return 1;
+				return ACK_continue;
+			if (strstr(line+45, "common"))
+				return ACK_common;
+			if (strstr(line+45, "ready"))
+				return ACK_ready;
+			return ACK;
 		}
 	}
 	die("git fetch_pack: expected ACK/NAK, got '%s'", line);
@@ -218,7 +230,8 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 		remote_hex = sha1_to_hex(remote);
 		if (!fetching) {
 			struct strbuf c = STRBUF_INIT;
-			if (multi_ack)          strbuf_addstr(&c, " multi_ack");
+			if (multi_ack == 2)     strbuf_addstr(&c, " multi_ack_detailed");
+			if (multi_ack == 1)     strbuf_addstr(&c, " multi_ack");
 			if (use_sideband == 2)  strbuf_addstr(&c, " side-band-64k");
 			if (use_sideband == 1)  strbuf_addstr(&c, " side-band");
 			if (args.use_thin_pack) strbuf_addstr(&c, " thin-pack");
@@ -298,18 +311,23 @@ static int find_common(int fd[2], unsigned char *result_sha1,
 				if (args.verbose && ack)
 					fprintf(stderr, "got ack %d %s\n", ack,
 							sha1_to_hex(result_sha1));
-				if (ack == 1) {
+				switch (ack) {
+				case ACK:
 					flushes = 0;
 					multi_ack = 0;
 					retval = 0;
 					goto done;
-				} else if (ack == 2) {
+				case ACK_common:
+				case ACK_ready:
+				case ACK_continue: {
 					struct commit *commit =
 						lookup_commit(result_sha1);
 					mark_common(commit, 0, 1);
 					retval = 0;
 					in_vain = 0;
 					got_continue = 1;
+					break;
+					}
 				}
 			} while (ack);
 			flushes--;
@@ -336,7 +354,7 @@ done:
 			if (args.verbose)
 				fprintf(stderr, "got ack (%d) %s\n", ack,
 					sha1_to_hex(result_sha1));
-			if (ack == 1)
+			if (ack == ACK)
 				return 0;
 			multi_ack = 1;
 			continue;
@@ -618,7 +636,12 @@ static struct ref *do_fetch_pack(int fd[2],
 
 	if (is_repository_shallow() && !server_supports("shallow"))
 		die("Server does not support shallow clients");
-	if (server_supports("multi_ack")) {
+	if (server_supports("multi_ack_detailed")) {
+		if (args.verbose)
+			fprintf(stderr, "Server supports multi_ack_detailed\n");
+		multi_ack = 2;
+	}
+	else if (server_supports("multi_ack")) {
 		if (args.verbose)
 			fprintf(stderr, "Server supports multi_ack\n");
 		multi_ack = 1;
diff --git a/upload-pack.c b/upload-pack.c
index 38ddac2..f1dc3a3 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -498,7 +498,7 @@ static int get_common_commits(void)
 {
 	static char line[1000];
 	unsigned char sha1[20];
-	char hex[41], last_hex[41];
+	char last_hex[41];
 
 	save_commit_buffer = 0;
 
@@ -515,19 +515,22 @@ static int get_common_commits(void)
 		if (!prefixcmp(line, "have ")) {
 			switch (got_sha1(line+5, sha1)) {
 			case -1: /* they have what we do not */
-				if (multi_ack && ok_to_give_up())
-					packet_write(1, "ACK %s continue\n",
-						     sha1_to_hex(sha1));
+				if (multi_ack && ok_to_give_up()) {
+					const char *hex = sha1_to_hex(sha1);
+					if (multi_ack == 2)
+						packet_write(1, "ACK %s ready\n", hex);
+					else
+						packet_write(1, "ACK %s continue\n", hex);
+				}
 				break;
 			default:
-				memcpy(hex, sha1_to_hex(sha1), 41);
-				if (multi_ack) {
-					const char *msg = "ACK %s continue\n";
-					packet_write(1, msg, hex);
-					memcpy(last_hex, hex, 41);
-				}
+				memcpy(last_hex, sha1_to_hex(sha1), 41);
+				if (multi_ack == 2)
+					packet_write(1, "ACK %s common\n", last_hex);
+				else if (multi_ack)
+					packet_write(1, "ACK %s continue\n", last_hex);
 				else if (have_obj.nr == 1)
-					packet_write(1, "ACK %s\n", hex);
+					packet_write(1, "ACK %s\n", last_hex);
 				break;
 			}
 			continue;
@@ -587,7 +590,9 @@ static void receive_needs(void)
 		    get_sha1_hex(line+5, sha1_buf))
 			die("git upload-pack: protocol error, "
 			    "expected to get sha, not '%s'", line);
-		if (strstr(line+45, "multi_ack"))
+		if (strstr(line+45, "multi_ack_detailed"))
+			multi_ack = 2;
+		else if (strstr(line+45, "multi_ack"))
 			multi_ack = 1;
 		if (strstr(line+45, "thin-pack"))
 			use_thin_pack = 1;
@@ -681,7 +686,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 {
 	static const char *capabilities = "multi_ack thin-pack side-band"
 		" side-band-64k ofs-delta shallow no-progress"
-		" include-tag";
+		" include-tag multi_ack_detailed";
 	struct object *o = parse_object(sha1);
 
 	if (!o)
-- 
1.6.5.52.g0ff2e

^ permalink raw reply related

* [RFC PATCH v3 12/17] Add stateless RPC options to upload-pack, receive-pack
From: Shawn O. Pearce @ 2009-10-15  3:36 UTC (permalink / raw)
  To: git
In-Reply-To: <1255577814-14745-1-git-send-email-spearce@spearce.org>

When --stateless-rpc is passed as a command line parameter to
upload-pack or receive-pack the programs now assume they may
perform only a single read-write cycle with stdin and stdout.
This fits with the HTTP POST request processing model where a
program may read the request, write a response, and must exit.

When --advertise-refs is passed as a command line parameter only
the initial ref advertisement is output, and the program exits
immediately.  This fits with the HTTP GET request model, where
no request content is received but a response must be produced.

HTTP headers and/or environment are not processed here, but
instead are assumed to be handled by the program invoking
either service backend.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-receive-pack.c |   26 ++++++++++++++++++++------
 upload-pack.c          |   40 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 56 insertions(+), 10 deletions(-)

diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index b771fe9..70ff8c5 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -615,6 +615,8 @@ static void add_alternate_refs(void)
 
 int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 {
+	int advertise_refs = 0;
+	int stateless_rpc = 0;
 	int i;
 	char *dir = NULL;
 
@@ -623,7 +625,15 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		const char *arg = *argv++;
 
 		if (*arg == '-') {
-			/* Do flag handling here */
+			if (!strcmp(arg, "--advertise-refs")) {
+				advertise_refs = 1;
+				continue;
+			}
+			if (!strcmp(arg, "--stateless-rpc")) {
+				stateless_rpc = 1;
+				continue;
+			}
+
 			usage(receive_pack_usage);
 		}
 		if (dir)
@@ -652,12 +662,16 @@ int cmd_receive_pack(int argc, const char **argv, const char *prefix)
 		" report-status delete-refs ofs-delta " :
 		" report-status delete-refs ";
 
-	add_alternate_refs();
-	write_head_info();
-	clear_extra_refs();
+	if (advertise_refs || !stateless_rpc) {
+		add_alternate_refs();
+		write_head_info();
+		clear_extra_refs();
 
-	/* EOF */
-	packet_flush(1);
+		/* EOF */
+		packet_flush(1);
+	}
+	if (advertise_refs)
+		return 0;
 
 	read_head_info();
 	if (commands) {
diff --git a/upload-pack.c b/upload-pack.c
index f1dc3a3..70badcf 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -39,6 +39,8 @@ static unsigned int timeout;
  */
 static int use_sideband;
 static int debug_fd;
+static int advertise_refs;
+static int stateless_rpc;
 
 static void reset_timeout(void)
 {
@@ -509,6 +511,8 @@ static int get_common_commits(void)
 		if (!len) {
 			if (have_obj.nr == 0 || multi_ack)
 				packet_write(1, "NAK\n");
+			if (stateless_rpc)
+				exit(0);
 			continue;
 		}
 		strip(line, len);
@@ -710,12 +714,32 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 	return 0;
 }
 
+static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+{
+	struct object *o = parse_object(sha1);
+	if (!o)
+		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
+	if (!(o->flags & OUR_REF)) {
+		o->flags |= OUR_REF;
+		nr_our_refs++;
+	}
+	return 0;
+}
+
 static void upload_pack(void)
 {
-	reset_timeout();
-	head_ref(send_ref, NULL);
-	for_each_ref(send_ref, NULL);
-	packet_flush(1);
+	if (advertise_refs || !stateless_rpc) {
+		reset_timeout();
+		head_ref(send_ref, NULL);
+		for_each_ref(send_ref, NULL);
+		packet_flush(1);
+	} else {
+		head_ref(mark_our_ref, NULL);
+		for_each_ref(mark_our_ref, NULL);
+	}
+	if (advertise_refs)
+		return;
+
 	receive_needs();
 	if (want_obj.nr) {
 		get_common_commits();
@@ -737,6 +761,14 @@ int main(int argc, char **argv)
 
 		if (arg[0] != '-')
 			break;
+		if (!strcmp(arg, "--advertise-refs")) {
+			advertise_refs = 1;
+			continue;
+		}
+		if (!strcmp(arg, "--stateless-rpc")) {
+			stateless_rpc = 1;
+			continue;
+		}
 		if (!strcmp(arg, "--strict")) {
 			strict = 1;
 			continue;
-- 
1.6.5.52.g0ff2e

^ 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