Git development
 help / color / mirror / Atom feed
* Re: [PATCHv2] connect: display connection progress
From: Junio C Hamano @ 2007-05-10 19:29 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Alex Riesen, git
In-Reply-To: <20070510120802.GG13655@mellanox.co.il>

"Michael S. Tsirkin" <mst@dev.mellanox.co.il> writes:

>> Quoting Alex Riesen <raa.lkml@gmail.com>:
>> Subject: Re: [PATCHv2] connect: display connection progress
>> 
>> On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
>> >-static int git_tcp_connect_sock(char *host)
>> >+static int git_tcp_connect_sock(char *host, int flags)
>> 
>> There is only one bit of flags ever used. What are the others for?
>
> Hmm, I thought it's easier to read 
> git_tcp_connect_sock(host, NET_QUIET)
> 	than
> git_tcp_connect_sock(host, 1)
>
> but maybe that's overdesign.
>
>> Why use negative logic?
>> What was wrong with plain "int verbose"?
>
> I want the default to report connections, and -q
> to silence them. Maybe "int quiet"?

I would really feel this extra verbosity should not be the
default.   Thanks.

^ permalink raw reply

* Re: Merging commits together into a super-commit
From: J. Bruce Fields @ 2007-05-10 19:22 UTC (permalink / raw)
  To: Carl Worth; +Cc: Linus Torvalds, Johannes Sixt, git
In-Reply-To: <87vef0350y.wl%cworth@cworth.org>

On Thu, May 10, 2007 at 11:30:37AM -0700, Carl Worth wrote:
> So, compared to the rebase usage, this does add two commands for
> bookkeeping the original state and cleaning it up. But the syntax for
> the cherry-pick part is quite a bit simpler than the original rebase
> at least.

Yeah, something like that would be great.  I think I've seen others
suggest similar syntax before, so it's probably just a question of one
of us who want this finding time to write the patches.

> Also, "reset --hard" isn't actually what I want in this case. I'd like
> this recipe to use something that would move the current branch to
> some other point, but in a safe way, (that is, not destroy any
> uncommitted changes that might exist at the beginning). I don't have
> any proposal for what that would be.

The tag creation and cleanup could get to be annoying too.  You could
scrounge through the reflog instead of using a temporary tag, but
depending on the amount of --amend'ing and cherry-picking you do the
reflog entry may end up in a different place each time, so it's probably
hard to make this automatic.

> stg - This probably works great if you're using it as a primary
>       interface. But trying to use it as a quick one-off when
>       generally using core git does not work well at all. Instead of
>       the two "git tag" commands in my recipe above, an stg recipe
>       would involve a lot of additional bookkeeping with stg init, stg
>       uncommit [N times for fixing a commit N steps back in the
>       history], stg goto, stg push, etc.

I also didn't like having to come up with another name for each
patch--I'd rather just run git-log or gitk and cut-n-paste the sha1.

For kernel work I started out working with multiple (sym- or
hard-linked) trees, then used akpm's patch scripts, then stgit.  I think
I'm happiest just using plain git.

The one thing I've never been good at is keeping the history of the
patch series itself.

--b.

^ permalink raw reply

* Re: Merging commits together into a super-commit
From: Petr Baudis @ 2007-05-10 19:21 UTC (permalink / raw)
  To: Carl Worth; +Cc: J. Bruce Fields, Linus Torvalds, Johannes Sixt, git
In-Reply-To: <87vef0350y.wl%cworth@cworth.org>

On Thu, May 10, 2007 at 08:30:37PM CEST, Carl Worth wrote:
> stg - This probably works great if you're using it as a primary
>       interface. But trying to use it as a quick one-off when
>       generally using core git does not work well at all. Instead of
>       the two "git tag" commands in my recipe above, an stg recipe
>       would involve a lot of additional bookkeeping with stg init, stg
>       uncommit [N times for fixing a commit N steps back in the
>       history], stg goto, stg push, etc.

I think you are underestimating stg here. You can stg init just once per
branch (ever), I think. Then,

	stg uncommit -n N
	stg pop -n N-1
	..hack..
	stg refresh
	stg push -a

It seems to be a bit shorter than the sequence you've presented above,
and overally working with volatile commits using StGIT feels much more
natural to me - and I haven't even ever used quilt seriously! (I have
special antipathy to the git reset UI, too.)

Few days ago Santi Bejar has sent me a bundle with some updates to the
Git homepage (thanks again a lot!). Since I didn't want some of the
patches and wanted to tweak others, what I eventually did was pretty
much this: I fast-forwarded my master to his bundle's head, then
uncommitted the patches, popped them all and repeated the sequence

	stg push
	..review..
		stg refresh
		stg commit
	..or..
		stg delete `stg top`

for each patch.

-- 
				Petr "Pasky" Baudis
Stuff: http://pasky.or.cz/
Ever try. Ever fail. No matter. // Try again. Fail again. Fail better.
		-- Samuel Beckett

^ permalink raw reply

* Re: Merging commits together into a super-commit
From: Carl Worth @ 2007-05-10 18:30 UTC (permalink / raw)
  To: J. Bruce Fields; +Cc: Linus Torvalds, Johannes Sixt, git
In-Reply-To: <20070510171457.GK13719@fieldses.org>

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

On Thu, 10 May 2007 13:14:57 -0400, "J. Bruce Fields" wrote:
> I use it all the time to fix up old commits with
>
> 	git checkout sha1-of-bad-commit
> 	...edit, test,...
> 	git commit -a ---amend
> 	git rebase --onto HEAD sha1-of-bad-commit original-branch

Excellent. Thanks for the description.

Fixing up some broken (unpublished) commit in the past is a useful
thing to support[*]. Of course, "commit --amend" takes care of this for
the case where it's the most recent commit. For an older commit, here
is exactly what I'd like to do, (showing that my suggestion of
cherry-pick with a range would cover exactly this scenario):

	git tag tainted		# Could be "git branch tainted" just as well

	git reset --hard bad-commit
	...edit, test...
	git commit --amend
	git cherry-pick bad-commit..tainted

	git tag -d tainted

So, compared to the rebase usage, this does add two commands for
bookkeeping the original state and cleaning it up. But the syntax for
the cherry-pick part is quite a bit simpler than the original rebase
at least.

Also, "reset --hard" isn't actually what I want in this case. I'd like
this recipe to use something that would move the current branch to
some other point, but in a safe way, (that is, not destroy any
uncommitted changes that might exist at the beginning). I don't have
any proposal for what that would be.

-Carl

[*] I've also experimented with using other "non-core git" ways of
addressing this same problem. Here are a couple that I haven't found
satisfactory for this particular use case:

stg - This probably works great if you're using it as a primary
      interface. But trying to use it as a quick one-off when
      generally using core git does not work well at all. Instead of
      the two "git tag" commands in my recipe above, an stg recipe
      would involve a lot of additional bookkeeping with stg init, stg
      uncommit [N times for fixing a commit N steps back in the
      history], stg goto, stg push, etc.

cg-admin-rewritehist - This is a powerful tool, but its interface
      isn't geared toward interactively fixing things up, (instead
      requiring a filter to be executed at all steps). So, while it's
      great for changing history, (as its name suggests), such as
      performing a sed operation on the commit messages, or
      eliminating a file, it doesn't help much with the "fix up one
      broken commit in the past".

      It is worth noting that quite unlike rebase,
      cg-admin-rewritehist can deal quite nicely with history that
      involves branching and merging.


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

^ permalink raw reply

* Re: [RFC] Second parent for reverts
From: Linus Torvalds @ 2007-05-10 18:22 UTC (permalink / raw)
  To: Johan Herland; +Cc: Junio C Hamano, Daniel Barkalow, git
In-Reply-To: <200705102006.08624.johan@herland.net>



On Thu, 10 May 2007, Johan Herland wrote:
> 
> BTW, I'm wondering whether anybody has ever thought about allowing 
> after-the-fact annotations on commits. Kinda like free-form 
> continuations on the commit message. It would allow people to make 
> notes on previous commits that were either forgotten at commit-time, or 
> only became apparent after the commit was done.

We kind of have some of that.

Tag objects can be used that way, and the "grafts" file is a very special 
case. 

But if you want to do it on a larger scale, you'd need something that is 
really optimized for that. For example, git internally now has a notion of 
"decorating" arbitrary objects with arbitrary data, and if you just had an 
efficient file format to create such decorations (for blame or other 
special ops), the *code* is easy to write. It's how

	git log --decorate

works right now (the "data" is just the tag names, but you could make it 
read other decorations, and the git data structures are very efficient, 
and allow different types of decorations to be used independently of 
each other).

		Linus

^ permalink raw reply

* Re: [RFC] Second parent for reverts
From: Johan Herland @ 2007-05-10 18:06 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Junio C Hamano, Daniel Barkalow, git
In-Reply-To: <alpine.LFD.0.98.0705100927340.3986@woody.linux-foundation.org>

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

On Thursday 10 May 2007, Linus Torvalds wrote:
> On Wed, 9 May 2007, Linus Torvalds wrote:
> > If you want a "related to that commit" field, it should be a
> > separate field in the commit object. But since it doesn't really
> > have any real *semantic* meaning to git itself, it shouldn't be in
> > the header. We could, for example, make it be in the free-form
> > section, and teach our graphical visualization tools to
> > automatically turn it into a hyperlink.
> >
> > .. which we already do.
>
> Btw, sorry for harping on this issue, but one of the really *great*
> things about putting things in the free-form section is a somewhat
> unanticipated huge advantage:
>
>  - we've had much better integration with non-git users than any
> other SCM I've ever seen!
>
> [...]
>
> So in general, putting things into the headers and having git
> semantic meaning should be discouraged. The "parents" thing is
> special, because the whole "history" thing is very deeply integrated
> in git, and obviously has to be (any SCM that does _not_ have
> parenthood information is totally broken *cough*CVS/SVN*cough*), but
> other than that we should actually strive to _avoid_ anything with
> deep git semantics.

Ok. I'm sold. I will take my header fields and go away before y'all 
replace me with a very small shell script. :)


BTW, I'm wondering whether anybody has ever thought about allowing 
after-the-fact annotations on commits. Kinda like free-form 
continuations on the commit message. It would allow people to make 
notes on previous commits that were either forgotten at commit-time, or 
only became apparent after the commit was done.

Furthermore, if we make git-blame pay attention to hints in the commit 
message (like Junio suggested somewhere else in this thread) - 
including the annotations - we can then add annotations to guide 
git-blame whenever it gets the blame wrong.

There's probably other things we could use this for.

Obviously we can't store the annotations in the commit object itself 
(because commit objects are immutable). I'm thinking annotations could 
be stored as simple (compressed) text files in .git/annotations/, under 
the same sha1/filename as the corresponding commit object is stored 
under .git/objects/. That would make them easy to retrieve from their 
corresponding commit.


Anyway, it's just an idea that struck me. Feel free to tell me why this 
is the worst idea since, oh, I don't know, say, my header fields 
idea...


Have fun! :)

...Johan

-- 
Johan Herland, <johan@herland.net>
www.herland.net

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Alex Riesen @ 2007-05-10 17:40 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Junio C Hamano, git
In-Reply-To: <20070510150225.GS13655@mellanox.co.il>

On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
>
> Do you really have git servers accessed over a local lan or on local system?

Yes and yes.

> I just use ssh in this case, and I think that's the common case ...

not on windows

> We *could* try doing something smart with non-blocking connect + select,
> and only print the message if it takes > 1 second. Are you
> sure it's worth the complication?

I'm not sure this suggestion of yours is worth the complication.
Besides, it's hard to get portably

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Alex Riesen @ 2007-05-10 17:38 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Michael S. Tsirkin, Junio C Hamano, git
In-Reply-To: <alpine.LFD.0.98.0705100901320.3986@woody.linux-foundation.org>

On 5/10/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> > What addresses were tried by connect?
>
> That would be _really_ verbose. Maybe a CONNECT_EXTRA_VERBOSE?
>

It's nice to have. That's how I discovered which one of kernel.org
addresses is more stable.

^ permalink raw reply

* Re: Merging commits together into a super-commit
From: J. Bruce Fields @ 2007-05-10 17:14 UTC (permalink / raw)
  To: Carl Worth; +Cc: Linus Torvalds, Johannes Sixt, git
In-Reply-To: <87wszg39cp.wl%cworth@cworth.org>

On Thu, May 10, 2007 at 09:57:10AM -0700, Carl Worth wrote:
> I'm sure the most complex form of git-rebase solves some precise
> problem that someone has, (and maybe even gets used regularly). But
> it's got enough complications that I just ignore it, (and would
> instead really prefer being able to just cherry-pick a whole range).

I use it all the time to fix up old commits with

	git checkout sha1-of-bad-commit
	...edit, test,...
	git commit -a ---amend
	git rebase --onto HEAD sha1-of-bad-commit original-branch

But though it usually does what I want, I'm in total agreement about the
confusing syntax and branch-switching behavior....

--b.

^ permalink raw reply

* Re: quick bare clones taking longer?
From: Andy Whitcroft @ 2007-05-10 17:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: David Miller, git
In-Reply-To: <7vd519r10c.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano wrote:
> Junio C Hamano <junkio@cox.net> writes:
> 
>> David Miller <davem@davemloft.net> writes:
>>
>>> From: Junio C Hamano <junkio@cox.net>
>>> Date: Wed, 09 May 2007 15:59:23 -0700
>>>
>>>> The above sequence is called before we create the new directory
>>>> and chdir to it.  Maybe pwd has funny behaviour (e.g. $PWD) and
>>>> we need to explicitly say /bin/pwd or somesuch...
>>> Indeed:
>>>
>>> [davem@hera ~]$ pwd
>>> /home/davem
>>> [davem@hera ~]$ cd git
>>> [davem@hera git]$ pwd
>>> /home/davem/git
>>> [davem@hera git]$ /bin/pwd
>>> /home/ftp/pub/scm/linux/kernel/git/davem
>>> [davem@hera git]$ 
>> Thanks.
> 
> This would fix it, but I find this kind of ugly.
> 
> -- >8 --
> git-clone: don't get fooled by $PWD
> 
> If you have /home/me/git symlink pointing at /pub/git/mine,
> trying to clone from /pub/git/his/ using relative path would not
> work as expected:
> 
> 	$ cd /home/me
>         $ cd git
>         $ ls ../
>         his    mine
>         $ git clone -l -s -n ../his/stuff.git
> 
> This is because "cd ../his/stuff.git" done inside git-clone to
> check if the repository is local is confused by $PWD, which is
> set to /home/me, and tries to go to /home/his/stuff.git which is
> different from /pub/git/his/stuff.git.
> 
> We could probably say "set -P" (or "cd -P") instead, if we know
> the shell is POSIX, but the way the patch is coded is probably
> more portable.
> 
> Signed-off-by: Junio C Hamano <junkio@cox.net>
> ---
> 
> diff --git a/git-clone.sh b/git-clone.sh
> index cad5c0c..c5852a2 100755
> --- a/git-clone.sh
> +++ b/git-clone.sh
> @@ -18,7 +18,14 @@ usage() {
>  }
>  
>  get_repo_base() {
> -	(cd "$1" && (cd .git ; pwd)) 2> /dev/null
> +	(
> +		cd "`/bin/pwd`" &&
> +		cd "$1" &&
> +		(
> +			cd .git
> +			pwd
> +		)
> +	) 2>/dev/null
>  }
>  
>  if [ -n "$GIT_SSL_NO_VERIFY" ]; then

That is pretty much how I have seen this solved in the past.  One thing
while you are playing with this code.  There seems to be an extra
sub-shell in there unnecesarily and the error redirection seems a little
aggressive?

This seems to be semantically equivalent:

get_repo_base() {
	(
		cd "`/bin/pwd`" &&
		cd "$1" &&
		{
			cd .git 2>/dev/null
			pwd
		}
	)
}

-apw

^ permalink raw reply

* Re: Merging commits together into a super-commit
From: Carl Worth @ 2007-05-10 16:57 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Johannes Sixt, git
In-Reply-To: <alpine.LFD.0.98.0705100857450.3986@woody.linux-foundation.org>

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

On Thu, 10 May 2007 09:01:15 -0700 (PDT), Linus Torvalds wrote:
> Clearly git can, but equally clearly it really *would* be pretty nice if
> you could just do
>
> 	git cherry-pick x y z
>
> and create one commit and have the message already somewhat done for you
> (and "git revert" doing the same).

Perhaps with a --squash option. I've already been wanting a
cherry-pick that accepts a range, but that makes separate commits.

Yes, I know there's some git-rebase thing that will do it, but I can
never remember the right syntax for that without studying the
documentation[*]. What I find myself wanting to type is just:

	git cherry-pick A..B

But there is the whole problem of how to deal with any conflict that
appears during the process.

-Carl

[*] I do use one form of rebase without ever needing to consult the
documentation, but it's in the opposite "direction", if you will, from
the cherry-pick-a-range operation. I use it when I want to rebase a
set of commits from my current branch to some other branch, such as:

	git rebase origin

Not surprisingly, what's common about both of the operations above is
that they are really only accepting a single argument, (a range in one
case, and a branch-name in the other). That's what makes for an
easy-to-use command. Things that require multiple branch names in a
particular order, or extra options, (see "git rebase --onto newbase
upstream branch"), need someone smarter than me to drive them.

Another problem is that using the optional final [<branch>] argument
to git-rebase makes it change the current branch, (which no other
git-rebase operation does), and that's another thing I find very
confusing.

I'm sure the most complex form of git-rebase solves some precise
problem that someone has, (and maybe even gets used regularly). But
it's got enough complications that I just ignore it, (and would
instead really prefer being able to just cherry-pick a whole range).


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

^ permalink raw reply

* Re: FFmpeg considering GIT
From: Jan Hudec @ 2007-05-10 16:52 UTC (permalink / raw)
  To: Marco Costalba
  Cc: Fredrik Kuivinen, Paul Mackerras, Alex Riesen, Linus Torvalds,
	Karl Hasselstr?m, Junio C Hamano, Carl Worth, Michael Niedermayer,
	Git Mailing List
In-Reply-To: <e5bfff550705100420x63b365f7x526c1d58d9d5c761@mail.gmail.com>

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

On Thu, May 10, 2007 at 13:20:02 +0200, Marco Costalba wrote:
> On 5/9/07, Jan Hudec <bulb@ucw.cz> wrote:
> >On Wed, May 09, 2007 at 23:09:25 +0200, Fredrik Kuivinen wrote:
> >> I have used PyQt for some smaller projects (notably Hgct, a no longer
> >> developed
> >> commit tool for git and Mercurial. See
> >> http://repo.or.cz/w/hgct.git?a=tree). For me
> >> PyQt has worked very well. The python interface to Qt is more or less a
> >> direct
> >> translation of the C++ interface, so the excellent documentation troll
> >> tech provides
> >> for Qt can be used when developing with PyQt as well.
> >>
> >> I have never seen the segfaulting you mention. Maybe my programs have 
> >been
> >> too
> >> small to trigger that bug...
> >
> >It's not about size of the programs. It's about having to be careful not to
> >refer to widgets inside eg. dialog box from outside and close that dialog
> >box.
> 
> In Qt all the classes that ineriths from QObject are memory managed,
> to be more clear
> you can say that one class is "child" of another class (always
> ineritherd from QObject) that becames the parent.
> 
> When you delete the parent, all his children are deleted too, this is
> a (big) feature to avoid
> missing free() calls for resources created with mallocs() , (well, in
> C++ we say 'delete' for resources created by 'new' but the concept is
> more or less the same).

I know well how it works. And while it is definitely a nice feature in C++
(though it can't beat well done reference-counting smart pointers as Gtkmm
has), it is a gross misfeature in any dynamic language.

And no, I am not objecting to existence of that system -- it's useful in C++.
What I say is, that the PyQt bindings are buggy because it completely
fails to make this feature compatible with python memory management - python
program should not be able to segfault the interpreter no matter how buggy
that program is.

-- 
						 Jan 'Bulb' Hudec <bulb@ucw.cz>

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

^ permalink raw reply

* Re: [PATCH 1/3] Move remote parsing into a library file out of builtin-push.
From: Daniel Barkalow @ 2007-05-10 16:40 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v3b25kr0t.fsf@assigned-by-dhcp.cox.net>

On Thu, 10 May 2007, Junio C Hamano wrote:

> Daniel Barkalow <barkalow@iabervon.org> writes:
> 
> > On Thu, 10 May 2007, Junio C Hamano wrote:
> >
> >> Daniel Barkalow <barkalow@iabervon.org> writes:
> >> 
> >> >> And I think it does today.
> >> >
> >> > Hmm, and I guess URIs on the command line work the same way. How about 
> >> > requiring a '/' somewhere in a repository argument in order to treat it as 
> >> > a repository instead of a remote name? Then "../next-door-neighbour" would 
> >> > work, "./gitcvs.git" would work (in the odd case where you actually have a 
> >> > bare repository sitting in your working directory), but we'd avoid the 
> >> > current default of pushing to a bare repository in "./origin/" if nothing 
> >> > at all is configured.
> >> 
> >> When I wrote the message you are responding to, I thought this
> >> was a regression from the current behaviour, which (IIRC--it's
> >> getting late and I am tired to double check) essentially says if
> >> the token is a name of the directory, the target repository is a
> >> local one, but "we'd avoid..." part seems to suggest that you
> >> actually did this deliberately as a fix to some problem in the
> >> current behaviour.  I am not however sure what it exactly is.
> >> Could you care to elaborate the part after "we'd avoid..." to
> >> clarify what the problem is, please?
> >
> > The problem, in general, is that, if the remote name you specify (or 
> > "origin" if you don't specify any) is not configured as a remote, it is 
> > treated as a filename in the current directory for a local push. E.g.:
> >
> > $ git init
> > $ git push
> > fatal: 'origin': unable to chdir or not a git archive
> > fatal: The remote end hung up unexpectedly
> 
> Ahh.  You were trying to give it a better error message.
> 
> I think I lied in the previous message.  I said we try to see if
> it is a local directory name before using that name, but we do
> not do it, and leave the error detection to the lower level on
> the other side (push spawns send-pack which in turn spawns
> receive-pack) instead.
> 
> Perhaps an alternative is to see if the name is configured as a
> remote (if so, we obviously use it), and if not do stat() to see
> if it is a directory (if so, use it as a local repository).
> Then we do not have to impose new restriction of slash at all,
> although it might complicate the code a bit more.

The problem I see with allowing paths without slashes is if you've got a 
subproject with a name similar to a remote name, and type the wrong one 
(particularly due to tab-completion), or if you've got a remote name you 
use in other projects that matches a subproject in a project where you 
aren't using that remote name. I think that a repository in your working 
directory is unlikely to be something you actually want to push to or 
fetch from (and if this is actually what you want, ./directory is the 
usual unixy thing for saying, no really, I want a relative path in the 
current directory, and would work here; and it would be good practice 
anyway, so that you don't get tripped up if you create a remote 
configuration with that name later). Obviously, ../something has a slash; 
it should also take ':' to mean a URI (which I didn't realize last night), 
so that "person@machine:directory.git" is a URI.

I think, as a general rule, that it would be cleanest to distinguish 
lexically between repository names that indicate configured remotes and 
repository names that are URIs, particularly if we only break usage that 
people only do for writing git regression tests.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [RFC] Second parent for reverts
From: Linus Torvalds @ 2007-05-10 16:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Daniel Barkalow, git
In-Reply-To: <alpine.LFD.0.98.0705091513050.4062@woody.linux-foundation.org>



On Wed, 9 May 2007, Linus Torvalds wrote:
> 
> If you want a "related to that commit" field, it should be a separate 
> field in the commit object. But since it doesn't really have any real 
> *semantic* meaning to git itself, it shouldn't be in the header. We 
> could, for example, make it be in the free-form section, and teach our 
> graphical visualization tools to automatically turn it into a hyperlink.
> 
> .. which we already do.

Btw, sorry for harping on this issue, but one of the really *great* things 
about putting things in the free-form section is a somewhat unanticipated 
huge advantage:

 - we've had much better integration with non-git users than any other SCM 
   I've ever seen!

Now, a lot of that was by design (ie one of the primary design goals for 
git was to work well with patches), and it's one of the reasons that I 
totally dismiss the whole "track file ID's" idiocy: anything but "content" 
will pretty much by definition not be tracked by any other source control 
system.

But it turns out that the whole "you can point to commits in the free-form 
commit message" thing has worked out really well. It means, for example, 
that people can do "git revert" operations in their own local repository, 
AND THEY TRANSLATE BEAUTIFULLY EVEN AS EMAILED PATCHES!

I'm shouting, because it's easy to overlook these kinds of issues, but 
they are really really important. Designing your SCM around the notion 
that everybody will use a totally integrated system is a mistake! It's a 
*huge* mistake. Even a lot of git users end up sending patches back and 
forth, just because for many things it's actually more appropriate.

So I'm literally getting patches that refer to commits that I've 
integrated ("Commit xyz introduced a nasty bug", or "Revert commit abc") 
and they work very well even when I'm not merging with those people 
natively through git. 

And yes, maybe the kernel is a bit unusual in this, but I really don't 
think it should be. In many ways, emailing patches around is a much better 
workflow for actual *development* than doing git merges. The git merges 
are wonderful, but they are kind of a "the development is done, let's 
merge it" operation - they are not good for sending stuff out for comments 
or discussion!

So in general, putting things into the headers and having git semantic 
meaning should be discouraged. The "parents" thing is special, because 
the whole "history" thing is very deeply integrated in git, and obviously 
has to be (any SCM that does _not_ have parenthood information is totally 
broken *cough*CVS/SVN*cough*), but other than that we should actually 
strive to _avoid_ anything with deep git semantics.

		Linus

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Linus Torvalds @ 2007-05-10 16:05 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Michael S. Tsirkin, Junio C Hamano, git
In-Reply-To: <81b0412b0705100439j4e6b072bk1ba19a4f971e5d0c@mail.gmail.com>



On Thu, 10 May 2007, Alex Riesen wrote:
> 
> There is only one bit of flags ever used. What are the others for?

I actually think it tends to be better to have a "flags" field rather than 
a boolean, even if it only ends up having one flag.

> Why use negative logic?

This one I agree with. Ity would be nicer with CONNECT_VERBOSE than with 
NET_QUIET, and having the tests be

	if (flags & CONNECT_VERBOSE)
		..

instead.

> What was wrong with plain "int verbose"?

I could see wanting to add flags to do things like disable insecure 
connections etc, so there's certainly nothing saying that "verbose" is the 
only valid way to do things.

> What addresses were tried by connect?

That would be _really_ verbose. Maybe a CONNECT_EXTRA_VERBOSE?

		Linus

^ permalink raw reply

* Re: Merging commits together into a super-commit
From: Linus Torvalds @ 2007-05-10 16:01 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git
In-Reply-To: <4643049C.3D5F30D8@eudaptics.com>



On Thu, 10 May 2007, Johannes Sixt wrote:
>
> - cherry-pick them before commit
> 
>   $ git cherry-pick -n x
>   $ git cherry-pick -n y
>   $ git cherry-pick -n z

I've done this (actually, mostly with "revert", but cherry-pick and revert 
are literally the same things).

However:

>   $ git commit -m "$(for c in x y z; do git show --stat $c; done)" -e

I'm too lazy to do this part, so I always do it by hand.

> You didn't really think that git couldn't do that, did you? ;)

Clearly git can, but equally clearly it really *would* be pretty nice if 
you could just do

	git cherry-pick x y z

and create one commit and have the message already somewhat done for you 
(and "git revert" doing the same).

So if somebody does that, I'll certainly applaud..

		Linus

^ permalink raw reply

* Re: quick bare clones taking longer?
From: Brian Gernhardt @ 2007-05-10 15:38 UTC (permalink / raw)
  To: Matthieu Moy; +Cc: Git Mailing List
In-Reply-To: <vpq4pmlys5b.fsf@bauges.imag.fr>


On May 10, 2007, at 4:55 AM, Matthieu Moy wrote:

> Junio C Hamano <junkio@cox.net> writes:
>
>> Is that a serious question?
>
> It is. I have to admit that my knowledge about POSIX kind of things on
> windows approaches zero, but a hardcoded /bin/something path sounds
> suspicious to me.

I think every POSIX environment provides _something_ for /bin and / 
usr/bin.  There are too many scripts that start "#!/bin/bash" or "#!/ 
usr/bin/env interpreter" for it not to.  And to be POSIX, the basic  
utilities (like pwd and env) should be in there.  Someday Git may  
work on Windows without a funny (for MS) environment.  But that day  
is not today.  Tomorrow doesn't look too good either.  ;-)

~~ Brian

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Michael S. Tsirkin @ 2007-05-10 15:02 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Michael S. Tsirkin, Junio C Hamano, git
In-Reply-To: <81b0412b0705100752wa6dec37t787ccd61266f8944@mail.gmail.com>


> Quoting Alex Riesen <raa.lkml@gmail.com>:
> Subject: Re: [PATCHv2] connect: display connection progress
> 
> On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> >So, that's why the "connecting" message belongs in the default setup
> >(it can hang there for minutes), IP and such technicalia
> >belong with -v, and -q would only print data on connection error.
> 
> How about a config option? So that people working with
> repos connected through fast links (say, in local network or
> even locally on the same system) are not bothered by the
> "connecting" messages (they're is useless then, local networks
> usually work).

Do you really have git servers accessed over a local lan or on local system?
I just use ssh in this case, and I think that's the common case ...

I think making it possible to make -q a config option would be useful, though.

We *could* try doing something smart with non-blocking connect + select,
and only print the message if it takes > 1 second. Are you
sure it's worth the complication?

-- 
MST

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Alex Riesen @ 2007-05-10 14:52 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Junio C Hamano, git
In-Reply-To: <20070510143913.GF22029@mellanox.co.il>

On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> So, that's why the "connecting" message belongs in the default setup
> (it can hang there for minutes), IP and such technicalia
> belong with -v, and -q would only print data on connection error.

How about a config option? So that people working with
repos connected through fast links (say, in local network or
even locally on the same system) are not bothered by the
"connecting" messages (they're is useless then, local networks
usually work).

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Michael S. Tsirkin @ 2007-05-10 14:39 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Michael S. Tsirkin, Junio C Hamano, git
In-Reply-To: <81b0412b0705100716t680290a3qd1d10cf588a65f5a@mail.gmail.com>

> >> How about cleaning up this (reduce the amount of date
> >> on screen)
> >
> >Isn't this why we have -q?
> 
> Only fetch-pack has -q (and -v, which is confusing to
> say the least).

I find it quite proper to have both.
I would expect the following:

- git fetch normally displays progress meter, possibly
  tells me what stage it's in (connecting/downloading ....)
  so I know it's not hung.
- git fetch -q only tells me about errors/exceptional events
  good e.g. for scripts.
- git fetch -v gives a lot of detail useful for debugging
  only used if I see problems and want to debug.

Isn't this what's going on?

So, that's why the "connecting" message belongs in the default setup
(it can hang there for minutes), IP and such technicalia
belong with -v, and -q would only print data on connection error.
 
-- 
MST

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Alex Riesen @ 2007-05-10 14:16 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Junio C Hamano, git
In-Reply-To: <20070510134622.GN13655@mellanox.co.il>

On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> > >Why not only on failure? IP addresses look ugly.
> >
> > So you can see DNS problems you wanted to uncover.
>
> I really just wanted git to tell me what it's doing,
> so that I know it's not actually blocked on network,
> not doing any work.

Aren't you interested in _what_ work is it doing?

> > DNS is all about mapping names to that ugly IP.
>
> Yes, but so far git port does not seem to be commonly open
> on random IPs ;).

Well, it does. It happened.

> > And DNS _problems_ often manifest themselves
> > by mapping the name to an unexpected IP.
> > Now that's really ugly
>
> So, let's print the IP if -v is set?
> Oh, look, now we'll have
> NET_QUIET
> NET_VERBOSE

No. All you have is QUIET and !QUIET (or VERBOSE and
!VERBOSE which is the same).

> > How about cleaning up this (reduce the amount of date
> > on screen)
>
> Isn't this why we have -q?

Only fetch-pack has -q (and -v, which is confusing to
say the least).

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Michael S. Tsirkin @ 2007-05-10 13:46 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Michael S. Tsirkin, Junio C Hamano, git
In-Reply-To: <81b0412b0705100633t61ac0309jfc8536b30244adf6@mail.gmail.com>

> Quoting Alex Riesen <raa.lkml@gmail.com>:
> Subject: Re: [PATCHv2] connect: display connection progress
> 
> On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> >> >> What addresses were tried by connect?
> >> >
> >> >You are speaking about your patch reporting the IP on failure?
> >>
> >> Yes. Not on failure (not only). Every time an address is tried
> >> to connect.
> >
> >Why not only on failure? IP addresses look ugly.
> 
> So you can see DNS problems you wanted to uncover.

I really just wanted git to tell me what it's doing,
so that I know it's not actually blocked on network,
not doing any work.

> DNS is all about mapping names to that ugly IP.

Yes, but so far git port does not seem to be commonly open
on random IPs ;).

> And DNS _problems_ often manifest themselves
> by mapping the name to an unexpected IP.


> Now that's really ugly

So, let's print the IP if -v is set?
Oh, look, now we'll have
NET_QUIET
NET_VERBOSE

> >> >I think it makes sense, but it's a separate issue, isn't it?
> >>
> >> You are just about to make git_tcp_connect verbose,
> >> are you not?
> >
> >Only if the flag is set. So git-fetch without -q qill be more verbose -
> >but it already spits out a fair amount of data on screen.
> 
> And so you added some more? Does not sound logical.
> 
> How about cleaning up this (reduce the amount of date
> on screen)

Isn't this why we have -q?

> and adding another verbosity level (with your
> messages and IP) instead?

What, yet another flag? Nooooooo

-- 
MST

^ permalink raw reply

* Re: Yet another Perforce importer
From: Alex Riesen @ 2007-05-10 13:37 UTC (permalink / raw)
  To: git
In-Reply-To: <20070505224805.GD2898@steel.home>

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

Updated. A very bad bug fixed (the old script cut the imported
history from the previous history on first import).
And I'm sorry for txt (and for .bat).

[-- Attachment #2: git-p4-import.bat.txt --]
[-- Type: text/plain, Size: 22120 bytes --]

@rem = 'NT: CMD.EXE vim: syntax=perl noet sw=4
@perl -x -s %0 -- %*
@exit
@rem ';
#!perl -w
#line 7

local $VERBOSE = 0;
local $DRYRUN = 0;
local $AUTO_COMMIT = 0;
local $JUST_COMMIT = 0;
local $P4CLIENT = undef;
local @EDIT_COMMIT = 0;
local @FULL_IMPORT = 0;
local @DESC = ();
local $SPEC = undef;
local @P4ARGS = ();
local $P4HAVE_FILE = undef;
local %P4USERS = ();
local $FULL_DESC = 1;
push(@P4ARGS, '-P', $ENV{P4PASSWD})
    if defined($ENV{P4PASSWD}) and length($ENV{P4PASSWD});
use Cwd;
local $start_dir = cwd();

sub read_args {
    my ($in_client, $in_cl, $in_fi, $in_p4) = (0,0,0,0);
    foreach my $f ( @_ ) {
	if ($in_client) { $in_client = 0; $P4CLIENT = $f; next }
	if ($in_cl) { $in_cl=0; push(@DESC,"c$f"); next }
	if ($in_fi) { $in_fi=0; push(@DESC,"f$f"); next }
	if ($in_p4) { $in_p4=0; push(@DESC,"4$f"); next }
	$DRYRUN=1, next if $f eq '-n' or $f eq '--dry-run';
	$AUTO_COMMIT=1, next if $f eq '-y' or $f eq '--yes';
	$JUST_COMMIT=1, next if $f eq '--just-commit';
	$EDIT_COMMIT=1, next if ($f eq '-e') or ($f eq '--edit');
	$FULL_IMPORT=1, next if $f eq '--full';
	$FULL_DESC++, next if $f eq '--p4-desc';
	$VERBOSE++, next if $f eq '-v' or $f eq '--verbose';
	$in_client = 1, next if $f eq '--client';
	$in_cl = 1, next if $f eq '-C';
	$in_fi = 1, next if $f eq '-F';
	$in_p4 = 1, next if ($f eq '--ptr') or ($f eq '--p4');
	if ($f eq '--help' or $f eq '-h') {
	    print <<EOF;
$0 <specification> [-n|--dry-run] [-y|--yes] [--client <client-name>] \
[-e|--edit] [--just-commit] [--full] [-v|--verbose] [-C <change-number>] \
[-F <filename>] [--ptr|--p4 <p4-path-and/or-revision>] [--p4-desc]

Perforce client state importer. Creates a git commit on the current
branch from a state the given p4 client and working directory hold.

<specification> must be given and is expected to be a file which will be
stored on the side branch under the name "spec".
Remote-to-local mapping and the revisions of files are stored in "have",
and the client definition - in "client".

--client client Specify client name (saved in .git/p4/client for the next time)
--full          Perform full import, don't even try to figure out what changed
-y|--yes        Commit automatically (by default only index updated)
--just-commit   To be used after you forgot to run with --yes first time
-n|--dry-run    Do not update the index and do not commit
-e|--edit       Edit commit description before committing
-v|--verbose    Be more verbose. Can be given many times, increases verbosity
-F file         Take description for the commit from a file in the
                next parameter
-C change       Take description for the commit from this p4 change
--p4|--ptr p4-path-and/or-revision Take description for the commit from the p4
                change described by this p4 path, possibly including revision
                specification
--p4-desc       Increase amount of junk from p4 change description

The descriptions taken from p4 changes given by -C and --p4 will
be concatenated if the options given multiple times.

EOF
	    exit(0);
	}
	warn "$0: spec was already set, $SPEC ignored\n" if defined($SPEC);
	$SPEC = $f;
    }
}
read_args(@ARGV);

local ($GIT_DIR) = qx{git rev-parse --git-dir};
$GIT_DIR =~ s/\r?\n$//s if defined($GIT_DIR);
die "$0: git directory not found\n" if !defined($GIT_DIR) or !-d $GIT_DIR;

local $editor = $ENV{VISUAL};
$editor = $ENV{EDITOR} unless defined($editor);
$editor = 'd:/Programs/Vim/vim70/gvim.exe' unless defined($editor);
die "$0: no editor defined\n" unless defined($editor);

# P4 client was given in command-line. Store it
if ( defined($P4CLIENT) ) {
    mkdir "$GIT_DIR/p4", 0777;
    if ( open(F, '>', "$GIT_DIR/p4/client") ) {
	print F "$P4CLIENT\n";
	close(F);
    } else {
	die "$0: cannot store client name: $!\n"
    }
} else {
    if ( open(F, '<', "$GIT_DIR/p4/client") ) {
	($P4CLIENT) = <F>;
	close(F);
	$P4CLIENT =~ s/^\s*//,$P4CLIENT =~ s/\s*$// if defined($P4CLIENT);
    }
}
die "P4 client not defined\n" if !defined($P4CLIENT) or !length($P4CLIENT);
print "reading P4 client $P4CLIENT\n" if $VERBOSE;
local ($P4ROOT, $p4clnt, $P4HOST);
open(my $fdo, '>', "$GIT_DIR/p4/client.def") or die "p4/client.def: $!\n";
binmode($fdo);
open(my $fdi, '-|', "p4 client -o $P4CLIENT") or die "p4 client: $!\n";
binmode($fdi);
my $last_line_len = 0;
while (<$fdi>) {
    next if /^#/o;
    if ( m/^\s*Root:\s*(\S+)[\\\/]*\s*$/so ) { $P4ROOT = $1 }
    elsif ( m/^\s*Client:\s*(\S+)/o ) { $p4clnt = $1 }
    elsif ( m/^\s*Host:\s*(\S+)/o ) { $P4HOST = $1 }
    ($VERBOSE and print), next if /^(Access|Update):/;
    s/\r?\n$//so;
    my $len = length($_);
    print $fdo "$_\n" if $len or $len != $last_line_len;
    $last_line_len = $len;
}
close($fdi);
close($fdo);

die "Client root not defined\n" unless defined($P4ROOT);
if ( $VERBOSE ) {
    print "GIT_DIR: $GIT_DIR\n";
    print "Root: $P4ROOT (cwd: $start_dir)\n";
    print "Host: $P4HOST\n";
    print "Client: $p4clnt\n" if $p4clnt ne $P4CLIENT;
}
my ($git_head,$git_p4_head,$git_p4_have) = &git_p4_init;

if ($JUST_COMMIT) {
    git_p4_commit($git_head, $git_p4_head);
    exit 0;
}

local %gitignore_dirs = ();
$gitignore_dirs{'/'} = read_filter_file("$GIT_DIR/info/exclude");
push(@{$gitignore_dirs{'/'}}, @{read_filter_file('.gitignore')});

my %git_index = ();
$/ = "\0";
my @git_X = ();
print "Reading git file list(git ls-files @git_X --cached -z)...\n" if $VERBOSE;
foreach ( qx{git ls-files @git_X --cached -z} ) {
    chop; # chop \0
    next if m/^\.gitignore$/o;
    next if m/\/\.gitignore$/o;
    next if filtered($_);
    $git_index{$_} = 1;
}

my @git_add = ();
my @git_addx = ();
my @git_del = ();
my @git_upd = ();

print "Reading P4 file list...\n" if $VERBOSE;
local ($Conflicts,$Ignored,$Added,$Deleted,$Updated) = (0,0,0,0,0);
$/ = "\n";
my $in_name = 0;
my @root = split(/[\/\\]+/, $P4ROOT);
my %p4_index = ();
my %p4_a_lc = ();
my %lnames = ();
my %lconflicts = ();
if (opendir(DIR, '.')) {
    $lnames{'.'} = [grep {$_ ne '.' and $_ ne '..'} readdir(DIR)];
    closedir(DIR);
    #print "read $start_dir (",scalar(@{$lnames{'.'}}),")\n";
}
open(my $have, "p4 -G @P4ARGS -c $P4CLIENT -H $P4HOST -d $P4ROOT have |") or
    die "$0: failed to start p4: $!\n";
binmode($have);
$P4HAVE_FILE = "$GIT_DIR/p4/have";
open(my $storedhave, '>', $P4HAVE_FILE) or die "$P4HAVE_FILE: $!\n";
binmode($storedhave);
my $ent;
while (defined($ent=read_pydict_entry($have))) {
    next if !defined($ent->{depotFile}) or !defined($ent->{clientFile});
    my $a = $ent->{depotFile};
    $ent->{clientFile} =~ m!^//[^/]+/(.*)!o;
    my $b = $1;
    my @bb = split(/\/+/, $b);
    print $storedhave "$a\0$ent->{clientFile}\0$ent->{haveRev}\0\n";

    if ( $^O eq 'MSWin32' ) {
	# stupid windows, daft activestate, dumb P4
	# This piece below is checking for file name conflicts
	# which happen on windows because of it mangling the names.
	my $blc = lc $b;
	if ( $#bb > 0 ) {
	    my $path = '.';
	    foreach my $n (@bb[0 .. $#bb -1]) {
		my @conflicts =
		    grep {lc $_ eq lc $n and $_ ne $n} @{$lnames{$path}};
		if (@conflicts and !exists($lconflicts{"$path/$n"})) {
		    warn "warning: $a -> $b\n".
			 "warning: conflict between path \"$path/$n\" and ".
			 "local filesystem in \"@conflicts\"\n";
		    $Conflicts++;
		    $lconflicts{"$path/$n"} = 1;
		}
		$path .= "/$n";
		if (!exists($lnames{$path})) {
		    if (opendir(DIR, $path)) {
			$lnames{$path} =
			    [grep {$_ ne '.' and $_ ne '..'} readdir(DIR)];
			closedir(DIR);
			#print "read $path (",scalar(@{$lnames{$path}}),")\n";
		    }
		}
	    }
	}
	if (!exists($p4_a_lc{$blc})) {
	    $p4_a_lc{$blc} = [$a, $b];
	} else {
	    warn("warning: $a -> $b\n".
		 "warning: conflicts with ".
		 $p4_a_lc{$blc}->[0]." -> ".
		 $p4_a_lc{$blc}->[1]."\n");
	    $Conflicts++;
	    next;
	}
    }

    my $i;
    for ($i = 0; $i < $#bb; ++$i) {
	my $bdir = join('/',@bb[0 .. $i]) . '/';
	if ( !exists($gitignore_dirs{$bdir}) ) {
	    $gitignore_dirs{$bdir} = read_filter_file("$bdir.gitignore");
	}
    }
    if (filtered($b)) {
	print " i $b\n" if $VERBOSE > 3;
	$Ignored++;
	next
    }
    $p4_index{$b} = $a;
    if ( exists($git_index{$b}) ) {
	my $needup = 1;
	if (defined($git_p4_have)) {
	    $prev = $git_p4_have->{$a};
	    if (defined($prev)) {
		$prev->[0] =~ m!^//[^/]+/(.*)!o;
		$needup = 0 if ($b eq $1) and ($prev->[1] eq $ent->{haveRev});
		if ($needup and $VERBOSE > 1) {
		    my $reason;
		    $reason = 'local file' if $b ne $1;
		    $reason = 'revision' if $prev->[1] ne $ent->{haveRev};
		    print "$a ($reason changed)\n";
		}
	    }
	}
	if ($needup) {
	    $Updated++;
	    push(@git_upd, $b);
	}
    } else {
	$Added++;
	if ( $b =~ m/\.(bat|cmd|pl|sh|exe|dll)$/io )
	{ push(@git_addx, $b) } else { push(@git_add, $b) }
    }
}
close($storedhave);
close($have);
undef %p4_a_lc;

@git_del = grep { !exists($p4_index{$_}) } keys %git_index;
$Deleted = $#git_del + 1;

#foreach (keys %git_index)
#{ push(@git_del, $_) if !exists($p4_index{$_}) }

if ( $DRYRUN ) {
    print($#git_add+$#git_addx+ 2," files to add\n") if $VERBOSE;
    print map {" a $_\n"} @git_add if $VERBOSE > 2;
    print map {" a $_\n"} @git_addx if $VERBOSE > 2;
    print($#git_del+1," files to unreg\n") if $VERBOSE;
    print map {" d $_\n"} @git_del if $VERBOSE > 2;
    print($#git_upd+1," files to update\n") if $VERBOSE;
    print map {" u $_\n"} @git_upd if $VERBOSE > 2;
    print "added: $Added, unregd: $Deleted, updated: $Updated, ignored: $Ignored";
    print ", conflicts: $Conflicts" if $Conflicts;
    print "\n";
} else {
    if (@git_add || @git_addx) {
	print($#git_add+$#git_addx+ 2,
	      " files | git update-index --add -z --stdin\n")
	    if $VERBOSE;
	if (@git_add) {
	    open(GIT, '| git update-index --add --chmod=-x -z --stdin') or
		die "$0 git-update-index(add): $!\n";
	    print GIT map {print " a $_\n" if $VERBOSE > 1; "$_\0"} @git_add;
	    close(GIT);
	}
	if (@git_addx) {
	    open(GIT, '| git update-index --add --chmod=+x -z --stdin') or
		die "$0 git-update-index(add): $!\n";
	    print GIT map {print " a $_\n" if $VERBOSE > 1; "$_\0"} @git_addx;
	    close(GIT);
	}
    }

    if (@git_del) {
	print($#git_del+1," files | git update-index --remove -z --stdin\n")
	    if $VERBOSE;
	open(GIT, '| git update-index --force-remove -z --stdin') or
	    die "$0 git-update-index(del): $!\n";
	print GIT map {print " d $_\n" if $VERBOSE > 1; "$_\0"} @git_del;
	close(GIT);
    }

    if (@git_upd) {
	print($#git_upd+1," files | git update-index -z --stdin\n")
	    if $VERBOSE;
	open(GIT, '| git update-index -z --stdin') or
	    die "$0 git-update-index(upd): $!\n";
	print GIT map {print " u $_\n" if $VERBOSE > 1; "$_\0"} @git_upd;
	close(GIT);
    }
    
    print "added: $Added, unregd: $Deleted, updated: $Updated, ignored: $Ignored";
    print ", conflicts: $Conflicts" if $Conflicts;
    print "\n";
    git_p4_commit($git_head, $git_p4_head) if $AUTO_COMMIT;
}

exit 0;

sub filtered {
    my $name = shift;
    study($name);
    my @path = split(/\/+/o, $name);
    my $dir = '';
    $name = '';
    
    foreach my $d (@path) {
	$name .= $d;
#	print STDERR "$dir: $name $d\n" if $v;
	foreach my $re (@{$gitignore_dirs{'/'}}) {
	    return 1 if $name =~ m/$re/;
	    return 1 if $d =~ m/$re/;
	}
	if ( length($dir) and exists($gitignore_dirs{$dir}) ) {
	    foreach my $re (@{$gitignore_dirs{$dir}}) {
		return 1 if $name =~ m/$re/;
		return 1 if $d =~ m/$re/;
	    }
	}
	$name .= '/';
	$dir = $name;
    }
#    print STDERR "$name not filtered\n" if $v;
    return 0;
}

sub read_filter_file {
    my @filts = ();
    my $file = shift;
    if ( open(my $if, '<', $file) ) {
	print "added ignore file $file\n" if $VERBOSE;
	$/ = "\n";
	while (my $l = <$if>) {
	    next if $l =~ /^\s*#/o;
	    next if $l =~ /^\s*$/o;
	    $l =~ s/[\r\n]+$//so;
	    $l =~ s/\./\\./go;
	    $l =~ s/\*/.*/go;
	    if ( $l =~ m/\// ) {
		$l = "^$l($|/)";
	    } else {
		$l = "(^|/)$l\$";
	    }
	    print " filter $l\n" if $VERBOSE > 1;
	    push(@filts, qr/$l/);
	}
	close($if);
    }
    return \@filts;
}

sub r_pystr
{
    my $fd = shift;
    my ($len,$str)=('','');
    my ($c,$rd,$b) = (4,0,'');
    while ($c > 0) {
	$rd = sysread($fd,$b,$c);
	warn("failed to read len: $!"), return undef if !defined($rd);
	warn("not enough data for len"), return undef if !$rd;
	$len .= $b;
	$c -= $rd;
    }
    $len = unpack('V',$len);
    while ($len > 0) {
	$rd = sysread($fd,$b,$len);
	warn("failed to read data: $!"), return undef if !defined($rd);
	warn("not enough data"), return undef if !$rd;
	$str .= $b;
	$len -= $rd;
    }
    return $str;
}

sub read_pydict_entry
{
    my $f = shift;
    my ($buf,$rd);
    FIL: while (1) {
	# object type identifier
	$rd = sysread($f, $buf, 1);
	last FIL if $rd == 0;
	warn("object type: $!\n"),last if $rd != 1;
	# '{' is a python marshalled dict
	warn("object type: not {\n"),last if $buf ne '{';
	my $ent = {};
	PAIR: while (1) {
	    my ($b,$key);
	    # key type identifier
	    $rd = sysread($f, $b, 1);
	    warn("key type: $!\n"),last FIL if $rd != 1;
	    if ($b eq 's') { # length-prefixed string
		$key = r_pystr($f);
		warn("key: $!\n"),last FIL if !defined($b);
	    } elsif ($b eq '0') { # NULL-element, end of entry
		last PAIR;
	    } else {
		warn("key type: not s");
		last FIL;
	    }
	    # value type identifier
	    $rd = sysread($f, $b, 1);
	    warn("$key value type: $!\n"),last FIL if $rd != 1;
	    if ($b eq 's') { # length-prefixed string
		$b = r_pystr($f);
		warn("$key value: $!"),last FIL if !defined($b);
		$ent->{$key} = $b;
	    } else {
		warn("$key value type: not s ($b)");
		last FIL;
	    }
	}
	return $ent;
    }
    return undef;
}

sub cl2msg {
    my $cl = shift;
    my($o1,$o2,$i);
    if(!open($o1, '>>', "$GIT_DIR/p4/msg")) {
	warn "p4/msg: $!\n";
	return;
    }
    binmode($o1);
    if(!open($o2, '>>', "$GIT_DIR/p4/p4msg")) {
	warn "p4/p4msg: $!\n";
	close($o1);
	return
    }
    binmode($o2);
    if(!open($i, '-|', "p4 describe -s $cl")){
	warn "p4 describe: $!\n";
	close($o1);
	close($o2);
	return
    }
    binmode($i);
    print $o1 "$cl: " if $FULL_DESC;
    print $o2 "$cl: ";
    my @a;
    my $u = undef;
    while (my $l = <$i>) {
	if ($l =~ /^Change \d+ by (\S+)@[^ ]* on ([^\r\n]*)/so) {
	    $u = $1;
	    $ENV{GIT_AUTHOR_DATE} = $2 if length($2);
	}
	last if $FULL_DESC < 2 and $l =~ /^\s*Affected files \.{3}\s*$/so;
	$l =~ s/\r?\n$//so;
	push @a, $l;
    }
    close($i);
    print $o2 substr($a[2],1),"\n"; # p4 side-branch commit description
    close($o2);
    # import branch commit description
    if ($FULL_DESC > 1) {
	# desc level 2+: keep the Change line
	print $o1 map {"$_\n"} (substr($a[2],1),"\n",@a);
    } else {
	# levels 0 and 1: remove the Change line
	print $o1 map { (length($_) ? substr($_,1):'')."\n" } @a[2..$#a];
    }
    close($o1);
    if (defined($u)) {
	if (!exists($P4USERS{$u})) {
	    my ($mail,$name) = grep {/^(Email|FullName):/} qx{p4 user -o $u};
	    if ($? == 0 and defined($mail) and defined($name)) {
		s/^\S+:	([^\r\n]*)\r?\n$/$1/so for ($mail,$name);
		if (length($name) and length($mail)) {
		    $P4USERS{$u} = {name=>$name, email=>$mail};
		}
	    }
	}
	if ($P4USERS{$u}) {
	    $p4u = $P4USERS{$u};
	    $ENV{GIT_AUTHOR_NAME}  = $p4u->{name};
	    $ENV{GIT_AUTHOR_EMAIL} = $p4u->{email};
	}
    }
}

sub git_p4_init {
    my ($commit,$parent,$p4commit,$p4parent);
    my ($HEAD) = qx{git rev-parse HEAD};
    $HEAD = '' if $?;
    my ($p4head) = qx{git rev-parse refs/p4import/$P4CLIENT};
    $p4head = '' if $?;
    s/\r?\n//gs for ($HEAD, $p4head);
    die "No HEAD commit! Refusing to import.\n" if !length($HEAD);
    if (length($p4head)) {
	($commit,$p4parent) =
	    grep { s/^parent (.{40}).*/$1/s }
	    qx{git cat-file commit $p4head};
	$commit = $p4parent = '' if $?;
	$p4parent = '' if !defined($p4parent);
    } else {
	$commit = $p4parent = '';
    }
    while (($commit ne $HEAD) and length($p4parent)) {
	$p4head = $p4parent;
	($commit,$p4parent) =
	    grep { s/^parent (.{40}).*/$1/s }
	    qx{git cat-file commit $p4head};
	$commit = $p4parent = '' if $?;
	if ($VERBOSE and ($HEAD eq $commit)) {
	    print "found p4 import commit ";
	    system('git','name-rev',$p4head);
	}
    }
    warn "Current HEAD was not imported from $P4CLIENT, doing full import\n"
	if $HEAD ne $commit;
    my $p4have = undef;
    if (!$FULL_IMPORT and ($HEAD eq $commit) and length($p4head)) {
	if (open(my $f, '-|', "git cat-file blob $p4head:have")) {
	    my $old = $/;
	    $/ = "\0";
	    my $cnt = 0;
	    while(1) {
		my $p4name = <$f>;
		last if !defined($p4name);
		$p4name =~ s/^.//so if $cnt; # remove \n
		my $name = <$f>;
		my $rev = <$f>;
		last if !defined($name) or !defined($rev);
		chop($p4name,$name,$rev);
		++$cnt;
		if (defined($p4have)) {
		    $p4have->{$p4name} = [$name,$rev];
		} else {
		    $p4have = {$p4name=>[$name,$rev]};
		}
	    }
	    $/ = $old;
	    close($f);
	    print "loaded $cnt revisions from $p4head\n" if $VERBOSE;
	}
    }
    return ($HEAD, $p4head, $p4have);
}

sub git_p4_commit {
    my ($HEAD, $p4head) = @_;
    my ($commit,$parent,$p4commit,$p4parent);

    my ($fdo,$fdi,$rc);
    $rc = system('git','diff-index','--exit-code','--quiet','--cached','HEAD');
    if ($rc == 0) {
	warn("No changes\n");
	return;
    }

    return if $DRYRUN;

    my $p4x = "$GIT_DIR/p4/idx.tmp";
    unlink($p4x);
    my $oldidx = $ENV{GIT_INDEX_FILE};

    $ENV{PAGER} = 'cat';
    $ENV{GIT_INDEX_FILE} = $p4x;

    if (!defined($SPEC) or !open(STDIN, '<', $SPEC)) {
	if ( $^O eq 'MSWin32' ) {
	    open(STDIN, '<', 'NUL') or die "$SPEC: $!\n";
	} else {
	    open(STDIN, '<', '/dev/null') or die "$SPEC: $!\n";
	}
    }
    my ($p4spec) = qx{git hash-object -t blob -w --stdin};
    die "Failed to store $SPEC in git repo\n" if $?;

    open(STDIN, '<', "$GIT_DIR/p4/client.def") or die "cldef: $!\n";
    my ($p4clnt) = qx{git hash-object -t blob -w --stdin};
    die "Failed to save mappings of $P4CLIENT in git repo" if $?;

    if (!defined($P4HAVE_FILE)) {
	print "reading state of $P4CLIENT\n" if $VERBOSE;
	$P4HAVE_FILE = "$GIT_DIR/p4/have"; 
	open($fdo, '>', $P4HAVE_FILE) or die "p4/have: $!\n";
	binmode($fdo);
	open($fdi, "p4 -G @P4ARGS -c $P4CLIENT -H $P4HOST -d $P4ROOT have|") or
	    die "p4 have: $!\n";
	binmode($fdi);
	my $ent;
	while (defined($ent=read_pydict_entry($fdi))) {
	    next if !defined($ent->{depotFile});
	    next if !defined($ent->{clientFile});
	    print $fdo "$ent->{depotFile}\0",
		       "$ent->{clientFile}\0",
		       "$ent->{haveRev}\0\n";
	}
	close($fdi);
	close($fdo);
    }

    open(STDIN, '<', $P4HAVE_FILE) or die "$P4HAVE_FILE: $!\n";
    my ($p4have) = qx{git hash-object -t blob -w --stdin};
    die "Failed to save state of $P4CLIENT in git repo" if $?;

    unlink("$GIT_DIR/p4/msg", "$GIT_DIR/p4/p4msg");
    foreach my $i (@DESC) {
	$i =~ s/^(.)//o;
	if ('c' eq $1) {
	    print "reading changes for $i\n" if $VERBOSE;
	    cl2msg($i);
	} elsif ('f' eq $1) {
	    my($o1,$o2,$i);
	    if (open($o1, '>>', "$GIT_DIR/p4/msg")) {
		if (open($o2, '>>', "$GIT_DIR/p4/p4msg")) {
		    if (open($i, '<', $i)) {
			my $n = 0;
			while(<$i>) {
			    $n++;
			    print $o1 $_;
			    print $o2 $_ if $n == 1;
			}
			close($i);
		    }
		    close($o2);
		}
		close($o1);
	    }
	} elsif ('4' eq $1) {
	    print "reading changes for $i\n" if $VERBOSE;
	    my ($change)=qx{p4 changes -m1 $i};
	    if (!defined($change) or $change !~ m/\s+(\d+)\s/) {
		die "$i does not resolve into a change number\n";
	    }
	    cl2msg($1);
	}
    }
    system("$editor $GIT_DIR/p4/msg") if $EDIT_COMMIT;

    if (defined($oldidx)) { $ENV{GIT_INDEX_FILE} = $oldidx }
    else { delete $ENV{GIT_INDEX_FILE} }

    #
    # Store the imported file data
    #

    if ( $^O eq 'MSWin32' ) { open(STDERR, "NUL") }
    else { open(STDERR, "/dev/null") }

    my ($tree) = qx{git write-tree};
    die "Failed to write current tree\n" if $?;
    $parent = length($HEAD) ? "-p $HEAD": '';
    open(STDIN, '<', "$GIT_DIR/p4/msg") or die "p4/msg: $!\n";
    $tree =~ s/\r?\n//gs;
    ($commit)=qx{git commit-tree $tree $parent};
    die "failed to commit current tree\n" if $?;
    s/\r?\n//gs for ($commit);

    #
    # Storing import control data
    #
    $ENV{GIT_INDEX_FILE} = $p4x;
    open($fdo, '|-', 'git update-index --add --index-info') or
	die "could not start git update-index\n";
    binmode($fdo);
    s/\r?\n//gs for ($p4spec,$p4clnt,$p4have);
    print $fdo "100644 $p4spec\tspec\n";
    print $fdo "100644 $p4clnt\tclient\n";
    print $fdo "100644 $p4have\thave\n";
    close($fdo);
    if($?) {
	die "Failed to store $SPEC in p4import index and git repo\n".
	    "Failed to save mappings of $P4CLIENT in p4import index and git repo\n".
	    "Failed to save state of $P4CLIENT in p4import index and git repo\n"
    }
    my ($p4tree)=qx{git write-tree};
    die "Failed to store $SPEC (tree) in git repo\n" if $?;

    # Bind import control data to the file data
    $p4parent="-p $commit";
    $p4parent="$p4parent -p $p4head" if length($p4head);
    open(STDIN, '<', "$GIT_DIR/p4/p4msg") or die "p4/p4msg: $!\n";
    $p4tree =~ s/\r?\n//gs;
    ($p4commit)=qx{git commit-tree $p4tree $p4parent};
    die "Failed to store $SPEC (commit) in git repo\n" if $?;
    $p4commit =~ s/\r?\n//gs;

    # Finishing touches: update references
    system('git','update-ref','-m','backup ref of current branch',
	   'p4/backup-HEAD','HEAD');
    system('git','update-ref','-m','backup ref of p4import',
	   'p4/backup-p4import',"refs/p4import/$P4CLIENT");
    $rc = system('git','update-ref','-m','data of p4import','HEAD',$commit);
    die "Failed to update HEAD\n" if $rc;
    $rc = system('git','update-ref','-m','p4import',"refs/p4import/$P4CLIENT",$p4commit);
    die "Failed to store $SPEC (reference) in git repo\n" if $rc;

    if ($VERBOSE) {
	print STDOUT (grep {s/\r?\n//gs;s/.*?\s//} qx{git name-rev refs/p4import/$P4CLIENT}), ":\n";
	system('git','log','--max-count=1','--pretty=format:%h %s%n',$p4commit);
    }
    print STDOUT (grep {s/\r?\n//gs;s/.*?\s//} qx{git name-rev HEAD}), ":\n";
    system('git','log','--max-count=1','--pretty=format:%h %s%n',$commit);
}


^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Alex Riesen @ 2007-05-10 13:33 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Junio C Hamano, git
In-Reply-To: <20070510122550.GJ13655@mellanox.co.il>

On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> > >> What addresses were tried by connect?
> > >
> > >You are speaking about your patch reporting the IP on failure?
> >
> > Yes. Not on failure (not only). Every time an address is tried
> > to connect.
>
> Why not only on failure? IP addresses look ugly.

So you can see DNS problems you wanted to uncover.
DNS is all about mapping names to that ugly IP.
And DNS _problems_ often manifest themselves
by mapping the name to an unexpected IP.
Now that's really ugly

> > >I think it makes sense, but it's a separate issue, isn't it?
> >
> > You are just about to make git_tcp_connect verbose,
> > are you not?
>
> Only if the flag is set. So git-fetch without -q qill be more verbose -
> but it already spits out a fair amount of data on screen.

And so you added some more? Does not sound logical.

How about cleaning up this (reduce the amount of date
on screen) and adding another verbosity level (with your
messages and IP) instead?

^ permalink raw reply

* Re: [PATCHv2] connect: display connection progress
From: Michael S. Tsirkin @ 2007-05-10 12:25 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Michael S. Tsirkin, Junio C Hamano, git
In-Reply-To: <81b0412b0705100519i3028fbc4y25e7c407c7c8216@mail.gmail.com>

> Quoting Alex Riesen <raa.lkml@gmail.com>:
> Subject: Re: [PATCHv2] connect: display connection progress
> 
> On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> >> Quoting Alex Riesen <raa.lkml@gmail.com>:
> >> Subject: Re: [PATCHv2] connect: display connection progress
> >>
> >> On 5/10/07, Michael S. Tsirkin <mst@dev.mellanox.co.il> wrote:
> >> >-static int git_tcp_connect_sock(char *host)
> >> >+static int git_tcp_connect_sock(char *host, int flags)
> >>
> >> There is only one bit of flags ever used. What are the others for?
> >
> >Hmm, I thought it's easier to read
> >git_tcp_connect_sock(host, NET_QUIET)
> 
> It is easier to read. "int flags" isn't easier to understand.
> 
> >> Why use negative logic?
> >> What was wrong with plain "int verbose"?
> >
> >I want the default to report connections, and -q
> >to silence them. Maybe "int quiet"?
> 
> It depends. "Quiet" is negative, which automatically
> makes the logic harder to follow (for humans, at least),
> and you had to put negations all over git_tcp_connect,
> exactly because the meaning is exactly the opposite to
> what you need.
> 
> >> What addresses were tried by connect?
> >
> >You are speaking about your patch reporting the IP on failure?
> 
> Yes. Not on failure (not only). Every time an address is tried
> to connect.

Why not only on failure? IP addresses look ugly.

> >I think it makes sense, but it's a separate issue, isn't it?
> 
> You are just about to make git_tcp_connect verbose,
> are you not?

Only if the flag is set. So git-fetch without -q qill be more verbose -
but it already spits out a fair amount of data on screen.

-- 
MST

^ permalink raw reply


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