* Re: [PATCH] git-bisect: call the found commit "*the* first bad commit"
From: Jeff King @ 2009-08-26 15:29 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Junio C Hamano, Nanako Shiraishi, git
In-Reply-To: <alpine.DEB.1.00.0908261207400.4713@intel-tinevez-2-302>
On Wed, Aug 26, 2009 at 12:08:11PM +0200, Johannes Schindelin wrote:
> Well, I learnt at school that it is "learnt" and "at school"...
>
> double ;-)
Bloody Europeans. ;)
-Peff
^ permalink raw reply
* Re: [PATCH] Add option -b/--branch to clone for select a new HEAD
From: Björn Steinbrink @ 2009-08-26 15:50 UTC (permalink / raw)
To: Kirill A. Korinskiy; +Cc: git
In-Reply-To: <1251298007-18693-1-git-send-email-catap@catap.ru>
On 2009.08.26 18:46:47 +0400, Kirill A. Korinskiy wrote:
> @@ -518,8 +521,22 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
>
> mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
>
> - remote_head = find_ref_by_name(refs, "HEAD");
> - head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
> + if (option_branch) {
> + strbuf_addf(&branch_head, "%s%s", src_ref_prefix, option_branch);
> +
> + remote_head = find_ref_by_name(refs, branch_head.buf);
> + }
> +
> + if (!remote_head) {
> + if (option_branch)
> + warning("Remote branch %s not found in upstream %s"
> + ", using HEAD instead",
> + option_branch, option_origin);
> +
> + remote_head = find_ref_by_name(refs, "HEAD");
> + }
> +
> + head_points_at = guess_remote_head(remote_head, mapped_refs, 1);
Just setting "all" to 1 there is wrong. With "all" set to 1,
guess_remote_head() returns a linked list of _all_ matching refs. The
first entry in that list depends on the order of mapped_refs.
doener@atjola:h $ mkdir a; cd a; git init
Initialized empty Git repository in /home/doener/h/a/.git/
doener@atjola:a (master) $ git commit --allow-empty -m init
[master (root-commit) aa39247] init
doener@atjola:a (master) $ git branch foo
doener@atjola:a (master) $ cd ..
doener@atjola:h $ (git clone -b foo a foo; cd foo; git branch)
Initialized empty Git repository in /home/doener/h/foo/.git/
* foo
doener@atjola:h $ (git clone -b master a master; cd master; git branch)
Initialized empty Git repository in /home/doener/h/master/.git/
* foo
Here, "foo" was first in mapped_refs, and so "-b master" used that, too.
Using guess_remote_head() seems pretty wrong. With -b given, you don't
want to guess anymore, you _know_ which one you want. Unfortunately, I
don't see a straight-forward way to handle that (but I'm totally
clueless about the code, so don't let me scare you ;-)).
> diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh
> new file mode 100755
> index 0000000..b5fec50
> --- /dev/null
> +++ b/t/t5706-clone-branch.sh
> @@ -0,0 +1,49 @@
> +#!/bin/sh
> +
> +test_description='branch clone options'
> +. ./test-lib.sh
> +
> +test_expect_success 'setup' '
> +
> + mkdir parent &&
> + (cd parent && git init &&
> + echo one >file && git add file &&
> + git commit -m one && git branch foo &&
> + git checkout -b two &&
> + echo two >f && git add f && git commit -m two &&
> + git checkout master)
> +
> +'
> +
> +test_expect_success 'clone' '
> +
> + git clone parent clone &&
> + (cd clone &&
> + test $(git rev-parse --verify HEAD) = \
> + $(git rev-parse --verify refs/remotes/origin/master) &&
> + test $(git rev-parse --verify HEAD) != \
> + $(git rev-parse --verify refs/remotes/origin/two))
> +
> +
> +'
> +
> +test_expect_success 'clone -b two' '
> +
> + git clone -b two parent clone-b &&
> + (cd clone-b &&
> + test $(git rev-parse --verify HEAD) = \
> + $(git rev-parse --verify refs/remotes/origin/two) &&
> + test $(git rev-parse --verify HEAD) != \
> + $(git rev-parse --verify refs/remotes/origin/master))
> +
> +'
> +
> +test_expect_success 'clone -b foo' '
> +
> + git clone -b foo parent clone-b-foo &&
> + (cd clone-b-foo &&
> + test $(git branch | grep \* | sed -e s:\*\ ::) = foo)
This should probably do "git symbolic-ref HEAD" instead of the branch +
grep + sed. And it should also verify that rev-parse foo == rev-parse
origin/foo.
And to catch the above bug, you need a second test like that, but for
"master" instead of "foo".
HTH
Björn
^ permalink raw reply
* Re: Newbie / git / gitosis question
From: Jeff King @ 2009-08-26 15:56 UTC (permalink / raw)
To: Howard Miller; +Cc: git
In-Reply-To: <26ae428a0908260227k7ac6aeden9a4eae7ee95d4d45@mail.gmail.com>
On Wed, Aug 26, 2009 at 10:27:30AM +0100, Howard Miller wrote:
> I've been working away at Gitosis and it's mostly fair enough but
> there's one bit that's unclear to me...
>
> git push origin master:refs/heads/master
>
> Would somebody kindly explain (or point to docs) what
> refs/heads/master means? How is this different from just 'git push
> origin master' or even 'git push origin master:master'?
I'll try to explain.
Refs are pointers to commits. In other words, you can think of
"refs/heads/master" as a key pointing to a SHA-1 commit id. The long-ish
name divides up the namespace for refs.
There are a few special refs that live outside of the refs/ hierarchy,
like HEAD, FETCH_HEAD, MERGE_HEAD, ORIG_HEAD, etc. Normal refs are
generally under refs/.
The refs/heads/ hierarchy is for branches (they are the "head" of a line
of development). The refs/tags hierarchy is for tags. The refs/remotes
hierarchy is where we store our local idea of where remote repositories'
branches point.
Pushing (and fetching) take a "refspec": two refs, a source and
destination, separated by a colon. So "git push foo:bar" means "look up
my local ref 'foo' and update or create the remote ref 'bar' with the
same commit".
Every ref has a "full name" that is much longer than what we often
see. We can generally abbreviate because one of the following applies:
1. We are specifying a name to look up, and there is a set of lookup
rules. For example, the name "master" will be considered as a tag,
and then as a branch, and then as a remote branch.
The lookup rules are described in "git help rev-parse" under the
section "Specifying Revisions".
2. We are using a name in a context that expects a particular type.
For example, "git branch foo" knows that "foo" is a new branch
name, and so will create the ref as refs/heads/foo. Similarly "git
tag foo" will create refs/tags/foo.
3. We can infer the type from the other half of a refspec. For
example, given a local branch "master" and a tag "v1.0" (and
neither currently existing on the remote side), we can do:
git push origin master:master v1.0:v1.0
and we know that the "master" we create on the remote will be a
branch, because the local "master" is a branch, and similarly the
"v1.0" we create on the remote will be a tag because the local
"v1.0" is a tag.
And finally, "git push" knows a shorthand for refspecs: a refspec
without a colon is treated as having the same string on both sides. So
"master" is really a shortcut for "master:master".
Knowing all of that, let's look at your examples:
A. git push origin master
This is really a syntactic shortcut for "git push origin
master:master".
B. git push origin master:master
The left-hand side of the refspec is looked up locally. In this
case, it is probably going to be "refs/heads/master". The right-hand
side is looked up on the remote. If it exists (i.e., you are
updating your branch), it is probably "refs/heads/master".
If it doesn't exist on the remote (i.e., you are pushing a new
branch), then we can infer from the prefix of the left-hand side
that the right-hand side should also be a branch (i.e., under
"refs/heads/").
So assuming "master" is a branch, this is really equivalent to:
git push origin refs/heads/master:refs/heads/master
C. git push origin master:refs/heads/master
If you understood the explanation for (B) above, you will know that
this is again basically the same thing. :)
However, note that in (B), if the branch is being created on the
remote, we rely on the "refspec inference" rule described earlier.
This behavior was adopted in git in v1.5.5.2 (commit f8aae120,
2008-04-23). So you may still see examples that pre-date this
feature and recommend using the full ref-name, which should no
longer be necessary.
Hope that helps. Let me know if you need clarification on any of the
above.
-Peff
^ permalink raw reply
* Re: [PATCH] Add option -b/--branch to clone for select a new HEAD
From: Jeff King @ 2009-08-26 16:10 UTC (permalink / raw)
To: Björn Steinbrink; +Cc: Kirill A. Korinskiy, git
In-Reply-To: <20090826155029.GA5750@atjola.homenet>
On Wed, Aug 26, 2009 at 05:50:29PM +0200, Björn Steinbrink wrote:
> Using guess_remote_head() seems pretty wrong. With -b given, you don't
> want to guess anymore, you _know_ which one you want. Unfortunately, I
> don't see a straight-forward way to handle that (but I'm totally
> clueless about the code, so don't let me scare you ;-)).
Thanks for pointing this out, Björn (I really should have noticed it on
first review, but I guess many eyes, shallow bugs, etc. :) ).
This code is a little bit confusing, so let me explain:
- we look up the remote HEAD, getting its commit sha1. If the protocol
supports it, we also get its symref information.
- we then pass the result to guess_remote_head. _If_ we have symref
information, then we can quit immediately, as the symref contains
what we want. If it doesn't, then we proceed with trying to match up
the commit sha1 with one of the other refs.
So if you want to create a "remote_head" object via "-b" which acts as
if it was the remote HEAD, you would need to actually create a new ref
object and set the "symref" field appropriately.
But I don't think there is any need to do that here. We simply want to
avoid calling guess_remote_head at all, since we know there is nothing
to guess at. We do still need to know whether remote_head is non-NULL
later, though.
So I think the code should probably look like this (totally untested):
remote_head = find_ref_by_name(refs, "HEAD");
if (option_branch) {
strbuf_addf(&branch_head, "%s%s", src_ref_prefix, option_branch);
head_points_at = find_ref_by_name(refs, branch_head.buf);
if (!head_points_at)
warning("remote branch not found, etc");
}
if (!head_points_at)
head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
and then initialize head_points_at to NULL instead of remote_head.
-Peff
^ permalink raw reply
* Re: [PATCH] Add option -b/--branch to clone for select a new HEAD
From: Björn Steinbrink @ 2009-08-26 16:56 UTC (permalink / raw)
To: Jeff King; +Cc: Kirill A. Korinskiy, git
In-Reply-To: <20090826161059.GC32741@coredump.intra.peff.net>
On 2009.08.26 12:10:59 -0400, Jeff King wrote:
> So I think the code should probably look like this (totally untested):
>
> remote_head = find_ref_by_name(refs, "HEAD");
> if (option_branch) {
> strbuf_addf(&branch_head, "%s%s", src_ref_prefix, option_branch);
> head_points_at = find_ref_by_name(refs, branch_head.buf);
> if (!head_points_at)
> warning("remote branch not found, etc");
> }
> if (!head_points_at)
> head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
Hm, why "refs" for find_ref_by_name(), but "mapped_ref" for
guess_remote_head()?
Björn
^ permalink raw reply
* [git-svn] [FEATURE-REQ] track merges from git
From: Ximin Luo @ 2009-08-26 16:42 UTC (permalink / raw)
To: git
Hi,
I'm have 2 separate svn projects from googlecode imported into a single git
repo. One is a semi-fork of the other, so I thought I'd be able to use git's
merge feature to repeatedly merge from the mother project (and possibly vice
versa too).
However, this doesn't happen. I "git pull" and this works fine, but when I "git
svn dcommit" back into svn, this rewrites my git history and it loses track of
the merge (and next time I try to pull, the same conflicts appear).
For now I just have a .git/info/grafts, but this doesn't get exported anywhere,
so if other people "git svn clone" from svn, or "git clone" from my git repo,
they don't get the merge information.
It would be nice if git-svn saved the merge info somewhere instead of getting
rid of it. #git tells me this is impossible at the moment, hence the mail.
Relevant parts of the convo are pasted below.
I understand if this is a low priority, but I don't think it would be a major
PITA to implement (some suggestions are listed in the convo log). And it'd be
useful for people converting from svn to git.
Thanks for your time.
X
P.S. please don't troll me.
(17:13:10) The topic for #git is: 1.6.4.1 | Homepage: http://git-scm.com |
Everyone asleep or clueless? Try git@vger.kernel.org | Git User's Survey 2009!
http://tinyurl.com/GitSurvey2009 | Channel log http://tinyurl.com/gitlog |
Mailing list archives: http://tinyurl.com/gitml | Gits on git:
http://tinyurl.com/gittalks | Pastebin: http://gist.github.com/ | GSoC '09:
http://socghop.appspot.com/org/home/google/gsoc2009/git
(17:13:14) infinity0: hi
(17:13:21) infinity0: i've used git-svn to import two svn repo
(17:13:23) infinity0: repos*
(17:13:28) infinity0: and used git to merge the two
(17:13:45) infinity0: the problem is, when i git-svn dcommit back to svn,
git-svn rewrites my git history
(17:13:50) infinity0: and loses the merge i just did
(17:14:01) offby1: infinity0: of course
(17:14:04) infinity0: how do i get it to retain knowledge of the merge?
(17:14:11) offby1: infinity0: you don't. Next questions.
(17:14:16) infinity0: why not?
(17:14:29) offby1: svn is incapable of storing a merge, at least in the sense
that we git people use the term "merge"
(17:14:46) Grum: you should be able to store the result of a merge as a commit
(17:14:51) offby1: sure
(17:14:57) infinity0: sure, but why does git-svn have to rewrite my *git*
history to remove knowledge of the merge?
(17:15:02) offby1: but not as a "merge commit", whatever that might mean in svn
(17:15:35) Grum: because it has to be representative of the svn repo after you
dcommit there obviously
(17:15:42) offby1: infinity0: it's trying to mirror the svn repository in your
git repository. I assume the original, un-rewritten commits are still in your
git repository; they're just not pointed at by any branch. Poke around in the
reflog; I imagine you'll find 'em in there
(17:16:09) infinity0: ok, but that's not useful if they're dangling
(17:16:26) infinity0: it's trying to mirror the svn repo yes... but as you
said, svn doesn't know about merges
(17:16:26) ***offby1 idly wonders if it'd be possible for git svn to indeed
store merge commits, by applying the appropriate svn:mergeinfo properties
(17:16:40) infinity0: i read a thread where it says those are different things
(17:16:41) offby1: infinity0: I suspect you're using git svn for something for
which it wasn't designed.
(17:17:17) infinity0: would it be possible, in theory, to have git-svn store
the git merge information in eg. the same way it stores the git-svn tag in the
svn commit message
(17:17:33) Grum: then just use svn?
(17:17:37) Grum: and a postit?
(17:18:01) infinity0: i'm trying to link two separate svn repos together via git
(17:18:17) Grum: and that is just what offby1 said
(17:18:30) infinity0: "what" is
(17:18:40) Grum: I suspect you're using git svn for something for which it
wasn't designed.
(17:18:42) infinity0: as you all are saying, git merges and svn "merges" are
different things
(17:18:58) infinity0: ok, but it would be possible to make git-svn have this
functionality? or not
(17:18:59) offby1: certainly
(17:19:16) offby1: I fear not, since Eric Wong seems like a smart fella; if it
were doable, I suspect he'd have done it already.
(17:19:21) offby1: But then ... who knows, maybe he's busy.
(17:20:07) infinity0: well afaic it would just involve adding some extra
git-svn info to the svn commit messages, but meh
(17:20:10) infinity0: i'll go file a bug
(17:21:14) offby1: infinity0: if it were me, I'd shy away from cramming more
junk into the svn commit messages; that strikes me as an unreliable storage medium
(17:21:22) offby1: I'd use properties instead
(17:21:24) Grum: ok lets do this properly
(17:21:31) Grum: why do you want to 'merge' 2 svn 'repos' this way?
(17:21:34) Grum: as you are not actually merging them
(17:21:45) offby1: Grum: go, man, go!
(17:21:58) infinity0: what do you mean "not actually merging them"
(17:22:17) infinity0: they are "actually merged" in git
(17:22:24) infinity0: then i git-svn dcommit and they become unmerged again
(17:22:34) Grum: why do you want to merge them?
(17:22:42) infinity0: so i can grab changes from one into the other
(17:22:42) Grum: and what is your goal with dcommitting this?
(17:22:57) infinity0: long story short, the two projects use svn on google code
(17:23:06) infinity0: one is a semi-fork of the other
(17:23:10) offby1: aaahhh
(17:23:13) infinity0: i need to pull changes quite often
(17:23:17) offby1: and you want to keep them in sync, kinda
(17:23:19) infinity0: yeah
(17:23:28) offby1: yeesh, dunno how I'd do that
(17:24:09) infinity0: ok well i guess the only thing i can do atm is file a bug
for git-svn and tell people to manually add the .git/info/grafts
(17:24:12) infinity0: but thanks for your info
(17:27:24) infinity0: uh, where is the git bug tracker
(17:27:40) Grum: its the mailinglist =)
(17:27:41) sitaram: no bugs, so no tracker
(17:27:44) sitaram: :
(17:27:45) sitaram: :D
(17:27:51) infinity0: lol
(17:27:59) Grum: and erm you want a feature, its nt a bug you are reporting
(17:27:59) Grum: s
(17:28:00) infinity0: ok i'll post on the mailing list then.. *grumble*
(17:28:08) infinity0: ok, *feature request :p
(17:28:08) Grum: you are not using the tool for what it is meant to
(17:28:13) Grum: and you can still do waht you want in either case
(17:28:17) Grum: just not by merging
(17:28:22) infinity0: well, how then?
(17:29:48) infinity0: aww fuck 120 messages a day? oh come on... are
non-members allowed to post to it?
(17:30:00) Grum: infinity0: just 120 yeah, and yeah they are
(17:30:06) infinity0: ah ok
^ permalink raw reply
* Re: [PATCH] fix simple deepening of a repo
From: Shawn O. Pearce @ 2009-08-26 17:03 UTC (permalink / raw)
To: Junio C Hamano
Cc: Johannes Sixt, Nicolas Pitre, Julian Phillips, Daniel Barkalow,
Johannes Schindelin, git
In-Reply-To: <7vk50reykp.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> >> How will this mesh with 'git clone --mirror'?
> >
> > Not well.
>
> But we at least can assume that the server operator is reasonable and
> wouldn't go overboard, (ab)using this "abbreviated advertisement" feature
> to hide heads and tags from the clients.
Yes. My patch is hardcoded to show only heads and tags, and nothing else.
But I think we want to make this configurable, and show everything
by default, but if there is a configuration entry, show only what
the configuration entry patterns suggest to advertise.
Thus an admin could hide refs/heads/*, but maybe he wants to, and
show only refs/heads/master, refs/heads/maint, refs/heads/next by
default. This is actually a rather clear indication to a client
that although there may be individual cooking topics scattered
through the expanded refs/heads/* space, any reasonable default
clone wouldn't take them.
> Think about in what situation you would want to do a mirror clone.
...
> That means the version of git used to prime, update
> and serve the mirror will know the expand extention.
Great point Junio. The backwards compatibility may be a non-issue
then, especially if this is configurable and we advertise refs/*
by default like we do now, and any reasonable admin who does enable
the hiding still advertises the core namspaces that really matter
to the majority of clients.
> I am hoping that we can finish 1.6.5 by mid September (let's tentatively
> say we will shoot for 16th). I expect the expand extention to be in
> 'next' by that time, cooking for 1.7.0. How does that timetable sound?
Oh, if 1.6.5 is mid-September, this is certainly not 1.6.5 material.
I'm not in any rush, this should go in when its ready, but 1.7
might be reasonable.
--
Shawn.
^ permalink raw reply
* [PATCH] git-p4: Avoid modules deprecated in Python 2.6.
From: Reilly Grant @ 2009-08-26 16:52 UTC (permalink / raw)
To: git, gitster; +Cc: Reilly Grant
The popen2, sha and sets modules are deprecated in Python 2.6 (sha in
Python 2.5). Both popen2 and sha are not actually used in git-p4.
Replace usage of sets.Set with the builtin set object.
Signed-off-by: Reilly Grant <reillyeon@qotw.net>
---
contrib/fast-import/git-p4 | 12 +++++-------
1 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 342529d..ca58700 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -8,12 +8,10 @@
# License: MIT <http://www.opensource.org/licenses/mit-license.php>
#
-import optparse, sys, os, marshal, popen2, subprocess, shelve
-import tempfile, getopt, sha, os.path, time, platform
+import optparse, sys, os, marshal, subprocess, shelve
+import tempfile, getopt, os.path, time, platform
import re
-from sets import Set;
-
verbose = False
@@ -861,8 +859,8 @@ class P4Sync(Command):
self.usage += " //depot/path[@revRange]"
self.silent = False
- self.createdBranches = Set()
- self.committedChanges = Set()
+ self.createdBranches = set()
+ self.committedChanges = set()
self.branch = ""
self.detectBranches = False
self.detectLabels = False
@@ -1627,7 +1625,7 @@ class P4Sync(Command):
if len(self.changesFile) > 0:
output = open(self.changesFile).readlines()
- changeSet = Set()
+ changeSet = set()
for line in output:
changeSet.add(int(line))
--
1.6.3.3
^ permalink raw reply related
* Re: [PATCH] Add option -b/--branch to clone for select a new HEAD
From: Jeff King @ 2009-08-26 17:48 UTC (permalink / raw)
To: Björn Steinbrink; +Cc: Kirill A. Korinskiy, git
In-Reply-To: <20090826165618.GA7477@atjola.homenet>
On Wed, Aug 26, 2009 at 06:56:18PM +0200, Björn Steinbrink wrote:
> On 2009.08.26 12:10:59 -0400, Jeff King wrote:
> > So I think the code should probably look like this (totally untested):
> >
> > remote_head = find_ref_by_name(refs, "HEAD");
> > if (option_branch) {
> > strbuf_addf(&branch_head, "%s%s", src_ref_prefix, option_branch);
> > head_points_at = find_ref_by_name(refs, branch_head.buf);
> > if (!head_points_at)
> > warning("remote branch not found, etc");
> > }
> > if (!head_points_at)
> > head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
>
> Hm, why "refs" for find_ref_by_name(), but "mapped_ref" for
> guess_remote_head()?
Blind copying of the current code? :)
Good question, though. AFAICT, the difference between mapped_refs and
refs is that the former contains only the refs we are actually fetching,
and its peer_ref member is filled in as appropriate.
Later in the code, we look at head_points_at->peer_ref, which means it
_must_ come from mapped_refs. And which means the code I posted is
bogus, as the ref we look up in "refs" will not have that member filled
in. So I think we do need:
head_points_at = find_ref_by_name(mapped_refs, branch_head.buf);
Good catch.
-Peff
^ permalink raw reply
* Re: [PATCH] git-p4: Avoid modules deprecated in Python 2.6.
From: Junio C Hamano @ 2009-08-26 18:14 UTC (permalink / raw)
To: Reilly Grant; +Cc: git
In-Reply-To: <1251305536-25887-1-git-send-email-reillyeon@qotw.net>
Reilly Grant <reillyeon@qotw.net> writes:
> The popen2, sha and sets modules are deprecated in Python 2.6 (sha in
> Python 2.5). Both popen2 and sha are not actually used in git-p4.
> Replace usage of sets.Set with the builtin set object.
Does the code already rely on a feature not found in Python older than 2.4
before your patch? Otherwise I would have liked to see the last sentence
like this:
Replace usage of sets.Set with the builtin set object, which has
been available since Python 2.4.
This change makes the script unusable with Python older than 2.4,
which was released in 2004. Hopefully nobody uses ancient 2.3.
So that I did not have to check myself to get a feel of how safe this
change is.
^ permalink raw reply
* Re: [PATCH] git-p4: Avoid modules deprecated in Python 2.6.
From: Reilly Grant @ 2009-08-26 18:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vhbvucuj5.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> Reilly Grant <reillyeon@qotw.net> writes:
>
>
>> The popen2, sha and sets modules are deprecated in Python 2.6 (sha in
>> Python 2.5). Both popen2 and sha are not actually used in git-p4.
>> Replace usage of sets.Set with the builtin set object.
>>
>
> Does the code already rely on a feature not found in Python older than 2.4
> before your patch? Otherwise I would have liked to see the last sentence
> like this:
>
> Replace usage of sets.Set with the builtin set object, which has
> been available since Python 2.4.
>
> This change makes the script unusable with Python older than 2.4,
> which was released in 2004. Hopefully nobody uses ancient 2.3.
>
> So that I did not have to check myself to get a feel of how safe this
> change is.
>
Thank you for the advice, this is my first patch. The existing code
uses the built-in set module in other places so the 2.4 requirement
already exists. I should have mentioned this in the original description.
--
Reilly Grant
reillyeon@qotw.net http://www.qotw.net/~reillyeon
GPG Key Signature: 2A41 A3E5 F3CA D3A0 F5CF 02DF B1EB CDEC 7850 E278
^ permalink raw reply
* Re: [PATCH] Add option -b/--branch to clone for select a new HEAD
From: Jeff King @ 2009-08-26 19:05 UTC (permalink / raw)
To: Björn Steinbrink; +Cc: Kirill A. Korinskiy, Junio C Hamano, git
In-Reply-To: <20090826174823.GA1202@coredump.intra.peff.net>
On Wed, Aug 26, 2009 at 01:48:23PM -0400, Jeff King wrote:
> Later in the code, we look at head_points_at->peer_ref, which means it
> _must_ come from mapped_refs. And which means the code I posted is
> bogus, as the ref we look up in "refs" will not have that member filled
> in. So I think we do need:
>
> head_points_at = find_ref_by_name(mapped_refs, branch_head.buf);
Actually, it is much more complicated than that. We want to do several
things with the remote HEAD:
1. set up our HEAD; this uses head_points_at now
2. set up a pointer in refs/remotes/$origin/HEAD; this uses
head_points_at now
3. check out the actual contents; this uses remote_head (and it can't
just blindly use head_points_at, because it may be a detached HEAD).
So you can see by (1) and (2) that we actually need to distinguish
between the remote's HEAD and where we want our HEAD to be. And we need
to checkout _our_ HEAD, if available, falling back to the remote's head.
I really wish clone was implemented simply as "init && remote add &&
fetch && checkout", which would have made this a lot easier. We would
simply be munging the HEAD file in the middle.
Anyway, here is a patch which I think does the right thing, and tests
each of the desired behaviors in the test script. If there are further
"should it do X or Y" questions, please phrase them in the form of a
patch to the test script. ;)
I also tried to roll in comments on the documentation to make it a bit
clearer.
-- >8 --
Subject: [PATCH] clone: add --branch option to select a different HEAD
We currently point the HEAD of a newly cloned repo to the
same ref as the parent repo's HEAD. While a user can then
"git checkout -b foo origin/foo" whichever branch they
choose, it is more convenient and more efficient to tell
clone which branch you want in the first place.
Based on a patch by Kirill A. Korinskiy.
Signed-off-by: Jeff King <peff@peff.net>
---
Documentation/git-clone.txt | 7 ++++
builtin-clone.c | 75 +++++++++++++++++++++++++++----------------
t/t5706-clone-branch.sh | 68 +++++++++++++++++++++++++++++++++++++++
3 files changed, 122 insertions(+), 28 deletions(-)
create mode 100755 t/t5706-clone-branch.sh
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 2c63a0f..1cd1ecc 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -127,6 +127,13 @@ objects from the source repository into a pack in the cloned repository.
Instead of using the remote name 'origin' to keep track
of the upstream repository, use <name>.
+--branch <name>::
+-b <name>::
+ Instead of pointing the newly created HEAD to the branch pointed
+ to by the cloned repositoroy's HEAD, point to <name> branch
+ instead. In a non-bare repository, this is the branch that will
+ be checked out.
+
--upload-pack <upload-pack>::
-u <upload-pack>::
When given, and the repository to clone from is accessed
diff --git a/builtin-clone.c b/builtin-clone.c
index 32dea74..9d79301 100644
--- a/builtin-clone.c
+++ b/builtin-clone.c
@@ -41,6 +41,7 @@ static int option_quiet, option_no_checkout, option_bare, option_mirror;
static int option_local, option_no_hardlinks, option_shared;
static char *option_template, *option_reference, *option_depth;
static char *option_origin = NULL;
+static char *option_branch = NULL;
static char *option_upload_pack = "git-upload-pack";
static int option_verbose;
@@ -65,6 +66,8 @@ static struct option builtin_clone_options[] = {
"reference repository"),
OPT_STRING('o', "origin", &option_origin, "branch",
"use <branch> instead of 'origin' to track upstream"),
+ OPT_STRING('b', "branch", &option_branch, "branch",
+ "checkout <branch> instead of the remote's HEAD"),
OPT_STRING('u', "upload-pack", &option_upload_pack, "path",
"path to git-upload-pack on the remote"),
OPT_STRING(0, "depth", &option_depth, "depth",
@@ -347,7 +350,9 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
const char *repo_name, *repo, *work_tree, *git_dir;
char *path, *dir;
int dest_exists;
- const struct ref *refs, *head_points_at, *remote_head, *mapped_refs;
+ const struct ref *refs, *remote_head, *mapped_refs;
+ const struct ref *remote_head_points_at;
+ const struct ref *our_head_points_at;
struct strbuf key = STRBUF_INIT, value = STRBUF_INIT;
struct strbuf branch_top = STRBUF_INIT, reflog_msg = STRBUF_INIT;
struct transport *transport = NULL;
@@ -519,11 +524,31 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
mapped_refs = write_remote_refs(refs, refspec, reflog_msg.buf);
remote_head = find_ref_by_name(refs, "HEAD");
- head_points_at = guess_remote_head(remote_head, mapped_refs, 0);
+ remote_head_points_at =
+ guess_remote_head(remote_head, mapped_refs, 0);
+
+ if (option_branch) {
+ struct strbuf head = STRBUF_INIT;
+ strbuf_addstr(&head, src_ref_prefix);
+ strbuf_addstr(&head, option_branch);
+ our_head_points_at =
+ find_ref_by_name(mapped_refs, head.buf);
+ strbuf_release(&head);
+
+ if (!our_head_points_at) {
+ warning("Remote branch %s not found in "
+ "upstream %s, using HEAD instead",
+ option_branch, option_origin);
+ our_head_points_at = remote_head_points_at;
+ }
+ }
+ else
+ our_head_points_at = remote_head_points_at;
}
else {
warning("You appear to have cloned an empty repository.");
- head_points_at = NULL;
+ our_head_points_at = NULL;
+ remote_head_points_at = NULL;
remote_head = NULL;
option_no_checkout = 1;
if (!option_bare)
@@ -531,41 +556,35 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
"refs/heads/master");
}
- if (head_points_at) {
- /* Local default branch link */
- create_symref("HEAD", head_points_at->name, NULL);
+ if (remote_head_points_at && !option_bare) {
+ struct strbuf head_ref = STRBUF_INIT;
+ strbuf_addstr(&head_ref, branch_top.buf);
+ strbuf_addstr(&head_ref, "HEAD");
+ create_symref(head_ref.buf,
+ remote_head_points_at->peer_ref->name,
+ reflog_msg.buf);
+ }
+ if (our_head_points_at) {
+ /* Local default branch link */
+ create_symref("HEAD", our_head_points_at->name, NULL);
if (!option_bare) {
- struct strbuf head_ref = STRBUF_INIT;
- const char *head = head_points_at->name;
-
- if (!prefixcmp(head, "refs/heads/"))
- head += 11;
-
- /* Set up the initial local branch */
-
- /* Local branch initial value */
+ const char *head = skip_prefix(our_head_points_at->name,
+ "refs/heads/");
update_ref(reflog_msg.buf, "HEAD",
- head_points_at->old_sha1,
+ our_head_points_at->old_sha1,
NULL, 0, DIE_ON_ERR);
-
- strbuf_addstr(&head_ref, branch_top.buf);
- strbuf_addstr(&head_ref, "HEAD");
-
- /* Remote branch link */
- create_symref(head_ref.buf,
- head_points_at->peer_ref->name,
- reflog_msg.buf);
-
install_branch_config(0, head, option_origin,
- head_points_at->name);
+ our_head_points_at->name);
}
} else if (remote_head) {
/* Source had detached HEAD pointing somewhere. */
- if (!option_bare)
+ if (!option_bare) {
update_ref(reflog_msg.buf, "HEAD",
remote_head->old_sha1,
NULL, REF_NODEREF, DIE_ON_ERR);
+ our_head_points_at = remote_head;
+ }
} else {
/* Nothing to checkout out */
if (!option_no_checkout)
@@ -597,7 +616,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
opts.src_index = &the_index;
opts.dst_index = &the_index;
- tree = parse_tree_indirect(remote_head->old_sha1);
+ tree = parse_tree_indirect(our_head_points_at->old_sha1);
parse_tree(tree);
init_tree_desc(&t, tree->buffer, tree->size);
unpack_trees(1, &t, &opts);
diff --git a/t/t5706-clone-branch.sh b/t/t5706-clone-branch.sh
new file mode 100755
index 0000000..f3f9a76
--- /dev/null
+++ b/t/t5706-clone-branch.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+test_description='clone --branch option'
+. ./test-lib.sh
+
+check_HEAD() {
+ echo refs/heads/"$1" >expect &&
+ git symbolic-ref HEAD >actual &&
+ test_cmp expect actual
+}
+
+check_file() {
+ echo "$1" >expect &&
+ test_cmp expect file
+}
+
+test_expect_success 'setup' '
+ mkdir parent &&
+ (cd parent && git init &&
+ echo one >file && git add file && git commit -m one &&
+ git checkout -b two &&
+ echo two >file && git add file && git commit -m two &&
+ git checkout master)
+'
+
+test_expect_success 'vanilla clone chooses HEAD' '
+ git clone parent clone &&
+ (cd clone &&
+ check_HEAD master &&
+ check_file one
+ )
+'
+
+test_expect_success 'clone -b chooses specified branch' '
+ git clone -b two parent clone-two &&
+ (cd clone-two &&
+ check_HEAD two &&
+ check_file two
+ )
+'
+
+test_expect_success 'clone -b sets up tracking' '
+ (cd clone-two &&
+ echo origin >expect &&
+ git config branch.two.remote >actual &&
+ echo refs/heads/two >>expect &&
+ git config branch.two.merge >>actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'clone -b does not munge remotes/origin/HEAD' '
+ (cd clone-two &&
+ echo refs/remotes/origin/master >expect &&
+ git symbolic-ref refs/remotes/origin/HEAD >actual &&
+ test_cmp expect actual
+ )
+'
+
+test_expect_success 'clone -b with bogus branch chooses HEAD' '
+ git clone -b bogus parent clone-bogus &&
+ (cd clone-bogus &&
+ check_HEAD master &&
+ check_file one
+ )
+'
+
+test_done
--
1.6.4.1.340.ge9f66.dirty
^ permalink raw reply related
* Re: [git-svn] [FEATURE-REQ] track merges from git
From: Bryan Donlan @ 2009-08-26 19:06 UTC (permalink / raw)
To: Ximin Luo; +Cc: git
In-Reply-To: <4A9565ED.4010608@cam.ac.uk>
On Wed, Aug 26, 2009 at 12:42 PM, Ximin Luo<xl269@cam.ac.uk> wrote:
> Hi,
>
> I'm have 2 separate svn projects from googlecode imported into a single git
> repo. One is a semi-fork of the other, so I thought I'd be able to use git's
> merge feature to repeatedly merge from the mother project (and possibly vice
> versa too).
>
> However, this doesn't happen. I "git pull" and this works fine, but when I "git
> svn dcommit" back into svn, this rewrites my git history and it loses track of
> the merge (and next time I try to pull, the same conflicts appear).
>
> For now I just have a .git/info/grafts, but this doesn't get exported anywhere,
> so if other people "git svn clone" from svn, or "git clone" from my git repo,
> they don't get the merge information.
>
> It would be nice if git-svn saved the merge info somewhere instead of getting
> rid of it. #git tells me this is impossible at the moment, hence the mail.
> Relevant parts of the convo are pasted below.
>
> I understand if this is a low priority, but I don't think it would be a major
> PITA to implement (some suggestions are listed in the convo log). And it'd be
> useful for people converting from svn to git.
>
> Thanks for your time.
>
> X
>
> P.S. please don't troll me.
For the particular use case you have, I suspect svk would be a better
tool for merging between those two projects...
git-svn is rather specifically designed to only deal with a single
upstream repository, you see, and it isn't very easy to change this to
accept multiple repos.
^ permalink raw reply
* [PATCH v3] import-tars: Allow per-tar author and commit message.
From: Peter Krefting @ 2009-08-26 19:26 UTC (permalink / raw)
To: git
If the "--metainfo=<ext>" option is given on the command line, a file
called "<filename.tar>.<ext>" will be used to create the commit message
for "<filename.tar>", instead of using "Imported from filename.tar".
The author and committer of the tar ball can also be overridden by
embedding an "Author:" or "Committer:" header in the metainfo file.
Signed-off-by: Peter Krefting <peter@softwolves.pp.se>
---
This version adds a command line option --metainfo that is used to
enable the new behaviour, as suggested by Junio C Hamano.
contrib/fast-import/import-tars.perl | 54 +++++++++++++++++++++++++++++++--
1 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl
index 78e40d2..15835cb 100755
--- a/contrib/fast-import/import-tars.perl
+++ b/contrib/fast-import/import-tars.perl
@@ -8,9 +8,20 @@
## perl import-tars.perl *.tar.bz2
## git whatchanged import-tars
##
+## Use --metainfo to specify the extension for a meta data file, where
+## import-tars can read the commit message and optionally author and
+## committer information.
+##
+## echo 'This is the commit message' > myfile.tar.bz2.msg
+## perl import-tars.perl --metainfo=msg myfile.tar.bz2
use strict;
-die "usage: import-tars *.tar.{gz,bz2,Z}\n" unless @ARGV;
+use Getopt::Long;
+
+my $metaext = '';
+
+die "usage: import-tars [--metainfo=extension] *.tar.{gz,bz2,Z}\n"
+ unless GetOptions('metainfo=s' => \$metaext) && @ARGV;
my $branch_name = 'import-tars';
my $branch_ref = "refs/heads/$branch_name";
@@ -109,12 +120,47 @@ foreach my $tar_file (@ARGV)
$have_top_dir = 0 if $top_dir ne $1;
}
+ my $commit_msg = "Imported from $tar_file.";
+ my $this_committer_name = $committer_name;
+ my $this_committer_email = $committer_email;
+ my $this_author_name = $author_name;
+ my $this_author_email = $author_email;
+ if ($metaext ne '')
+ {
+ # Optionally read a commit message from <filename.tar>.msg
+ # Add a line on the form "Committer: name <e-mail>" to override
+ # the committer and "Author: name <e-mail>" to override the
+ # author for this tar ball.
+ if (open MSG, '<', "${tar_file}.${metaext}")
+ {
+ $commit_msg = '';
+ while (<MSG>)
+ {
+ if (/^Committer:\s+([^<>]*)\s+<(.*)>\s*$/i)
+ {
+ $this_committer_name = $1;
+ $this_committer_email = $2;
+ }
+ elsif (/^Author:\s+([^<>]*)\s+<(.*)>\s*$/i)
+ {
+ $this_author_name = $1;
+ $this_author_email = $2;
+ }
+ else
+ {
+ $commit_msg .= $_;
+ }
+ }
+ close MSG;
+ }
+ }
+
print FI <<EOF;
commit $branch_ref
-author $author_name <$author_email> $author_time +0000
-committer $committer_name <$committer_email> $commit_time +0000
+author $this_author_name <$this_author_email> $author_time +0000
+committer $this_committer_name <$this_committer_email> $commit_time +0000
data <<END_OF_COMMIT_MESSAGE
-Imported from $tar_file.
+$commit_msg
END_OF_COMMIT_MESSAGE
deleteall
--
1.6.3.3
^ permalink raw reply related
* [PATCH] git-gui: fix diff for partially staged submodule changes
From: Jens Lehmann @ 2009-08-26 20:25 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Junio C Hamano, git
When a submodule commit had already been staged and another commit had
been checked out inside the submodule, the diff always displayed the
submodule commit log messages between the last supermodule commit and
the working tree, totally ignoring the commit in the index.
Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---
This fixes a regression introduced by this recent patch of mine:
"git-gui: display summary when showing diff of a submodule"
Sorry for the inconvenience.
git-gui/lib/diff.tcl | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index ae1ea3a..d593323 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -298,7 +298,12 @@ proc start_show_diff {cont_info {add_opts {}}} {
if {[string match {160000 *} [lindex $s 2]]
|| [string match {160000 *} [lindex $s 3]]} {
- set cmd {submodule summary -- $current_diff_path}
+ set is_submodule_diff 1
+ if {$w eq $ui_index} {
+ set cmd {submodule summary --cached -- $current_diff_path}
+ } else {
+ set cmd {submodule summary --files -- $current_diff_path}
+ }
}
if {[catch {set fd [eval git_read --nice $cmd]} err]} {
@@ -343,9 +348,6 @@ proc read_diff {fd cont_info} {
}
set ::current_diff_inheader 0
- if {[regexp {^\* } $line]} {
- set is_submodule_diff 1
- }
# -- Automatically detect if this is a 3 way diff.
#
if {[string match {@@@ *} $line]} {set is_3way_diff 1}
--
1.6.4.184.ge7b6.dirty
^ permalink raw reply related
* Re: [git-svn] [BUG] merge-tracking inconsistencies; Was: [FEATURE-REQ] track merges from git
From: Ximin Luo @ 2009-08-26 20:55 UTC (permalink / raw)
To: Bryan Donlan; +Cc: git
In-Reply-To: <4A95A032.3000801@cam.ac.uk>
Ximin Luo wrote:
> the tip of trunk is NOT a tip of test1
er, that should read "the tip of trunk is NOT a parent of the tip of test1"
X
^ permalink raw reply
* Re: [git-svn] [BUG] merge-tracking inconsistencies; Was: [FEATURE-REQ] track merges from git
From: Ximin Luo @ 2009-08-26 21:13 UTC (permalink / raw)
To: Bryan Donlan; +Cc: git
In-Reply-To: <4A95A032.3000801@cam.ac.uk>
Ximin Luo wrote:
> The only difference between the two runs is that in the unfucked version, we
> run "git svn dcommit" after every git commit.
Hmm, now that I think about it, the "bug" would be quite hard to "fix"...
Basically, it happens if you try to dcommit a commit A which has two parents, B
and X, where X is in a different branch, and hasn't already been dcommited. It
would seem that there isn't (in general) a way to detect whether X would become
(ie. in the future) a dcommitted svn commit - and actually this might not even
be the case, if eg. someone "svn commited" before we could get that dcommit in.
However about having git-svn outputting a warning when it detects merge
commits, one of whose parents is *not* a dcommitted commit, but does belongs to
a branch that is also being tracked by git-svn?
Something like "Warning: commit aaaa has parent bbbb; however, parent bbbb has
not been dcommited to the remote svn yet. If you proceed with this dcommit, the
merge history will be lost; to preserve the history, dcommit the branch
containing bbbb instead and then continue to dcommit this branch"?
X
^ permalink raw reply
* Re: What's cooking in git.git (Aug 2009, #04; Sun, 23)
From: Brandon Casey @ 2009-08-26 23:07 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Junio C Hamano, git
In-Reply-To: <YE4QMh4rA1r2X3ZG5TvGJZspm0UdCWyP-r6KFthp8PuFewAhHPJ3GQ@cipher.nrlssc.navy.mil>
Brandon Casey wrote:
> Nicolas Pitre wrote:
>> On Sun, 23 Aug 2009, Junio C Hamano wrote:
>>
>>> * lt/block-sha1 (2009-08-17) 4 commits
>>> (merged to 'next' on 2009-08-18 at 67a1ce8)
>>> + remove ARM and Mozilla SHA1 implementations
>>> + block-sha1: guard gcc extensions with __GNUC__
>>> + make sure byte swapping is optimal for git
>>> + block-sha1: make the size member first in the context struct
>>>
>>> Finishing touches ;-) There were a few Solaris portability patches
>>> floated around that I didn't pick up, waiting for them to finalize.
>> Those would be described better as Solaris _optimization_ patches. The
>> code is already fully portable as it is, except not necessarily optimal
>> in some cases.
>
> Nicolas is right, the code compiles and executes correctly on Solaris as-is.
>
> Here is the state of the two unsubmitted optimization patches:
>
> 1) Change things like __i386__ to __i386 since GCC defines both, but
> SUNWspro only defines __i386.
>
> This works correctly in my testing. I'm assuming that a test for
> __amd64 is not necessary and expect that __x86_64 is set whenever
> __amd64 is set.
>
> 2) Set __GNUC__ on SUNWspro v5.10 and up.
>
> This compiles correctly and passes the test suite, but produces
> warnings for __attribute__'s that sun's compiler has not implemented.
> This produces a very noisy compile.
>
> I've wanted to do some performance testing to see whether this actually
> produces an _improvement_. I'll try today.
Ok, I've done some testing.
I've compiled on two Solaris 5.10 x86 boxes. One has Sun compiler 5.10,
the other has version 5.8. The 5.10 version supports GCC inline assembler,
statement expressions, and __builtin_x functions. I timed how long
'git fsck --full HEAD' took on the git repository (best of three runs at
each stage).
It seems that #1 provides almost 1% improvement when using Sun compiler
v5.10, but a 2.5% regression on compiler v5.8. #2 (implemented using
Junio's suggestion, not by setting __GNUC__), which additionally enables
the fast htonl/ntohl and the rol/ror assembly in block-sha1 when using
the v5.10 compiler, produces a performance regression. I tried compiling
with '-fast -native', and also with just '-O', and both were slower with
the addition of part #2.
If this is the only data point for non-GNU compilers on x86, and since
there was only <1% improvement with the v5.10 compiler, I'm inclined
to say that we leave the series as it is and don't apply either change.
-brandon
^ permalink raw reply
* Re: [PATCH] upload-pack: add a trigger for post-upload-pack hook
From: Junio C Hamano @ 2009-08-26 23:39 UTC (permalink / raw)
To: Jeff King, Tom Werner; +Cc: Junio C Hamano, Tom Preston-Werner, git
In-Reply-To: <7vprajmp16.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
>> Is there any other information that might be useful to other non-GitHub
>> users of the hook? The only thing I can think of is the list of refs
>> that were fetched.
>
> I do not think that information is available. "want" will tell you what
> object they want, but that does not necessarily uniquey translate to a
> ref.
>
> If we are allowed to talk about asking for the moon, and if one of the
> primary reason for this new hook is statistics, it would be useful to see
> the number of bytes given, where the fetch-pack came from, and if we are
> using git-daemon virtual hosting which of our domain served the request.
I briefly looked at upload-pack.c.
As I said, the names of the refs asked is not available but in that file,
create_pack_file() should be able to gather transfer statistics (timeing
and bytes transferred). It also has access to the want_obj[]/have_obj[]
array, so it should be able to keep the rev-list parameters to be fed to
the hook if it wanted to (and with that information you could recreate the
exact pack data later if necessary).
And want_obj[]/have_obj[] information is much more useful than a crude
"fetch/clone" distinction. You can not just tell if the clients have
nothing, but how stale they are.
So at a minimum, if this is primarily meant as a statistics hook, I would
suggest the hook not to take _any_ argument, but is fed the information
from its command line in the following form, one piece of information per
line, from the very beginning:
want 40-byte SHA-1 - what were in want_obj[] array
have 40-byte SHA-1 - what were in have_obj[] array
As long as the hook scripts are written to ignore lines they do not
understand, in later rounds, we should also be able to feed two more
pieces of information with minimum modification to create_pack_file():
time float - number of seconds create_pack_file spent,
size decimal - number of bytes transferred
Here is an illustration patch.
upload-pack.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/upload-pack.c b/upload-pack.c
index 4d8be83..69a6f46 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -141,8 +141,60 @@ static int do_rev_list(int fd, void *create_full_pack)
return 0;
}
+static int feed_obj_to_hook(const char *label, struct object_array *oa, int i, int fd)
+{
+ int cnt;
+ char buf[512];
+
+ cnt = sprintf(buf, "%s %s\n", label,
+ sha1_to_hex(oa->objects[i].item->sha1));
+ return write_in_full(fd, buf, cnt) != cnt;
+}
+
+static int run_post_upload_pack_hook(size_t total, struct timeval *tv)
+{
+ const char *argv[2];
+ struct child_process proc;
+ int err, i;
+ int cnt;
+ char buf[512];
+
+ argv[0] = "hooks/post-upload-pack";
+ argv[1] = NULL;
+
+ if (access(argv[0], X_OK) < 0)
+ return 0;
+
+ memset(&proc, 0, sizeof(proc));
+ proc.argv = argv;
+ proc.in = -1;
+ proc.stdout_to_stderr = 1;
+ err = start_command(&proc);
+ if (err)
+ return err;
+ for (i = 0; !err && i < want_obj.nr; i++)
+ err |= feed_obj_to_hook("want", &want_obj, i, proc.in);
+ for (i = 0; !err && i < have_obj.nr; i++)
+ err |= feed_obj_to_hook("have", &have_obj, i, proc.in);
+ if (!err) {
+ cnt = sprintf(buf, "time %ld.%06ld\n",
+ (long)tv->tv_sec, (long)tv->tv_usec);
+ err |= (write_in_full(proc.in, buf, cnt) != cnt);
+ }
+ if (!err) {
+ cnt = sprintf(buf, "size %ld\n", (long)total);
+ err |= (write_in_full(proc.in, buf, cnt) != cnt);
+ }
+ if (close(proc.in))
+ err = 1;
+ if (finish_command(&proc))
+ err = 1;
+ return err;
+}
+
static void create_pack_file(void)
{
+ struct timeval start_tv, tv;
struct async rev_list;
struct child_process pack_objects;
int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
@@ -150,10 +202,12 @@ static void create_pack_file(void)
char abort_msg[] = "aborting due to possible repository "
"corruption on the remote side.";
int buffered = -1;
- ssize_t sz;
+ ssize_t sz, total_sz;
const char *argv[10];
int arg = 0;
+ gettimeofday(&start_tv, NULL);
+ total_sz = 0;
if (shallow_nr) {
rev_list.proc = do_rev_list;
rev_list.data = 0;
@@ -262,7 +316,7 @@ static void create_pack_file(void)
sz = xread(pack_objects.out, cp,
sizeof(data) - outsz);
if (0 < sz)
- ;
+ total_sz += sz;
else if (sz == 0) {
close(pack_objects.out);
pack_objects.out = -1;
@@ -314,6 +368,16 @@ static void create_pack_file(void)
}
if (use_sideband)
packet_flush(1);
+
+ gettimeofday(&tv, NULL);
+ tv.tv_sec -= start_tv.tv_sec;
+ if (tv.tv_usec < start_tv.tv_usec) {
+ tv.tv_sec--;
+ tv.tv_usec += 1000000;
+ }
+ tv.tv_usec -= start_tv.tv_usec;
+ if (run_post_upload_pack_hook(total_sz, &tv))
+ warning("post-upload-hook failed");
return;
fail:
^ permalink raw reply related
* What's cooking in git.git (Aug 2009, #05; Wed, 26)
From: Junio C Hamano @ 2009-08-26 23:45 UTC (permalink / raw)
To: git
Here are the topics that have been cooking. Commits prefixed with '-' are
only in 'pu' while commits prefixed with '+' are in 'next'. The ones
marked with '.' do not appear in any of the integration branches, but I am
still holding onto them.
After the 1.6.5 cycle, the next release will be 1.7.0, and we will push
out the planned "push safety" change. 1.7.0 would be a good time to
introduce "justifiable" changes that are not strictly backward compatible.
During 1.6.5 cycle, 'next' will hold topics meant for 1.6.5 and 1.7.0.
--------------------------------------------------
[Graduated to "master"]
* aj/fix-read-tree-from-scratch (2009-08-17) 1 commit
(merged to 'next' on 2009-08-20 at 7a04133)
+ read-tree: Fix regression with creation of a new index file.
* jc/maint-checkout-index-to-prefix (2009-08-16) 1 commit
(merged to 'next' on 2009-08-20 at 2f6aea2)
+ check_path(): allow symlinked directories to checkout-index --prefix
* jl/submodule-summary-diff-files (2009-08-15) 2 commits
(merged to 'next' on 2009-08-15 at 165bd8e)
+ Documentaqtion/git-submodule.txt: Typofix
(merged to 'next' on 2009-08-14 at a702e78)
+ git submodule summary: add --files option
* lh/short-decorate (2009-08-15) 1 commit
(merged to 'next' on 2009-08-18 at b8c1d96)
+ git-log: allow --decorate[=short|full]
* oa/stash-na (2009-08-11) 1 commit
(merged to 'next' on 2009-08-14 at 12c2e2b)
+ git stash: Give friendlier errors when there is nothing to apply
--------------------------------------------------
[New Topics]
* np/maint-1.6.3-deepen (2009-08-24) 1 commit.
(merged to 'next' on 2009-08-25 at 8e383d4)
+ fix simple deepening of a repo
* jk/maint-1.6.3-checkout-unborn (2009-08-24) 1 commit.
(merged to 'next' on 2009-08-25 at 5f29625)
+ checkout: do not imply "-f" on unborn branches
* mr/gitweb-snapshot (2009-08-25) 3 commits
- gitweb: add t9501 tests for checking HTTP status codes
- gitweb: split test suite into library and tests
- gitweb: improve snapshot error handling
--------------------------------------------------
[Stalled]
* js/stash-dwim (2009-07-27) 1 commit.
(merged to 'next' on 2009-08-16 at 67896c4)
+ Make 'git stash -k' a short form for 'git stash save --keep-index'
(this branch is used by tr/reset-checkout-patch.)
* tr/reset-checkout-patch (2009-08-18) 8 commits.
(merged to 'next' on 2009-08-18 at e465bb3)
+ tests: disable interactive hunk selection tests if perl is not available
(merged to 'next' on 2009-08-16 at 67896c4)
+ DWIM 'git stash save -p' for 'git stash -p'
+ Implement 'git stash save --patch'
+ Implement 'git checkout --patch'
+ Implement 'git reset --patch'
+ builtin-add: refactor the meat of interactive_add()
+ Add a small patch-mode testing library
+ git-apply--interactive: Refactor patch mode code
(this branch uses js/stash-dwim.)
There was a discussion on better DWIMmery for the above two topics to (1)
forbid "git stash save --anything-with-dash" and (2) redirect with any
option "git stash --opt" to "git stash save --opt", to keep it flexible
and safe at the same time. I think it is a sane thing to do, but nothing
has happened lately.
* jn/gitweb-blame (2009-08-06) 3 commits
- gitweb: Create links leading to 'blame_incremental' using JavaScript
- gitweb: Incremental blame (WIP)
- gitweb: Add optional "time to generate page" info in footer
Ajax-y blame WIP
* db/vcs-helper (2009-08-09) 17 commits
- Allow helpers to request marks for fast-import
- Allow helpers to report in "list" command that the ref is unchanged
- Add support for "import" helper command
- transport-helper_init(): fix a memory leak in error path
- Add a config option for remotes to specify a foreign vcs
- Allow programs to not depend on remotes having urls
- Allow fetch to modify refs
- Use a function to determine whether a remote is valid
- Use a clearer style to issue commands to remote helpers
(merged to 'next' on 2009-08-07 at f3533ba)
+ Makefile: install hardlinks for git-remote-<scheme> supported by libcurl if possible
+ Makefile: do not link three copies of git-remote-* programs
+ Makefile: git-http-fetch does not need expat
(merged to 'next' on 2009-08-06 at 15da79d)
+ http-fetch: Fix Makefile dependancies
+ Add transport native helper executables to .gitignore
(merged to 'next' on 2009-08-05 at 33d491e)
+ git-http-fetch: not a builtin
+ Use an external program to implement fetching with curl
+ Add support for external programs for handling native fetches
(this branch is used by jh/cvs-helper.)
There was a discussion that suggests that the use of colon ':' before vcs
helper name needs to be corrected. Nothing happened since.
* je/send-email-no-subject (2009-08-05) 1 commit
- send-email: confirm on empty mail subjects
This seems to break t9001. Near the tip of 'pu' I have a iffy
workaround.
--------------------------------------------------
[Cooking]
* mm/reset-report (2009-08-21) 2 commits
(merged to 'next' on 2009-08-25 at f2a4424)
+ reset: make the reminder output consistent with "checkout"
+ Rename REFRESH_SAY_CHANGED to REFRESH_IN_PORCELAIN.
* wl/insta-mongoose (2009-08-21) 1 commit
(merged to 'next' on 2009-08-25 at da1d566)
+ Add support for the Mongoose web server.
* lt/approxidate (2009-08-22) 2 commits
(merged to 'next' on 2009-08-26 at 62853f9)
+ Further 'approxidate' improvements
+ Improve on 'approxidate'
Fixes a few "reasonably formatted but thus-far misparsed" date strings.
As Nico suggested, we would need a test to prevent regression to existing
support for date strings that are "reasonably formatted".
* jc/mailinfo-scissors (2009-08-25) 2 commits
- Documentation: describe the scissors mark support of "git am"
- Teach mailinfo to ignore everything before -- >8 -- mark
* tf/diff-whitespace-incomplete-line (2009-08-23) 2 commits.
(merged to 'next' on 2009-08-26 at 4fc7784)
+ xutils: Fix xdl_recmatch() on incomplete lines
+ xutils: Fix hashing an incomplete line with whitespaces at the end
* cc/sequencer-rebase-i (2009-08-21) 17 commits.
- rebase -i: use "git sequencer--helper --cherry-pick"
- sequencer: add "--cherry-pick" option to "git sequencer--helper"
- sequencer: add "do_commit()" and related functions
- pick: libify "pick_help_msg()"
- revert: libify pick
- rebase -i: use "git sequencer--helper --fast-forward"
- sequencer: let "git sequencer--helper" callers set "allow_dirty"
- sequencer: add "--fast-forward" option to "git sequencer--helper"
- sequencer: add "do_fast_forward()" to perform a fast forward
- rebase -i: use "git sequencer--helper --reset-hard"
- sequencer: add "--reset-hard" option to "git sequencer--helper"
- sequencer: add comments about reset_almost_hard()
- sequencer: add "reset_almost_hard()" and related functions
- rebase -i: use "git sequencer--helper --make-patch"
- sequencer: free memory used in "make_patch" function
- sequencer: add "make_patch" function to save a patch
- sequencer: add "builtin-sequencer--helper.c"
Migrating "rebase -i" bit by bit to C. I am inclined to agree with Dscho
that maybe this approach forces the migration to follow the structure of
the shell script too much, and could force a suboptimal end result, but
we'll see.
* as/maint-graph-interesting-fix (2009-08-21) 2 commits.
(merged to 'next' on 2009-08-25 at 9d5e215)
+ Add tests for rev-list --graph with options that simplify history
+ graph API: fix bug in graph_is_interesting()
Looked sane.
* jc/shortstatus (2009-08-15) 11 commits
(merged to 'next' on 2009-08-15 at 7e40766)
+ git commit --dry-run -v: show diff in color when asked
+ Documentation/git-commit.txt: describe --dry-run
(merged to 'next' on 2009-08-12 at 53bda17)
+ wt-status: collect untracked files in a separate "collect" phase
+ Make git_status_config() file scope static to builtin-commit.c
+ wt-status: move wt_status_colors[] into wt_status structure
+ wt-status: move many global settings to wt_status structure
+ commit: --dry-run
(merged to 'next' on 2009-08-06 at fe8cb94)
+ status: show worktree status of conflicted paths separately
+ wt-status.c: rework the way changes to the index and work tree are summarized
+ diff-index: keep the original index intact
+ diff-index: report unmerged new entries
(this branch is used by jc/1.7.0-status.)
Will cook for a bit more and then merge.
* jc/maint-unpack-objects-strict (2009-08-13) 1 commit.
(merged to 'next' on 2009-08-23 at 38eb750)
+ Fix "unpack-objects --strict"
Will merge.
* jh/submodule-foreach (2009-08-20) 9 commits
(merged to 'next' on 2009-08-20 at 671bea4)
+ git clone: Add --recursive to automatically checkout (nested) submodules
+ t7407: Use 'rev-parse --short' rather than bash's substring expansion notation
(merged to 'next' on 2009-08-18 at f4a881d)
+ git submodule status: Add --recursive to recurse into nested submodules
+ git submodule update: Introduce --recursive to update nested submodules
+ git submodule foreach: Add --recursive to recurse into nested submodules
+ git submodule foreach: test access to submodule name as '$name'
+ Add selftest for 'git submodule foreach'
+ git submodule: Cleanup usage string and add option parsing to cmd_foreach()
+ git submodule foreach: Provide access to submodule name, as '$name'
Will merge.
* jh/notes (2009-07-29) 8 commits.
- t3302-notes-index-expensive: Speed up create_repo()
- fast-import: Add support for importing commit notes
- First draft of notes tree parser with support for fanout subtrees
- Teach "-m <msg>" and "-F <file>" to "git notes edit"
- Add an expensive test for git-notes
- Speed up git notes lookup
- Add a script to edit/inspect notes
- Introduce commit notes
The cvs-helper series depends on this one. I have a recollection
that some people were not happy about the fan-out of the notes tree
layout, but has the issue been resolved to a concensus?
* ne/rev-cache (2009-08-21) 6 commits
. support for path name caching in rev-cache
. full integration of rev-cache into git, completed test suite
. administrative functions for rev-cache, start of integration into git
. support for non-commit object caching in rev-cache
. basic revision cache system, no integration or features
. man page and technical discussion for rev-cache
Updated but seems to break upload-pack tests when merged to 'pu'; given
what this series touches, breakages in that area are expected.
May discard if a working reroll comes, to give it a fresh start.
* jh/cvs-helper (2009-08-18) 7 commits
- More fixes to the git-remote-cvs installation procedure
- Fix the Makefile-generated path to the git_remote_cvs package in git-remote-cvs
- Add simple selftests of git-remote-cvs functionality
- git-remote-cvs: Remote helper program for CVS repositories
- 2/2: Add Python support library for CVS remote helper
- 1/2: Add Python support library for CVS remote helper
- Basic build infrastructure for Python scripts
(this branch uses db/vcs-helper.)
Builds on db/vcs-helper (which is stalled, so this cannot move).
The testing of Python part seemed to be still fragile even with the latest
fix on one of my boches with an earlier round already installed, but I
didn't look very deeply before removing the older installation.
* sr/gfi-options (2009-08-24) 4 commits
- fast-import: test the new option command
- fast-import: add option command
- fast-import: put marks reading in it's own function
- fast-import: put option parsing code in seperate functions
Will merge to 'next' shortly.
* lt/block-sha1 (2009-08-17) 4 commits
(merged to 'next' on 2009-08-18 at 67a1ce8)
+ remove ARM and Mozilla SHA1 implementations
+ block-sha1: guard gcc extensions with __GNUC__
+ make sure byte swapping is optimal for git
+ block-sha1: make the size member first in the context struct
May merge soon; Solaris performance patches that was discussed
earlier can happen on 'master', as the series is usable as-is.
* nd/sparse (2009-08-20) 20 commits
- sparse checkout: inhibit empty worktree
- Add tests for sparse checkout
- read-tree: add --no-sparse-checkout to disable sparse checkout support
- unpack-trees(): ignore worktree check outside checkout area
- unpack_trees(): apply $GIT_DIR/info/sparse-checkout to the final index
- unpack-trees(): "enable" sparse checkout and load $GIT_DIR/info/sparse-checkout
- unpack-trees.c: generalize verify_* functions
- unpack-trees(): add CE_WT_REMOVE to remove on worktree alone
- Introduce "sparse checkout"
- dir.c: export excluded_1() and add_excludes_from_file_1()
- excluded_1(): support exclude files in index
- unpack-trees(): carry skip-worktree bit over in merged_entry()
- Read .gitignore from index if it is skip-worktree
- Avoid writing to buffer in add_excludes_from_file_1()
- Teach Git to respect skip-worktree bit (writing part)
- Teach Git to respect skip-worktree bit (reading part)
- Introduce "skip-worktree" bit in index, teach Git to get/set this bit
- Add test-index-version
- update-index: refactor mark_valid() in preparation for new options
(merged to 'next' on 2009-08-20 at ea167d7)
+ Prevent diff machinery from examining assume-unchanged entries on worktree
The first one was an independent fix; the rest has been replaced with the
"return of no-checkout" series.
--------------------------------------------------
[For 1.7.0]
* jc/1.7.0-status (2009-08-15) 3 commits
(merged to 'next' on 2009-08-22 at b3507bb)
+ git status: not "commit --dry-run" anymore
+ git stat -s: short status output
+ git stat: the beginning of "status that is not a dry-run of commit"
(this branch uses jc/shortstatus.)
With this, "git status" is no longer "git commit --preview".
* jc/1.7.0-send-email-no-thread-default (2009-08-22) 1 commit
(merged to 'next' on 2009-08-22 at 5106de8)
+ send-email: make --no-chain-reply-to the default
* jc/1.7.0-diff-whitespace-only-status (2009-05-23) 2 commits.
(merged to 'next' on 2009-08-02 at 9c08420)
+ diff: Rename QUIET internal option to QUICK
+ diff: change semantics of "ignore whitespace" options
This changes exit code from "git diff --ignore-whitespace" and friends
when there is no actual output. It is a backward incompatible change, but
we could argue that it is a bugfix.
* jc/1.7.0-push-safety (2009-02-09) 2 commits
(merged to 'next' on 2009-08-02 at 38b82fe)
+ Refuse deleting the current branch via push
+ Refuse updating the current branch in a non-bare repository via push
--------------------------------------------------
[I have been too busy to purge these]
* jc/log-tz (2009-03-03) 1 commit.
- Allow --date=local --date=other-format to work as expected
Maybe some people care about this. I dunno.
* jc/mailinfo-remove-brackets (2009-07-15) 1 commit.
- mailinfo: -b option keeps [bracketed] strings that is not a [PATCH] marker
Maybe some people care about this. I dunno.
* ar/maint-1.6.2-merge-recursive-d-f (2009-05-11) 2 commits.
. Fix for a merge where a branch has an F->D transition
. Add a reminder test case for a merge with F/D transition
* jc/merge-convert (2009-01-26) 1 commit.
. git-merge-file: allow converting the results for the work tree
* lt/read-directory (2009-05-15) 3 commits.
. Add initial support for pathname conversion to UTF-8
. read_directory(): infrastructure for pathname character set conversion
. Add 'fill_directory()' helper function for directory traversal
* ps/blame (2009-03-12) 1 commit.
. blame.c: start libifying the blame infrastructure
* pb/tracking (2009-07-16) 7 commits.
. branch.c: if remote is not config'd for branch, don't try delete push config
. branch, checkout: introduce autosetuppush
. move deletion of merge configuration to branch.c
. remote: add per-remote autosetupmerge and autosetuprebase configuration
. introduce a struct tracking_config
. branch: install_branch_config and struct tracking refactoring
. config: allow false and true values for branch.autosetuprebase
Has been ejected from 'pu' for some time, expecting a reroll.
^ permalink raw reply
* Re: What's cooking in git.git (Aug 2009, #05; Wed, 26)
From: Shawn O. Pearce @ 2009-08-26 23:49 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, sverre
In-Reply-To: <7vfxbeb0mt.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
> * sr/gfi-options (2009-08-24) 4 commits
> - fast-import: test the new option command
> - fast-import: add option command
> - fast-import: put marks reading in it's own function
> - fast-import: put option parsing code in seperate functions
>
> Will merge to 'next' shortly.
Please don't.
There is an off-git ML thread running between the various DVCS
tool developers who work on the fast-import/fast-export tools for
the respective DVCSes. In that thread we have decided to slightly
change this grammar and this series needs to be respun.
If you are itching to do something, eject it from pu and wait for
the respin.
--
Shawn.
^ permalink raw reply
* Re: What's cooking in git.git (Aug 2009, #05; Wed, 26)
From: Sverre Rabbelier @ 2009-08-27 0:10 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Junio C Hamano, git
In-Reply-To: <20090826234903.GR1033@spearce.org>
Heya,
On Wed, Aug 26, 2009 at 16:49, Shawn O. Pearce<spearce@spearce.org> wrote:
> In that thread we have decided to slightly
> change this grammar and this series needs to be respun.
Speaking of which, do you want me to add the feature command to the
grammar and rebase this on top of that? I got the impression we were
far enough discussing that for at least an RPC patch?
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* Re: What's cooking in git.git (Aug 2009, #05; Wed, 26)
From: Shawn O. Pearce @ 2009-08-27 0:12 UTC (permalink / raw)
To: Sverre Rabbelier; +Cc: Junio C Hamano, git
In-Reply-To: <fabb9a1e0908261710l2a957basff5eb5d7225ce099@mail.gmail.com>
Sverre Rabbelier <srabbelier@gmail.com> wrote:
> On Wed, Aug 26, 2009 at 16:49, Shawn O. Pearce<spearce@spearce.org> wrote:
> > In that thread we have decided to slightly
> > change this grammar and this series needs to be respun.
>
> Speaking of which, do you want me to add the feature command to the
> grammar and rebase this on top of that? I got the impression we were
> far enough discussing that for at least an RPC patch?
RFC patch. And yes, because I think we already agreed in that
thread that the date-format option is actually a feature command,
and not an option command. The other feature commands being kicked
around can be held for another series.
--
Shawn.
^ permalink raw reply
* [git-svn] always prompted for passphrase with subversion 1.6
From: Tim Potter @ 2009-08-27 0:38 UTC (permalink / raw)
To: git
Hi everyone. I am using git-svn with the Subversion 1.6 client compiled
with GNOME Keyring support. This neat features allows a SSL client
certificate password to be cached inside GNOME Keyring instead of being
prompted to enter it every time. However the git-svn script doesn't
appear to know about this and always prompts for a password.
Obviously there's some tweak required in the _auth_providers()
subroutine but I don't know enough about the Subversion Perl client to
figure out a fix.
Has anyone else run in to this problem? I did a quick search on the
list but didn't find anything relevant.
Regards,
Tim.
^ permalink raw reply
* [PATCH] upload-pack: add a trigger for post-upload-pack hook
From: Junio C Hamano @ 2009-08-27 0:47 UTC (permalink / raw)
To: Jeff King, Tom Werner; +Cc: Tom Preston-Werner, git
In-Reply-To: <7v1vmycfhd.fsf@alter.siamese.dyndns.org>
After upload-pack successfully finishes its operation, post-upload-pack
hook can be called for logging purposes.
The hook is passed various pieces of information, one per line, from its
standard input. Currently the following items can be fed to the hook, but
more types of information may be added in the future:
want SHA-1::
40-byte hexadecimal object name the client asked to include in the
resulting pack. Can occur one or more times in the input.
have SHA-1::
40-byte hexadecimal object name the client asked to exclude from
the resulting pack, claiming to have them already. Can occur zero
or more times in the input.
time float::
Number of seconds spent for creating the packfile.
size decimal::
Size of the resulting packfile in bytes.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
> Here is an illustration patch.
And here is a bit more polished one with necessary supporting material.
Documentation/git-upload-pack.txt | 2 +
Documentation/githooks.txt | 25 +++++++++++++
t/t5501-post-upload-pack.sh | 49 ++++++++++++++++++++++++++
upload-pack.c | 68 +++++++++++++++++++++++++++++++++++-
4 files changed, 142 insertions(+), 2 deletions(-)
create mode 100755 t/t5501-post-upload-pack.sh
diff --git a/Documentation/git-upload-pack.txt b/Documentation/git-upload-pack.txt
index b8e49dc..63f3b5c 100644
--- a/Documentation/git-upload-pack.txt
+++ b/Documentation/git-upload-pack.txt
@@ -20,6 +20,8 @@ The UI for the protocol is on the 'git-fetch-pack' side, and the
program pair is meant to be used to pull updates from a remote
repository. For push operations, see 'git-send-pack'.
+After finishing the operation successfully, `post-upload-pack`
+hook is called (see linkgit:githooks[5]).
OPTIONS
-------
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 1c73673..036f6c7 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -307,6 +307,31 @@ Both standard output and standard error output are forwarded to
'git-send-pack' on the other end, so you can simply `echo` messages
for the user.
+post-upload-pack
+----------------
+
+After upload-pack successfully finishes its operation, this hook is called
+for logging purposes.
+
+The hook is passed various pieces of information, one per line, from its
+standard input. Currently the following items can be fed to the hook, but
+more types of information may be added in the future:
+
+want SHA-1::
+ 40-byte hexadecimal object name the client asked to include in the
+ resulting pack. Can occur one or more times in the input.
+
+have SHA-1::
+ 40-byte hexadecimal object name the client asked to exclude from
+ the resulting pack, claiming to have them already. Can occur zero
+ or more times in the input.
+
+time float::
+ Number of seconds spent for creating the packfile.
+
+size decimal::
+ Size of the resulting packfile in bytes.
+
pre-auto-gc
-----------
diff --git a/t/t5501-post-upload-pack.sh b/t/t5501-post-upload-pack.sh
new file mode 100755
index 0000000..2cb63f8
--- /dev/null
+++ b/t/t5501-post-upload-pack.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='post upload-hook'
+
+. ./test-lib.sh
+
+LOGFILE=".git/post-upload-pack-log"
+
+test_expect_success setup '
+ test_commit A &&
+ test_commit B &&
+ git reset --hard A &&
+ test_commit C &&
+ git branch prev B &&
+ mkdir -p .git/hooks &&
+ {
+ echo "#!$SHELL_PATH" &&
+ echo "cat >post-upload-pack-log"
+ } >".git/hooks/post-upload-pack" &&
+ chmod +x .git/hooks/post-upload-pack
+'
+
+: test_expect_success initial '
+ rm -fr sub &&
+ git init sub &&
+ (
+ cd sub &&
+ git fetch --no-tags .. prev
+ ) &&
+ want=$(sed -n "s/^want //p" "$LOGFILE") &&
+ test "$want" = "$(git rev-parse --verify B)" &&
+ ! grep "^have " "$LOGFILE"
+'
+
+test_expect_success second '
+ rm -fr sub &&
+ git init sub &&
+ (
+ cd sub &&
+ git fetch --no-tags .. prev:refs/remotes/prev &&
+ git fetch --no-tags .. master
+ ) &&
+ want=$(sed -n "s/^want //p" "$LOGFILE") &&
+ test "$want" = "$(git rev-parse --verify C)" &&
+ have=$(sed -n "s/^have //p" "$LOGFILE") &&
+ test "$have" = "$(git rev-parse --verify B)"
+'
+
+test_done
diff --git a/upload-pack.c b/upload-pack.c
index 4d8be83..69a6f46 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -141,8 +141,60 @@ static int do_rev_list(int fd, void *create_full_pack)
return 0;
}
+static int feed_obj_to_hook(const char *label, struct object_array *oa, int i, int fd)
+{
+ int cnt;
+ char buf[512];
+
+ cnt = sprintf(buf, "%s %s\n", label,
+ sha1_to_hex(oa->objects[i].item->sha1));
+ return write_in_full(fd, buf, cnt) != cnt;
+}
+
+static int run_post_upload_pack_hook(size_t total, struct timeval *tv)
+{
+ const char *argv[2];
+ struct child_process proc;
+ int err, i;
+ int cnt;
+ char buf[512];
+
+ argv[0] = "hooks/post-upload-pack";
+ argv[1] = NULL;
+
+ if (access(argv[0], X_OK) < 0)
+ return 0;
+
+ memset(&proc, 0, sizeof(proc));
+ proc.argv = argv;
+ proc.in = -1;
+ proc.stdout_to_stderr = 1;
+ err = start_command(&proc);
+ if (err)
+ return err;
+ for (i = 0; !err && i < want_obj.nr; i++)
+ err |= feed_obj_to_hook("want", &want_obj, i, proc.in);
+ for (i = 0; !err && i < have_obj.nr; i++)
+ err |= feed_obj_to_hook("have", &have_obj, i, proc.in);
+ if (!err) {
+ cnt = sprintf(buf, "time %ld.%06ld\n",
+ (long)tv->tv_sec, (long)tv->tv_usec);
+ err |= (write_in_full(proc.in, buf, cnt) != cnt);
+ }
+ if (!err) {
+ cnt = sprintf(buf, "size %ld\n", (long)total);
+ err |= (write_in_full(proc.in, buf, cnt) != cnt);
+ }
+ if (close(proc.in))
+ err = 1;
+ if (finish_command(&proc))
+ err = 1;
+ return err;
+}
+
static void create_pack_file(void)
{
+ struct timeval start_tv, tv;
struct async rev_list;
struct child_process pack_objects;
int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
@@ -150,10 +202,12 @@ static void create_pack_file(void)
char abort_msg[] = "aborting due to possible repository "
"corruption on the remote side.";
int buffered = -1;
- ssize_t sz;
+ ssize_t sz, total_sz;
const char *argv[10];
int arg = 0;
+ gettimeofday(&start_tv, NULL);
+ total_sz = 0;
if (shallow_nr) {
rev_list.proc = do_rev_list;
rev_list.data = 0;
@@ -262,7 +316,7 @@ static void create_pack_file(void)
sz = xread(pack_objects.out, cp,
sizeof(data) - outsz);
if (0 < sz)
- ;
+ total_sz += sz;
else if (sz == 0) {
close(pack_objects.out);
pack_objects.out = -1;
@@ -314,6 +368,16 @@ static void create_pack_file(void)
}
if (use_sideband)
packet_flush(1);
+
+ gettimeofday(&tv, NULL);
+ tv.tv_sec -= start_tv.tv_sec;
+ if (tv.tv_usec < start_tv.tv_usec) {
+ tv.tv_sec--;
+ tv.tv_usec += 1000000;
+ }
+ tv.tv_usec -= start_tv.tv_usec;
+ if (run_post_upload_pack_hook(total_sz, &tv))
+ warning("post-upload-hook failed");
return;
fail:
--
1.6.4.1.288.g10d22
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox