* Re: [PATCH 16/18] blob.c: remove unused function
From: Daniel Barkalow @ 2010-01-12 17:37 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1263282781-25596-17-git-send-email-gitster@pobox.com>
On Mon, 11 Jan 2010, Junio C Hamano wrote:
> parse_blob() is not used anywhere since a510bfa (Mark blobs as parsed when
> they're actually parsed, 2005-04-28).
Perhaps it should be replaced with a comment that blobs are never parsed,
because they don't need to be? We don't need the actual function, but I
think it's worth having a note where the function would be.
-Daniel
*This .sig left intentionally blank*
^ permalink raw reply
* [PATCH] remote-curl: Fix Accept header for smart HTTP connections
From: Shawn O. Pearce @ 2010-01-12 17:54 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
We actually expect to see an application/x-git-upload-pack-result
but we lied and said we Accept *-response. This was a typo on my
part when I was writing the code.
Fortunately the wrong Accept header had no real impact, as the
deployed git-http-backend servers were not testing the Accept
header before they returned their content.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
This should go in maint.
remote-curl.c | 2 +-
t/t5551-http-fetch.sh | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/remote-curl.c b/remote-curl.c
index a331bae..8f169dd 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -480,7 +480,7 @@ static int rpc_service(struct rpc_state *rpc, struct discovery *heads)
strbuf_addf(&buf, "Content-Type: application/x-%s-request", svc);
rpc->hdr_content_type = strbuf_detach(&buf, NULL);
- strbuf_addf(&buf, "Accept: application/x-%s-response", svc);
+ strbuf_addf(&buf, "Accept: application/x-%s-result", svc);
rpc->hdr_accept = strbuf_detach(&buf, NULL);
while (!err) {
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index c0505ec..7faa31a 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -38,7 +38,7 @@ cat >exp <<EOF
> POST /smart/repo.git/git-upload-pack HTTP/1.1
> Accept-Encoding: deflate, gzip
> Content-Type: application/x-git-upload-pack-request
-> Accept: application/x-git-upload-pack-response
+> Accept: application/x-git-upload-pack-result
> Content-Length: xxx
< HTTP/1.1 200 OK
< Pragma: no-cache
--
1.6.6.280.ge295b
--
Shawn.
^ permalink raw reply related
* Re: default behaviour for `gitmerge` (no arguments)
From: Junio C Hamano @ 2010-01-12 18:11 UTC (permalink / raw)
To: Jeff King; +Cc: Gareth Adams, git
In-Reply-To: <20100112162355.GB25092@coredump.intra.peff.net>
Jeff King <peff@peff.net> writes:
> Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for
> "the upstream of" then we wouldn't need a special merge option. You
> could just do:
>
> git merge %HEAD ;# (or git merge %, IIRC the proposal correctly)
I don't think "whatever _HEAD_ tracks" makes sense at the semantic level
(i.e. you don't do "branch.HEAD.merge") but a syntax for "whatever the
named _branch_ tracks" with "if a branch is not named, the current branch
is implied" (i.e. the one in parentheses) would.
It is an entirely different matter what the special syntax to trigger that
"upstream-ness" should be. I vaguely recall @{upstream} or @{u} were the
concensus?
^ permalink raw reply
* Interest in locking mechanism?
From: Edward Z. Yang @ 2010-01-12 18:10 UTC (permalink / raw)
To: git
I have a few friends that still use RCS for their version control
needs. We have argued over various points between RCS and Git, and
as far as I can tell the one thing RCS has that Git does not is
a locking mechanism. That is to say, co -l checks out a file and
also gives you a lock on it, preventing others from futzing with it,
and ci -u checks in the file and releases your lock. This is
useful if you have a shared working copy on a multiuser system or
on a network file system, and you don't want conflicts.
I was wondering if there would be interest in such a feature on
the Git developers side.
Cheers,
Edward
^ permalink raw reply
* Re: default behaviour for `gitmerge` (no arguments)
From: Jeff King @ 2010-01-12 18:25 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Schindelin, Gareth Adams, git
In-Reply-To: <7vhbqr2nxt.fsf@alter.siamese.dyndns.org>
On Tue, Jan 12, 2010 at 10:11:26AM -0800, Junio C Hamano wrote:
> Jeff King <peff@peff.net> writes:
>
> > Hmm. If we had the oft-discussed-but-never-agreed-upon shorthand for
> > "the upstream of" then we wouldn't need a special merge option. You
> > could just do:
> >
> > git merge %HEAD ;# (or git merge %, IIRC the proposal correctly)
>
> I don't think "whatever _HEAD_ tracks" makes sense at the semantic level
> (i.e. you don't do "branch.HEAD.merge") but a syntax for "whatever the
> named _branch_ tracks" with "if a branch is not named, the current branch
> is implied" (i.e. the one in parentheses) would.
The patch that Dscho provided would actually convert HEAD@{upstream}
into the upstream of whatever HEAD pointed at. Which I think makes
sense. We don't do it for reflogs, but that is because it is useful to
distinguish between the reflog for a symref and the thing it points to.
But since one would presumably not make such a configuration for a
symref, that distinction is not useful.
> It is an entirely different matter what the special syntax to trigger that
> "upstream-ness" should be. I vaguely recall @{upstream} or @{u} were the
> concensus?
Ah, right. I remembered hating "%" even as I typed it, but I had
forgotten about the followup discussion. Looking at it again, I note:
1. The last posted patch still has a misplaced free() (patch below),
but I think otherwise is not buggy.
2. We don't complain on "git show @{usptream}" and we probably should.
I remember there being some complications because the contents of
@{} were passed to approxidate, but I think we can get around that
by letting approxidate complain if _nothing_ in the date was
useful. So "git show @{2.weeks.and.7.hot.dogs.ago}" would still
work, but "git show @{totally.bogus.input}" would complain.
3. I have actually been running with Dscho's patch for the last couple
of months, and I don't remember using it once. So perhaps it is not
as useful as I might have thought. :)
Anyway, fixup patch is below. I don't expect you to pick up the topic or
anything, but since I went to the trouble to find the bug once upon a
time, I thought I would post the fix for anybody who does want to pick
it up.
diff --git a/sha1_name.c b/sha1_name.c
index b73b93e..da90ebe 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -275,9 +275,9 @@ static char *substitute_branch_name(const char **string, int *len)
char *ref = xstrndup(*string, *len - ret);
struct branch *tracking = branch_get(*ref ? ref : NULL);
- free(ref);
if (!tracking)
die ("No tracking branch found for '%s'", ref);
+ free(ref);
if (tracking->merge && tracking->merge[0]->dst) {
*string = xstrdup(tracking->merge[0]->dst);
*len = strlen(*string);
^ permalink raw reply related
* Re: Interest in locking mechanism?
From: B Smith-Mannschott @ 2010-01-12 18:29 UTC (permalink / raw)
To: Edward Z. Yang; +Cc: git
In-Reply-To: <1263319565-sup-1767@ezyang>
On Tue, Jan 12, 2010 at 19:10, Edward Z. Yang <ezyang@mit.edu> wrote:
> I have a few friends that still use RCS for their version control
> needs. We have argued over various points between RCS and Git, and
> as far as I can tell the one thing RCS has that Git does not is
> a locking mechanism. That is to say, co -l checks out a file and
> also gives you a lock on it, preventing others from futzing with it,
> and ci -u checks in the file and releases your lock. This is
> useful if you have a shared working copy on a multiuser system or
> on a network file system, and you don't want conflicts.
>
> I was wondering if there would be interest in such a feature on
> the Git developers side.
How do you imagine that this would work in a distributed system such
as git? What would it mean to have the lock for "a file", when each
user effectively has their own branch?
// Ben
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Tomas Carnecky @ 2010-01-12 18:37 UTC (permalink / raw)
To: B Smith-Mannschott; +Cc: Edward Z. Yang, git
In-Reply-To: <28c656e21001121029h42544f3er6eedf8465851fec1@mail.gmail.com>
On 01/12/2010 07:29 PM, B Smith-Mannschott wrote:
> On Tue, Jan 12, 2010 at 19:10, Edward Z. Yang<ezyang@mit.edu> wrote:
>> I have a few friends that still use RCS for their version control
>> needs. We have argued over various points between RCS and Git, and
>> as far as I can tell the one thing RCS has that Git does not is
>> a locking mechanism. That is to say, co -l checks out a file and
>> also gives you a lock on it, preventing others from futzing with it,
>> and ci -u checks in the file and releases your lock. This is
>> useful if you have a shared working copy on a multiuser system or
>> on a network file system, and you don't want conflicts.
>>
>> I was wondering if there would be interest in such a feature on
>> the Git developers side.
>
> How do you imagine that this would work in a distributed system such
> as git? What would it mean to have the lock for "a file", when each
> user effectively has their own branch?
He mentioned a shared working copy, in which case there can be problems
if multiple users edit the same file.
Usually you'd work around that by cloning the repo, working in the
clone, and push the result back. This can get a bit tricky if the main
repository is not bare, but there is a solution even to that (either
explicitly run git reset --hard or have a post-receive hook which
updates the working tree).
tom
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Edward Z. Yang @ 2010-01-12 18:33 UTC (permalink / raw)
To: B Smith-Mannschott; +Cc: git
In-Reply-To: <28c656e21001121029h42544f3er6eedf8465851fec1@mail.gmail.com>
Excerpts from B Smith-Mannschott's message of Tue Jan 12 13:29:41 -0500 2010:
> How do you imagine that this would work in a distributed system such
> as git? What would it mean to have the lock for "a file", when each
> user effectively has their own branch?
Hi Ben,
Good question. I don't intend for the locking mechanism to leak into
the distributed model of Git. It is solely for working copies, which /are/
centralized (just there can be a lot of them), when multiple people might
be editing the same working copy.
There is a somewhat natural question of: well, you should clone, make your
changes in your own copy, and then push them back. That is arguably the
correct mechanism. However, for casual users batonning changes from one
repository to another is often more overhead than is really necessary, and
I think a working copy locking mechanism will help for simple cases.
Cheers,
Edward
^ permalink raw reply
* [BUGFIX] Unbork remote helper execution
From: Ilari Liusvaara @ 2010-01-12 18:49 UTC (permalink / raw)
To: git
Someone that obiviously didn't test the change did the following (the
code blames to me, but I didn't write this):
code = start_command(helper);
if (code < 0 && errno == ENOENT)
die("Unable to find remote helper for '%s'", data->name);
else
exit(code);
Which is obiviously wrong. The code shouldn't exit if code is 0.
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
---
transport-helper.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index fece6d6..7012101 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -121,7 +121,7 @@ static struct child_process *get_helper(struct transport *transport)
code = start_command(helper);
if (code < 0 && errno == ENOENT)
die("Unable to find remote helper for '%s'", data->name);
- else
+ else if (code != 0)
exit(code);
data->helper = helper;
--
1.6.6.102.gd6f8f.dirty
^ permalink raw reply related
* Re: Interest in locking mechanism?
From: Avery Pennarun @ 2010-01-12 19:01 UTC (permalink / raw)
To: Edward Z. Yang; +Cc: git
In-Reply-To: <1263319565-sup-1767@ezyang>
On Tue, Jan 12, 2010 at 1:10 PM, Edward Z. Yang <ezyang@mit.edu> wrote:
> I have a few friends that still use RCS for their version control
> needs. We have argued over various points between RCS and Git, and
> as far as I can tell the one thing RCS has that Git does not is
> a locking mechanism. That is to say, co -l checks out a file and
> also gives you a lock on it, preventing others from futzing with it,
> and ci -u checks in the file and releases your lock. This is
> useful if you have a shared working copy on a multiuser system or
> on a network file system, and you don't want conflicts.
If what you want is just one shared working copy with locking, then
what you want is RCS. Why change what's not broken? You're not doing
anything distributed or even any branching, and you don't need to
atomically commit multiple files at once (which would be very
confusing if more than one person is changing stuff in the current
tree), so git doesn't seem buy you anything.
There are lots of arguments that the central-shared-copy-with-locking
is obsolete. It's been obsolete since at least CVS (the "concurrent
versions system", named after the fact that you didn't have to have
one central working copy). But if you don't agree that this model is
obsolete, you might as well use a tool that treats your use case as a
first class citizen.
Have fun,
Avery
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Edward Z. Yang @ 2010-01-12 19:11 UTC (permalink / raw)
To: Avery Pennarun; +Cc: git
In-Reply-To: <32541b131001121101i76ad8062p3a7f3571ad86b0ce@mail.gmail.com>
Excerpts from Avery Pennarun's message of Tue Jan 12 14:01:42 -0500 2010:
> If what you want is just one shared working copy with locking, then
> what you want is RCS. Why change what's not broken? You're not doing
> anything distributed or even any branching, and you don't need to
> atomically commit multiple files at once (which would be very
> confusing if more than one person is changing stuff in the current
> tree), so git doesn't seem buy you anything.
I would like to respectfully disagree. I want to use git because:
* I use Git on a regular basis, and do not use RCS. I constantly
have to go digging through the manpages when I occasionally do
stumble upon an RCS system. Interface familiarity is nice.
* Putting it in Git means that you can easily grow; you can decide
"Hey, maybe we want to do branchy development" and just do it,
rather than have to drum up the activation energy to do an
rcsimport.
* If code is deployed in a production context as a Git checkout,
you can definitely have both branchy development as well as
a shared working copy (with low contention, but contention nonetheless).
Cheers,
Edward
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Avery Pennarun @ 2010-01-12 19:24 UTC (permalink / raw)
To: Edward Z. Yang; +Cc: git
In-Reply-To: <1263323292-sup-4182@ezyang>
On Tue, Jan 12, 2010 at 2:11 PM, Edward Z. Yang <ezyang@mit.edu> wrote:
> * I use Git on a regular basis, and do not use RCS. I constantly
> have to go digging through the manpages when I occasionally do
> stumble upon an RCS system. Interface familiarity is nice.
But the users who are arguing in favour RCS would say the opposite, right?
> * Putting it in Git means that you can easily grow; you can decide
> "Hey, maybe we want to do branchy development" and just do it,
> rather than have to drum up the activation energy to do an
> rcsimport.
But then you'd have to do an import now instead of later, for no
immediate gain. The extreme programming people would say YAGNI here;
delay the work until it's actually required, because it'll be no more
work later than it is right now.
> * If code is deployed in a production context as a Git checkout,
> you can definitely have both branchy development as well as
> a shared working copy (with low contention, but contention nonetheless).
I would suggest that by the time you're doing this, you're just lying
to yourself if you think you have RCS-style locking. People will
quite easy be able to change the same files as other people, then push
into git, and sooner or later someone will have to pull from git into
the original shared repository, possibly stomping on other people's
work. So you end up not having the advantage you were trying to
achieve.
BTW, I will try be a bit more constructive in case you *really* want
this: I've never heard of anyone doing RCS-style locking with git, so
you're probably out of luck if you're looking for a pre-made solution.
But it's probably rather easy to construct a simple shell script
implementation that's independent of your revision control system
(since locking files has nothing to do with revision tracking,
really). Just make a 'co' command that writes your username to
.filename.lock and chmods the file; then write a ci command that
checks the lockfile to make sure it's yours, deletes the lock file,
git commits it, and chmods the file back again.
Have fun,
Avery
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Martin Langhoff @ 2010-01-12 19:26 UTC (permalink / raw)
To: Edward Z. Yang; +Cc: Avery Pennarun, git
In-Reply-To: <1263323292-sup-4182@ezyang>
On Tue, Jan 12, 2010 at 8:11 PM, Edward Z. Yang <ezyang@mit.edu> wrote:
> I would like to respectfully disagree. I want to use git because:
I have to say, Avery's got a very good point, and my position (as a
cross SCM user) is that he's right. But I have two suggestions that
might work to at least try out what you say you want...:
- Write a wrapper around your editor invokation to call `flock $EDITOR $@`
- Use rcs on top of git, just for the locking -- write a commit hook
that auto-commits to rcs when you commit to git; add suitable excludes
so git doesn't worry about ,v files.
And a comment on your points -
> * I use Git on a regular basis, and do not use RCS. I constantly
> have to go digging through the manpages when I occasionally do
> stumble upon an RCS system. Interface familiarity is nice.
that's very weak. Write your our wrappers that mimic git commands you
want to use...
> * Putting it in Git means that you can easily grow; you can decide
> "Hey, maybe we want to do branchy development" and just do it,
> rather than have to drum up the activation energy to do an
> rcsimport
"Drum up the energy" is somewhat exaggerated ;-)
> * If code is deployed in a production context as a Git checkout,
If that's what you are doing (or will be doing), just drop rcs, and
explore workflows that help bring attention to any case where there
were edits on the same file.
Actually -- you can focus on workflows that prevent or highlight cases
where the same file is "being edited" in a pre-commit hook that checks
and warns...
- if new commits (on the matching branch) touch the file (evil: will
have to do git-fetch)
- if the file was committed recently by a different committer
- if we're committing a merge involving files changing on more than
one of the heads involved (this case can sometimes be auto-merged with
a diff3-like algorythm)
maybe something on that track helps
m
--
martin.langhoff@gmail.com
martin@laptop.org -- School Server Architect
- ask interesting questions
- don't get distracted with shiny stuff - working code first
- http://wiki.laptop.org/go/User:Martinlanghoff
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Martin Langhoff @ 2010-01-12 19:33 UTC (permalink / raw)
To: Avery Pennarun; +Cc: Edward Z. Yang, git
In-Reply-To: <32541b131001121124u541de280na9184183d8704dc8@mail.gmail.com>
On Tue, Jan 12, 2010 at 8:24 PM, Avery Pennarun <apenwarr@gmail.com> wrote:
> really). Just make a 'co' command that writes your username to
> .filename.lock and chmods the file; then write a ci command that
> checks the lockfile to make sure it's yours, deletes the lock file,
> git commits it, and chmods the file back again.
Actually -- on the same track but even better: if you are using a
unixy system, you are likely to have all the users belong to a group,
and the files are editable by the group because they are rwx by group
members.
So write your own "git-lock" command that does "chmod g-w $@";
git-unlock reenables the group-writable bit. Done.
For more arcane things, use ACLs. On Windows I am sure there is a
commandline tool to touch ACL bits.
hth,
m
--
martin.langhoff@gmail.com
martin@laptop.org -- School Server Architect
- ask interesting questions
- don't get distracted with shiny stuff - working code first
- http://wiki.laptop.org/go/User:Martinlanghoff
^ permalink raw reply
* Re: Interest in locking mechanism?
From: Edward Z. Yang @ 2010-01-12 19:43 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Avery Pennarun, git
In-Reply-To: <46a038f91001121133r62b3d748n38ca27234f18e960@mail.gmail.com>
Excerpts from Martin Langhoff's message of Tue Jan 12 14:33:18 -0500 2010:
> So write your own "git-lock" command that does "chmod g-w $@";
> git-unlock reenables the group-writable bit. Done.
That was what I was thinking of doing (with modestly more cleverness for
recursive operation), and maybe some convenience flags for git-commit
for automatically unlocking or preserving the lock across a commit.
Cheers,
Edward
^ permalink raw reply
* Re: [BUGFIX] Unbork remote helper execution
From: Johannes Sixt @ 2010-01-12 19:53 UTC (permalink / raw)
To: Ilari Liusvaara; +Cc: Junio C Hamano, git
In-Reply-To: <1263321344-21237-1-git-send-email-ilari.liusvaara@elisanet.fi>
[added git@vger]
On Dienstag, 12. Januar 2010, Ilari Liusvaara wrote:
> Someone that obiviously didn't test the change did the following (the
> code blames to me, but I didn't write this):
>
> code = start_command(helper);
> if (code < 0 && errno == ENOENT)
> die("Unable to find remote helper for '%s'", data->name);
> else
> exit(code);
>
> Which is obiviously wrong. The code shouldn't exit if code is 0.
Duh! Sorry for that. Your original code indeed has 'else if (code != 0)'.
Thanks for catching this. BTW, the test suite passes nevertheless.
Aren't there any tests that exercise the code path, or do I have them
disabled somehow? So, yes: I didn't test the change.
Here is the amended commit that replaces the tip of js/exec-error-report,
with some light testing this time.
--- 8< ---
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Subject: [PATCH] Improve error message when a transport helper was not found
Perviously, the error message was:
git: 'remote-foo' is not a git-command. See 'git --help'.
By not treating the transport helper as a git command, a more suitable
error is reported:
fatal: Unable to find remote helper for 'foo'
Signed-off-by: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
transport-helper.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/transport-helper.c b/transport-helper.c
index 6ece0d9..7dce4a4 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -102,6 +102,7 @@ static struct child_process *get_helper(struct transport *transport)
int refspec_nr = 0;
int refspec_alloc = 0;
int duped;
+ int code;
if (data->helper)
return data->helper;
@@ -111,13 +112,18 @@ static struct child_process *get_helper(struct transport *transport)
helper->out = -1;
helper->err = 0;
helper->argv = xcalloc(4, sizeof(*helper->argv));
- strbuf_addf(&buf, "remote-%s", data->name);
+ strbuf_addf(&buf, "git-remote-%s", data->name);
helper->argv[0] = strbuf_detach(&buf, NULL);
helper->argv[1] = transport->remote->name;
helper->argv[2] = remove_ext_force(transport->url);
- helper->git_cmd = 1;
- if (start_command(helper))
- die("Unable to run helper: git %s", helper->argv[0]);
+ helper->git_cmd = 0;
+ helper->silent_exec_failure = 1;
+ code = start_command(helper);
+ if (code < 0 && errno == ENOENT)
+ die("Unable to find remote helper for '%s'", data->name);
+ else if (code != 0)
+ exit(code);
+
data->helper = helper;
data->no_disconnect_req = 0;
--
1.6.6.115.gd1ab3
^ permalink raw reply related
* Re: Interest in locking mechanism?
From: Avery Pennarun @ 2010-01-12 20:25 UTC (permalink / raw)
To: Martin Langhoff; +Cc: Edward Z. Yang, git
In-Reply-To: <46a038f91001121133r62b3d748n38ca27234f18e960@mail.gmail.com>
On Tue, Jan 12, 2010 at 2:33 PM, Martin Langhoff
<martin.langhoff@gmail.com> wrote:
> On Tue, Jan 12, 2010 at 8:24 PM, Avery Pennarun <apenwarr@gmail.com> wrote:
>> really). Just make a 'co' command that writes your username to
>> .filename.lock and chmods the file; then write a ci command that
>> checks the lockfile to make sure it's yours, deletes the lock file,
>> git commits it, and chmods the file back again.
>
> Actually -- on the same track but even better: if you are using a
> unixy system, you are likely to have all the users belong to a group,
> and the files are editable by the group because they are rwx by group
> members.
>
> So write your own "git-lock" command that does "chmod g-w $@";
> git-unlock reenables the group-writable bit. Done.
The trick is to track which user has the file checked out; you don't
want some random person to (accidentally) check in someone else's
file. That's the whole point. Of course, you can arrange for this
with some simple shell scripting.
I doubt ACLs are needed really. RCS certainly works(1) fine without them.
Have fun,
Avery
(1) depending on your definition of "works"
^ permalink raw reply
* Re: [PATCH 1/5] MSVC: Windows-native implementation for subset of Pthreads API
From: Johannes Sixt @ 2010-01-12 21:13 UTC (permalink / raw)
To: kusmabite; +Cc: Dmitry Potapov, msysgit, git, Andrzej K. Haczewski
In-Reply-To: <40aa078e1001080258n67e0711sf4733a99d512bf1@mail.gmail.com>
On Freitag, 8. Januar 2010, Erik Faye-Lund wrote:
> On Fri, Jan 8, 2010 at 4:32 AM, Dmitry Potapov <dpotapov@gmail.com> wrote:
> > AFAIK, Win32 API assumes that reading LONG is always atomic, so
> > the critical section is not really necesary here, but you need
> > to declare 'waiters' as 'volatile':
>
> "Simple reads and writes to properly-aligned 32-bit variables are
> atomic operations."
> http://msdn.microsoft.com/en-us/library/ms684122(VS.85).aspx
But then the next sentence is:
"However, access is not guaranteed to be synchronized. If two threads are
reading and writing from the same variable, you cannot determine if one
thread will perform its read operation before the other performs its write
operation."
This goes without saying, IOW, those Microsofties don't know what they write,
which makes the documentation a bit less trustworthy.
Nevertheless, I rewrote the code to use Interlocked* functions, and then read
the documentation again. InterlockedIncrement reads, for example:
"... This function is atomic with respect to calls to other interlocked
functions."
In particular, it doesn't say that it is atomic WRT reads such as we have
here:
> >> + /* we're done waiting, so make sure we decrease waiters count */
> >> + EnterCriticalSection(&cond->waiters_lock);
> >> + --cond->waiters;
> >> + LeaveCriticalSection(&cond->waiters_lock);
I've no assembly-fu, but I could imagine that it does not matter, but I really
would have confirmation from an x86 guru.
-- Hannes
^ permalink raw reply
* Re: [PATCH] grep: -L should show empty files
From: Sverre Rabbelier @ 2010-01-12 21:27 UTC (permalink / raw)
To: Junio C Hamano
Cc: git, Linus Torvalds, Miles Bader, Jeff King, Nguyen Thai Ngoc Duy
In-Reply-To: <7vvdf73eql.fsf_-_@alter.siamese.dyndns.org>
Heya,
On Tue, Jan 12, 2010 at 09:32, Junio C Hamano <gitster@pobox.com> wrote:
> This optimization doesn't matter too much in practice (a tracked empty
> file must be rare, or there is something wrong with your project);
How about python projects, where there's an __init__.py file
everywhere you turn your head? ;)
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* git-svn dcommit ignores --username if there are cached credentials
From: Michel Jouvin @ 2010-01-12 22:47 UTC (permalink / raw)
To: git
Hi,
I am new to Git and using 1.6.6. I'm very interested by using it to mirror SVN
repositories. But I am running into troubles with the way git-svn handles SVN
credentials.
For one SVN I use I have some cached credentials that have only very restricted
write access. With svn command, I am using --username for every commit and this
cached credential is just ignored: I'm asked for a password.
With git-svn, I use --username at init/fetch but during dcommit --username is
ignored becaused of the cached credential. I can see in SVN logs that the
cached credential (which doesn't have the right to commit the mods I made) has
been used instead of the one specified during fetch. If I removed the cached
credential, the username specified with --username is taken into account (I'm
asked a password for it and it works) and if I ommit the --username, the one
specified at fetch time is used.
IMO, looks like a bug... Thanks in advance for any comment.
Cheers,
Michel
^ permalink raw reply
* [PATCH v2] Threaded grep
From: Fredrik Kuivinen @ 2010-01-12 23:44 UTC (permalink / raw)
To: git
Cc: Linus Torvalds, Junio C Hamano, Miles Bader, Nguyen Thai Ngoc Duy,
Jeff King
This the second version of the threaded grep patch. It applies cleanly
on top of pu.
Two environment variables can be used to control the threading. If
NO_THREADS is set, then the old non-threaded code will be used.
THREADS can be set to an integer to specify the number of threads that
should be used. If neither NO_THREADS nor THREADS is set, 8 threads
are used.
The results below are best of five runs in the Linux repository on a
box with two cores.
git grep --no-ext-grep qwerty
4.38user 0.57system 0:02.69elapsed 183%CPU (0avgtext+0avgdata
0maxresident)k 0inputs+784outputs (0major+6206minor)pagefaults 0swaps
NO_THREADS=1 git grep --no-ext-grep qwerty
4.33user 0.48system 0:04.82elapsed 99%CPU (0avgtext+0avgdata
0maxresident)k 0inputs+784outputs (0major+3523minor)pagefaults 0swaps
And with a pattern with quite a few matches:
git grep --no-ext-grep function
6.28user 0.63system 0:03.97elapsed 173%CPU (0avgtext+0avgdata
0maxresident)k 0inputs+784outputs (0major+8101minor)pagefaults 0swaps
NO_THREADS=1 git grep --no-ext-grep function
6.21user 0.50system 0:06.71elapsed 100%CPU (0avgtext+0avgdata
0maxresident)k 0inputs+784outputs (0major+3523minor)pagefaults 0swaps
In either case we gain about 40% by the threading. More testing is, as
always, greatly appreciated.
The patch needs some further clean-ups before it can be considered for
application.
---
Major changes since v1:
* Buffer the output from the threads instead of waiting until the
result can be written to stdout.
* Limit the maximum number of pending work_items.
builtin-grep.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
grep.c | 85 ++++++++++++--
grep.h | 6 +
strbuf.c | 19 ++-
strbuf.h | 1
5 files changed, 413 insertions(+), 38 deletions(-)
diff --git a/builtin-grep.c b/builtin-grep.c
index 59c4b12..ebeede9 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -15,6 +15,13 @@
#include "grep.h"
#include "quote.h"
+#ifdef THREADED_DELTA_SEARCH
+#include "thread-utils.h"
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/syscall.h>
+#endif
+
#ifndef NO_EXTERNAL_GREP
#ifdef __unix__
#define NO_EXTERNAL_GREP 0
@@ -23,6 +30,262 @@
#endif
#endif
+static int use_threads = 1;
+
+#ifdef THREADED_DELTA_SEARCH
+
+static void* load_file(const char *filename, size_t *sz);
+
+enum work_type {WORK_BUF, WORK_FILE};
+
+/* We use one producer thread and number_of_threads consumer
+ threads. The producer adds struct work_items to 'todo' and the
+ consumers pick work items from the same array. */
+struct work_item
+{
+ enum work_type type;
+ char *name;
+
+ /* if type == WORK_BUF, then 'buf' points to a buffer of size
+ 'size' otherwise type == WORK_FILE and 'buf' is a nul
+ terminated filename. */
+ char *buf;
+ size_t size;
+ char done;
+ struct strbuf out;
+};
+
+/* Number of consumer threads. */
+static int number_of_threads;
+static pthread_t *threads;
+
+/* In the range [todo_done, todo_start) in 'todo' we have work_items
+ that have been or are processed by a consumer thread. We haven't
+ written the result for these to stdout yet.
+
+ The work_items in [todo_start, todo_end) are waiting to be picked
+ up by a consumer thread.
+
+ The ranges are modulo todo_alloc.
+*/
+static struct work_item *todo = NULL;
+static int todo_alloc = 0;
+static int todo_start = 0;
+static int todo_end = 0;
+static int todo_done = 0;
+
+/* Has all work items been added? */
+static int all_work_added = 0;
+
+/* This lock protects all the variables above. */
+static pthread_mutex_t grep_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* Signalled when a new work_item is added to todo. */
+static pthread_cond_t cond_add = PTHREAD_COND_INITIALIZER;
+
+/* Signalled when the result from one work_item is written to
+ stdout. */
+static pthread_cond_t cond_write = PTHREAD_COND_INITIALIZER;
+
+/* Signalled when we are finished with everything. */
+static pthread_cond_t cond_result = PTHREAD_COND_INITIALIZER;
+
+static void add_work(enum work_type type, char *name, char *buf, size_t size)
+{
+ pthread_mutex_lock(&grep_lock);
+
+ while ((todo_end+1) % todo_alloc == todo_done) {
+ pthread_cond_wait(&cond_write, &grep_lock);
+ }
+
+ todo[todo_end].type = type;
+ todo[todo_end].name = name;
+ todo[todo_end].buf = buf;
+ todo[todo_end].size = size;
+ todo[todo_end].done = 0;
+ strbuf_reset(&todo[todo_end].out);
+ todo_end = (todo_end + 1) % todo_alloc;
+
+ pthread_mutex_unlock(&grep_lock);
+ pthread_cond_signal(&cond_add);
+}
+
+static struct work_item* get_work()
+{
+ struct work_item* ret;
+
+ pthread_mutex_lock(&grep_lock);
+ while (todo_start == todo_end && !all_work_added) {
+ pthread_cond_wait(&cond_add, &grep_lock);
+ }
+
+ if (todo_start == todo_end && all_work_added) {
+ ret = NULL;
+ } else {
+ ret = &todo[todo_start];
+ todo_start = (todo_start + 1) % todo_alloc;
+ }
+ pthread_mutex_unlock(&grep_lock);
+ return ret;
+}
+
+/* This function takes ownership of 'name' and 'buf'. They will be
+ deallocated with free. */
+static int grep_buffer_async(struct grep_opt *opt, char *name, char *buf,
+ size_t size)
+{
+ add_work(WORK_BUF, name, buf, size);
+ return 0;
+}
+
+static int grep_file_async(struct grep_opt *opt, char *name,
+ const char *filename)
+{
+ add_work(WORK_FILE, name, (char*) filename, 0);
+ return 0;
+}
+
+static void work_done(struct work_item* w)
+{
+ int old_done;
+
+ pthread_mutex_lock(&grep_lock);
+ w->done = 1;
+ old_done = todo_done;
+ for(; todo[todo_done].done && todo_done != todo_start;
+ todo_done = (todo_done+1) % todo_alloc) {
+ w = &todo[todo_done];
+ write_or_die(1, w->out.buf, w->out.len);
+ if (w->type == WORK_BUF)
+ free(w->buf);
+
+ free(w->name);
+ }
+
+ if (old_done != todo_done)
+ pthread_cond_signal(&cond_write);
+
+ if (all_work_added && todo_done == todo_end)
+ pthread_cond_signal(&cond_result);
+
+ pthread_mutex_unlock(&grep_lock);
+}
+
+static void* run(void *arg)
+{
+ int hit = 0;
+ struct grep_opt *opt = arg;
+
+ while (1) {
+ struct work_item *w = get_work();
+ if (!w)
+ break;
+
+ opt->output_priv = w;
+ if (w->type == WORK_BUF) {
+ hit |= grep_buffer(opt, w->name, w->buf, w->size);
+ } else {
+ size_t sz;
+ void* data = load_file(w->buf, &sz);
+ if (data) {
+ hit |= grep_buffer(opt, w->name, data, sz);
+ free(data);
+ }
+ }
+
+ work_done(w);
+ }
+
+ return (void*) (intptr_t) hit;
+}
+
+static void strbuf_out(struct grep_opt *opt, const char *fmt, ...)
+{
+ struct work_item *w = opt->output_priv;
+ va_list ap;
+
+ va_start(ap, fmt);
+ strbuf_vaddf(&w->out, fmt, ap);
+ va_end(ap);
+}
+
+static void start_threads(struct grep_opt *opt)
+{
+ int i;
+
+ if (getenv("THREADS"))
+ number_of_threads = atoi(getenv("THREADS"));
+ else
+ number_of_threads = 8;
+
+ todo_alloc = 100;
+ todo = xmalloc(sizeof(struct work_item)*todo_alloc);
+ for (i = 0; i < todo_alloc; i++) {
+ strbuf_init(&todo[i].out, 0);
+ }
+
+ threads = xmalloc(sizeof(pthread_t)*number_of_threads);
+ for (i = 0; i < number_of_threads; i++) {
+ struct grep_opt *o = grep_opt_dup(opt);
+ o->show_hunk_mark = 1;
+ o->output = strbuf_out;
+ compile_grep_patterns(o);
+ int err = pthread_create(&threads[i], NULL, run, o);
+
+ if (err)
+ die("grep: failed to create thread: %s", strerror(err));
+ }
+}
+#endif /* THREADED_DELTA_SEARCH */
+
+#ifdef THREADED_DELTA_SEARCH
+static int wait_all()
+{
+ int hit = 0;
+ int i;
+
+ pthread_mutex_lock(&grep_lock);
+ all_work_added = 1;
+
+ /* Wait until all work is done. */
+ while (todo_done != todo_end)
+ pthread_cond_wait(&cond_result, &grep_lock);
+
+ /* Wake up all the consumer threads so they can see that there
+ is no more work to do. */
+ pthread_cond_broadcast(&cond_add);
+ pthread_mutex_unlock(&grep_lock);
+
+ for (i = 0; i < number_of_threads; i++) {
+ void *h;
+ pthread_join(threads[i], &h);
+ hit |= (int) (intptr_t) h;
+ }
+
+ return hit;
+}
+#else
+static int wait_all()
+{
+ return 0;
+}
+#endif
+
+static int grep_buffer_internal(struct grep_opt *opt, char *name, char *buf,
+ size_t size)
+{
+#ifdef THREADED_DELTA_SEARCH
+ if (use_threads)
+ return grep_buffer_async(opt, name, buf, size);
+#endif
+ {
+ int hit = grep_buffer(opt, name, buf, size);
+ free(name);
+ free(buf);
+ return hit;
+ }
+}
+
static char const * const grep_usage[] = {
"git grep [options] [-e] <pattern> [<rev>...] [[--] path...]",
NULL
@@ -169,21 +432,21 @@ static int grep_sha1(struct grep_opt *opt, const unsigned char *sha1, const char
if (opt->relative && opt->prefix_length) {
quote_path_relative(name + tree_name_len, -1, &pathbuf, opt->prefix);
strbuf_insert(&pathbuf, 0, name, tree_name_len);
- name = pathbuf.buf;
+ } else {
+ strbuf_addstr(&pathbuf, name);
}
- hit = grep_buffer(opt, name, data, size);
- strbuf_release(&pathbuf);
- free(data);
+
+ hit = grep_buffer_internal(opt, strbuf_detach(&pathbuf, NULL),
+ data, size);
+
return hit;
}
-static int grep_file(struct grep_opt *opt, const char *filename)
+static void* load_file(const char *filename, size_t *sz)
{
struct stat st;
+ char* data;
int i;
- char *data;
- size_t sz;
- struct strbuf buf = STRBUF_INIT;
if (lstat(filename, &st) < 0) {
err_ret:
@@ -195,24 +458,47 @@ static int grep_file(struct grep_opt *opt, const char *filename)
return 0; /* empty file -- no grep hit */
if (!S_ISREG(st.st_mode))
return 0;
- sz = xsize_t(st.st_size);
+ *sz = xsize_t(st.st_size);
i = open(filename, O_RDONLY);
if (i < 0)
goto err_ret;
- data = xmalloc(sz + 1);
- if (st.st_size != read_in_full(i, data, sz)) {
+ data = xmalloc(*sz + 1);
+ data[*sz] = 0;
+ if (st.st_size != read_in_full(i, data, *sz)) {
error("'%s': short read %s", filename, strerror(errno));
close(i);
free(data);
return 0;
}
close(i);
+ return data;
+}
+
+static int grep_file(struct grep_opt *opt, const char *filename)
+{
+ char *data;
+ size_t sz;
+ struct strbuf buf = STRBUF_INIT;
+ char *name;
+
if (opt->relative && opt->prefix_length)
- filename = quote_path_relative(filename, -1, &buf, opt->prefix);
- i = grep_buffer(opt, filename, data, sz);
- strbuf_release(&buf);
- free(data);
- return i;
+ quote_path_relative(filename, -1, &buf, opt->prefix);
+ else
+ strbuf_addstr(&buf, filename);
+ name = strbuf_detach(&buf, NULL);
+
+#ifdef THREADED_DELTA_SEARCH
+ if (use_threads) {
+ return grep_file_async(opt, name, filename);
+ } else
+#endif
+ {
+ data = load_file(filename, &sz);
+ if (!data)
+ return 0;
+
+ return grep_buffer_internal(opt, name, data, sz);
+ }
}
#if !NO_EXTERNAL_GREP
@@ -809,6 +1095,8 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
OPT_END()
};
+ use_threads = getenv("NO_THREADS") == NULL;
+
/*
* 'git grep -h', unlike 'git grep -h <pattern>', is a request
* to show usage information and exit.
@@ -862,6 +1150,17 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
opt.regflags |= REG_ICASE;
if ((opt.regflags != REG_NEWLINE) && opt.fixed)
die("cannot mix --fixed-strings and regexp");
+
+#ifdef THREADED_DELTA_SEARCH
+ if (!grep_threads_ok(&opt))
+ use_threads = 0;
+
+ if (use_threads)
+ start_threads(&opt);
+#else
+ use_threads = 0;
+#endif
+
compile_grep_patterns(&opt);
/* Check revs and then paths */
@@ -899,9 +1198,13 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
if (!list.nr) {
+ int hit;
if (!cached)
setup_work_tree();
- return !grep_cache(&opt, paths, cached, external_grep_allowed);
+ hit = grep_cache(&opt, paths, cached, external_grep_allowed);
+ if (use_threads)
+ hit |= wait_all();
+ return !hit;
}
if (cached)
@@ -913,6 +1216,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (grep_object(&opt, paths, real_obj, list.objects[i].name))
hit = 1;
}
+
+ if (use_threads)
+ hit |= wait_all();
free_grep_patterns(&opt);
return !hit;
}
diff --git a/grep.c b/grep.c
index 62723da..3dd3918 100644
--- a/grep.c
+++ b/grep.c
@@ -29,6 +29,28 @@ void append_grep_pattern(struct grep_opt *opt, const char *pat,
p->next = NULL;
}
+struct grep_opt* grep_opt_dup(const struct grep_opt *opt)
+{
+ struct grep_pat *pat;
+ struct grep_opt *ret = xmalloc(sizeof(struct grep_opt));
+ *ret = *opt;
+
+ ret->pattern_list = NULL;
+ ret->pattern_tail = &ret->pattern_list;
+
+ for(pat = opt->pattern_list; pat != NULL; pat = pat->next)
+ {
+ if(pat->token == GREP_PATTERN_HEAD)
+ append_header_grep_pattern(ret, pat->field,
+ pat->pattern);
+ else
+ append_grep_pattern(ret, pat->pattern, pat->origin,
+ pat->no, pat->token);
+ }
+
+ return ret;
+}
+
static int is_fixed(const char *s)
{
while (*s && !is_regex_special(*s))
@@ -260,7 +282,7 @@ static int word_char(char ch)
static void show_name(struct grep_opt *opt, const char *name)
{
- printf("%s%c", name, opt->null_following_name ? '\0' : '\n');
+ opt->output(opt, "%s%c", name, opt->null_following_name ? '\0' : '\n');
}
@@ -501,20 +523,20 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
if (opt->pre_context || opt->post_context) {
if (opt->last_shown == 0) {
if (opt->show_hunk_mark)
- fputs("--\n", stdout);
+ opt->output(opt, "--\n");
else
opt->show_hunk_mark = 1;
} else if (lno > opt->last_shown + 1)
- fputs("--\n", stdout);
+ opt->output(opt, "--\n");
}
opt->last_shown = lno;
if (opt->null_following_name)
sign = '\0';
if (opt->pathname)
- printf("%s%c", name, sign);
+ opt->output(opt, "%s%c", name, sign);
if (opt->linenum)
- printf("%d%c", lno, sign);
+ opt->output(opt, "%d%c", lno, sign);
if (opt->color) {
regmatch_t match;
enum grep_context ctx = GREP_CONTEXT_BODY;
@@ -525,18 +547,19 @@ static void show_line(struct grep_opt *opt, char *bol, char *eol,
while (next_match(opt, bol, eol, ctx, &match, eflags)) {
if (match.rm_so == match.rm_eo)
break;
- printf("%.*s%s%.*s%s",
- (int)match.rm_so, bol,
- opt->color_match,
- (int)(match.rm_eo - match.rm_so), bol + match.rm_so,
- GIT_COLOR_RESET);
+ opt->output(opt, "%.*s%s%.*s%s",
+ (int)match.rm_so, bol,
+ opt->color_match,
+ (int)(match.rm_eo - match.rm_so),
+ bol + match.rm_so,
+ GIT_COLOR_RESET);
bol += match.rm_eo;
rest -= match.rm_eo;
eflags = REG_NOTBOL;
}
*eol = ch;
}
- printf("%.*s\n", rest, bol);
+ opt->output(opt, "%.*s\n", rest, bol);
}
static int match_funcname(struct grep_opt *opt, char *bol, char *eol)
@@ -674,6 +697,33 @@ static int look_ahead(struct grep_opt *opt,
return 0;
}
+int grep_threads_ok(const struct grep_opt *opt)
+{
+ /* If this condition is true, then we may use the attribute
+ machinery in grep_buffer_1. The attribute code is not
+ thread safe, so we disable the use of threads. */
+ if (opt->funcname && !opt->unmatch_name_only && !opt->status_only &&
+ !opt->name_only)
+ return 0;
+
+ /* If we are showing hunk marks, we should not do it for the
+ first match. The synchronization problem we get for this
+ constraint is not yet solved, so we disable threading in
+ this case. */
+ if (opt->pre_context || opt->post_context)
+ return 0;
+
+ return 1;
+}
+
+static void std_output(struct grep_opt *opt, const char* fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
static int grep_buffer_1(struct grep_opt *opt, const char *name,
char *buf, unsigned long size, int collect_hits)
{
@@ -689,6 +739,9 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
opt->last_shown = 0;
+ if (!opt->output)
+ opt->output = std_output;
+
if (buffer_is_binary(buf, size)) {
switch (opt->binary) {
case GREP_BINARY_DEFAULT:
@@ -761,7 +814,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
if (opt->status_only)
return 1;
if (binary_match_only) {
- printf("Binary file %s matches\n", name);
+ opt->output(opt,
+ "Binary file %s matches\n", name);
return 1;
}
if (opt->name_only) {
@@ -817,9 +871,10 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
* which feels mostly useless but sometimes useful. Maybe
* make it another option? For now suppress them.
*/
- if (opt->count && count)
- printf("%s%c%u\n", name,
- opt->null_following_name ? '\0' : ':', count);
+ if (opt->count && count) {
+ opt->output(opt, "%s%c%u\n", name,
+ opt->null_following_name ? '\0' : ':', count);
+ }
return !!last_hit;
}
diff --git a/grep.h b/grep.h
index 75370f6..f5031c7 100644
--- a/grep.h
+++ b/grep.h
@@ -92,6 +92,9 @@ struct grep_opt {
unsigned last_shown;
int show_hunk_mark;
void *priv;
+
+ void (*output)(struct grep_opt*, const char*, ...);
+ void *output_priv;
};
extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
@@ -100,4 +103,7 @@ extern void compile_grep_patterns(struct grep_opt *opt);
extern void free_grep_patterns(struct grep_opt *opt);
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
+extern struct grep_opt* grep_opt_dup(const struct grep_opt *opt);
+extern int grep_threads_ok(const struct grep_opt *opt);
+
#endif
diff --git a/strbuf.c b/strbuf.c
index 4017476..a41f0ea 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -194,21 +194,28 @@ void strbuf_adddup(struct strbuf *sb, size_t pos, size_t len)
void strbuf_addf(struct strbuf *sb, const char *fmt, ...)
{
- int len;
va_list ap;
+ va_start(ap, fmt);
+ strbuf_vaddf(sb, fmt, ap);
+ va_end(ap);
+}
+
+void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap)
+{
+ int len;
+ va_list ap2;
+
+ va_copy(ap2, ap);
if (!strbuf_avail(sb))
strbuf_grow(sb, 64);
- va_start(ap, fmt);
len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
- va_end(ap);
if (len < 0)
die("your vsnprintf is broken");
if (len > strbuf_avail(sb)) {
strbuf_grow(sb, len);
- va_start(ap, fmt);
- len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
- va_end(ap);
+ len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap2);
+ va_end(ap2);
if (len > strbuf_avail(sb)) {
die("this should not happen, your snprintf is broken");
}
diff --git a/strbuf.h b/strbuf.h
index b37f06a..20129ad 100644
--- a/strbuf.h
+++ b/strbuf.h
@@ -118,6 +118,7 @@ extern size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
__attribute__((format (printf,2,3)))
extern void strbuf_addf(struct strbuf *sb, const char *fmt, ...);
+extern void strbuf_vaddf(struct strbuf *sb, const char *fmt, va_list ap);
extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);
/* XXX: if read fails, any partial read is undone */
^ permalink raw reply related
* Bug? git-svn clone dies with "fatal: ambiguous argument '...': unknown revision or path not in the working tree."
From: Eric Hanchrow @ 2010-01-12 23:58 UTC (permalink / raw)
To: git; +Cc: Eric Wong
I have been using git-svn happily for many months, updating git from
git://git.kernel.org/pub/scm/git/git.git every once in a while. I
just updated to c0eb604330e1288300d915f25868d1eed88d3038, and tried to
clone the same svn repo that I've been using for a long time:
$ git svn clone http://svn/repos/cozi/kits --stdlayout
It chugged along happily for a while, but then died like this:
fatal: ambiguous argument
'2d2df13977551168a54ffa9b706484242a58736a^..d038748d49a0de5802fe3c13f46d0e080d064290':
unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
rev-list 2d2df13977551168a54ffa9b706484242a58736a^..d038748d49a0de5802fe3c13f46d0e080d064290:
command returned error: 128
"git show 2d2df13977551168a54ffa9b706484242a58736a" shows that the
commit in question corresponds to a commit in svn that created an
empty directory:
15:56:46 [COZIGROUP\erich@ubuntu64-erich kits] (master)$ git show -w
2d2df13977551168a54ffa9b706484242a58736a
commit 2d2df13977551168a54ffa9b706484242a58736a
Author: cozigroup\erich <cozigroup\erich@1248e456-dc32-5a46-b6cc-76877e1dc968>
Date: Wed Jan 14 18:35:00 2009 +0000
This branch will hold work I've done to refactor the vcs backend
stuff, and add support for Mercurial.
git-svn-id: http://svn/repos/cozi/kits/branches/vcs-refactor@18735
1248e456-dc32-5a46-b6cc-76877e1dc968
15:41:01 [COZIGROUP\erich@ubuntu64-erich hmm]$ svn log --limit=1
-vr18735 http://svn/repos/cozi
------------------------------------------------------------------------
r18735 | cozigroup\erich | 2009-01-14 10:35:00 -0800 (Wed, 14 Jan
2009) | 2 lines
Changed paths:
A /kits/branches/vcs-refactor
This branch will hold work I've done to refactor the vcs backend
stuff, and add support for Mercurial.
If I recall correctly, that commit was a mistake: I'd forgotten that
the proper way to create a branch in svn is to copy the trunk, and not
to create an empty directory first.
Here I am creating that branch the proper way:
r18736 | cozigroup\erich | 2009-01-14 10:35:30 -0800 (Wed, 14 Jan
2009) | 2 lines
Changed paths:
D /kits/branches/vcs-refactor
D'oh. We branch by _copying_, not making empty directories :-|
------------------------------------------------------------------------
r18737 | cozigroup\erich | 2009-01-14 10:36:37 -0800 (Wed, 14 Jan
2009) | 2 lines
Changed paths:
A /kits/branches/vcs-refactor (from /kits/trunk:18671)
Refactoring the version-control stuff, and adding Mercurial support.
------------------------------------------------------------------------
15:56:51 [COZIGROUP\erich@ubuntu64-erich kits] (master)$ git show -w
d038748d49a0de5802fe3c13f46d0e080d064290
commit d038748d49a0de5802fe3c13f46d0e080d064290
Merge: 5108824 a370f0b
Author: cozigroup\erich <cozigroup\erich@1248e456-dc32-5a46-b6cc-76877e1dc968>
Date: Tue Jan 20 18:34:26 2009 +0000
Merged from trunk.
git-svn-id: http://svn/repos/cozi/kits/branches/vcs-refactor@18920
1248e456-dc32-5a46-b6cc-76877e1dc968
And here is (what might be) the first attempt to modify stuff in that directory:
15:52:52 [COZIGROUP\erich@ubuntu64-erich kits] (master)$ svn log
--limit=1 -vr18920 http://svn/repos/cozi
------------------------------------------------------------------------
r18920 | cozigroup\erich | 2009-01-20 10:34:26 -0800 (Tue, 20 Jan
2009) | 2 lines
Changed paths:
M /kits/branches/vcs-refactor
A /kits/branches/vcs-refactor/lib/CoziPlatform/cozi/resources.py
(from /kits/trunk/lib/CoziPlatform/cozi/resources.py:18919)
M /kits/branches/vcs-refactor/lib/CoziSecurity/cozi/authorize.py
M /kits/branches/vcs-refactor/lib/CoziSecurity/cozi/eguidtests.py
M /kits/branches/vcs-refactor/lib/CoziVaultRESTServices/cozi/screen_saver_api.py
M /kits/branches/vcs-refactor/lib/CoziVaultRESTServices/cozi/screen_saver_calendar_xml.tmpl
M /kits/branches/vcs-refactor/lib/CoziVaultRESTServices/cozi/web_client.py
Merged from trunk.
Anyway -- I suspect that my svn repos layout is ... er ... unusual,
and has hit some sorta edge case in git-svn. Is there some workaround
I can use, or is this a bug?
Thanks
^ permalink raw reply
* Lists for internal medicine, general practice, family practice
From: Alan home @ 2010-01-13 3:03 UTC (permalink / raw)
To: cargillmeats_centroamerica, lasse.turunen, oskar,
alexanderkai-lik.so, marketing
Please advise if you were still looking for lists of US doctors or dentists.
I have many different US medical lists, let me know what you need and I will get you some details, samples and discounted prices.
Please email me here instead: Rosario@choicemedicaldata.net (make sure to include a copy of this email in your reply)
Otherwise if you needed to have your email unlisted from our campaigns please send a request here: rembox@choicemedicaldata.net
^ permalink raw reply
* [PATCH] Add `commit.signoff` configuration variable.
From: Steven Drake @ 2010-01-13 3:36 UTC (permalink / raw)
To: git
Signed-off-by: Steven Drake <sdrake@xnet.co.nz>
---
Documentation/config.txt | 4 ++++
Documentation/git-commit.txt | 2 +-
builtin-commit.c | 4 ++++
3 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 23a965e..dd261cf 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -712,6 +712,10 @@ color.ui::
terminal. When more specific variables of color.* are set, they always
take precedence over this setting. Defaults to false.
+commit.signoff::
+ Add Signed-off-by line by the committer at the end of the commit
+ log message.
+
commit.template::
Specify a file to use as the template for new commit messages.
"{tilde}/" is expanded to the value of `$HOME` and "{tilde}user/" to the
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index c97c151..5a977b6 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -114,7 +114,7 @@ OPTIONS
-s::
--signoff::
Add Signed-off-by line by the committer at the end of the commit
- log message.
+ log message. This overrides the `commit.signoff` configuration variable.
-n::
--no-verify::
diff --git a/builtin-commit.c b/builtin-commit.c
index 3dfcd77..db90e7a 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -1093,6 +1093,10 @@ static int git_commit_config(const char *k, const char *v, void *cb)
if (!strcmp(k, "commit.template"))
return git_config_pathname(&template_file, k, v);
+ if (!strcmp(k, "commit.signoff")) {
+ signoff = git_config_bool(k, v);
+ return 0;
+ }
return git_status_config(k, v, s);
}
--
1.6.4
^ permalink raw reply related
* [PATCH] Add 'git commit --no-signoff' option.
From: Steven Drake @ 2010-01-13 3:36 UTC (permalink / raw)
To: git
Do not add a signed-off-by line. This overrides both the `--signoff`
option and the `commit.signoff` configuration variable.
Signed-off-by: Steven Drake <sdrake@xnet.co.nz>
---
Documentation/git-commit.txt | 4 ++++
builtin-commit.c | 5 ++++-
2 files changed, 8 insertions(+), 1 deletions(-)
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 5a977b6..2dfc989 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -116,6 +116,10 @@ OPTIONS
Add Signed-off-by line by the committer at the end of the commit
log message. This overrides the `commit.signoff` configuration variable.
+--no-signoff::
+ Do not add igned-off-by line. This overrides both the `--signoff`
+ option and the `commit.signoff` configuration variable.
+
-n::
--no-verify::
This option bypasses the pre-commit and commit-msg hooks.
diff --git a/builtin-commit.c b/builtin-commit.c
index db90e7a..f236068 100644
--- a/builtin-commit.c
+++ b/builtin-commit.c
@@ -51,7 +51,7 @@ static const char *logfile, *force_author;
static const char *template_file;
static char *edit_message, *use_message;
static char *author_name, *author_email, *author_date;
-static int all, edit_flag, also, interactive, only, amend, signoff;
+static int all, edit_flag, also, interactive, only, amend, signoff, no_signoff;
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
static char *untracked_files_arg;
/*
@@ -103,6 +103,7 @@ static struct option builtin_commit_options[] = {
OPT_STRING('C', "reuse-message", &use_message, "COMMIT", "reuse message from specified commit"),
OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
+ OPT_BOOLEAN(0, "no-signoff", &no_signoff, "Do not add Signed-off-by:"),
OPT_FILENAME('t', "template", &template_file, "use specified template file"),
OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
@@ -797,6 +798,8 @@ static int parse_and_validate_options(int argc, const char *argv[],
if (force_author && renew_authorship)
die("Using both --reset-author and --author does not make sense");
+ signoff = no_signoff ? 0 : signoff;
+
if (logfile || message.len || use_message)
use_editor = 0;
if (edit_flag)
--
1.6.4
^ 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