Re: Sources for 3.18-rc1 not uploaded

2014-10-21 Thread Michael J Gruber
Linus Torvalds schrieb am 21.10.2014 um 01:17:
> On Mon, Oct 20, 2014 at 3:28 PM, brian m. carlson
>  wrote:
>>
>> It doesn't appear that the stability of git archive --format=tar is
>> documented anywhere.  Given that, it doesn't seem reasonable to expect
>> that any tar implementation produces bit-for-bit compatible output
>> between versions.
> 
> The kernel has simple stability rules: if it breaks users, it gets
> fixed or reverted. That is a damn good rule.
> 
> I realize that some other projects are crap, and don't care about
> their users. I hope and believe that git is not in that sad group.
> 
> The whole "it's not documented" excuse is pure and utter bollocks.
> Users don't care. And stability of data should be *expected*, not need
> some random documentation entry to make it explicit.
> 
>   Linus
> 

Linus, with all due respect, this is not the LKML, so please watch your
tone over here on the git list (and keep ranting on LKML however you want).

Brian made a very valid point about what his patch was trying to fix -
after all that is why it was applied. Konstantin made a very valid point
about why the existing behavior is useful for KUP. Interestingly, both
cared about the users of git, just different kinds users.

Git is probably one of the most conservative projects regarding
backwards compatibility and heeding users' expectations (sometimes to my
own dismay). That being said, we distinguish between justified
expectations and those without a solid base - which is why we have
porcelain vs. plumbing, for example, to make clear which part of the ui
is stable. (Yeah, I know you know, but you didn't argue as if you did.)

"data" in git is stable. "data exports" by git are as stable as the
output format is intrinsically or due to the (hopefully documented) way
git produces it.

Unfortunately, the git archive doc clearly says that the umask is
applied to all archive entries. And that clearly wasn't the case (for
extended metadata headers) before Brian's fix.

Brian: How old is the newest tar that get's the extended metadata
headers wrong? If those tars are a "real concern" then we should
probably do the extra pax_umask as suggested by Linus, but have the
default protect the "unknowing users" and give the "knowing users" that
config knob to twitch (sorry, Linus). Otherwise a revert is in order.

Michael
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: please document --cached option to git-difftool

2014-10-21 Thread Michael J Gruber
Joseph Nahmias schrieb am 20.10.2014 um 23:24:
> Hello,
> 
> It would be great if the documentation showed that the git-difftool(1)
> command accepted the --cached option.  You can probably steal appropriate
> verbiage from the git-diff(1) manpage.
> 
> $ git --version
> git version 2.1.1
> 
> Thanks,
> --Joe
> 

>From git-difftool(1):

"git difftool is a frontend to git diff and accepts the same options and
arguments. See git-diff(1)."

Michael
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


git reflog --date

2014-10-21 Thread John Tapsell
Hi all,

  Could we add a default to "--date" so that:

git reflog --date

just works?  (Currently you need to do:   git reflog --date=iso)  It
should probably obey the default in log.date?

Also, could we add this "--date" option to the man page please?  It's
an extremely useful option to know.  At the moment you have to notice
the comment that "all normal log options" are there, and then try to
work it out from there etc.

Thank you,

John

John
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Copy mergetool "bc3" as "bc4"

2014-10-21 Thread David Aguilar
On Mon, Oct 20, 2014 at 11:40:23AM -0700, Junio C Hamano wrote:
> Sebastian Schuberth  writes:
> 
> >> Perhaps something like this, so that existing users can still use
> >> "bc3" and other people can use "bc" if it bothers them that they
> >> have to say "3" when the backend driver works with both 3 and 4?
> >
> > That indeed sounds like the best approach.
> >
> >> --- a/git-mergetool--lib.sh
> >> +++ b/git-mergetool--lib.sh
> >> @@ -250,7 +250,7 @@ list_merge_tool_candidates () {
> >>tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
> >>fi
> >>tools="$tools gvimdiff diffuse diffmerge ecmerge"
> >> -  tools="$tools p4merge araxis bc3 codecompare"
> >> +  tools="$tools p4merge araxis bc bc3 codecompare"
> >
> > Why keep bc3 here?
> 
> I didn't carefully look at the code that uses this list to see if we
> have to list everything or can list just the ones we recommend, and
> erred on the safer side (unlike the one for completion where I
> omitted bc3 as "deprecated").

We should drop "bc3" here.  This is the list of candidates that
is used when no configuration exists.  Listing "bc" twice here
implies that we might try that candidate twice.

Otherwise, this patch looks like the right way to go ~ it makes
"bc" available and keeps compatibility for "bc3".

If we wanted to phase out "bc3" for Git 3.0 we could start
warning inside of the "bc3" scriptlet, but I don't see any
reason to do so a.t.m.

Thanks,
-- 
David
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git-svn performance

2014-10-21 Thread Eric Wong
Jakob Stoklund Olesen  wrote:
> Yes, but I think you can remove cached_mergeinfo_rev too. 

Thanks, pushed the patch at the bottom, too.
Also started working on some memory reductions here:
 http://mid.gmane.org/20141021033912.ga27...@dcvr.yhbt.net
But there seem to be more problems :<

8<-
From: Eric Wong 
Date: Tue, 21 Oct 2014 06:23:22 +
Subject: [PATCH] git-svn: remove mergeinfo rev caching

This should further reduce memory usage from the new mergeinfo
speedups without hurting performance too much, assuming
reasonable latency to the SVN server.

Cc: Hin-Tak Leung 
Suggested-by: Jakob Stoklund Olesen 
Signed-off-by: Eric Wong 
---
 perl/Git/SVN.pm | 30 +-
 1 file changed, 9 insertions(+), 21 deletions(-)

diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
index f8a75b1..4364506 100644
--- a/perl/Git/SVN.pm
+++ b/perl/Git/SVN.pm
@@ -1710,32 +1710,20 @@ sub mergeinfo_changes {
my %minfo = map {split ":", $_ } split "\n", $mergeinfo_prop;
my $old_minfo = {};
 
-   # Initialize cache on the first call.
-   unless (defined $self->{cached_mergeinfo_rev}) {
-   $self->{cached_mergeinfo_rev} = {};
-   }
-
-   my $cached_rev = $self->{cached_mergeinfo_rev}{$old_path};
-   unless (defined $cached_rev && $cached_rev == $old_rev) {
-   my $ra = $self->ra;
-   # Give up if $old_path isn't in the repo.
-   # This is probably a merge on a subtree.
-   if ($ra->check_path($old_path, $old_rev) != $SVN::Node::dir) {
-   warn "W: ignoring svn:mergeinfo on $old_path, ",
-   "directory didn't exist in r$old_rev\n";
-   return {};
-   }
-   }
-   my (undef, undef, $props) = $self->ra->get_dir($old_path, $old_rev);
+   my $ra = $self->ra;
+   # Give up if $old_path isn't in the repo.
+   # This is probably a merge on a subtree.
+   if ($ra->check_path($old_path, $old_rev) != $SVN::Node::dir) {
+   warn "W: ignoring svn:mergeinfo on $old_path, ",
+   "directory didn't exist in r$old_rev\n";
+   return {};
+   }
+   my (undef, undef, $props) = $ra->get_dir($old_path, $old_rev);
if (defined $props->{"svn:mergeinfo"}) {
my %omi = map {split ":", $_ } split "\n",
$props->{"svn:mergeinfo"};
$old_minfo = \%omi;
}
-   $self->{cached_mergeinfo_rev}{$old_path} = $old_rev;
-
-   # Cache the new mergeinfo.
-   $self->{cached_mergeinfo_rev}{$path} = $rev;
 
my %changes = ();
foreach my $p (keys %minfo) {
-- 
EW
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Bug in fetch-pack causing ever-growing http requests. (Was: git fetch (http) hanging/failing on one specific repository, http only)

2014-10-21 Thread Dennis Kaarsemaker
On ma, 2014-10-20 at 16:29 +0200, Dennis Kaarsemaker wrote:
> Since a few days, one of our repos is causing problems during git fetch,
> basically git fetch over http hangs during find_common. When using ssh,
> this does not happen. 

.

> And for the hanging git-upload-pack:
> #0  0x7f7c8034b4d0 in __write_nocancel () from /lib64/libpthread.so.0
> #1  0x0043c9dc in xwrite (fd=1, buf=0x6c70e0, len=56) at wrapper.c:170
> #2  0x0043ca5b in write_in_full (fd=1, buf=, 
> count=56) at wrapper.c:220
> #3  0x0043d019 in write_or_die (fd=, buf= optimized out>, 
> count=) at write_or_die.c:61
> #4  0x004131fa in packet_write (fd=1, fmt=) at 
> pkt-line.c:93
> #5  0x0040538c in get_common_commits (argc=, 
> argv=0x7fff0001) at upload-pack.c:420
> #6  upload_pack (argc=, argv=0x7fff0001) at 
> upload-pack.c:778
> #7  main (argc=, argv=0x7fff0001) at 
> upload-pack.c:846
> 
> And the hanging git-http-backend:
> #0  0x7f4c9553d4d0 in __write_nocancel () from /lib64/libpthread.so.0
> #1  0x0042d31c in xwrite (fd=4, buf=0x7fff394ea570, len=8192) at 
> wrapper.c:170
> #2  0x0042d39b in write_in_full (fd=4, buf=, 
> count=8192) at wrapper.c:220
> #3  0x00403e5d in inflate_request (prog_name=0x490d98 "upload-pack", 
> out=4) at http-backend.c:305
> #4  0x0040405d in run_service (argv=0x7fff394ee6d0) at 
> http-backend.c:355
> #5  0x004041d2 in service_rpc (service_name=) at 
> http-backend.c:508
> #6  0x00404b35 in main (argc=, argv= optimized out>) at http-backend.c:631
> 
> Both git-http-backend and git-upload-pack are trying to write at the
> same time. I'm *guessing* I've hit some buffer limit here, given that
> the have/ack exchanges are increasing in size and suddenly this one is
> misbehaving. However I have no idea where to look next and would really
> appreciate some help.

I think the reasoning in 44d8dc54e73e8010c4bdf57a422fc8d5ce709029 is
incomplete: there's still a pipe involved in the case of gzip'ed request
bodies, and it's here that it hangs. However, I now do think that this
is merely a symptom, because after inspecting the output a bit further I
noticed that all reponses start with the same lines:

got ack 3 a669f13aab3a2c192c15574ead70f92b303e8aee
got ack 3 360530ff695a4deb01575e85976060a083e17245
got ack 3 bab20d62a5a4c34885cf2acbf83aca91908f9af8

In fact, response N, is the same as response N-1 plus acks for the
commits in the 'have' lines of the debug output for the next request. So
it looks like every request sends all common commits again, which seems
wrong but does explain the ever-growing request size. After commenting
out line 413 in fetch-pack.c (state_len = req_buf.len) the requests and
responses don't increase in size, and fetch completes, though the
received pack seems too large (http response is 400MB), which makes me
think it's not actually ack'ing. Subsequent HTTP fetches don't get a big
pack in response though, so maybe the pack is the right size. THis is a
*very* busy repo with thousands of commits between the last succesful
fetch 5 days ago and the first succesfil fetch after my hack.

In any case, I think there's a bug here, but I don't know nearly enough
about the protocol to judge if my "fix" is even close to correct. I've
also not tested my "fix" with any other protocol yet.

-- 
Dennis Kaarsemaker
http://www.kaarsemaker.net

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] dir.c: remove the second declaration of "stk" in prep_exclude()

2014-10-21 Thread Nguyễn Thái Ngọc Duy
This "stk" shadows the first declaration at the top. There's currently
no bad effect. But let's avoid it.

Signed-off-by: Nguyễn Thái Ngọc Duy 
---
 dir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/dir.c b/dir.c
index bd274a7..3f7a025 100644
--- a/dir.c
+++ b/dir.c
@@ -826,9 +826,9 @@ static void prep_exclude(struct dir_struct *dir, const char 
*base, int baselen)
current = stk ? stk->baselen : -1;
strbuf_setlen(&dir->basebuf, current < 0 ? 0 : current);
while (current < baselen) {
-   struct exclude_stack *stk = xcalloc(1, sizeof(*stk));
const char *cp;
 
+   stk = xcalloc(1, sizeof(*stk));
if (current < 0) {
cp = base;
current = 0;
-- 
2.1.0.rc0.78.gc0d8480

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: Git Help needed

2014-10-21 Thread RaviKiranGoud_Palpanoori
Hi Brian,
My Open SSL vendor is IBM. In fact I am using AIX OS from IBM. When we (Myself 
and Frank. Frank is cc'ed in this email)  discussed with IBM team, they asked 
some details on what flag settings need to be used to recompile, what parameter 
settings they need to do, etc.  IBM team told it is easy to recompile if they 
have provided with the details.

Could you please help us to provide additional details for compilation. Thanks 
in advance.

Regards,
Ravi.

-Original Message-
From: Ravi Kiran Goud Palpanoori 
Sent: Friday, August 01, 2014 5:03 PM
To: 'brian m. carlson'
Cc: git@vger.kernel.org
Subject: RE: Git Help needed

Hi Brian,
Thank you.
Understood OpeSSL and vendor from your original message now.

Thanks,
Ravi.

-Original Message-
From: brian m. carlson [mailto:sand...@crustytoothpaste.net]
Sent: Friday, August 01, 2014 5:00 PM
To: Ravi Kiran Goud Palpanoori
Cc: git@vger.kernel.org
Subject: Re: Git Help needed

On Fri, Aug 01, 2014 at 08:27:24PM +, ravikirangoud_palpano...@vfc.com 
wrote:
> Hi brian,
> Thanks for your quick reply.
> 
> I downloaded git 1.9.0 from the site
> https://code.google.com/p/git-core/downloads/list.

That URL is obsolete.  Try https://www.kernel.org/pub/software/scm/git/
Google Code no longer allows anyone to upload tarballs.

> Does it mean the package available at above location has built with 
> specific version of OpenSSL. How can I find out which OpenSSL version 
> is used in the packages available at the above location.

If you're downloading the source tarball and building it yourself, then it's 
whatever version of OpenSSL is on your system.  To my knowledge, nobody 
provides pre-built packages of git for AIX.

> Could you please suggest the site from where I need to download git 
> for AIX OS.

As I mentioned above, you'll probably need to build it yourself.

> Who are the vendors of git so that I will check how to proceed on this.

When I referred to having your vendor patch the check out, I meant your vendor 
of OpenSSL.

--
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: Urgent Order

2014-10-21 Thread Parker Nick
Hello,

Please send me a price list and quotation for your products we want to import 
from your country this is a very large order for long term import and urgent 
request.

Thank you in advance for your prompt confirmation.
Regards,

Parker Nick

Equipos de Elevaci n , S.A. de C.V.Av. Texcoco #35,
54070 Tlalnepantla , Edo . de M xico
M xico
Tels.+27840117769
Email:nickpar...@hotmail.com
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] fetch-pack: don't resend known-common refs in find_common

2014-10-21 Thread Dennis Kaarsemaker
By not clearing the request buffer in stateless-rpc mode, fetch-pack
would keep sending already known-common commits, leading to ever bigger
http requests, eventually getting too large for git-http-backend to
handle properly without filling up the pipe buffer in inflate_request.
---
I'm still not quite sure whether this is the right thing to do, but make
test still passes :) The new testcase demonstrates the problem, when
running t5551 with EXPENSIVE, this test will hang without the patch to
fetch-pack.c and succeed otherwise.

 fetch-pack.c|  1 -
 t/t5551-http-fetch-smart.sh | 32 
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/fetch-pack.c b/fetch-pack.c
index 655ee64..258245c 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -410,7 +410,6 @@ static int find_common(struct fetch_pack_args *args,
 */
const char *hex = 
sha1_to_hex(result_sha1);
packet_buf_write(&req_buf, 
"have %s\n", hex);
-   state_len = req_buf.len;
}
mark_common(commit, 0, 1);
retval = 0;
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 6cbc12d..2aac237 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -245,5 +245,37 @@ test_expect_success EXPENSIVE 'clone the 50,000 tag repo 
to check OS command lin
)
 '
 
+test_expect_success EXPENSIVE 'create 50,000 more tags' '
+   (
+   cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
+   for i in `test_seq 50001 10`
+   do
+   echo "commit refs/heads/too-many-refs-again"
+   echo "mark :$i"
+   echo "committer git  $i +"
+   echo "data 0"
+   echo "M 644 inline bla.txt"
+   echo "data 4"
+   echo "bla"
+   # make every commit dangling by always
+   # rewinding the branch after each commit
+   echo "reset refs/heads/too-many-refs-again"
+   echo "from :50001"
+   done | git fast-import --export-marks=marks &&
+
+   # now assign tags to all the dangling commits we created above
+   tag=$(perl -e "print \"bla\" x 30") &&
+   sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|" >packed-refs
+   )
+'
+
+test_expect_success EXPENSIVE 'fetch the new tags' '
+   (
+   cd too-many-refs &&
+   git fetch --tags &&
+   test $(git for-each-ref refs/tags | wc -l) = 10
+   )
+'
+
 stop_httpd
 test_done
-- 
2.1.0-245-g26e60d4

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Sources for 3.18-rc1 not uploaded

2014-10-21 Thread Linus Torvalds
On Tue, Oct 21, 2014 at 1:08 AM, Michael J Gruber
 wrote:
>
> Unfortunately, the git archive doc clearly says that the umask is
> applied to all archive entries. And that clearly wasn't the case (for
> extended metadata headers) before Brian's fix.

Hey, it's time for another round of the world-famous "Captain Obvious
Quiz Game"! Yay!

The questions these week are:

 (1) "If reality and documentation do not match, where is the bug?"
(a) Documentation is buggy
(b) Reality is buggy

 (2) "Where would you put the horse in relationship to a horse-drawn carriage?"
(a) in front
(b) in the carriage

Now, if you answered (a) to both these questions, and had this been a
real quiz show, you might have been a winner and the happy new owner
of a remote-controlled four-slice toaster with a fancy digital timer.

Sadly, this was just a dry-run for the real thing, to give people a
quick taste of the world-famous "Captain Obvious Quiz Game". I hope
you tune in next week for our exciting all-new questions.

   Linus
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git reflog --date

2014-10-21 Thread Junio C Hamano
John Tapsell  writes:

> Hi all,
>
>   Could we add a default to "--date" so that:
>
> git reflog --date
>
> just works?  (Currently you need to do:   git reflog --date=iso)  It
> should probably obey the default in log.date?

Hmph.  "--date=

Re: Sources for 3.18-rc1 not uploaded

2014-10-21 Thread David Kastrup
Linus Torvalds  writes:

> On Tue, Oct 21, 2014 at 1:08 AM, Michael J Gruber
>  wrote:
>>
>> Unfortunately, the git archive doc clearly says that the umask is
>> applied to all archive entries. And that clearly wasn't the case (for
>> extended metadata headers) before Brian's fix.
>
> Hey, it's time for another round of the world-famous "Captain Obvious
> Quiz Game"! Yay!
>
> The questions these week are:
>
>  (1) "If reality and documentation do not match, where is the bug?"
> (a) Documentation is buggy
> (b) Reality is buggy
>
>  (2) "Where would you put the horse in relationship to a horse-drawn 
> carriage?"
> (a) in front
> (b) in the carriage

You are aware that a buggy _is_ a horse-drawn carriage?

-- 
Captain Facepalm
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git reflog --date

2014-10-21 Thread John Tapsell
For me, writing "git reflog @{now}"  is a lot less intuitive than "git
reflog --date"

Currently the top google search for this question is here:

http://stackoverflow.com/questions/17369254/is-there-a-way-to-cause-git-reflog-to-show-a-date-alongside-each-entry

Which doesn't mention "@{now}"   at all.

My opinion:

1. Add --date   as an option to reflog.  Perhaps using the log.date
format as the default.
2. Document --date in the man page for "git reflog"
3. Document @{now}  in the man page for "git reflog"

Sound good?

John

On 21 October 2014 18:24, Junio C Hamano  wrote:
> John Tapsell  writes:
>
>> Hi all,
>>
>>   Could we add a default to "--date" so that:
>>
>> git reflog --date
>>
>> just works?  (Currently you need to do:   git reflog --date=iso)  It
>> should probably obey the default in log.date?
>
> Hmph.  "--date=

Re: [PATCH] fetch-pack: don't resend known-common refs in find_common

2014-10-21 Thread Junio C Hamano
Dennis Kaarsemaker  writes:

> By not clearing the request buffer in stateless-rpc mode, fetch-pack
> would keep sending already known-common commits, leading to ever bigger
> http requests, eventually getting too large for git-http-backend to
> handle properly without filling up the pipe buffer in inflate_request.
> ---
> I'm still not quite sure whether this is the right thing to do, but make
> test still passes :) The new testcase demonstrates the problem, when
> running t5551 with EXPENSIVE, this test will hang without the patch to
> fetch-pack.c and succeed otherwise.

IIUC, because "stateless" is just that, i.e. the server-end does not
keep track of what is already known, not telling what is known to be
common in each request would fundamentally break the protocol.  Am I
mistaken?


>  fetch-pack.c|  1 -
>  t/t5551-http-fetch-smart.sh | 32 
>  2 files changed, 32 insertions(+), 1 deletion(-)
>
> diff --git a/fetch-pack.c b/fetch-pack.c
> index 655ee64..258245c 100644
> --- a/fetch-pack.c
> +++ b/fetch-pack.c
> @@ -410,7 +410,6 @@ static int find_common(struct fetch_pack_args *args,
>*/
>   const char *hex = 
> sha1_to_hex(result_sha1);
>   packet_buf_write(&req_buf, 
> "have %s\n", hex);
> - state_len = req_buf.len;
>   }
>   mark_common(commit, 0, 1);
>   retval = 0;
> diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
> index 6cbc12d..2aac237 100755
> --- a/t/t5551-http-fetch-smart.sh
> +++ b/t/t5551-http-fetch-smart.sh
> @@ -245,5 +245,37 @@ test_expect_success EXPENSIVE 'clone the 50,000 tag repo 
> to check OS command lin
>   )
>  '
>  
> +test_expect_success EXPENSIVE 'create 50,000 more tags' '
> + (
> + cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
> + for i in `test_seq 50001 10`
> + do
> + echo "commit refs/heads/too-many-refs-again"
> + echo "mark :$i"
> + echo "committer git  $i +"
> + echo "data 0"
> + echo "M 644 inline bla.txt"
> + echo "data 4"
> + echo "bla"
> + # make every commit dangling by always
> + # rewinding the branch after each commit
> + echo "reset refs/heads/too-many-refs-again"
> + echo "from :50001"
> + done | git fast-import --export-marks=marks &&
> +
> + # now assign tags to all the dangling commits we created above
> + tag=$(perl -e "print \"bla\" x 30") &&
> + sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|"  >>packed-refs
> + )
> +'
> +
> +test_expect_success EXPENSIVE 'fetch the new tags' '
> + (
> + cd too-many-refs &&
> + git fetch --tags &&
> + test $(git for-each-ref refs/tags | wc -l) = 10
> + )
> +'
> +
>  stop_httpd
>  test_done
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git reflog --date

2014-10-21 Thread Junio C Hamano
John Tapsell  writes:

> For me, writing "git reflog @{now}"  is a lot less intuitive than "git
> reflog --date"
>
> Currently the top google search for this question is here:
>
> http://stackoverflow.com/questions/17369254/is-there-a-way-to-cause-git-reflog-to-show-a-date-alongside-each-entry
>
> Which doesn't mention "@{now}"   at all.

I would say that a site where cluelesses attempt to lead other
cluelesses is not the best source of information ;-), but that tells
us that either our docs are not read by people or they do not give
necessary information to them clearly enough.

> My opinion:
>
> 1. Add --date   as an option to reflog.  Perhaps using the log.date
> format as the default.
> 2. Document --date in the man page for "git reflog"
> 3. Document @{now}  in the man page for "git reflog"
>
> Sound good?

The order of changes is questionable, but other than that, I think
that would be a good way forward.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git reflog --date

2014-10-21 Thread John Tapsell
Great - now I just need to persuade someone very nice nicely.. :-)

On 21 October 2014 19:06, Junio C Hamano  wrote:
> John Tapsell  writes:
>
>> For me, writing "git reflog @{now}"  is a lot less intuitive than "git
>> reflog --date"
>>
>> Currently the top google search for this question is here:
>>
>> http://stackoverflow.com/questions/17369254/is-there-a-way-to-cause-git-reflog-to-show-a-date-alongside-each-entry
>>
>> Which doesn't mention "@{now}"   at all.
>
> I would say that a site where cluelesses attempt to lead other
> cluelesses is not the best source of information ;-), but that tells
> us that either our docs are not read by people or they do not give
> necessary information to them clearly enough.
>
>> My opinion:
>>
>> 1. Add --date   as an option to reflog.  Perhaps using the log.date
>> format as the default.
>> 2. Document --date in the man page for "git reflog"
>> 3. Document @{now}  in the man page for "git reflog"
>>
>> Sound good?
>
> The order of changes is questionable, but other than that, I think
> that would be a good way forward.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Sources for 3.18-rc1 not uploaded

2014-10-21 Thread Junio C Hamano
Michael J Gruber  writes:

> Unfortunately, the git archive doc clearly says that the umask is
> applied to all archive entries.

Is an extended pax header "an archive entry"?  I doubt it, and the
above is not relevant.  The mode bits for the archive entry that it
applies to does not come from there.

See my other message for my final judgement on this one.  I wouldn't
have minded if the original used the same umask for those ignored
mode bits, but changing the bits to be ignored after the fact is not
helping any real use case and only hurts existing users.

That is not to say that we cannot later fix bigger issues in the
output.  I just do not see that otherwise-unused mode bits in the
extended pax header big enough an issue to spend brain cycles to
carefully lay and execute transition plans to avoid breaking
existing users.

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] Copy mergetool "bc3" as "bc4"

2014-10-21 Thread Junio C Hamano
David Aguilar  writes:

> Otherwise, this patch looks like the right way to go ~ it makes
> "bc" available and keeps compatibility for "bc3".

OK, thanks.  Here is what I'll queue.

-- >8 --
From: Junio C Hamano 
Date: Mon, 20 Oct 2014 15:49:36 -0700
Subject: [PATCH] mergetool: rename bc3 to bc

Beyond Compare version 4 works the same way as version 3, so rename
the existing "bc3" adaptor to just "bc", while keeping "bc3" as a
backward compatible wrapper.

Noticed-by: Olivier Croquette 
Helped-by: David Aguilar 
Signed-off-by: Junio C Hamano 
---
 contrib/completion/git-completion.bash |  2 +-
 git-mergetool--lib.sh  |  2 +-
 mergetools/bc  | 25 +
 mergetools/bc3 | 26 +-
 4 files changed, 28 insertions(+), 27 deletions(-)
 create mode 100644 mergetools/bc

diff --git a/contrib/completion/git-completion.bash 
b/contrib/completion/git-completion.bash
index 06bf262..8a19b3e 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -1207,7 +1207,7 @@ _git_diff ()
 }
 
 __git_mergetools_common="diffuse diffmerge ecmerge emerge kdiff3 meld opendiff
-   tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc3 
codecompare
+   tkdiff vimdiff gvimdiff xxdiff araxis p4merge bc 
codecompare
 "
 
 _git_difftool ()
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index c45a020..a40d3df 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -250,7 +250,7 @@ list_merge_tool_candidates () {
tools="opendiff kdiff3 tkdiff xxdiff meld $tools"
fi
tools="$tools gvimdiff diffuse diffmerge ecmerge"
-   tools="$tools p4merge araxis bc3 codecompare"
+   tools="$tools p4merge araxis bc codecompare"
fi
case "${VISUAL:-$EDITOR}" in
*vim*)
diff --git a/mergetools/bc b/mergetools/bc
new file mode 100644
index 000..b6319d2
--- /dev/null
+++ b/mergetools/bc
@@ -0,0 +1,25 @@
+diff_cmd () {
+   "$merge_tool_path" "$LOCAL" "$REMOTE"
+}
+
+merge_cmd () {
+   touch "$BACKUP"
+   if $base_present
+   then
+   "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
+   -mergeoutput="$MERGED"
+   else
+   "$merge_tool_path" "$LOCAL" "$REMOTE" \
+   -mergeoutput="$MERGED"
+   fi
+   check_unchanged
+}
+
+translate_merge_tool_path() {
+   if type bcomp >/dev/null 2>/dev/null
+   then
+   echo bcomp
+   else
+   echo bcompare
+   fi
+}
diff --git a/mergetools/bc3 b/mergetools/bc3
index b6319d2..5d8dd48 100644
--- a/mergetools/bc3
+++ b/mergetools/bc3
@@ -1,25 +1 @@
-diff_cmd () {
-   "$merge_tool_path" "$LOCAL" "$REMOTE"
-}
-
-merge_cmd () {
-   touch "$BACKUP"
-   if $base_present
-   then
-   "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" \
-   -mergeoutput="$MERGED"
-   else
-   "$merge_tool_path" "$LOCAL" "$REMOTE" \
-   -mergeoutput="$MERGED"
-   fi
-   check_unchanged
-}
-
-translate_merge_tool_path() {
-   if type bcomp >/dev/null 2>/dev/null
-   then
-   echo bcomp
-   else
-   echo bcompare
-   fi
-}
+. "$MERGE_TOOLS_DIR/bc"
-- 
2.1.2-583-g325e495

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Sources for 3.18-rc1 not uploaded

2014-10-21 Thread Junio C Hamano
Konstantin Ryabitsev  writes:

> On 20/10/14 06:28 PM, brian m. carlson wrote:
>>> Junio, quite frankly, I don't think that that fix was a good idea. I'd
>>> > suggest having a *separate* umask for the pax headers, so that we do
>>> > not  break this long-lasting stability of "git archive" output in ways
>>> > that are unfixable and not compatible. kernel.org has relied (for a
>>> > *long* time) on being able to just upload the signature of the
>>> > resulting tar-file, because both sides can generate the same tar-fiel
>>> > bit-for-bit.
>> It sounds like kernel.org has a bug, then.  Perhaps that's the
>> appropriate place to fix the issue.
>
> It's not a bug, it's a feature (TM). KUP relies on git-archive's ability
> to create identical tar archives across platforms and versions. The
> benefit is that Linus or Greg can create a detached PGP signature
> against a tarball created from "git archive [tag]" on their system, and
> just tell kup to create the same archive remotely, thus saving them the
> trouble of uploading 80Mb each time they cut a release.
>
> With their frequent travel to places where upload bandwidth is both slow
> and unreliable, this ability to not have to upload hundreds of Mbs each
> time they cut a release is very handy and certainly helps keep kernel
> releases on schedule.
>
> So, while it's fair to point out that git-archive was never intended to
> always create bit-for-bit identical outputs, it would be *very nice* if
> this remained in place, as at least one large-ish deployment (us) finds
> it really handy.

While I agree that it is a nice "feature", I wish KUP folks thought
more about what should happen when the archive output _must_ change
when a more serious bug is discovered, and coordinated with us
better.

During a period where older and buggy versions of "git archive" are
used by some uploaders while a new version is used by others, KUP
could:

 - avail itself to a version (or versions) of "git archive" so that
   it can recreate both older and newer output;

 - upon receiving a tarball and signature, try recreating newer
   output and see if signature matches, and when the signature does
   not match, recreate older output and try again.

And we could supply "git archive --compatible=v1.7" option in the
newer version if that is easier on KUP folks than having to keep
multiple installations of versions of "git archive" around.

While I am on the topic of KUP, one feature I wish, which is the
only thing that is preventing me from updating the preformatted
documentation https://www.kernel.org/pub/software/scm/git/docs/, is
to allow me to upload a single tarball and extract it at one
location (e.g. /pub/software/scm/git/docs/) while removing existing
files in that location (i.e. removing deleted files).  Where do I
file such a feature request?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] grep: fix match highlighting for combined patterns with context lines

2014-10-21 Thread Junio C Hamano
Zoltan Klinger  writes:

> When git grep is run with combined patterns such as '-e p1 --and -e p2'
> and surrounding context lines are requested, the output contains
> incorrectly highlighted matches.
>
> Consider the following output (highlighted matches are surrounded by '*'
> characters):
> $ cat testfile
> foo a
> foo b
> foo bar
> baz bar foo
> bar x
> bar y
> $ git grep -n -C2 -e foo --and -e bar testfile
> testfile-1-*foo* a
> testfile-2-*foo* b
> testfile:3:*foo* *bar*
> testfile:4:baz *bar* *foo*
> testfile-5-*bar* x
> testfile-6-*bar* y
>
> Lines 1, 2, 5 and 6 do not match the combined patterns, they only
> contain incorrectly highlighted 'false positives'.
>
> Modify the show_line() function in grep.c to highlight matches only on
> lines that match the combined pattern. Do not highlight matches on lines
> that provide only context or contain only the function name of the match.
>
> The output of the same command after the change:
> $ git grep -n -C2 -e foo --and -e bar testfile
> testfile-1-foo a
> testfile-2-foo b
> testfile:3:*foo* *bar*
> testfile:4:baz *bar* *foo*
> testfile-5-bar x
> testfile-6-bar y

If your goal is to stop colouring words on context and other kinds
of lines, do you still need the "while (next_match(...))" loop for
them?  Can't you make the resulting code clearer by restructuring
the inside of the whole "if (opt->color)" block further, something
along the lines of...

if (sign != ':') {
regmatch_t match; ...
enum grep_context ctx = GREP_CONTEXT_BODY;
...
while (next_match(...)) {
... the "word-by-word" loop ...
}
} else {
switch (sign) {
case '-':
line_color = opt->color_context;
break;
case ':':
line_color = opt->color_function;
break;
}
output_color(opt, bol, ..., line_color);
}

Hmm?
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/15] refs.c: add a flag to allow reflog updates to truncate the log

2014-10-21 Thread Ronnie Sahlberg
commit 8d0a342375fbd926ae6ae93f9be42a436a787fb6 upstream.

Add a flag that allows us to truncate the reflog before we write the
update.

Change-Id: I187b22e0910499b1976689b46866698b6fd46eb3
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 17 +++--
 refs.h | 10 +-
 2 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/refs.c b/refs.c
index 100b3a3..d54c3b9 100644
--- a/refs.c
+++ b/refs.c
@@ -3873,7 +3873,12 @@ int transaction_commit(struct transaction *transaction,
}
}
 
-   /* Update all reflog files */
+   /*
+* Update all reflog files
+* We have already done all ref updates and deletes.
+* There is not much we can do here if there are any reflog
+* update errors other than complain.
+*/
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
@@ -3881,7 +3886,15 @@ int transaction_commit(struct transaction *transaction,
continue;
if (update->reflog_fd == -1)
continue;
-
+   if (update->flags & REFLOG_TRUNCATE)
+   if (lseek(update->reflog_fd, 0, SEEK_SET) < 0 ||
+   ftruncate(update->reflog_fd, 0)) {
+   error("Could not truncate reflog: %s. %s",
+ update->refname, strerror(errno));
+   rollback_lock_file(&update->reflog_lock);
+   update->reflog_fd = -1;
+   continue;
+   }
if (log_ref_write_fd(update->reflog_fd, update->old_sha1,
 update->new_sha1,
 update->committer, update->msg)) {
diff --git a/refs.h b/refs.h
index 8220d18..5075073 100644
--- a/refs.h
+++ b/refs.h
@@ -328,7 +328,15 @@ int transaction_delete_ref(struct transaction *transaction,
   struct strbuf *err);
 
 /*
- * Append a reflog entry for refname.
+ * Flags controlling transaction_update_reflog().
+ * REFLOG_TRUNCATE: Truncate the reflog.
+ *
+ * Flags >= 0x100 are reserved for internal use.
+ */
+#define REFLOG_TRUNCATE 0x01
+/*
+ * Append a reflog entry for refname. If the REFLOG_TRUNCATE flag is set
+ * this update will first truncate the reflog before writing the entry.
  */
 int transaction_update_reflog(struct transaction *transaction,
  const char *refname,
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 07/15] refs.c: add a transaction function to append a reflog entry

2014-10-21 Thread Ronnie Sahlberg
commit de045215a52a6a9591b0e786488de2293d79d245 upstream.

Define a new transaction update type, UPDATE_LOG, and a new function
transaction_update_reflog. This function will lock the reflog and append
an entry to it during transaction commit.

Change-Id: I8cc935ef311688d561d447fa51b44ac98492693b
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 102 +++--
 refs.h |  12 
 2 files changed, 112 insertions(+), 2 deletions(-)

diff --git a/refs.c b/refs.c
index 0e11b1c..100b3a3 100644
--- a/refs.c
+++ b/refs.c
@@ -3517,7 +3517,8 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
 }
 
 enum transaction_update_type {
-   UPDATE_SHA1 = 0
+   UPDATE_SHA1 = 0,
+   UPDATE_LOG = 1
 };
 
 /**
@@ -3535,6 +3536,12 @@ struct ref_update {
struct ref_lock *lock;
int type;
char *msg;
+
+   /* used by reflog updates */
+   int reflog_fd;
+   struct lock_file reflog_lock;
+   char *committer;
+
const char refname[FLEX_ARRAY];
 };
 
@@ -3581,6 +3588,7 @@ void transaction_free(struct transaction *transaction)
 
for (i = 0; i < transaction->nr; i++) {
free(transaction->updates[i]->msg);
+   free(transaction->updates[i]->committer);
free(transaction->updates[i]);
}
free(transaction->updates);
@@ -3601,6 +3609,41 @@ static struct ref_update *add_update(struct transaction 
*transaction,
return update;
 }
 
+int transaction_update_reflog(struct transaction *transaction,
+ const char *refname,
+ const unsigned char *new_sha1,
+ const unsigned char *old_sha1,
+ const unsigned char *email,
+ unsigned long timestamp, int tz,
+ const char *msg, int flags,
+ struct strbuf *err)
+{
+   struct ref_update *update;
+
+   if (transaction->state != TRANSACTION_OPEN)
+   die("BUG: update_reflog called for transaction that is not 
open");
+
+   update = add_update(transaction, refname, UPDATE_LOG);
+   hashcpy(update->new_sha1, new_sha1);
+   hashcpy(update->old_sha1, old_sha1);
+   update->reflog_fd = -1;
+   if (email) {
+   struct strbuf buf = STRBUF_INIT;
+   char sign = (tz < 0) ? '-' : '+';
+   int zone = (tz < 0) ? (-tz) : tz;
+
+   strbuf_addf(&buf, "%s %lu %c%04d", email, timestamp, sign,
+   zone);
+   update->committer = xstrdup(buf.buf);
+   strbuf_release(&buf);
+   }
+   if (msg)
+   update->msg = xstrdup(msg);
+   update->flags = flags;
+
+   return 0;
+}
+
 int transaction_update_ref(struct transaction *transaction,
   const char *refname,
   const unsigned char *new_sha1,
@@ -3773,7 +3816,28 @@ int transaction_commit(struct transaction *transaction,
}
}
 
-   /* Perform updates first so live commits remain referenced */
+   /* Lock all reflog files */
+   for (i = 0; i < n; i++) {
+   struct ref_update *update = updates[i];
+
+   if (update->update_type != UPDATE_LOG)
+   continue;
+   update->reflog_fd = hold_lock_file_for_append(
+   &update->reflog_lock,
+   git_path("logs/%s", update->refname),
+   0);
+   if (update->reflog_fd < 0) {
+   const char *str = "Cannot lock reflog for '%s'. %s";
+
+   ret = -1;
+   if (err)
+   strbuf_addf(err, str, update->refname,
+   strerror(errno));
+   goto cleanup;
+   }
+   }
+
+   /* Perform ref updates first so live commits remain referenced */
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
@@ -3809,6 +3873,40 @@ int transaction_commit(struct transaction *transaction,
}
}
 
+   /* Update all reflog files */
+   for (i = 0; i < n; i++) {
+   struct ref_update *update = updates[i];
+
+   if (update->update_type != UPDATE_LOG)
+   continue;
+   if (update->reflog_fd == -1)
+   continue;
+
+   if (log_ref_write_fd(update->reflog_fd, update->old_sha1,
+update->new_sha1,
+update->committer, update->msg)) {
+   error("Could write to reflog: %s. %s",
+ update->refname, strerror(errno));
+   roll

[PATCH 04/15] refs.c: add a new update_type field to ref_update

2014-10-21 Thread Ronnie Sahlberg
commit 1bfd3091a3d95a6268894182117eed823217dd9d upstream.

Add a field that describes what type of update this refers to. For now
the only type is UPDATE_SHA1 but we will soon add more types.

Change-Id: I9bf76454d1c789877a6aeb360cbb309971c9b5c4
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 27 +++
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index a1bfaa2..8803b95 100644
--- a/refs.c
+++ b/refs.c
@@ -3504,6 +3504,10 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
return retval;
 }
 
+enum transaction_update_type {
+   UPDATE_SHA1 = 0
+};
+
 /**
  * Information needed for a single ref update.  Set new_sha1 to the
  * new value or to zero to delete the ref.  To check the old value
@@ -3511,6 +3515,7 @@ int for_each_reflog(each_ref_fn fn, void *cb_data)
  * value or to zero to ensure the ref does not exist before update.
  */
 struct ref_update {
+   enum transaction_update_type update_type;
unsigned char new_sha1[20];
unsigned char old_sha1[20];
int flags; /* REF_NODEREF? */
@@ -3571,12 +3576,14 @@ void transaction_free(struct transaction *transaction)
 }
 
 static struct ref_update *add_update(struct transaction *transaction,
-const char *refname)
+const char *refname,
+enum transaction_update_type update_type)
 {
size_t len = strlen(refname);
struct ref_update *update = xcalloc(1, sizeof(*update) + len + 1);
 
strcpy((char *)update->refname, refname);
+   update->update_type = update_type;
ALLOC_GROW(transaction->updates, transaction->nr + 1, 
transaction->alloc);
transaction->updates[transaction->nr++] = update;
return update;
@@ -3606,7 +3613,7 @@ int transaction_update_ref(struct transaction 
*transaction,
return -1;
}
 
-   update = add_update(transaction, refname);
+   update = add_update(transaction, refname, UPDATE_SHA1);
hashcpy(update->new_sha1, new_sha1);
update->flags = flags;
update->have_old = have_old;
@@ -3684,13 +3691,17 @@ static int ref_update_reject_duplicates(struct 
ref_update **updates, int n,
 
assert(err);
 
-   for (i = 1; i < n; i++)
+   for (i = 1; i < n; i++) {
+   if (updates[i - 1]->update_type != UPDATE_SHA1 ||
+   updates[i]->update_type != UPDATE_SHA1)
+   continue;
if (!strcmp(updates[i - 1]->refname, updates[i]->refname)) {
strbuf_addf(err,
"Multiple updates for ref '%s' not 
allowed.",
updates[i]->refname);
return 1;
}
+   }
return 0;
 }
 
@@ -3722,13 +3733,17 @@ int transaction_commit(struct transaction *transaction,
goto cleanup;
}
 
-   /* Acquire all locks while verifying old values */
+   /* Acquire all ref locks while verifying old values */
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
int flags = update->flags;
 
+   if (update->update_type != UPDATE_SHA1)
+   continue;
+
if (is_null_sha1(update->new_sha1))
flags |= REF_DELETING;
+
update->lock = lock_ref_sha1_basic(update->refname,
   (update->have_old ?
update->old_sha1 :
@@ -3750,6 +3765,8 @@ int transaction_commit(struct transaction *transaction,
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
+   if (update->update_type != UPDATE_SHA1)
+   continue;
if (!is_null_sha1(update->new_sha1)) {
if (write_ref_sha1(update->lock, update->new_sha1,
   update->msg)) {
@@ -3767,6 +3784,8 @@ int transaction_commit(struct transaction *transaction,
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
+   if (update->update_type != UPDATE_SHA1)
+   continue;
if (update->lock) {
if (delete_ref_loose(update->lock, update->type, err)) {
ret = TRANSACTION_GENERIC_ERROR;
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 12/15] refs.c: rename log_ref_setup to create_reflog

2014-10-21 Thread Ronnie Sahlberg
commit 8f78d5d7a1e62f04c75524bb3e87aaad24372250 upstream.

log_ref_setup is used to do several semi-related things :
* sometimes it will create a new reflog including missing parent directories
  and cleaning up any conflicting stale directories in the path.
* fill in a filename buffer for the full path to the reflog.
* unconditionally re-adjust the permissions for the file.

This function is only called from two places: checkout.c where it is always
used to create a reflog and refs.c:log_ref_write where it sometimes are
used to create a reflog and sometimes just used to fill in the filename.

Rename log_ref_setup to create_reflog and change it to only take the
refname as argument to make its signature similar to delete_reflog and
reflog_exists. Change create_reflog to ignore log_all_ref_updates and
"unconditionally" create the reflog when called. Since checkout.c always
wants to create a reflog we can call create_reflog directly and avoid the
temp-and-log_all_ref_update dance.

In log_ref_write, only call create_reflog iff we want to create a reflog
and if the reflog does not yet exist. This means that for the common case
where the log already exists we now only need to perform a single lstat()
instead of a open(O_CREAT)+lstat()+close().

Change-Id: Ib9493b3b81a97a0e154cc44303a5ed7cdceaaca7
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 builtin/checkout.c |  8 +---
 refs.c | 22 +-
 refs.h |  8 +++-
 3 files changed, 17 insertions(+), 21 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 5410dac..8550b6d 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -587,19 +587,13 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
if (opts->new_branch) {
if (opts->new_orphan_branch) {
if (opts->new_branch_log && !log_all_ref_updates) {
-   int temp;
-   char log_file[PATH_MAX];
char *ref_name = mkpath("refs/heads/%s", 
opts->new_orphan_branch);
 
-   temp = log_all_ref_updates;
-   log_all_ref_updates = 1;
-   if (log_ref_setup(ref_name, log_file, 
sizeof(log_file))) {
+   if (create_reflog(ref_name)) {
fprintf(stderr, _("Can not do reflog 
for '%s'\n"),
opts->new_orphan_branch);
-   log_all_ref_updates = temp;
return;
}
-   log_all_ref_updates = temp;
}
}
else
diff --git a/refs.c b/refs.c
index 3189f11..952cc66 100644
--- a/refs.c
+++ b/refs.c
@@ -2947,16 +2947,16 @@ static int copy_msg(char *buf, const char *msg)
 }
 
 /* This function must set a meaningful errno on failure */
-int log_ref_setup(const char *refname, char *logfile, int bufsize)
+int create_reflog(const char *refname)
 {
int logfd, oflags = O_APPEND | O_WRONLY;
+   char logfile[PATH_MAX];
 
-   git_snpath(logfile, bufsize, "logs/%s", refname);
-   if (log_all_ref_updates &&
-   (starts_with(refname, "refs/heads/") ||
-starts_with(refname, "refs/remotes/") ||
-starts_with(refname, "refs/notes/") ||
-!strcmp(refname, "HEAD"))) {
+   git_snpath(logfile, sizeof(logfile), "logs/%s", refname);
+   if (starts_with(refname, "refs/heads/") ||
+   starts_with(refname, "refs/remotes/") ||
+   starts_with(refname, "refs/notes/") ||
+   !strcmp(refname, "HEAD")) {
if (safe_create_leading_directories(logfile) < 0) {
int save_errno = errno;
error("unable to create directory for %s", logfile);
@@ -3025,16 +3025,20 @@ static int log_ref_write_fd(int fd, const unsigned char 
*old_sha1,
 static int log_ref_write(const char *refname, const unsigned char *old_sha1,
 const unsigned char *new_sha1, const char *msg)
 {
-   int logfd, result, oflags = O_APPEND | O_WRONLY;
+   int logfd, result = 0, oflags = O_APPEND | O_WRONLY;
char log_file[PATH_MAX];
 
if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository();
 
-   result = log_ref_setup(refname, log_file, sizeof(log_file));
+   if (log_all_ref_updates && !reflog_exists(refname))
+   result = create_reflog(refname);
+
if (result)
return result;
 
+   git_snpath(log_file, sizeof(log_file), "logs/%s", refname);
+
logfd = open(log_file, oflags);
if (logfd < 0)
return 0;
diff --git a/refs.h b/refs.h
index 9f70b89..17e3a3c 100644
--- a/refs.h
+++ b/refs.h
@@ -207,11 +207,6 @@

[PATCH 01/15] refs.c make ref_transaction_create a wrapper to ref_transaction_update

2014-10-21 Thread Ronnie Sahlberg
commit 03001144a015f81db5252005841bb78f57d62774 upstream.

The ref_transaction_update function can already be used to create refs by
passing null_sha1 as the old_sha1 parameter. Simplify by replacing
transaction_create with a thin wrapper.

Change-Id: I687dd47cc4f4e06766e8313b4fd1b07cd4a56c1a
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 27 ++-
 1 file changed, 2 insertions(+), 25 deletions(-)

diff --git a/refs.c b/refs.c
index 0368ed4..ed0485e 100644
--- a/refs.c
+++ b/refs.c
@@ -3623,31 +3623,8 @@ int ref_transaction_create(struct ref_transaction 
*transaction,
   int flags, const char *msg,
   struct strbuf *err)
 {
-   struct ref_update *update;
-
-   assert(err);
-
-   if (transaction->state != REF_TRANSACTION_OPEN)
-   die("BUG: create called for transaction that is not open");
-
-   if (!new_sha1 || is_null_sha1(new_sha1))
-   die("BUG: create ref with null new_sha1");
-
-   if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
-   strbuf_addf(err, "refusing to create ref with bad name %s",
-   refname);
-   return -1;
-   }
-
-   update = add_update(transaction, refname);
-
-   hashcpy(update->new_sha1, new_sha1);
-   hashclr(update->old_sha1);
-   update->flags = flags;
-   update->have_old = 1;
-   if (msg)
-   update->msg = xstrdup(msg);
-   return 0;
+   return ref_transaction_update(transaction, refname, new_sha1,
+ null_sha1, flags, 1, msg, err);
 }
 
 int ref_transaction_delete(struct ref_transaction *transaction,
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 13/15] refs.c: make unlock_ref/close_ref/commit_ref static

2014-10-21 Thread Ronnie Sahlberg
commit a4369f77d1975566bcd29bfa46720d48372c241d upstream.

unlock|close|commit_ref can be made static since there are no more external
callers.

Change-Id: I743f9daaa1c101fdc781a76283c2e8b462591d07
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 24 
 refs.h |  9 -
 2 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/refs.c b/refs.c
index 952cc66..5e5f066 100644
--- a/refs.c
+++ b/refs.c
@@ -2096,6 +2096,16 @@ int refname_match(const char *abbrev_name, const char 
*full_name)
return 0;
 }
 
+static void unlock_ref(struct ref_lock *lock)
+{
+   /* Do not free lock->lk -- atexit() still looks at them */
+   if (lock->lk)
+   rollback_lock_file(lock->lk);
+   free(lock->ref_name);
+   free(lock->orig_ref_name);
+   free(lock);
+}
+
 /* This function should make sure errno is meaningful on error */
 static struct ref_lock *verify_lock(struct ref_lock *lock,
const unsigned char *old_sha1, int mustexist)
@@ -2894,7 +2904,7 @@ int rename_ref(const char *oldrefname, const char 
*newrefname, const char *logms
return 1;
 }
 
-int close_ref(struct ref_lock *lock)
+static int close_ref(struct ref_lock *lock)
 {
if (close_lock_file(lock->lk))
return -1;
@@ -2902,7 +2912,7 @@ int close_ref(struct ref_lock *lock)
return 0;
 }
 
-int commit_ref(struct ref_lock *lock)
+static int commit_ref(struct ref_lock *lock)
 {
if (commit_lock_file(lock->lk))
return -1;
@@ -2910,16 +2920,6 @@ int commit_ref(struct ref_lock *lock)
return 0;
 }
 
-void unlock_ref(struct ref_lock *lock)
-{
-   /* Do not free lock->lk -- atexit() still looks at them */
-   if (lock->lk)
-   rollback_lock_file(lock->lk);
-   free(lock->ref_name);
-   free(lock->orig_ref_name);
-   free(lock);
-}
-
 /*
  * copy the reflog message msg to buf, which has been allocated sufficiently
  * large, while cleaning up the whitespaces.  Especially, convert LF to space,
diff --git a/refs.h b/refs.h
index 17e3a3c..025e2cb 100644
--- a/refs.h
+++ b/refs.h
@@ -198,15 +198,6 @@ extern struct ref_lock *lock_any_ref_for_update(const char 
*refname,
const unsigned char *old_sha1,
int flags, int *type_p);
 
-/** Close the file descriptor owned by a lock and return the status */
-extern int close_ref(struct ref_lock *lock);
-
-/** Close and commit the ref locked by the lock */
-extern int commit_ref(struct ref_lock *lock);
-
-/** Release any lock taken but not written. **/
-extern void unlock_ref(struct ref_lock *lock);
-
 /** Reads log for the value of ref during at_time. **/
 extern int read_ref_at(const char *refname, unsigned int flags,
   unsigned long at_time, int cnt,
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/15] refs.c: add a function to append a reflog entry to a fd

2014-10-21 Thread Ronnie Sahlberg
commit 07baa71eda8d1047f003acc7ea32ad6b6600b179 upstream.

Break out the code to create the string and writing it to the file
descriptor from log_ref_write and into a dedicated function log_ref_write_fd.
For now this is only used from log_ref_write but later on we will call
this function from reflog transactions too which means that we will end
up with only a single place where we write a reflog entry to a file instead
of the current two places (log_ref_write and builtin/reflog.c).

Change-Id: I178e84a52af18c800844596af33dbc21bc076c1f
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 48 ++--
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/refs.c b/refs.c
index 8803b95..0e11b1c 100644
--- a/refs.c
+++ b/refs.c
@@ -2990,15 +2990,37 @@ int log_ref_setup(const char *refname, char *logfile, 
int bufsize)
return 0;
 }
 
+static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
+   const unsigned char *new_sha1,
+   const char *committer, const char *msg)
+{
+   int msglen, written;
+   unsigned maxlen, len;
+   char *logrec;
+
+   msglen = msg ? strlen(msg) : 0;
+   maxlen = strlen(committer) + msglen + 100;
+   logrec = xmalloc(maxlen);
+   len = sprintf(logrec, "%s %s %s\n",
+ sha1_to_hex(old_sha1),
+ sha1_to_hex(new_sha1),
+ committer);
+   if (msglen)
+   len += copy_msg(logrec + len - 1, msg) - 1;
+
+   written = len <= maxlen ? write_in_full(fd, logrec, len) : -1;
+   free(logrec);
+   if (written != len)
+   return -1;
+
+   return 0;
+}
+
 static int log_ref_write(const char *refname, const unsigned char *old_sha1,
 const unsigned char *new_sha1, const char *msg)
 {
-   int logfd, result, written, oflags = O_APPEND | O_WRONLY;
-   unsigned maxlen, len;
-   int msglen;
+   int logfd, result, oflags = O_APPEND | O_WRONLY;
char log_file[PATH_MAX];
-   char *logrec;
-   const char *committer;
 
if (log_all_ref_updates < 0)
log_all_ref_updates = !is_bare_repository();
@@ -3010,19 +3032,9 @@ static int log_ref_write(const char *refname, const 
unsigned char *old_sha1,
logfd = open(log_file, oflags);
if (logfd < 0)
return 0;
-   msglen = msg ? strlen(msg) : 0;
-   committer = git_committer_info(0);
-   maxlen = strlen(committer) + msglen + 100;
-   logrec = xmalloc(maxlen);
-   len = sprintf(logrec, "%s %s %s\n",
- sha1_to_hex(old_sha1),
- sha1_to_hex(new_sha1),
- committer);
-   if (msglen)
-   len += copy_msg(logrec + len - 1, msg) - 1;
-   written = len <= maxlen ? write_in_full(logfd, logrec, len) : -1;
-   free(logrec);
-   if (written != len) {
+   result = log_ref_write_fd(logfd, old_sha1, new_sha1,
+ git_committer_info(0), msg);
+   if (result) {
int save_errno = errno;
close(logfd);
error("Unable to append to %s", log_file);
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/15] refs.c: make ref_transaction_delete a wrapper for ref_transaction_update

2014-10-21 Thread Ronnie Sahlberg
commit 0beeda259297c92d411ecc92fa508ec7cfd87cc5 upstream.

Change-Id: I685291986e544a8dc14f94c73b6a7c6400acd9d2
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 22 ++
 refs.h |  2 +-
 2 files changed, 3 insertions(+), 21 deletions(-)

diff --git a/refs.c b/refs.c
index ed0485e..c607ab7 100644
--- a/refs.c
+++ b/refs.c
@@ -3633,26 +3633,8 @@ int ref_transaction_delete(struct ref_transaction 
*transaction,
   int flags, int have_old, const char *msg,
   struct strbuf *err)
 {
-   struct ref_update *update;
-
-   assert(err);
-
-   if (transaction->state != REF_TRANSACTION_OPEN)
-   die("BUG: delete called for transaction that is not open");
-
-   if (have_old && !old_sha1)
-   die("BUG: have_old is true but old_sha1 is NULL");
-
-   update = add_update(transaction, refname);
-   update->flags = flags;
-   update->have_old = have_old;
-   if (have_old) {
-   assert(!is_null_sha1(old_sha1));
-   hashcpy(update->old_sha1, old_sha1);
-   }
-   if (msg)
-   update->msg = xstrdup(msg);
-   return 0;
+   return ref_transaction_update(transaction, refname, null_sha1,
+ old_sha1, flags, have_old, msg, err);
 }
 
 int update_ref(const char *action, const char *refname,
diff --git a/refs.h b/refs.h
index 2bc3556..7d675b7 100644
--- a/refs.h
+++ b/refs.h
@@ -283,7 +283,7 @@ struct ref_transaction *ref_transaction_begin(struct strbuf 
*err);
 
 /*
  * Add a reference update to transaction.  new_sha1 is the value that
- * the reference should have after the update, or zeros if it should
+ * the reference should have after the update, or null_sha1 if it should
  * be deleted.  If have_old is true, then old_sha1 holds the value
  * that the reference should have had before the update, or zeros if
  * it must not have existed beforehand.
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/15] ref-transactions-reflog

2014-10-21 Thread Ronnie Sahlberg
List,

Please find a patch that updates the reflog handling to use transactions.
This patch series has previously been sent to the list but is now rebased on
the current content of next which contains ref changes we depend on in this
series.

This series converts the reflog handling and builtin/reflog.c to use
a transaction for both the ref as well as the reflog updates.
As a side effect of this it simplifies the reflog marshalling code so that we
only have one place where we marshall the entry.
It also means that we can remove several functions from the public api
towards the end of the series since we no longer need those functions.

This series can also be found at
https://github.com/rsahlberg/git/tree/ref-transactions-reflog

Ronnie Sahlberg (15):
  refs.c make ref_transaction_create a wrapper to ref_transaction_update
  refs.c: make ref_transaction_delete a wrapper for
ref_transaction_update
  refs.c: rename the transaction functions
  refs.c: add a new update_type field to ref_update
  refs.c: add a function to append a reflog entry to a fd
  copy.c: make copy_fd preserve meaningful errno
  refs.c: add a transaction function to append a reflog entry
  refs.c: add a flag to allow reflog updates to truncate the log
  refs.c: only write reflog update if msg is non-NULL
  refs.c: allow multiple reflog updates during a single transaction
  reflog.c: use a reflog transaction when writing during expire
  refs.c: rename log_ref_setup to create_reflog
  refs.c: make unlock_ref/close_ref/commit_ref static
  refs.c: remove lock_any_ref_for_update
  refs.c: allow deleting refs with a broken sha1

 branch.c|  14 +-
 builtin/branch.c|   5 +-
 builtin/checkout.c  |   8 +-
 builtin/commit.c|  10 +-
 builtin/fetch.c |  12 +-
 builtin/receive-pack.c  |  13 +-
 builtin/reflog.c|  85 --
 builtin/replace.c   |  10 +-
 builtin/tag.c   |  10 +-
 builtin/update-ref.c|  26 +--
 cache.h |   7 +
 copy.c  |  15 +-
 fast-import.c   |  22 +--
 refs.c  | 401 +---
 refs.h  |  87 +-
 sequencer.c |  12 +-
 t/t1402-check-ref-format.sh |   8 +
 walker.c|  10 +-
 18 files changed, 448 insertions(+), 307 deletions(-)

-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 10/15] refs.c: allow multiple reflog updates during a single transaction

2014-10-21 Thread Ronnie Sahlberg
commit 5fd1fa7d8520cf03e94fa7d0e9aa8685de0ef63f upstream.

Allow to make multiple reflog updates to the same ref during a transaction.
This means we only need to lock the reflog once, during the first update
that touches the reflog, and that all further updates can just write the
reflog entry since the reflog is already locked.

This allows us to write code such as:

t = transaction_begin()
transaction_reflog_update(t, "foo", REFLOG_TRUNCATE, NULL);
loop-over-something...
   transaction_reflog_update(t, "foo", 0, );
transaction_commit(t)

where we first truncate the reflog and then build the new content one line
at a time.

While this technically looks like O(n2) behavior it not that bad.
We only do this loop for transactions that cover a single ref during
reflog expire. This means that the linear search inside
transaction_update_reflog() will find the match on the very first entry
thus making it O(1) and not O(n) or our usecases. Thus the whole expire
becomes O(n) instead of O(n2). If in the future we start doing this for many
refs in one single transaction we might want to optimize this.
But there is no need to complexify the code and optimize for future usecases
that might never materialize at this stage.

Change-Id: Ibe703310e33a4db07e5bcc704310211268b788fc
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 46 +-
 1 file changed, 37 insertions(+), 9 deletions(-)

diff --git a/refs.c b/refs.c
index f14b76e..f7e947f 100644
--- a/refs.c
+++ b/refs.c
@@ -31,6 +31,12 @@ static unsigned char refname_disposition[256] = {
  */
 #define REF_ISPRUNING  0x0100
 /*
+ * Only the first reflog update needs to lock the reflog file. Further updates
+ * just use the lock taken by the first update.
+ */
+#define UPDATE_REFLOG_NOLOCK 0x0200
+
+/*
  * Try to read one refname component from the front of refname.
  * Return the length of the component found, or -1 if the component is
  * not legal.  It is legal if it is something reasonable to have under
@@ -3521,7 +3527,7 @@ enum transaction_update_type {
UPDATE_LOG = 1
 };
 
-/**
+/*
  * Information needed for a single ref update.  Set new_sha1 to the
  * new value or to zero to delete the ref.  To check the old value
  * while locking the ref, set have_old to 1 and set old_sha1 to the
@@ -3531,7 +3537,7 @@ struct ref_update {
enum transaction_update_type update_type;
unsigned char new_sha1[20];
unsigned char old_sha1[20];
-   int flags; /* REF_NODEREF? */
+   int flags; /* REF_NODEREF? or private flags */
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
struct ref_lock *lock;
int type;
@@ -3539,8 +3545,9 @@ struct ref_update {
 
/* used by reflog updates */
int reflog_fd;
-   struct lock_file reflog_lock;
+   struct lock_file *reflog_lock;
char *committer;
+   struct ref_update *orig_update; /* For UPDATE_REFLOG_NOLOCK */
 
const char refname[FLEX_ARRAY];
 };
@@ -3619,11 +3626,26 @@ int transaction_update_reflog(struct transaction 
*transaction,
  struct strbuf *err)
 {
struct ref_update *update;
+   int i;
 
if (transaction->state != TRANSACTION_OPEN)
die("BUG: update_reflog called for transaction that is not 
open");
 
update = add_update(transaction, refname, UPDATE_LOG);
+   update->flags = flags;
+   for (i = 0; i < transaction->nr - 1; i++) {
+   if (transaction->updates[i]->update_type != UPDATE_LOG)
+   continue;
+   if (!strcmp(transaction->updates[i]->refname,
+   update->refname)) {
+   update->flags |= UPDATE_REFLOG_NOLOCK;
+   update->orig_update = transaction->updates[i];
+   break;
+   }
+   }
+   if (!(update->flags & UPDATE_REFLOG_NOLOCK))
+   update->reflog_lock = xcalloc(1, sizeof(struct lock_file));
+
hashcpy(update->new_sha1, new_sha1);
hashcpy(update->old_sha1, old_sha1);
update->reflog_fd = -1;
@@ -3639,7 +3661,6 @@ int transaction_update_reflog(struct transaction 
*transaction,
}
if (msg)
update->msg = xstrdup(msg);
-   update->flags = flags;
 
return 0;
 }
@@ -3822,10 +3843,15 @@ int transaction_commit(struct transaction *transaction,
 
if (update->update_type != UPDATE_LOG)
continue;
+   if (update->flags & UPDATE_REFLOG_NOLOCK) {
+   update->reflog_fd = update->orig_update->reflog_fd;
+   update->reflog_lock = update->orig_update->reflog_lock;
+   continue;
+   }
update->reflog_fd = hold_lock_file_for_append(
-   &update->reflog_lock,
+   update->reflog

[PATCH 03/15] refs.c: rename the transaction functions

2014-10-21 Thread Ronnie Sahlberg
commit fd304abafb351f509b105da2d648298efd78df18 upstream.

Rename the transaction functions. Remove the leading ref_ from the
names and append _ref to the names for functions that create/delete/
update sha1 refs.

This also makes the names more appropriate for future changes that have been
discussed when the transactions could also operate on non ref objects. Such as
..git/config and .gitmodule.

Change-Id: Iffdc56536be71c5061caa23040ce0d89efd52196
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 branch.c   | 14 -
 builtin/commit.c   | 10 +++
 builtin/fetch.c| 12 
 builtin/receive-pack.c | 13 -
 builtin/replace.c  | 10 +++
 builtin/tag.c  | 10 +++
 builtin/update-ref.c   | 26 -
 fast-import.c  | 22 +++---
 refs.c | 78 +-
 refs.h | 36 +++
 sequencer.c| 12 
 walker.c   | 10 +++
 12 files changed, 126 insertions(+), 127 deletions(-)

diff --git a/branch.c b/branch.c
index 4bab55a..d9b1174 100644
--- a/branch.c
+++ b/branch.c
@@ -279,17 +279,17 @@ void create_branch(const char *head,
log_all_ref_updates = 1;
 
if (!dont_change_ref) {
-   struct ref_transaction *transaction;
+   struct transaction *transaction;
struct strbuf err = STRBUF_INIT;
 
-   transaction = ref_transaction_begin(&err);
+   transaction = transaction_begin(&err);
if (!transaction ||
-   ref_transaction_update(transaction, ref.buf, sha1,
-  null_sha1, 0, !forcing, msg, &err) ||
-   ref_transaction_commit(transaction, &err))
+   transaction_update_ref(transaction, ref.buf, sha1,
+  null_sha1, 0, !forcing, msg,
+  &err) ||
+   transaction_commit(transaction, &err))
die("%s", err.buf);
-   ref_transaction_free(transaction);
-   strbuf_release(&err);
+   transaction_free(transaction);
}
 
if (real_ref && track)
diff --git a/builtin/commit.c b/builtin/commit.c
index e108c53..f50b7df 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1673,7 +1673,7 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
struct stat statbuf;
struct commit *current_head = NULL;
struct commit_extra_header *extra = NULL;
-   struct ref_transaction *transaction;
+   struct transaction *transaction;
struct strbuf err = STRBUF_INIT;
 
if (argc == 2 && !strcmp(argv[1], "-h"))
@@ -1804,17 +1804,17 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
strbuf_insert(&sb, 0, reflog_msg, strlen(reflog_msg));
strbuf_insert(&sb, strlen(reflog_msg), ": ", 2);
 
-   transaction = ref_transaction_begin(&err);
+   transaction = transaction_begin(&err);
if (!transaction ||
-   ref_transaction_update(transaction, "HEAD", sha1,
+   transaction_update_ref(transaction, "HEAD", sha1,
   current_head
   ? current_head->object.sha1 : NULL,
   0, !!current_head, sb.buf, &err) ||
-   ref_transaction_commit(transaction, &err)) {
+   transaction_commit(transaction, &err)) {
rollback_index_files();
die("%s", err.buf);
}
-   ref_transaction_free(transaction);
+   transaction_free(transaction);
 
unlink(git_path("CHERRY_PICK_HEAD"));
unlink(git_path("REVERT_HEAD"));
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 6ffd023..323ffd9 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -404,7 +404,7 @@ static int s_update_ref(const char *action,
 {
char msg[1024];
char *rla = getenv("GIT_REFLOG_ACTION");
-   struct ref_transaction *transaction;
+   struct transaction *transaction;
struct strbuf err = STRBUF_INIT;
int ret, df_conflict = 0;
 
@@ -414,23 +414,23 @@ static int s_update_ref(const char *action,
rla = default_rla.buf;
snprintf(msg, sizeof(msg), "%s: %s", rla, action);
 
-   transaction = ref_transaction_begin(&err);
+   transaction = transaction_begin(&err);
if (!transaction ||
-   ref_transaction_update(transaction, ref->name, ref->new_sha1,
+   transaction_update_ref(transaction, ref->name, ref->new_sha1,
   ref->old_sha1, 0, check_old, msg, &err))
goto fail;
 
-   ret = ref_transaction_commit(transaction, &err);
+   ret = transaction_commit(transaction, &err);
if (ret) {
df_conflict = (ret == TRANSAC

[PATCH 09/15] refs.c: only write reflog update if msg is non-NULL

2014-10-21 Thread Ronnie Sahlberg
commit 020ed65a12838bdead64bc3c5de249d3c8f5cfd8 upstream.

When performing a reflog transaction update, only write to the reflog iff
msg is non-NULL. This can then be combined with REFLOG_TRUNCATE to perform
an update that only truncates but does not write.

Change-Id: I44c89caa7e7c4960777b79cfb5d339a5aa3ddf7a
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 5 +++--
 refs.h | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/refs.c b/refs.c
index d54c3b9..f14b76e 100644
--- a/refs.c
+++ b/refs.c
@@ -3895,8 +3895,9 @@ int transaction_commit(struct transaction *transaction,
update->reflog_fd = -1;
continue;
}
-   if (log_ref_write_fd(update->reflog_fd, update->old_sha1,
-update->new_sha1,
+   if (update->msg &&
+   log_ref_write_fd(update->reflog_fd,
+update->old_sha1, update->new_sha1,
 update->committer, update->msg)) {
error("Could write to reflog: %s. %s",
  update->refname, strerror(errno));
diff --git a/refs.h b/refs.h
index 5075073..bf96b36 100644
--- a/refs.h
+++ b/refs.h
@@ -337,6 +337,7 @@ int transaction_delete_ref(struct transaction *transaction,
 /*
  * Append a reflog entry for refname. If the REFLOG_TRUNCATE flag is set
  * this update will first truncate the reflog before writing the entry.
+ * If msg is NULL no update will be written to the log.
  */
 int transaction_update_reflog(struct transaction *transaction,
  const char *refname,
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/15] refs.c: remove lock_any_ref_for_update

2014-10-21 Thread Ronnie Sahlberg
commit 3a2f55c247ff290943fd552674e226062c13fd00 upstream.

No one is using this function so we can delete it.

Change-Id: I524dac239da500e5d4432328b997ed8ab34f6803
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 7 ---
 refs.h | 9 +
 2 files changed, 1 insertion(+), 15 deletions(-)

diff --git a/refs.c b/refs.c
index 5e5f066..5bd6d62 100644
--- a/refs.c
+++ b/refs.c
@@ -2352,13 +2352,6 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
return NULL;
 }
 
-struct ref_lock *lock_any_ref_for_update(const char *refname,
-const unsigned char *old_sha1,
-int flags, int *type_p)
-{
-   return lock_ref_sha1_basic(refname, old_sha1, NULL, flags, type_p);
-}
-
 /*
  * Write an entry to the packed-refs file for the specified refname.
  * If peeled is non-NULL, write it as the entry's peeled value.
diff --git a/refs.h b/refs.h
index 025e2cb..721e21f 100644
--- a/refs.h
+++ b/refs.h
@@ -181,8 +181,7 @@ extern int is_branch(const char *refname);
 extern int peel_ref(const char *refname, unsigned char *sha1);
 
 /*
- * Flags controlling lock_any_ref_for_update(), transaction_update_ref(),
- * transaction_create_ref(), etc.
+ * Flags controlling transaction_update_ref(), transaction_create_ref(), etc.
  * REF_NODEREF: act on the ref directly, instead of dereferencing
  *  symbolic references.
  * REF_DELETING: tolerate broken refs
@@ -191,12 +190,6 @@ extern int peel_ref(const char *refname, unsigned char 
*sha1);
  */
 #define REF_NODEREF0x01
 #define REF_DELETING   0x02
-/*
- * This function sets errno to something meaningful on failure.
- */
-extern struct ref_lock *lock_any_ref_for_update(const char *refname,
-   const unsigned char *old_sha1,
-   int flags, int *type_p);
 
 /** Reads log for the value of ref during at_time. **/
 extern int read_ref_at(const char *refname, unsigned int flags,
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/15] refs.c: allow deleting refs with a broken sha1

2014-10-21 Thread Ronnie Sahlberg
commit 8d75baa250c0f84cc438568cb53ef1a9dd3dfec9 upstream.

Add back support to make it possible to delete refs that have a broken
sha1.

Add new internal flags REF_ALLOW_BROKEN and RESOLVE_REF_ALLOW_BAD_SHA1
to pass intent from branch.c that we are willing to allow
resolve_ref_unsafe and lock_ref_sha1_basic to allow broken refs.
Since these refs can not actually be resolved to a sha1, they instead resolve
to null_sha1 when these flags are used.

For example, the ref:

   echo "Broken ref" > .git/refs/heads/foo-broken-1

can now be deleted using git branch -d foo-broken-1

Change-Id: I4e744d9e7d8b7e81dde5479965819117d03c98db
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 builtin/branch.c| 5 +++--
 cache.h | 7 +++
 refs.c  | 6 ++
 refs.h  | 6 --
 t/t1402-check-ref-format.sh | 8 
 5 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 3b79c50..04f57d4 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -238,7 +238,8 @@ static int delete_branches(int argc, const char **argv, int 
force, int kinds,
target = resolve_ref_unsafe(name,
RESOLVE_REF_READING
| RESOLVE_REF_NO_RECURSE
-   | RESOLVE_REF_ALLOW_BAD_NAME,
+   | RESOLVE_REF_ALLOW_BAD_NAME
+   | RESOLVE_REF_ALLOW_BAD_SHA1,
sha1, &flags);
if (!target) {
error(remote_branch
@@ -255,7 +256,7 @@ static int delete_branches(int argc, const char **argv, int 
force, int kinds,
continue;
}
 
-   if (delete_ref(name, sha1, REF_NODEREF)) {
+   if (delete_ref(name, sha1, REF_NODEREF|REF_ALLOW_BROKEN)) {
error(remote_branch
  ? _("Error deleting remote branch '%s'")
  : _("Error deleting branch '%s'"),
diff --git a/cache.h b/cache.h
index 99ed096..61e61af 100644
--- a/cache.h
+++ b/cache.h
@@ -1000,10 +1000,17 @@ extern int read_ref(const char *refname, unsigned char 
*sha1);
  * resolved. The function returns NULL for such ref names.
  * Caps and underscores refers to the special refs, such as HEAD,
  * FETCH_HEAD and friends, that all live outside of the refs/ directory.
+ *
+ * RESOLVE_REF_ALLOW_BAD_SHA1 when this flag is set and the ref contains
+ * an invalid sha1, resolve_ref_unsafe will clear the sha1 argument,
+ * set the REF_ISBROKEN flag and return the refname.
+ * This allows using resolve_ref_unsafe to check for existence of such
+ * broken refs.
  */
 #define RESOLVE_REF_READING 0x01
 #define RESOLVE_REF_NO_RECURSE 0x02
 #define RESOLVE_REF_ALLOW_BAD_NAME 0x04
+#define RESOLVE_REF_ALLOW_BAD_SHA1 0x08
 extern const char *resolve_ref_unsafe(const char *ref, int resolve_flags, 
unsigned char *sha1, int *flags);
 extern char *resolve_refdup(const char *ref, int resolve_flags, unsigned char 
*sha1, int *flags);
 
diff --git a/refs.c b/refs.c
index 5bd6d62..ae29d11 100644
--- a/refs.c
+++ b/refs.c
@@ -1584,6 +1584,10 @@ const char *resolve_ref_unsafe(const char *refname, int 
resolve_flags, unsigned
(buffer[40] != '\0' && !isspace(buffer[40]))) {
if (flags)
*flags |= REF_ISBROKEN;
+   if (resolve_flags & RESOLVE_REF_ALLOW_BAD_SHA1) 
{
+   hashclr(sha1);
+   return refname;
+   }
errno = EINVAL;
return NULL;
}
@@ -2265,6 +2269,8 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
if (flags & REF_NODEREF)
resolve_flags |= RESOLVE_REF_NO_RECURSE;
}
+   if (flags & REF_ALLOW_BROKEN)
+   resolve_flags |= RESOLVE_REF_ALLOW_BAD_SHA1;
 
refname = resolve_ref_unsafe(refname, resolve_flags,
 lock->old_sha1, &type);
diff --git a/refs.h b/refs.h
index 721e21f..2e97f4f 100644
--- a/refs.h
+++ b/refs.h
@@ -185,11 +185,13 @@ extern int peel_ref(const char *refname, unsigned char 
*sha1);
  * REF_NODEREF: act on the ref directly, instead of dereferencing
  *  symbolic references.
  * REF_DELETING: tolerate broken refs
+ * REF_ALLOW_BROKEN: allow locking refs that are broken.
  *
  * Flags >= 0x100 are reserved for internal use.
  */
-#define REF_NODEREF0x01
-#define REF_DELETING   0x02
+#define REF_NODEREF0x01
+#define REF_DELETING   0x02
+#define REF_ALLOW_BROKEN   0x04
 
 /** Reads log for the valu

[PATCH 11/15] reflog.c: use a reflog transaction when writing during expire

2014-10-21 Thread Ronnie Sahlberg
commit 5ac378cd8fad09a836d17fec379780854838bde5 upstream.

Use a transaction for all updates during expire_reflog.

Change-Id: Ieb81b2660cefeeecf0bcb3cdbc1ef3cbb86e7eb8
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 builtin/reflog.c | 85 
 refs.c   |  4 +--
 refs.h   |  2 +-
 3 files changed, 40 insertions(+), 51 deletions(-)

diff --git a/builtin/reflog.c b/builtin/reflog.c
index 2d85d26..6bb7454 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -32,8 +32,11 @@ struct cmd_reflog_expire_cb {
int recno;
 };
 
+static struct strbuf err = STRBUF_INIT;
+
 struct expire_reflog_cb {
-   FILE *newlog;
+   struct transaction *t;
+   const char *refname;
enum {
UE_NORMAL,
UE_ALWAYS,
@@ -316,20 +319,18 @@ static int expire_reflog_ent(unsigned char *osha1, 
unsigned char *nsha1,
if (cb->cmd->recno && --(cb->cmd->recno) == 0)
goto prune;
 
-   if (cb->newlog) {
-   char sign = (tz < 0) ? '-' : '+';
-   int zone = (tz < 0) ? (-tz) : tz;
-   fprintf(cb->newlog, "%s %s %s %lu %c%04d\t%s",
-   sha1_to_hex(osha1), sha1_to_hex(nsha1),
-   email, timestamp, sign, zone,
-   message);
+   if (cb->t) {
+   if (transaction_update_reflog(cb->t, cb->refname, nsha1, osha1,
+ email, timestamp, tz, message, 0,
+ &err))
+   return -1;
hashcpy(cb->last_kept_sha1, nsha1);
}
if (cb->cmd->verbose)
printf("keep %s", message);
return 0;
  prune:
-   if (!cb->newlog)
+   if (!cb->t)
printf("would prune %s", message);
else if (cb->cmd->verbose)
printf("prune %s", message);
@@ -353,29 +354,26 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
 {
struct cmd_reflog_expire_cb *cmd = cb_data;
struct expire_reflog_cb cb;
-   struct ref_lock *lock;
-   char *log_file, *newlog_path = NULL;
struct commit *tip_commit;
struct commit_list *tips;
int status = 0;
 
memset(&cb, 0, sizeof(cb));
+   cb.refname = ref;
 
-   /*
-* we take the lock for the ref itself to prevent it from
-* getting updated.
-*/
-   lock = lock_any_ref_for_update(ref, sha1, 0, NULL);
-   if (!lock)
-   return error("cannot lock ref '%s'", ref);
-   log_file = git_pathdup("logs/%s", ref);
if (!reflog_exists(ref))
goto finish;
-   if (!cmd->dry_run) {
-   newlog_path = git_pathdup("logs/%s.lock", ref);
-   cb.newlog = fopen(newlog_path, "w");
+   cb.t = transaction_begin(&err);
+   if (!cb.t) {
+   status |= error("%s", err.buf);
+   goto cleanup;
+   }
+   if (transaction_update_reflog(cb.t, cb.refname, null_sha1, null_sha1,
+ NULL, 0, 0, NULL, REFLOG_TRUNCATE,
+ &err)) {
+   status |= error("%s", err.buf);
+   goto cleanup;
}
-
cb.cmd = cmd;
 
if (!cmd->expire_unreachable || !strcmp(ref, "HEAD")) {
@@ -407,7 +405,10 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
mark_reachable(&cb);
}
 
-   for_each_reflog_ent(ref, expire_reflog_ent, &cb);
+   if (for_each_reflog_ent(ref, expire_reflog_ent, &cb)) {
+   status |= error("%s", err.buf);
+   goto cleanup;
+   }
 
if (cb.unreachable_expire_kind != UE_ALWAYS) {
if (cb.unreachable_expire_kind == UE_HEAD) {
@@ -420,32 +421,20 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
}
}
  finish:
-   if (cb.newlog) {
-   if (fclose(cb.newlog)) {
-   status |= error("%s: %s", strerror(errno),
-   newlog_path);
-   unlink(newlog_path);
-   } else if (cmd->updateref &&
-   (write_in_full(lock->lock_fd,
-   sha1_to_hex(cb.last_kept_sha1), 40) != 40 ||
-write_str_in_full(lock->lock_fd, "\n") != 1 ||
-close_ref(lock) < 0)) {
-   status |= error("Couldn't write %s",
-   lock->lk->filename.buf);
-   unlink(newlog_path);
-   } else if (rename(newlog_path, log_file)) {
-   status |= error("cannot rename %s to %s",
-   newlog_path, log_file);
-   unlink(newlog_path);
-  

[PATCH 06/15] copy.c: make copy_fd preserve meaningful errno

2014-10-21 Thread Ronnie Sahlberg
commit 306805ccd147bfdf160b288a8d51fdf9b77ae0fa upstream.

Update copy_fd to return a meaningful errno on failure.

Change-Id: I771f9703acc816902affcf35ff2a56d9426315ac
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 copy.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/copy.c b/copy.c
index f2970ec..a8d366e 100644
--- a/copy.c
+++ b/copy.c
@@ -8,12 +8,17 @@ int copy_fd(int ifd, int ofd)
if (!len)
break;
if (len < 0) {
-   return error("copy-fd: read returned %s",
-strerror(errno));
+   int save_errno = errno;
+   error("copy-fd: read returned %s", strerror(errno));
+   errno = save_errno;
+   return -1;
+   }
+   if (write_in_full(ofd, buffer, len) < 0) {
+   int save_errno = errno;
+   error("copy-fd: write returned %s", strerror(errno));
+   errno = save_errno;
+   return -1;
}
-   if (write_in_full(ofd, buffer, len) < 0)
-   return error("copy-fd: write returned %s",
-strerror(errno));
}
return 0;
 }
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/15] refs.c: use packed refs when deleting refs during a transaction

2014-10-21 Thread Ronnie Sahlberg
commit fb5fa1d338ce113b0fea3bb955b50bbb3e827805 upstream.

Make the deletion of refs during a transaction more atomic.
Start by first copying all loose refs we will be deleting to the packed
refs file and then commit the packed refs file. Then re-lock the packed refs
file to stop anyone else from modifying these refs and keep it locked until
we are finished.
Since all refs we are about to delete are now safely held in the packed refs
file we can proceed to immediately unlink any corresponding loose refs
and still be fully rollback-able.

The exception is for refs that can not be resolved. Those refs are never
added to the packed refs and will just be un-rollback-ably deleted during
commit.

By deleting all the loose refs at the start of the transaction we make make
it possible to both delete one ref and then re-create a different ref in
the same transaction even if the two refs would normally conflict.

Example: rename m->m/m

In that example we want to delete the file 'm' so that we make room so
that we can create a directory with the same name in order to lock and
write to the ref m/m and its lock-file m/m.lock.

If there is a failure during the commit phase we can rollback without losing
any refs since we have so far only deleted loose refs that that are
guaranteed to also have a corresponding entry in the packed refs file.
Once we have finished all updates for refs and their reflogs we can repack
the packed refs file and remove the to-be-deleted refs from the packed refs,
at which point all the deleted refs will disappear in one atomic rename
operation.

This also means that for an outside observer, deletion of multiple refs
in a single transaction will look atomic instead of one ref being deleted
at a time.

In order to do all this we need to change the semantics for the
repack_without_refs function so that we can lock the packed refs file,
do other stuff, and later be able to call repack_without_refs with the
lock already taken.
This means we need some additional changes in remote.c to reflect the
changes to the repack_without_refs semantics.

Change-Id: I1e4f58050acaabc6bcfa3409fbc0c2b866bb59aa
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 builtin/remote.c |  20 ++-
 refs.c   | 155 ++-
 2 files changed, 138 insertions(+), 37 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index 7f28f92..c25420f 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "lockfile.h"
 #include "parse-options.h"
 #include "transport.h"
 #include "remote.h"
@@ -753,6 +754,15 @@ static int remove_branches(struct string_list *branches)
const char **branch_names;
int i, result = 0;
 
+   if (lock_packed_refs(0)) {
+   struct strbuf err = STRBUF_INIT;
+
+   unable_to_lock_message(git_path("packed-refs"), errno, &err);
+   error("%s", err.buf);
+   strbuf_release(&err);
+   return -1;
+   }
+
branch_names = xmalloc(branches->nr * sizeof(*branch_names));
for (i = 0; i < branches->nr; i++)
branch_names[i] = branches->items[i].string;
@@ -1337,9 +1347,15 @@ static int prune_remote(const char *remote, int dry_run)
delete_refs[i] = states.stale.items[i].util;
if (!dry_run) {
struct strbuf err = STRBUF_INIT;
-   if (repack_without_refs(delete_refs, states.stale.nr,
-   &err))
+
+   if (lock_packed_refs(0)) {
+   unable_to_lock_message(git_path("packed-refs"),
+  errno, &err);
result |= error("%s", err.buf);
+   } else
+   if (repack_without_refs(delete_refs,
+   states.stale.nr, &err))
+   result |= error("%s", err.buf);
strbuf_release(&err);
}
free(delete_refs);
diff --git a/refs.c b/refs.c
index c088d36..662af9b 100644
--- a/refs.c
+++ b/refs.c
@@ -2660,6 +2660,9 @@ static int curate_packed_ref_fn(struct ref_entry *entry, 
void *cb_data)
return 0;
 }
 
+/*
+ * Must be called with packed refs already locked (and sorted)
+ */
 int repack_without_refs(const char **refnames, int n, struct strbuf *err)
 {
struct ref_dir *packed;
@@ -2674,14 +2677,12 @@ int repack_without_refs(const char **refnames, int n, 
struct strbuf *err)
if (get_packed_ref(refnames[i]))
break;
 
-   /* Avoid locking if we have nothing to do */
-   if (i == n)
+   /* Avoid processing if we have nothing to do */
+   if (i == n) {
+   rollback_packed_refs();
return 0; 

[PATCH 02/15] refs.c: return error instead of dying when locking fails during transaction

2014-10-21 Thread Ronnie Sahlberg
commit e193c10fc4f9274d1e751cfcdcc4507818e8d498 upstream.

Change lock_ref_sha1_basic to return an error instead of dying when
we fail to lock a file during a transaction.
This function is only called from transaction_commit() and it knows how
to handle these failures.

Change-Id: Ie830b7970412d9299e76a86f08633ce721130aed
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/refs.c b/refs.c
index e49fbe9..c088d36 100644
--- a/refs.c
+++ b/refs.c
@@ -2340,6 +2340,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
 
lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, lflags);
if (lock->lock_fd < 0) {
+   last_errno = errno;
if (errno == ENOENT && --attempts_remaining > 0)
/*
 * Maybe somebody just deleted one of the
@@ -2347,8 +2348,13 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
 * again:
 */
goto retry;
-   else
-   unable_to_lock_die(ref_file, errno);
+   else {
+   struct strbuf err = STRBUF_INIT;
+   unable_to_lock_message(ref_file, errno, &err);
+   error("%s", err.buf);
+   strbuf_reset(&err);
+   goto error_return;
+   }
}
return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
 
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 04/15] refs.c: use a stringlist for repack_without_refs

2014-10-21 Thread Ronnie Sahlberg
Change-Id: I87a1b93c4b4f4a10ad6a9f8e2bb4d53f89b28c4a
Signed-off-by: Ronnie Sahlberg 
---
 builtin/remote.c | 23 ---
 refs.c   | 42 +-
 refs.h   |  2 +-
 3 files changed, 30 insertions(+), 37 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index c25420f..6806251 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -751,7 +751,6 @@ static int mv(int argc, const char **argv)
 static int remove_branches(struct string_list *branches)
 {
struct strbuf err = STRBUF_INIT;
-   const char **branch_names;
int i, result = 0;
 
if (lock_packed_refs(0)) {
@@ -763,13 +762,9 @@ static int remove_branches(struct string_list *branches)
return -1;
}
 
-   branch_names = xmalloc(branches->nr * sizeof(*branch_names));
-   for (i = 0; i < branches->nr; i++)
-   branch_names[i] = branches->items[i].string;
-   if (repack_without_refs(branch_names, branches->nr, &err))
+   if (repack_without_refs(branches, &err))
result |= error("%s", err.buf);
strbuf_release(&err);
-   free(branch_names);
 
for (i = 0; i < branches->nr; i++) {
struct string_list_item *item = branches->items + i;
@@ -1327,7 +1322,6 @@ static int prune_remote(const char *remote, int dry_run)
int result = 0, i;
struct ref_states states;
struct string_list delete_refs_list = STRING_LIST_INIT_NODUP;
-   const char **delete_refs;
const char *dangling_msg = dry_run
? _(" %s will become dangling!")
: _(" %s has become dangling!");
@@ -1335,6 +1329,11 @@ static int prune_remote(const char *remote, int dry_run)
memset(&states, 0, sizeof(states));
get_remote_ref_states(remote, &states, GET_REF_STATES);
 
+   for (i = 0; i < states.stale.nr; i++) {
+   string_list_insert(&delete_refs_list,
+  states.stale.items[i].util);
+   }
+
if (states.stale.nr) {
printf_ln(_("Pruning %s"), remote);
printf_ln(_("URL: %s"),
@@ -1342,9 +1341,6 @@ static int prune_remote(const char *remote, int dry_run)
   ? states.remote->url[0]
   : _("(no URL)"));
 
-   delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs));
-   for (i = 0; i < states.stale.nr; i++)
-   delete_refs[i] = states.stale.items[i].util;
if (!dry_run) {
struct strbuf err = STRBUF_INIT;
 
@@ -1353,19 +1349,16 @@ static int prune_remote(const char *remote, int dry_run)
   errno, &err);
result |= error("%s", err.buf);
} else
-   if (repack_without_refs(delete_refs,
-   states.stale.nr, &err))
+   if (repack_without_refs(&delete_refs_list,
+   &err))
result |= error("%s", err.buf);
strbuf_release(&err);
}
-   free(delete_refs);
}
 
for (i = 0; i < states.stale.nr; i++) {
const char *refname = states.stale.items[i].util;
 
-   string_list_insert(&delete_refs_list, refname);
-
if (!dry_run)
result |= delete_ref(refname, NULL, 0);
 
diff --git a/refs.c b/refs.c
index 662af9b..b9c8f91 100644
--- a/refs.c
+++ b/refs.c
@@ -2663,31 +2663,32 @@ static int curate_packed_ref_fn(struct ref_entry 
*entry, void *cb_data)
 /*
  * Must be called with packed refs already locked (and sorted)
  */
-int repack_without_refs(const char **refnames, int n, struct strbuf *err)
+int repack_without_refs(struct string_list *without, struct strbuf *err)
 {
struct ref_dir *packed;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
struct string_list_item *ref_to_delete;
-   int i, ret, removed = 0;
+   int count, ret, removed = 0;
 
assert(err);
 
/* Look for a packed ref */
-   for (i = 0; i < n; i++)
-   if (get_packed_ref(refnames[i]))
-   break;
+   count = 0;
+   for_each_string_list_item(ref_to_delete, without)
+   if (get_packed_ref(ref_to_delete->string))
+   count++;
 
-   /* Avoid processing if we have nothing to do */
-   if (i == n) {
+   /* No refname exists in packed refs */
+   if (!count) {
rollback_packed_refs();
-   return 0; /* no refname exists in packed refs */
+   return 0;
}
 
packed = get_packed_refs(&ref_cache);
 
/* Remove refnames from the cache */
-   for (i = 0;

[PATCH 09/15] remote.c: use a transaction for deleting refs

2014-10-21 Thread Ronnie Sahlberg
Transactions now use packed refs when deleting multiple refs so there is no
need to do it manually from remote.c any more.

Change-Id: I50cf9c4ab0c190b99e2c6c4e2f05abe260b0fe62
Signed-off-by: Ronnie Sahlberg 
---
 builtin/remote.c | 80 
 1 file changed, 40 insertions(+), 40 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index 6806251..42702d7 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -750,30 +750,27 @@ static int mv(int argc, const char **argv)
 
 static int remove_branches(struct string_list *branches)
 {
-   struct strbuf err = STRBUF_INIT;
int i, result = 0;
+   struct transaction *transaction;
+   struct strbuf err = STRBUF_INIT;
 
-   if (lock_packed_refs(0)) {
-   struct strbuf err = STRBUF_INIT;
-
-   unable_to_lock_message(git_path("packed-refs"), errno, &err);
-   error("%s", err.buf);
-   strbuf_release(&err);
-   return -1;
-   }
+   transaction = transaction_begin(&err);
+   if (!transaction)
+   die("%s", err.buf);
 
-   if (repack_without_refs(branches, &err))
+   for (i = 0; i < branches->nr; i++)
+   if (transaction_delete_ref(transaction,
+  branches->items[i].string, NULL,
+  0, 0, "remote-branches", &err)) {
+   result |= error("%s", err.buf);
+   goto cleanup;
+   }
+   if (transaction_commit(transaction, &err))
result |= error("%s", err.buf);
-   strbuf_release(&err);
-
-   for (i = 0; i < branches->nr; i++) {
-   struct string_list_item *item = branches->items + i;
-   const char *refname = item->string;
-
-   if (delete_ref(refname, NULL, 0))
-   result |= error(_("Could not remove branch %s"), 
refname);
-   }
 
+ cleanup:
+   strbuf_release(&err);
+   transaction_free(transaction);
return result;
 }
 
@@ -1325,42 +1322,38 @@ static int prune_remote(const char *remote, int dry_run)
const char *dangling_msg = dry_run
? _(" %s will become dangling!")
: _(" %s has become dangling!");
+   struct transaction *transaction = NULL;
+   struct strbuf err = STRBUF_INIT;
 
memset(&states, 0, sizeof(states));
get_remote_ref_states(remote, &states, GET_REF_STATES);
 
-   for (i = 0; i < states.stale.nr; i++) {
-   string_list_insert(&delete_refs_list,
-  states.stale.items[i].util);
-   }
-
if (states.stale.nr) {
printf_ln(_("Pruning %s"), remote);
printf_ln(_("URL: %s"),
   states.remote->url_nr
   ? states.remote->url[0]
   : _("(no URL)"));
-
-   if (!dry_run) {
-   struct strbuf err = STRBUF_INIT;
-
-   if (lock_packed_refs(0)) {
-   unable_to_lock_message(git_path("packed-refs"),
-  errno, &err);
-   result |= error("%s", err.buf);
-   } else
-   if (repack_without_refs(&delete_refs_list,
-   &err))
-   result |= error("%s", err.buf);
-   strbuf_release(&err);
-   }
}
 
+   if (!dry_run) {
+   transaction = transaction_begin(&err);
+   if (!transaction)
+   die("%s", err.buf);
+   }
for (i = 0; i < states.stale.nr; i++) {
const char *refname = states.stale.items[i].util;
 
-   if (!dry_run)
-   result |= delete_ref(refname, NULL, 0);
+   string_list_insert(&delete_refs_list, refname);
+
+   if (!dry_run) {
+   if (transaction_delete_ref(transaction,
+  refname, NULL,
+  0, 0, "remote-branches", &err)) {
+   result |= error("%s", err.buf);
+   goto cleanup;
+   }
+   }
 
if (dry_run)
printf_ln(_(" * [would prune] %s"),
@@ -1370,6 +1363,13 @@ static int prune_remote(const char *remote, int dry_run)
   abbrev_ref(refname, "refs/remotes/"));
}
 
+   if (!dry_run)
+   if (transaction_commit(transaction, &err))
+   result |= error("%s", err.buf);
+
+ cleanup:
+   strbuf_release(&err);
+   transaction_free(transaction);
warn_dangling_symrefs(stdout, dangling_msg, &delete_refs

[PATCH 07/15] refs.c: move reflog updates into its own function

2014-10-21 Thread Ronnie Sahlberg
write_ref_sha1 tries to update the reflog while updating the ref.
Move these reflog changes out into its own function so that we can do the
same thing if we write a sha1 ref differently, for example by writing a ref
to the packed refs file instead.

No functional changes intended. We only move some code out into a separate
function.

Change-Id: I5ef6b32d183455685f8966379767f8c6e1ec49c9
Signed-off-by: Ronnie Sahlberg 
---
 refs.c | 60 +++-
 1 file changed, 35 insertions(+), 25 deletions(-)

diff --git a/refs.c b/refs.c
index 43df656..4eec7e4 100644
--- a/refs.c
+++ b/refs.c
@@ -3022,6 +3022,40 @@ int is_branch(const char *refname)
return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
 }
 
+static int write_sha1_update_reflog(struct ref_lock *lock,
+   const unsigned char *sha1, const char *logmsg)
+{
+   if (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0 ||
+   (strcmp(lock->ref_name, lock->orig_ref_name) &&
+log_ref_write(lock->orig_ref_name, lock->old_sha1, sha1, logmsg) < 
0)) {
+   unlock_ref(lock);
+   return -1;
+   }
+   if (strcmp(lock->orig_ref_name, "HEAD") != 0) {
+   /*
+* Special hack: If a branch is updated directly and HEAD
+* points to it (may happen on the remote side of a push
+* for example) then logically the HEAD reflog should be
+* updated too.
+* A generic solution implies reverse symref information,
+* but finding all symrefs pointing to the given branch
+* would be rather costly for this rare event (the direct
+* update of a branch) to be worth it.  So let's cheat and
+* check with HEAD only which should cover 99% of all usage
+* scenarios (even 100% of the default ones).
+*/
+   unsigned char head_sha1[20];
+   int head_flag;
+   const char *head_ref;
+   head_ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
+ head_sha1, &head_flag);
+   if (head_ref && (head_flag & REF_ISSYMREF) &&
+   !strcmp(head_ref, lock->ref_name))
+   log_ref_write("HEAD", lock->old_sha1, sha1, logmsg);
+   }
+   return 0;
+}
+
 /*
  * Write sha1 into the ref specified by the lock. Make sure that errno
  * is sane on error.
@@ -3065,34 +3099,10 @@ static int write_ref_sha1(struct ref_lock *lock,
return -1;
}
clear_loose_ref_cache(&ref_cache);
-   if (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0 ||
-   (strcmp(lock->ref_name, lock->orig_ref_name) &&
-log_ref_write(lock->orig_ref_name, lock->old_sha1, sha1, logmsg) < 
0)) {
+   if (write_sha1_update_reflog(lock, sha1, logmsg)) {
unlock_ref(lock);
return -1;
}
-   if (strcmp(lock->orig_ref_name, "HEAD") != 0) {
-   /*
-* Special hack: If a branch is updated directly and HEAD
-* points to it (may happen on the remote side of a push
-* for example) then logically the HEAD reflog should be
-* updated too.
-* A generic solution implies reverse symref information,
-* but finding all symrefs pointing to the given branch
-* would be rather costly for this rare event (the direct
-* update of a branch) to be worth it.  So let's cheat and
-* check with HEAD only which should cover 99% of all usage
-* scenarios (even 100% of the default ones).
-*/
-   unsigned char head_sha1[20];
-   int head_flag;
-   const char *head_ref;
-   head_ref = resolve_ref_unsafe("HEAD", RESOLVE_REF_READING,
- head_sha1, &head_flag);
-   if (head_ref && (head_flag & REF_ISSYMREF) &&
-   !strcmp(head_ref, lock->ref_name))
-   log_ref_write("HEAD", lock->old_sha1, sha1, logmsg);
-   }
if (commit_ref(lock)) {
error("Couldn't set %s", lock->ref_name);
unlock_ref(lock);
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 14/15] refs.c: make lock_packed_refs take an err argument

2014-10-21 Thread Ronnie Sahlberg
Change-Id: Ibfc64ab19257484129ab0ad861b72c02414388df
Signed-off-by: Ronnie Sahlberg 
---
 refs.c | 25 +
 1 file changed, 13 insertions(+), 12 deletions(-)

diff --git a/refs.c b/refs.c
index e0d5a82..7fb0d6c 100644
--- a/refs.c
+++ b/refs.c
@@ -2393,13 +2393,17 @@ static int write_packed_entry_fn(struct ref_entry 
*entry, void *cb_data)
return 0;
 }
 
-/* This should return a meaningful errno on failure */
-static int lock_packed_refs(int flags)
+static int lock_packed_refs(struct strbuf *err)
 {
struct packed_ref_cache *packed_ref_cache;
 
-   if (hold_lock_file_for_update(&packlock, git_path("packed-refs"), 
flags) < 0)
+   if (hold_lock_file_for_update(&packlock, git_path("packed-refs"),
+ 0) < 0) {
+   if (err)
+   unable_to_lock_message(git_path("packed-refs"),
+  errno, err);
return -1;
+   }
/*
 * Get the current packed-refs while holding the lock.  If the
 * packed-refs file has been modified since we last read it,
@@ -2587,11 +2591,14 @@ static void prune_refs(struct ref_to_prune *r)
 int pack_refs(unsigned int flags)
 {
struct pack_refs_cb_data cbdata;
+   struct strbuf err = STRBUF_INIT;
 
memset(&cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
 
-   lock_packed_refs(LOCK_DIE_ON_ERROR);
+   if (lock_packed_refs(&err))
+   die("%s", err.buf);
+
cbdata.packed_refs = get_packed_refs(&ref_cache);
 
do_for_each_entry_in_dir(get_loose_refs(&ref_cache), 0,
@@ -3757,10 +3764,7 @@ int transaction_commit(struct transaction *transaction,
}
 
/* Lock packed refs during commit */
-   if (lock_packed_refs(0)) {
-   if (err)
-   unable_to_lock_message(git_path("packed-refs"),
-  errno, err);
+   if (lock_packed_refs(err)) {
ret = -1;
goto cleanup;
}
@@ -3815,10 +3819,7 @@ int transaction_commit(struct transaction *transaction,
goto cleanup;
}
/* lock the packed refs again so no one can change it */
-   if (lock_packed_refs(0)) {
-   if (err)
-   unable_to_lock_message(git_path("packed-refs"),
-  errno, err);
+   if (lock_packed_refs(err)) {
ret = -1;
goto cleanup;
}
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/15] refs.c: update rename_ref to use a transaction

2014-10-21 Thread Ronnie Sahlberg
commit 0295e9cebc41020ee84da275549b164a8770ffba upstream.

Change refs.c to use a single transaction to copy/rename both the refs and
its reflog. Since we are no longer using rename() to move the reflog file
we no longer need to disallow rename_ref for refs with a symlink for its
reflog so we can remove that test from the testsuite.

Change the function to return 1 on failure instead of either -1 or 1.

These changes make the rename_ref operation atomic. This also eliminates the
need to use rename() to shift the reflog around via a temporary filename.
As an extension to this, since we no longer use rename() on the reflog file,
we can now safely perform renames even if the reflog is a symbolic link
and thus can remove the check and fail for that condition.

Change-Id: I59477d410a34298a29cf0cbf32328b9053b158fe
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c| 192 --
 t/t3200-branch.sh |   7 --
 2 files changed, 70 insertions(+), 129 deletions(-)

diff --git a/refs.c b/refs.c
index b9c8f91..f43fef4 100644
--- a/refs.c
+++ b/refs.c
@@ -2752,58 +2752,26 @@ int delete_ref(const char *refname, const unsigned char 
*sha1, int delopt)
return 0;
 }
 
-/*
- * People using contrib's git-new-workdir have .git/logs/refs ->
- * /some/other/path/.git/logs/refs, and that may live on another device.
- *
- * IOW, to avoid cross device rename errors, the temporary renamed log must
- * live into logs/refs.
- */
-#define TMP_RENAMED_LOG  "logs/refs/.tmp-renamed-log"
+struct rename_reflog_cb {
+   struct transaction *transaction;
+   const char *refname;
+   struct strbuf *err;
+};
 
-static int rename_tmp_log(const char *newrefname)
+static int rename_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
+const char *id, unsigned long timestamp, int tz,
+const char *message, void *cb_data)
 {
-   int attempts_remaining = 4;
+   struct rename_reflog_cb *cb = cb_data;
+   struct reflog_committer_info ci;
 
- retry:
-   switch (safe_create_leading_directories(git_path("logs/%s", 
newrefname))) {
-   case SCLD_OK:
-   break; /* success */
-   case SCLD_VANISHED:
-   if (--attempts_remaining > 0)
-   goto retry;
-   /* fall through */
-   default:
-   error("unable to create directory for %s", newrefname);
-   return -1;
-   }
-
-   if (rename(git_path(TMP_RENAMED_LOG), git_path("logs/%s", newrefname))) 
{
-   if ((errno==EISDIR || errno==ENOTDIR) && --attempts_remaining > 
0) {
-   /*
-* rename(a, b) when b is an existing
-* directory ought to result in ISDIR, but
-* Solaris 5.8 gives ENOTDIR.  Sheesh.
-*/
-   if (remove_empty_directories(git_path("logs/%s", 
newrefname))) {
-   error("Directory not empty: logs/%s", 
newrefname);
-   return -1;
-   }
-   goto retry;
-   } else if (errno == ENOENT && --attempts_remaining > 0) {
-   /*
-* Maybe another process just deleted one of
-* the directories in the path to newrefname.
-* Try again from the beginning.
-*/
-   goto retry;
-   } else {
-   error("unable to move logfile "TMP_RENAMED_LOG" to 
logs/%s: %s",
-   newrefname, strerror(errno));
-   return -1;
-   }
-   }
-   return 0;
+   memset(&ci, 0, sizeof(ci));
+   ci.id = id;
+   ci.timestamp = timestamp;
+   ci.tz = tz;
+   return transaction_update_reflog(cb->transaction, cb->refname,
+nsha1, osha1, &ci, message, 0,
+cb->err);
 }
 
 static int rename_ref_available(const char *oldname, const char *newname)
@@ -2823,91 +2791,71 @@ static int write_ref_sha1(struct ref_lock *lock, const 
unsigned char *sha1,
 
 int rename_ref(const char *oldrefname, const char *newrefname, const char 
*logmsg)
 {
-   unsigned char sha1[20], orig_sha1[20];
-   int flag = 0, logmoved = 0;
-   struct ref_lock *lock;
-   struct stat loginfo;
-   int log = !lstat(git_path("logs/%s", oldrefname), &loginfo);
+   unsigned char sha1[20];
+   int flag = 0, log;
+   struct transaction *transaction = NULL;
+   struct strbuf err = STRBUF_INIT;
const char *symref = NULL;
+   struct rename_reflog_cb cb;
+   struct reflog_committer_info ci;
 
-   if (log && S_ISLNK(loginfo.st_mode))
-   return error("reflog for %s is a symlink", oldrefname

[PATCH 00/15] ref-transaction-rename

2014-10-21 Thread Ronnie Sahlberg
List,

Thsi series builds on the previous series : ref-transaction-reflog
as applied to next. This series has been sent to the list before
but is now rebased to current git next.

This series can also be found at :
https://github.com/rsahlberg/git/tree/ref-transactions-rename

This series converts ref rename to use a transaction. This addesses several
issues in the old implementation, such as colliding renames might overwrite
someone elses reflog, and it makes the rename atomic.

As part of the series we also move changes that cover multiple refs to happen
as an atomic transaction/rename to the pacekd refs file. This makes it possible
to have both the rename case (one deleted ref + one created ref) as well
as any operation that updates multiple refs to become one atomic rename()
applied to the packed refs file. Thus all such changes are now also atomic
to all external observers.


Ronnie Sahlberg (15):
  refs.c: allow passing raw git_committer_info as email to
_update_reflog
  refs.c: return error instead of dying when locking fails during
transaction
  refs.c: use packed refs when deleting refs during a transaction
  refs.c: use a stringlist for repack_without_refs
  refs.c: update rename_ref to use a transaction
  refs.c: rollback the lockfile before we die() in repack_without_refs
  refs.c: move reflog updates into its own function
  refs.c: write updates to packed refs when a transaction has more than
one ref
  remote.c: use a transaction for deleting refs
  refs.c: make repack_without_refs static
  refs.c: make the *_packed_refs functions static
  refs.c: replace the onerr argument in update_ref with a strbuf err
  refs.c: make add_packed_ref return an error instead of calling die
  refs.c: make lock_packed_refs take an err argument
  refs.c: add an err argument to pack_refs

 builtin/checkout.c|   7 +-
 builtin/clone.c   |  36 ++--
 builtin/merge.c   |  20 +-
 builtin/notes.c   |  24 ++-
 builtin/pack-refs.c   |   8 +-
 builtin/reflog.c  |  19 +-
 builtin/remote.c  |  69 +++---
 builtin/reset.c   |  12 +-
 builtin/update-ref.c  |   7 +-
 notes-cache.c |   2 +-
 notes-utils.c |   5 +-
 refs.c| 568 +-
 refs.h|  71 +++
 t/t3200-branch.sh |   7 -
 t/t5516-fetch-push.sh |   2 +-
 transport-helper.c|   7 +-
 transport.c   |   9 +-
 17 files changed, 500 insertions(+), 373 deletions(-)

-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 08/15] refs.c: write updates to packed refs when a transaction has more than one ref

2014-10-21 Thread Ronnie Sahlberg
When we are updating more than one single ref, i.e. not a commit, then
write the updated refs directly to the packed refs file instead of writing
them as loose refs.

Change clone to use a transaction instead of using the packed refs API.
This changes the behavior of clone slightly. Previously clone would always
clone all refs into a packed refs file. With this change clone will only
clone into packed refs iff there are two or more refs being cloned.
If the repository we are cloning from only contains exactly one single ref
then clone will now store this as a loose ref. The benefit here is that
we no longer need to export a bunch of API functions to clone to access
packed refs directly. Clone can now just use a normal transaction and all
the packed refs goodness will happen automatically.

Update the t5516 test to cope with the fact that clone now only uses
packed refs if there are more than one ref being cloned.

We still use loose refs for single ref transactions, such as are used
by 'git commit' and friends. The reason for this is that if you have very
many refs then having to re-write the whole packed refs file for every
common operation like commit would have a performance impact.
That said, with these changes it should now be fairly straightforward to
add support to optionally start using packed refs for ALL updates
which could solve existing issues with name clashes in case insensitive
filesystems.

This change also means that multi-ref updates will now appear as a single
atomic change to any external observers instead of a sequence of discreete
changes.

Change-Id: I70cdcdb4341048386133e5b56b08c0b580b24c1b
Signed-off-by: Ronnie Sahlberg 
---
 builtin/clone.c   | 16 ++---
 refs.c| 89 ++-
 t/t5516-fetch-push.sh |  2 +-
 3 files changed, 72 insertions(+), 35 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index 7f509d0..5052fac 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -498,17 +498,25 @@ static struct ref *wanted_peer_refs(const struct ref 
*refs,
 static void write_remote_refs(const struct ref *local_refs)
 {
const struct ref *r;
+   struct transaction *transaction;
+   struct strbuf err = STRBUF_INIT;
 
-   lock_packed_refs(LOCK_DIE_ON_ERROR);
+   transaction = transaction_begin(&err);
+   if (!transaction)
+   die("%s", err.buf);
 
for (r = local_refs; r; r = r->next) {
if (!r->peer_ref)
continue;
-   add_packed_ref(r->peer_ref->name, r->old_sha1);
+   if (transaction_update_ref(transaction, r->peer_ref->name,
+  r->old_sha1, NULL, 0, 0, NULL,
+  &err))
+   die("%s", err.buf);
}
 
-   if (commit_packed_refs())
-   die_errno("unable to overwrite old ref-pack file");
+   if (transaction_commit(transaction, &err))
+   die("%s", err.buf);
+   transaction_free(transaction);
 }
 
 static void write_followtags(const struct ref *refs, const char *msg)
diff --git a/refs.c b/refs.c
index 4eec7e4..b64d0c7 100644
--- a/refs.c
+++ b/refs.c
@@ -2668,36 +2668,15 @@ int repack_without_refs(struct string_list *without, 
struct strbuf *err)
struct ref_dir *packed;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
struct string_list_item *ref_to_delete;
-   int count, ret, removed = 0;
+   int ret;
 
assert(err);
 
-   /* Look for a packed ref */
-   count = 0;
-   for_each_string_list_item(ref_to_delete, without)
-   if (get_packed_ref(ref_to_delete->string))
-   count++;
-
-   /* No refname exists in packed refs */
-   if (!count) {
-   rollback_packed_refs();
-   return 0;
-   }
-
packed = get_packed_refs(&ref_cache);
 
/* Remove refnames from the cache */
for_each_string_list_item(ref_to_delete, without)
-   if (remove_entry(packed, ref_to_delete->string) != -1)
-   removed = 1;
-   if (!removed) {
-   /*
-* All packed entries disappeared while we were
-* acquiring the lock.
-*/
-   rollback_packed_refs();
-   return 0;
-   }
+   remove_entry(packed, ref_to_delete->string);
 
/* Remove any other accumulated cruft */
do_for_each_entry_in_dir(packed, 0, curate_packed_ref_fn, 
&refs_to_delete);
@@ -3759,6 +3738,7 @@ int transaction_commit(struct transaction *transaction,
   struct strbuf *err)
 {
int ret = 0, i, need_repack = 0;
+   int num_updates = 0;
int n = transaction->nr;
struct packed_ref_cache *packed_ref_cache;
struct ref_update **updates = transaction->updates;
@@ -3792,14 +3772,30 @@ int transaction_commit

[PATCH 13/15] refs.c: make add_packed_ref return an error instead of calling die

2014-10-21 Thread Ronnie Sahlberg
Change add_packed_ref to return an error instead of calling die().
Update all callers to check the return value of add_packed_ref.

Change-Id: I5d5e4a75f641c4bbdb59199a233b71e86361c25c
Signed-off-by: Ronnie Sahlberg 
---
 refs.c | 21 +
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index c7d0825..e0d5a82 100644
--- a/refs.c
+++ b/refs.c
@@ -1224,15 +1224,16 @@ static struct ref_dir *get_packed_refs(struct ref_cache 
*refs)
return get_packed_ref_dir(get_packed_ref_cache(refs));
 }
 
-static void add_packed_ref(const char *refname, const unsigned char *sha1)
+static int add_packed_ref(const char *refname, const unsigned char *sha1)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
 
if (!packed_ref_cache->lock)
-   die("internal error: packed refs not locked");
+   return -1;
add_ref(get_packed_ref_dir(packed_ref_cache),
create_ref_entry(refname, sha1, REF_ISPACKED, 1));
+   return 0;
 }
 
 /*
@@ -3795,7 +3796,13 @@ int transaction_commit(struct transaction *transaction,
sha1, NULL))
continue;
 
-   add_packed_ref(update->refname, sha1);
+   if (add_packed_ref(update->refname, sha1)) {
+   if (err)
+   strbuf_addf(err, "Failed to add %s to packed "
+   "refs", update->refname);
+   ret = -1;
+   goto cleanup;
+   }
need_repack = 1;
}
if (need_repack) {
@@ -3909,7 +3916,13 @@ int transaction_commit(struct transaction *transaction,
 
packed = get_packed_refs(&ref_cache);
remove_entry(packed, update->refname);
-   add_packed_ref(update->refname, update->new_sha1);
+   if (add_packed_ref(update->refname, update->new_sha1)) {
+   if (err)
+   strbuf_addf(err, "Failed to add %s to packed "
+   "refs", update->refname);
+   ret = -1;
+   goto cleanup;
+   }
need_repack = 1;
 
try_remove_empty_parents((char *)update->refname);
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/15] refs.c: allow passing raw git_committer_info as email to _update_reflog

2014-10-21 Thread Ronnie Sahlberg
commit 167e0c6d205ed785cc17b96e22d9366accfa1665 upstream.

In many places in the code we do not have access to the individual fields
in the committer data. Instead we might only have access to prebaked data
such as what is returned by git_committer_info() containing a string
that consists of email, timestamp, zone etc.

This makes it inconvenient to use transaction_update_reflog since it means
you would have to first parse git_committer_info before you can call
update_reflog.

Add a new flag REFLOG_COMMITTER_INFO_IS_VALID to _update_reflog to tell it
that we pass in a fully prebaked committer info string that can be used as is.

At the same time, also go over and change all references from email
to id where the code actually refers to a committer id and not just an email
address. I.e. where the string is : NAME 

Change-Id: I179cd8cc88570801ce6ef1daa8f738e7d20851fa
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 builtin/reflog.c | 19 +--
 refs.c   | 21 -
 refs.h   | 25 +++--
 3 files changed, 48 insertions(+), 17 deletions(-)

diff --git a/builtin/reflog.c b/builtin/reflog.c
index 6bb7454..be88a53 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -292,7 +292,7 @@ static int unreachable(struct expire_reflog_cb *cb, struct 
commit *commit, unsig
 }
 
 static int expire_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-   const char *email, unsigned long timestamp, int tz,
+   const char *id, unsigned long timestamp, int tz,
const char *message, void *cb_data)
 {
struct expire_reflog_cb *cb = cb_data;
@@ -320,9 +320,14 @@ static int expire_reflog_ent(unsigned char *osha1, 
unsigned char *nsha1,
goto prune;
 
if (cb->t) {
+   struct reflog_committer_info ci;
+
+   memset(&ci, 0, sizeof(ci));
+   ci.id = id;
+   ci.timestamp = timestamp;
+   ci.tz = tz;
if (transaction_update_reflog(cb->t, cb->refname, nsha1, osha1,
- email, timestamp, tz, message, 0,
- &err))
+ &ci, message, 0, &err))
return -1;
hashcpy(cb->last_kept_sha1, nsha1);
}
@@ -356,6 +361,7 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
struct expire_reflog_cb cb;
struct commit *tip_commit;
struct commit_list *tips;
+   struct reflog_committer_info ci;
int status = 0;
 
memset(&cb, 0, sizeof(cb));
@@ -368,9 +374,10 @@ static int expire_reflog(const char *ref, const unsigned 
char *sha1, int unused,
status |= error("%s", err.buf);
goto cleanup;
}
+
+   memset(&ci, 0, sizeof(ci));
if (transaction_update_reflog(cb.t, cb.refname, null_sha1, null_sha1,
- NULL, 0, 0, NULL, REFLOG_TRUNCATE,
- &err)) {
+ &ci, NULL, REFLOG_TRUNCATE, &err)) {
status |= error("%s", err.buf);
goto cleanup;
}
@@ -672,7 +679,7 @@ static int cmd_reflog_expire(int argc, const char **argv, 
const char *prefix)
 }
 
 static int count_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
-   const char *email, unsigned long timestamp, int tz,
+   const char *id, unsigned long timestamp, int tz,
const char *message, void *cb_data)
 {
struct cmd_reflog_expire_cb *cb = cb_data;
diff --git a/refs.c b/refs.c
index ae29d11..e49fbe9 100644
--- a/refs.c
+++ b/refs.c
@@ -3226,7 +3226,7 @@ struct read_ref_at_cb {
 };
 
 static int read_ref_at_ent(unsigned char *osha1, unsigned char *nsha1,
-   const char *email, unsigned long timestamp, int tz,
+   const char *id, unsigned long timestamp, int tz,
const char *message, void *cb_data)
 {
struct read_ref_at_cb *cb = cb_data;
@@ -3273,7 +3273,7 @@ static int read_ref_at_ent(unsigned char *osha1, unsigned 
char *nsha1,
 }
 
 static int read_ref_at_ent_oldest(unsigned char *osha1, unsigned char *nsha1,
- const char *email, unsigned long timestamp,
+ const char *id, unsigned long timestamp,
  int tz, const char *message, void *cb_data)
 {
struct read_ref_at_cb *cb = cb_data;
@@ -3623,8 +3623,7 @@ int transaction_update_reflog(struct transaction 
*transaction,
  const char *refname,
  const unsigned char *new_sha1,
  const unsigned char *old_sha1,
- const char *email,
- unsigned long timestamp, int tz,
+

[PATCH 10/15] refs.c: make repack_without_refs static

2014-10-21 Thread Ronnie Sahlberg
Change-Id: Ibf02549e5485ad07da66fe4b1c84f9e2b76b2aca
Signed-off-by: Ronnie Sahlberg 
---
 refs.c | 2 +-
 refs.h | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index b64d0c7..fddd59c 100644
--- a/refs.c
+++ b/refs.c
@@ -2663,7 +2663,7 @@ static int curate_packed_ref_fn(struct ref_entry *entry, 
void *cb_data)
 /*
  * Must be called with packed refs already locked (and sorted)
  */
-int repack_without_refs(struct string_list *without, struct strbuf *err)
+static int repack_without_refs(struct string_list *without, struct strbuf *err)
 {
struct ref_dir *packed;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
diff --git a/refs.h b/refs.h
index d174380..db435bf 100644
--- a/refs.h
+++ b/refs.h
@@ -163,9 +163,6 @@ extern void rollback_packed_refs(void);
  */
 int pack_refs(unsigned int flags);
 
-extern int repack_without_refs(struct string_list *without,
-  struct strbuf *err);
-
 extern int ref_exists(const char *);
 
 extern int is_branch(const char *refname);
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/8] push.c: add an --atomic-push argument

2014-10-21 Thread Ronnie Sahlberg
Add a command line argument to the git push command to request atomic
pushes.

Change-Id: I9f8d06970b2fdd1cf7d933e0cce1288752034af1
Signed-off-by: Ronnie Sahlberg 
---
 Documentation/git-push.txt | 7 ++-
 builtin/push.c | 2 ++
 transport.c| 1 +
 transport.h| 1 +
 4 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 21b3f29..04de8d8 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -9,7 +9,7 @@ git-push - Update remote refs along with associated objects
 SYNOPSIS
 
 [verse]
-'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] 
[--receive-pack=]
+'git push' [--all | --mirror | --tags] [--follow-tags] [--atomic-push] [-n | 
--dry-run] [--receive-pack=]
   [--repo=] [-f | --force] [--prune] [-v | --verbose]
   [-u | --set-upstream] [--signed]
   [--force-with-lease[=[:]]]
@@ -136,6 +136,11 @@ already exists on the remote side.
logged.  See linkgit:git-receive-pack[1] for the details
on the receiving end.
 
+--atomic-push::
+   Try using atomic push. If atomic push is negotiated with the server
+   then any push covering multiple refs will be atomic. Either all
+   refs are updated, or on error, no refs are updated.
+
 --receive-pack=::
 --exec=::
Path to the 'git-receive-pack' program on the remote
diff --git a/builtin/push.c b/builtin/push.c
index ae56f73..0b9f21a 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -507,6 +507,8 @@ int cmd_push(int argc, const char **argv, const char 
*prefix)
OPT_BIT(0, "follow-tags", &flags, N_("push missing but relevant 
tags"),
TRANSPORT_PUSH_FOLLOW_TAGS),
OPT_BIT(0, "signed", &flags, N_("GPG sign the push"), 
TRANSPORT_PUSH_CERT),
+   OPT_BIT(0, "atomic-push", &flags, N_("use atomic push, if 
available"),
+   TRANSPORT_ATOMIC_PUSH),
OPT_END()
};
 
diff --git a/transport.c b/transport.c
index d3e9e27..e2a16b2 100644
--- a/transport.c
+++ b/transport.c
@@ -832,6 +832,7 @@ static int git_transport_push(struct transport *transport, 
struct ref *remote_re
args.dry_run = !!(flags & TRANSPORT_PUSH_DRY_RUN);
args.porcelain = !!(flags & TRANSPORT_PUSH_PORCELAIN);
args.push_cert = !!(flags & TRANSPORT_PUSH_CERT);
+   args.use_atomic_push = !!(flags & TRANSPORT_ATOMIC_PUSH);
args.url = transport->url;
 
ret = send_pack(&args, data->fd, data->conn, remote_refs,
diff --git a/transport.h b/transport.h
index 3e0091e..25fa1da 100644
--- a/transport.h
+++ b/transport.h
@@ -125,6 +125,7 @@ struct transport {
 #define TRANSPORT_PUSH_NO_HOOK 512
 #define TRANSPORT_PUSH_FOLLOW_TAGS 1024
 #define TRANSPORT_PUSH_CERT 2048
+#define TRANSPORT_ATOMIC_PUSH 4096
 
 #define TRANSPORT_SUMMARY_WIDTH (2 * DEFAULT_ABBREV + 3)
 #define TRANSPORT_SUMMARY(x) (int)(TRANSPORT_SUMMARY_WIDTH + strlen(x) - 
gettext_width(x)), (x)
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 8/8] refs.c: add an err argument to create_symref

2014-10-21 Thread Ronnie Sahlberg
Change-Id: I812e7600fb648df429df8a2c84745de4f5875626
Signed-off-by: Ronnie Sahlberg 
---
 builtin/branch.c   |  7 +--
 builtin/checkout.c | 13 ++---
 builtin/clone.c| 15 +++
 builtin/init-db.c  |  8 ++--
 builtin/notes.c|  7 ---
 builtin/remote.c   | 26 ++
 builtin/symbolic-ref.c |  6 +-
 cache.h|  1 -
 refs.c | 30 ++
 refs.h |  1 +
 10 files changed, 78 insertions(+), 36 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index 04f57d4..ab6d9f4 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -698,6 +698,7 @@ static void rename_branch(const char *oldname, const char 
*newname, int force)
 {
struct strbuf oldref = STRBUF_INIT, newref = STRBUF_INIT, logmsg = 
STRBUF_INIT;
struct strbuf oldsection = STRBUF_INIT, newsection = STRBUF_INIT;
+   struct strbuf err = STRBUF_INIT;
int recovery = 0;
int clobber_head_ok;
 
@@ -734,8 +735,10 @@ static void rename_branch(const char *oldname, const char 
*newname, int force)
warning(_("Renamed a misnamed branch '%s' away"), oldref.buf + 
11);
 
/* no need to pass logmsg here as HEAD didn't really move */
-   if (!strcmp(oldname, head) && create_symref("HEAD", newref.buf, NULL))
-   die(_("Branch renamed to %s, but HEAD is not updated!"), 
newname);
+   if (!strcmp(oldname, head) &&
+   create_symref("HEAD", newref.buf, NULL, &err))
+   die(_("Branch renamed to %s, but HEAD is not updated!. %s"),
+   newname, err.buf);
 
strbuf_addf(&oldsection, "branch.%s", oldref.buf + 11);
strbuf_release(&oldref);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index d9cb9c3..1efe353 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -634,7 +634,10 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
describe_detached_head(_("HEAD is now at"), 
new->commit);
}
} else if (new->path) { /* Switch branches. */
-   create_symref("HEAD", new->path, msg.buf);
+   if (create_symref("HEAD", new->path, msg.buf, &err)) {
+   error("%s", err.buf);
+   strbuf_release(&err);
+   }
if (!opts->quiet) {
if (old->path && !strcmp(new->path, old->path)) {
if (opts->new_branch_force)
@@ -1020,12 +1023,16 @@ static int parse_branchname_arg(int argc, const char 
**argv,
 static int switch_unborn_to_new_branch(const struct checkout_opts *opts)
 {
int status;
-   struct strbuf branch_ref = STRBUF_INIT;
+   struct strbuf branch_ref = STRBUF_INIT, err = STRBUF_INIT;
 
if (!opts->new_branch)
die(_("You are on a branch yet to be born"));
strbuf_addf(&branch_ref, "refs/heads/%s", opts->new_branch);
-   status = create_symref("HEAD", branch_ref.buf, "checkout -b");
+   status = create_symref("HEAD", branch_ref.buf, "checkout -b", &err);
+   if (status) {
+   error("%s", err.buf);
+   strbuf_release(&err);
+   }
strbuf_release(&branch_ref);
if (!opts->quiet)
fprintf(stderr, _("Switched to a new branch '%s'\n"),
diff --git a/builtin/clone.c b/builtin/clone.c
index e0a671d..1c92e84 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -565,6 +565,7 @@ static void update_remote_refs(const struct ref *refs,
   int check_connectivity)
 {
const struct ref *rm = mapped_refs;
+   struct strbuf err = STRBUF_INIT;
 
if (check_connectivity) {
if (transport->progress)
@@ -586,9 +587,12 @@ static void update_remote_refs(const struct ref *refs,
struct strbuf head_ref = STRBUF_INIT;
strbuf_addstr(&head_ref, branch_top);
strbuf_addstr(&head_ref, "HEAD");
-   create_symref(head_ref.buf,
- remote_head_points_at->peer_ref->name,
- msg);
+   if (create_symref(head_ref.buf,
+ remote_head_points_at->peer_ref->name,
+ msg, &err)) {
+   error("%s", err.buf);
+   strbuf_release(&err);
+   }
}
 }
 
@@ -599,7 +603,10 @@ static void update_head(const struct ref *our, const 
struct ref *remote,
const char *head;
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
-   create_symref("HEAD", our->name, NULL);
+   if (create_symref("HEAD", our->name, NULL, &err)) {
+   error("%s", err.buf);
+   strbuf_release(&err);
+   }
i

[PATCH 1/8] receive-pack.c: add protocol support to negotiate atomic-push

2014-10-21 Thread Ronnie Sahlberg
This adds support to the protocol between send-pack and receive-pack to
* allow receive-pack to inform the client that it has atomic push capability
* allow send-pack to request atomic push back.

There is currently no setting in send-pack to actually request that atomic
pushes are to be used yet. This only adds protocol capability not ability
for the user to activate it.

Change-Id: I9a12940fb5c7443a1ddf9e45f6ea33b547c7ecfd
Signed-off-by: Ronnie Sahlberg 
---
 Documentation/technical/protocol-capabilities.txt | 12 ++--
 builtin/receive-pack.c|  6 +-
 send-pack.c   |  6 ++
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/Documentation/technical/protocol-capabilities.txt 
b/Documentation/technical/protocol-capabilities.txt
index 0c92dee..26bc5b1 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -18,8 +18,9 @@ was sent.  Server MUST NOT ignore capabilities that client 
requested
 and server advertised.  As a consequence of these rules, server MUST
 NOT advertise capabilities it does not understand.
 
-The 'report-status', 'delete-refs', 'quiet', and 'push-cert' capabilities
-are sent and recognized by the receive-pack (push to server) process.
+The 'atomic-push', 'report-status', 'delete-refs', 'quiet', and 'push-cert'
+capabilities are sent and recognized by the receive-pack (push to server)
+process.
 
 The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized
 by both upload-pack and receive-pack protocols.  The 'agent' capability
@@ -244,6 +245,13 @@ respond with the 'quiet' capability to suppress 
server-side progress
 reporting if the local progress reporting is also being suppressed
 (e.g., via `push -q`, or if stderr does not go to a tty).
 
+atomic-push
+---
+
+If the server sends the 'atomic-push' capability, it means it is
+capable of accepting atomic pushes. If the pushing client requests this
+capability, the server will update the refs in one single atomic transaction.
+
 allow-tip-sha1-in-want
 --
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 7ddd756..b8ffd9e 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -40,6 +40,7 @@ static int transfer_unpack_limit = -1;
 static int unpack_limit = 100;
 static int report_status;
 static int use_sideband;
+static int use_atomic_push;
 static int quiet;
 static int prefer_ofs_delta = 1;
 static int auto_update_server_info;
@@ -171,7 +172,8 @@ static void show_ref(const char *path, const unsigned char 
*sha1)
struct strbuf cap = STRBUF_INIT;
 
strbuf_addstr(&cap,
- "report-status delete-refs side-band-64k quiet");
+ "report-status delete-refs side-band-64k quiet "
+ "atomic-push");
if (prefer_ofs_delta)
strbuf_addstr(&cap, " ofs-delta");
if (push_cert_nonce)
@@ -1173,6 +1175,8 @@ static struct command *read_head_info(struct sha1_array 
*shallow)
use_sideband = LARGE_PACKET_MAX;
if (parse_feature_request(feature_list, "quiet"))
quiet = 1;
+   if (parse_feature_request(feature_list, "atomic-push"))
+   use_atomic_push = 1;
}
 
if (!strcmp(line, "push-cert")) {
diff --git a/send-pack.c b/send-pack.c
index 949cb61..3520fe5 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -294,6 +294,8 @@ int send_pack(struct send_pack_args *args,
int use_sideband = 0;
int quiet_supported = 0;
int agent_supported = 0;
+   int atomic_push_supported = 0;
+   int atomic_push = 0;
unsigned cmds_sent = 0;
int ret;
struct async demux;
@@ -314,6 +316,8 @@ int send_pack(struct send_pack_args *args,
agent_supported = 1;
if (server_supports("no-thin"))
args->use_thin_pack = 0;
+   if (server_supports("atomic-push"))
+   atomic_push_supported = 1;
if (args->push_cert) {
int len;
 
@@ -337,6 +341,8 @@ int send_pack(struct send_pack_args *args,
strbuf_addstr(&cap_buf, " quiet");
if (agent_supported)
strbuf_addf(&cap_buf, " agent=%s", git_user_agent_sanitized());
+   if (atomic_push)
+   strbuf_addstr(&cap_buf, " atomic-push");
 
/*
 * NEEDSWORK: why does delete-refs have to be so specific to
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 15/15] refs.c: add an err argument to pack_refs

2014-10-21 Thread Ronnie Sahlberg
Change-Id: I1e65ac429c14f01073d95c6440f820dda1c6091b
Signed-off-by: Ronnie Sahlberg 
---
 builtin/pack-refs.c | 8 +++-
 refs.c  | 7 +++
 refs.h  | 3 ++-
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index b20b1ec..299768e 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -10,6 +10,7 @@ static char const * const pack_refs_usage[] = {
 int cmd_pack_refs(int argc, const char **argv, const char *prefix)
 {
unsigned int flags = PACK_REFS_PRUNE;
+   struct strbuf err = STRBUF_INIT;
struct option opts[] = {
OPT_BIT(0, "all",   &flags, N_("pack everything"), 
PACK_REFS_ALL),
OPT_BIT(0, "prune", &flags, N_("prune loose refs (default)"), 
PACK_REFS_PRUNE),
@@ -17,5 +18,10 @@ int cmd_pack_refs(int argc, const char **argv, const char 
*prefix)
};
if (parse_options(argc, argv, prefix, opts, pack_refs_usage, 0))
usage_with_options(pack_refs_usage, opts);
-   return pack_refs(flags);
+   if (pack_refs(flags, &err)) {
+   error("%s", err.buf);
+   strbuf_release(&err);
+   return -1;
+   }
+   return 0;
 }
diff --git a/refs.c b/refs.c
index 7fb0d6c..a5e1eff 100644
--- a/refs.c
+++ b/refs.c
@@ -2588,16 +2588,15 @@ static void prune_refs(struct ref_to_prune *r)
}
 }
 
-int pack_refs(unsigned int flags)
+int pack_refs(unsigned int flags, struct strbuf *err)
 {
struct pack_refs_cb_data cbdata;
-   struct strbuf err = STRBUF_INIT;
 
memset(&cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
 
-   if (lock_packed_refs(&err))
-   die("%s", err.buf);
+   if (lock_packed_refs(err))
+   return -1;
 
cbdata.packed_refs = get_packed_refs(&ref_cache);
 
diff --git a/refs.h b/refs.h
index f3e08f5..be16c08 100644
--- a/refs.h
+++ b/refs.h
@@ -130,8 +130,9 @@ extern void warn_dangling_symrefs(FILE *fp, const char 
*msg_fmt, const struct st
 /*
  * Write a packed-refs file for the current repository.
  * flags: Combination of the above PACK_REFS_* flags.
+ * Returns 0 on success and fills in err on failure.
  */
-int pack_refs(unsigned int flags);
+int pack_refs(unsigned int flags, struct strbuf *err);
 
 extern int ref_exists(const char *);
 
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/8] t5543-atomic-push.sh: add basic tests for atomic pushes

2014-10-21 Thread Ronnie Sahlberg
Change-Id: I3a6491515b78b564d1cc0892826a4bc77f9bffb0
Signed-off-by: Ronnie Sahlberg 
---
 t/t5543-atomic-push.sh | 101 +
 1 file changed, 101 insertions(+)
 create mode 100755 t/t5543-atomic-push.sh

diff --git a/t/t5543-atomic-push.sh b/t/t5543-atomic-push.sh
new file mode 100755
index 000..4903227
--- /dev/null
+++ b/t/t5543-atomic-push.sh
@@ -0,0 +1,101 @@
+#!/bin/sh
+
+test_description='pushing to a mirror repository'
+
+. ./test-lib.sh
+
+D=`pwd`
+
+invert () {
+   if "$@"; then
+   return 1
+   else
+   return 0
+   fi
+}
+
+mk_repo_pair () {
+   rm -rf master mirror &&
+   mkdir mirror &&
+   (
+   cd mirror &&
+   git init &&
+   git config receive.denyCurrentBranch warn
+   ) &&
+   mkdir master &&
+   (
+   cd master &&
+   git init &&
+   git remote add $1 up ../mirror
+   )
+}
+
+
+test_expect_success 'atomic push works for a single branch' '
+
+   mk_repo_pair &&
+   (
+   cd master &&
+   echo one >foo && git add foo && git commit -m one &&
+   git push --mirror up
+   echo two >foo && git add foo && git commit -m two &&
+   git push --atomic-push --mirror up
+   ) &&
+   master_master=$(cd master && git show-ref -s --verify 
refs/heads/master) &&
+   mirror_master=$(cd mirror && git show-ref -s --verify 
refs/heads/master) &&
+   test "$master_master" = "$mirror_master"
+
+'
+
+test_expect_success 'atomic push works for two branches' '
+
+   mk_repo_pair &&
+   (
+   cd master &&
+   echo one >foo && git add foo && git commit -m one &&
+   git branch second &&
+   git push --mirror up
+   echo two >foo && git add foo && git commit -m two &&
+   git checkout second &&
+   echo three >foo && git add foo && git commit -m three &&
+   git checkout master &&
+   git push --atomic-push --mirror up
+   ) &&
+   master_master=$(cd master && git show-ref -s --verify 
refs/heads/master) &&
+   mirror_master=$(cd mirror && git show-ref -s --verify 
refs/heads/master) &&
+   test "$master_master" = "$mirror_master"
+
+   master_second=$(cd master && git show-ref -s --verify 
refs/heads/second) &&
+   mirror_second=$(cd mirror && git show-ref -s --verify 
refs/heads/second) &&
+   test "$master_second" = "$mirror_second"
+'
+
+# set up two branches where master can be pushed but second can not
+# (non-fast-forward). Since second can not be pushed the whole operation
+# will fail and leave master untouched.
+test_expect_success 'atomic push fails if one branch fails' '
+   mk_repo_pair &&
+   (
+   cd master &&
+   echo one >foo && git add foo && git commit -m one &&
+   git branch second &&
+   git checkout second &&
+   echo two >foo && git add foo && git commit -m two &&
+   echo three >foo && git add foo && git commit -m three &&
+   echo four >foo && git add foo && git commit -m four &&
+   git push --mirror up
+   git reset --hard HEAD~2 &&
+   git checkout master
+   echo five >foo && git add foo && git commit -m five &&
+   ! git push --atomic-push --all up
+   ) &&
+   master_master=$(cd master && git show-ref -s --verify 
refs/heads/master) &&
+   mirror_master=$(cd mirror && git show-ref -s --verify 
refs/heads/master) &&
+   test "$master_master" != "$mirror_master" &&
+
+   master_second=$(cd master && git show-ref -s --verify 
refs/heads/second) &&
+   mirror_second=$(cd mirror && git show-ref -s --verify 
refs/heads/second) &&
+   test "$master_second" != "$mirror_second"
+'
+
+test_done
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 11/15] refs.c: make the *_packed_refs functions static

2014-10-21 Thread Ronnie Sahlberg
We no longer need to expose the lock/add/commit/rollback functions
for packed refs anymore so make them static and remove them from the
public api.

Change-Id: I1059f1690129f0232cb27872ef494024ef7f299e
Signed-off-by: Ronnie Sahlberg 
---
 refs.c |  8 
 refs.h | 30 --
 2 files changed, 4 insertions(+), 34 deletions(-)

diff --git a/refs.c b/refs.c
index fddd59c..1261a78 100644
--- a/refs.c
+++ b/refs.c
@@ -1224,7 +1224,7 @@ static struct ref_dir *get_packed_refs(struct ref_cache 
*refs)
return get_packed_ref_dir(get_packed_ref_cache(refs));
 }
 
-void add_packed_ref(const char *refname, const unsigned char *sha1)
+static void add_packed_ref(const char *refname, const unsigned char *sha1)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
@@ -2393,7 +2393,7 @@ static int write_packed_entry_fn(struct ref_entry *entry, 
void *cb_data)
 }
 
 /* This should return a meaningful errno on failure */
-int lock_packed_refs(int flags)
+static int lock_packed_refs(int flags)
 {
struct packed_ref_cache *packed_ref_cache;
 
@@ -2416,7 +2416,7 @@ int lock_packed_refs(int flags)
  * Commit the packed refs changes.
  * On error we must make sure that errno contains a meaningful value.
  */
-int commit_packed_refs(void)
+static int commit_packed_refs(void)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
@@ -2445,7 +2445,7 @@ int commit_packed_refs(void)
return error;
 }
 
-void rollback_packed_refs(void)
+static void rollback_packed_refs(void)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(&ref_cache);
diff --git a/refs.h b/refs.h
index db435bf..44ae7fe 100644
--- a/refs.h
+++ b/refs.h
@@ -120,36 +120,6 @@ extern void warn_dangling_symref(FILE *fp, const char 
*msg_fmt, const char *refn
 extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct 
string_list *refnames);
 
 /*
- * Lock the packed-refs file for writing.  Flags is passed to
- * hold_lock_file_for_update().  Return 0 on success.
- * Errno is set to something meaningful on error.
- */
-extern int lock_packed_refs(int flags);
-
-/*
- * Add a reference to the in-memory packed reference cache.  This may
- * only be called while the packed-refs file is locked (see
- * lock_packed_refs()).  To actually write the packed-refs file, call
- * commit_packed_refs().
- */
-extern void add_packed_ref(const char *refname, const unsigned char *sha1);
-
-/*
- * Write the current version of the packed refs cache from memory to
- * disk.  The packed-refs file must already be locked for writing (see
- * lock_packed_refs()).  Return zero on success.
- * Sets errno to something meaningful on error.
- */
-extern int commit_packed_refs(void);
-
-/*
- * Rollback the lockfile for the packed-refs file, and discard the
- * in-memory packed reference cache.  (The packed-refs file will be
- * read anew if it is needed again after this function is called.)
- */
-extern void rollback_packed_refs(void);
-
-/*
  * Flags for controlling behaviour of pack_refs()
  * PACK_REFS_PRUNE: Prune loose refs after packing
  * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6/8] receive-pack.c: add a receive.preferatomicpush configuration variable

2014-10-21 Thread Ronnie Sahlberg
Add receive.preferatomicpush setting to receive-pack.c. This triggers
a new capability "prefer-atomic-push" to be sent back to the send-pack
client, requesting the client, if it supports it, to request
an atomic push.

This is an alternative way to trigger an atomic push instead of having
to rely of the user using the --atomic-push command line argument.
For backward compatibility, this is only a hint to the client that is should
request atomic pushes if it can. Old clients that do not support atomic pushes
will just ignore this capability and use a normal push.

The reason we need to signal this capability back to the client is due
to that send_pack() has push failure modes where it will detect that
certain refs can not be pushed and fail them early. Those refs would not
even be sent by the client unless atomic-pushes are activated.
This means that IF we activate this feature from the server side we must
tell the client to not fail refs early and use an atomic push. We can not
enforce this on the server side only.

Change-Id: I6677cd565f48a09bb552fe3f4c00bbb6d343c224
Signed-off-by: Ronnie Sahlberg 
---
 Documentation/config.txt  |  4 +++
 Documentation/technical/protocol-capabilities.txt | 13 ++---
 builtin/receive-pack.c|  8 ++
 send-pack.c   |  2 ++
 t/t5543-atomic-push.sh| 32 +++
 5 files changed, 56 insertions(+), 3 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 400dcad..78c427e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2135,6 +2135,10 @@ receive.shallowupdate::
If set to true, .git/shallow can be updated when new refs
require new shallow roots. Otherwise those refs are rejected.
 
+receive.preferatomicpush::
+   This option is used in receive-pack to tell the client to try
+   to use an atomic push, if the client supports it.
+
 remote.pushdefault::
The remote to push to by default.  Overrides
`branch..remote` for all branches, and is overridden by
diff --git a/Documentation/technical/protocol-capabilities.txt 
b/Documentation/technical/protocol-capabilities.txt
index 26bc5b1..78c5469 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -18,9 +18,9 @@ was sent.  Server MUST NOT ignore capabilities that client 
requested
 and server advertised.  As a consequence of these rules, server MUST
 NOT advertise capabilities it does not understand.
 
-The 'atomic-push', 'report-status', 'delete-refs', 'quiet', and 'push-cert'
-capabilities are sent and recognized by the receive-pack (push to server)
-process.
+The 'atomic-push', 'report-status', 'delete-refs', 'prefer-atomic-push',
+'quiet', and 'push-cert' capabilities are sent and recognized by the
+receive-pack (push to server) process.
 
 The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized
 by both upload-pack and receive-pack protocols.  The 'agent' capability
@@ -252,6 +252,13 @@ If the server sends the 'atomic-push' capability, it means 
it is
 capable of accepting atomic pushes. If the pushing client requests this
 capability, the server will update the refs in one single atomic transaction.
 
+prefer-atomic-push
+--
+
+If the receive-pack server advertises the 'prefer-atomic-push' capability,
+it means that the client should use an atomic push, if the client supports it,
+even if the user did not request it explicitly.
+
 allow-tip-sha1-in-want
 --
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 6991d22..697f102 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -52,6 +52,7 @@ static const char *head_name;
 static void *head_name_to_free;
 static int sent_capabilities;
 static int shallow_update;
+static int prefer_atomic_push;
 static const char *alt_shallow_file;
 static struct strbuf push_cert = STRBUF_INIT;
 static unsigned char push_cert_sha1[20];
@@ -160,6 +161,11 @@ static int receive_pack_config(const char *var, const char 
*value, void *cb)
return 0;
}
 
+   if (strcmp(var, "receive.preferatomicpush") == 0) {
+   prefer_atomic_push = git_config_bool(var, value);
+   return 0;
+   }
+
return git_default_config(var, value, cb);
 }
 
@@ -178,6 +184,8 @@ static void show_ref(const char *path, const unsigned char 
*sha1)
  "atomic-push");
if (prefer_ofs_delta)
strbuf_addstr(&cap, " ofs-delta");
+   if (prefer_atomic_push)
+   strbuf_addstr(&cap, " prefer-atomic-push");
if (push_cert_nonce)
strbuf_addf(&cap, " push-cert=%s", push_cert_nonce);
strbuf_addf(&cap, " agent=%s", git_user_agent_sanitized());
diff --git a/send-pac

[PATCH 12/15] refs.c: replace the onerr argument in update_ref with a strbuf err

2014-10-21 Thread Ronnie Sahlberg
Get rid of the action_on_err enum and replace the action argument to
update_ref with a strbuf *err for error reporting.

Update all callers to the new api including two callers in transport*.c
which used the literal 0 instead of an enum.

Change-Id: I8ee1540380393380b5a06db380fb8491bfe1ecdd
Signed-off-by: Ronnie Sahlberg 
---
 builtin/checkout.c   |  7 +--
 builtin/clone.c  | 20 
 builtin/merge.c  | 20 +---
 builtin/notes.c  | 24 ++--
 builtin/reset.c  | 12 
 builtin/update-ref.c |  7 +--
 notes-cache.c|  2 +-
 notes-utils.c|  5 +++--
 refs.c   | 14 +++---
 refs.h   | 10 ++
 transport-helper.c   |  7 ++-
 transport.c  |  9 ++---
 12 files changed, 78 insertions(+), 59 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 8550b6d..60a68f7 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -584,6 +584,8 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
 {
struct strbuf msg = STRBUF_INIT;
const char *old_desc, *reflog_msg;
+   struct strbuf err = STRBUF_INIT;
+
if (opts->new_branch) {
if (opts->new_orphan_branch) {
if (opts->new_branch_log && !log_all_ref_updates) {
@@ -621,8 +623,9 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) {
/* Nothing to do. */
} else if (opts->force_detach || !new->path) {  /* No longer on any 
branch. */
-   update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
-  REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
+  REF_NODEREF, &err))
+   die("%s", err.buf);
if (!opts->quiet) {
if (old->path && advice_detached_head)
detach_advice(new->name);
diff --git a/builtin/clone.c b/builtin/clone.c
index 5052fac..e0a671d 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -522,6 +522,7 @@ static void write_remote_refs(const struct ref *local_refs)
 static void write_followtags(const struct ref *refs, const char *msg)
 {
const struct ref *ref;
+   struct strbuf err = STRBUF_INIT;
for (ref = refs; ref; ref = ref->next) {
if (!starts_with(ref->name, "refs/tags/"))
continue;
@@ -529,8 +530,9 @@ static void write_followtags(const struct ref *refs, const 
char *msg)
continue;
if (!has_sha1_file(ref->old_sha1))
continue;
-   update_ref(msg, ref->name, ref->old_sha1,
-  NULL, 0, UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg, ref->name, ref->old_sha1,
+  NULL, 0, &err))
+   die("%s", err.buf);
}
 }
 
@@ -593,28 +595,30 @@ static void update_remote_refs(const struct ref *refs,
 static void update_head(const struct ref *our, const struct ref *remote,
const char *msg)
 {
+   struct strbuf err = STRBUF_INIT;
const char *head;
if (our && skip_prefix(our->name, "refs/heads/", &head)) {
/* Local default branch link */
create_symref("HEAD", our->name, NULL);
if (!option_bare) {
-   update_ref(msg, "HEAD", our->old_sha1, NULL, 0,
-  UPDATE_REFS_DIE_ON_ERR);
+   update_ref(msg, "HEAD", our->old_sha1, NULL, 0, &err);
install_branch_config(0, head, option_origin, 
our->name);
}
} else if (our) {
struct commit *c = lookup_commit_reference(our->old_sha1);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
-   update_ref(msg, "HEAD", c->object.sha1,
-  NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+   if (update_ref(msg, "HEAD", c->object.sha1,
+  NULL, REF_NODEREF, &err))
+   die("%s", err.buf);
} else if (remote) {
/*
 * We know remote HEAD points to a non-branch, or
 * HEAD points to a branch but we don't know which one.
 * Detach HEAD in all these cases.
 */
-   update_ref(msg, "HEAD", remote->old_sha1,
-  NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
+ if (update_ref(msg, "HEAD", remote->old_sha1,
+NULL, REF_NODEREF, &err))
+   die("%s", err.buf);
}
 }
 
diff --git a/builtin/merge.c b/builtin/merge.c
index bebbe5b..a787b6a 100644
--- a/builtin

[PATCH 0/8] ref-transaction-send-pack

2014-10-21 Thread Ronnie Sahlberg
List,

This series has been posted before but is now rebased on the previous
ref-transaction-rename series that are against next.
This series can also be found at :
https://github.com/rsahlberg/git/tree/ref-transactions-send-pack

This series finishes the transaction work to provide atomic pushes.
With this series we can now perform atomic pushes to a repository.



Ronnie Sahlberg (8):
  receive-pack.c: add protocol support to negotiate atomic-push
  send-pack.c: add an --atomic-push command line argument
  receive-pack.c: use a single transaction when atomic-push is
negotiated
  push.c: add an --atomic-push argument
  t5543-atomic-push.sh: add basic tests for atomic pushes
  receive-pack.c: add a receive.preferatomicpush configuration variable
  refs.c: add an err argument to create_reflog
  refs.c: add an err argument to create_symref

 Documentation/config.txt  |   4 +
 Documentation/git-push.txt|   7 +-
 Documentation/git-send-pack.txt   |   7 +-
 Documentation/technical/protocol-capabilities.txt |  19 +++-
 builtin/branch.c  |   7 +-
 builtin/checkout.c|  21 +++-
 builtin/clone.c   |  15 ++-
 builtin/init-db.c |   8 +-
 builtin/notes.c   |   7 +-
 builtin/push.c|   2 +
 builtin/receive-pack.c|  87 +++---
 builtin/remote.c  |  26 +++--
 builtin/send-pack.c   |   6 +-
 builtin/symbolic-ref.c|   6 +-
 cache.h   |   1 -
 refs.c|  93 ---
 refs.h|   5 +-
 remote.h  |   3 +-
 send-pack.c   |  47 +++-
 send-pack.h   |   1 +
 t/t5543-atomic-push.sh| 133 ++
 transport.c   |   5 +
 transport.h   |   1 +
 23 files changed, 411 insertions(+), 100 deletions(-)
 create mode 100755 t/t5543-atomic-push.sh

-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/8] send-pack.c: add an --atomic-push command line argument

2014-10-21 Thread Ronnie Sahlberg
This adds support to send-pack to to negotiate and use atomic pushes
iff the server supports it. Atomic pushes are activated by a new command
line flag --atomic-push.

In order to do this we also need to change the semantics for send_pack()
slightly. The existing send_pack() function actually don't sent all the
refs back to the server when multiple refs are involved, for example
when using --all. Several of the failure modes for pushes can already be
detected locally in the send_pack client based on the information from the
initial server side list of all the refs as generated by receive-pack.
Any such refs that we thus know would fail to push are thus pruned from
the list of refs we send to the server to update.

For atomic pushes, we have to deal thus with both failures that are detected
locally as well as failures that are reported back from the server. In order
to do so we treat all local failures as push failures too.

We introduce a new status code REF_STATUS_ATOMIC_PUSH_FAILED so we can
flag all refs that we would normally have tried to push to the server
but we did not due to local failures. This is to improve the error message
back to the end user to flag that "these refs failed to update since the
atomic push operation failed."

Change-Id: Ifbcdc10c032a51d317ae7a6eacc03cf32e660bbe
Signed-off-by: Ronnie Sahlberg 
---
 Documentation/git-send-pack.txt |  7 ++-
 builtin/send-pack.c |  6 +-
 remote.h|  3 ++-
 send-pack.c | 39 ++-
 send-pack.h |  1 +
 transport.c |  4 
 6 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/Documentation/git-send-pack.txt b/Documentation/git-send-pack.txt
index 2a0de42..8f64feb 100644
--- a/Documentation/git-send-pack.txt
+++ b/Documentation/git-send-pack.txt
@@ -9,7 +9,7 @@ git-send-pack - Push objects over Git protocol to another 
repository
 SYNOPSIS
 
 [verse]
-'git send-pack' [--all] [--dry-run] [--force] 
[--receive-pack=] [--verbose] [--thin] [:] 
[...]
+'git send-pack' [--all] [--dry-run] [--force] 
[--receive-pack=] [--verbose] [--thin] [--atomic-push] 
[:] [...]
 
 DESCRIPTION
 ---
@@ -62,6 +62,11 @@ be in a separate packet, and the list must end with a flush 
packet.
Send a "thin" pack, which records objects in deltified form based
on objects not included in the pack to reduce network traffic.
 
+--atomic-push::
+   With atomic-push all refs are updated in one single atomic transaction.
+   This means that if any of the refs fails then the entire push will
+   fail without changing any refs.
+
 ::
A remote host to house the repository.  When this
part is specified, 'git-receive-pack' is invoked via
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index b564a77..93cb17c 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -13,7 +13,7 @@
 #include "sha1-array.h"
 
 static const char send_pack_usage[] =
-"git send-pack [--all | --mirror] [--dry-run] [--force] 
[--receive-pack=] [--verbose] [--thin] [:] 
[...]\n"
+"git send-pack [--all | --mirror] [--dry-run] [--force] 
[--receive-pack=] [--verbose] [--thin] [--atomic-push] 
[:] [...]\n"
 "  --all and explicit  specification are mutually exclusive.";
 
 static struct send_pack_args args;
@@ -170,6 +170,10 @@ int cmd_send_pack(int argc, const char **argv, const char 
*prefix)
args.use_thin_pack = 1;
continue;
}
+   if (!strcmp(arg, "--atomic-push")) {
+   args.use_atomic_push = 1;
+   continue;
+   }
if (!strcmp(arg, "--stateless-rpc")) {
args.stateless_rpc = 1;
continue;
diff --git a/remote.h b/remote.h
index 8b62efd..f346524 100644
--- a/remote.h
+++ b/remote.h
@@ -115,7 +115,8 @@ struct ref {
REF_STATUS_REJECT_SHALLOW,
REF_STATUS_UPTODATE,
REF_STATUS_REMOTE_REJECT,
-   REF_STATUS_EXPECTING_REPORT
+   REF_STATUS_EXPECTING_REPORT,
+   REF_STATUS_ATOMIC_PUSH_FAILED
} status;
char *remote_status;
struct ref *peer_ref; /* when renaming */
diff --git a/send-pack.c b/send-pack.c
index 3520fe5..5208305 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -190,7 +190,7 @@ static void advertise_shallow_grafts_buf(struct strbuf *sb)
for_each_commit_graft(advertise_shallow_grafts_cb, sb);
 }
 
-static int ref_update_to_be_sent(const struct ref *ref, const struct 
send_pack_args *args)
+static int ref_update_to_be_sent(const struct ref *ref, const struct 
send_pack_args *args, int *atomic_push_failed)
 {
if (!ref->peer_ref && !args->send_mirror)
return 0;
@@ -203,6 +203,13 @@ static int ref_update_to_b

[PATCH 7/8] refs.c: add an err argument to create_reflog

2014-10-21 Thread Ronnie Sahlberg
Add err argument to create_reflog that can explain the reason for a
failure. This then eliminates the need to manage errno through this
function since we can just add strerror(errno) to the err string when
meaningful. No callers relied on errno from this function for anything
else than the error message.

log_ref_write is a private function that calls create_reflog. Update
this function to also take an err argument and pass it back to the caller.
This again eliminates the need to manage errno in this function.

Update the private function write_sha1_update_reflog to also take an
err argument.

Change-Id: I8f796a8c0c5f5d3f26e3e59fbc6421c894a4e814
Signed-off-by: Ronnie Sahlberg 
---
 builtin/checkout.c |  8 +++---
 refs.c | 71 +++---
 refs.h |  4 +--
 3 files changed, 42 insertions(+), 41 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 60a68f7..d9cb9c3 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -590,10 +590,12 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
if (opts->new_orphan_branch) {
if (opts->new_branch_log && !log_all_ref_updates) {
char *ref_name = mkpath("refs/heads/%s", 
opts->new_orphan_branch);
+   struct strbuf err = STRBUF_INIT;
 
-   if (create_reflog(ref_name)) {
-   fprintf(stderr, _("Can not do reflog 
for '%s'\n"),
-   opts->new_orphan_branch);
+   if (create_reflog(ref_name, &err)) {
+   fprintf(stderr, _("Can not do reflog 
for '%s'. %s\n"),
+   opts->new_orphan_branch, err.buf);
+   strbuf_release(&err);
return;
}
}
diff --git a/refs.c b/refs.c
index a5e1eff..4d30623 100644
--- a/refs.c
+++ b/refs.c
@@ -2889,8 +2889,7 @@ static int copy_msg(char *buf, const char *msg)
return cp - buf;
 }
 
-/* This function must set a meaningful errno on failure */
-int create_reflog(const char *refname)
+int create_reflog(const char *refname, struct strbuf *err)
 {
int logfd, oflags = O_APPEND | O_WRONLY;
char logfile[PATH_MAX];
@@ -2901,9 +2900,8 @@ int create_reflog(const char *refname)
starts_with(refname, "refs/notes/") ||
!strcmp(refname, "HEAD")) {
if (safe_create_leading_directories(logfile) < 0) {
-   int save_errno = errno;
-   error("unable to create directory for %s", logfile);
-   errno = save_errno;
+   strbuf_addf(err, "unable to create directory for %s. "
+   "%s", logfile, strerror(errno));
return -1;
}
oflags |= O_CREAT;
@@ -2916,20 +2914,16 @@ int create_reflog(const char *refname)
 
if ((oflags & O_CREAT) && errno == EISDIR) {
if (remove_empty_directories(logfile)) {
-   int save_errno = errno;
-   error("There are still logs under '%s'",
- logfile);
-   errno = save_errno;
+   strbuf_addf(err, "There are still logs under "
+   "'%s'", logfile);
return -1;
}
logfd = open(logfile, oflags, 0666);
}
 
if (logfd < 0) {
-   int save_errno = errno;
-   error("Unable to append to %s: %s", logfile,
- strerror(errno));
-   errno = save_errno;
+   strbuf_addf(err, "Unable to append to %s: %s",
+   logfile, strerror(errno));
return -1;
}
}
@@ -2966,7 +2960,8 @@ static int log_ref_write_fd(int fd, const unsigned char 
*old_sha1,
 }
 
 static int log_ref_write(const char *refname, const unsigned char *old_sha1,
-const unsigned char *new_sha1, const char *msg)
+const unsigned char *new_sha1, const char *msg,
+struct strbuf *err)
 {
int logfd, result = 0, oflags = O_APPEND | O_WRONLY;
char log_file[PATH_MAX];
@@ -2975,7 +2970,7 @@ static int log_ref_write(const char *refname, const 
unsigned char *old_sha1,
log_all_ref_updates = !is_bare_repository();
 
if (log_all_ref_updates && !reflog_exists(refname))
-   result = create_reflog(refname);
+   result = cre

[PATCH 06/15] refs.c: rollback the lockfile before we die() in repack_without_refs

2014-10-21 Thread Ronnie Sahlberg
commit 3989c2a763c3b355785d609b3144c7935dffb273 upstream.

Change-Id: I63a22da521ecc8eb60d7a8aaa5af666d2827a599
Signed-off-by: Ronnie Sahlberg 
Signed-off-by: Jonathan Nieder 
---
 refs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index f43fef4..43df656 100644
--- a/refs.c
+++ b/refs.c
@@ -2702,8 +2702,10 @@ int repack_without_refs(struct string_list *without, 
struct strbuf *err)
/* Remove any other accumulated cruft */
do_for_each_entry_in_dir(packed, 0, curate_packed_ref_fn, 
&refs_to_delete);
for_each_string_list_item(ref_to_delete, &refs_to_delete) {
-   if (remove_entry(packed, ref_to_delete->string) == -1)
+   if (remove_entry(packed, ref_to_delete->string) == -1) {
+   rollback_packed_refs();
die("internal error");
+   }
}
 
/* Write what remains */
-- 
2.1.0.rc2.206.gedb03e5

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/8] receive-pack.c: use a single transaction when atomic-push is negotiated

2014-10-21 Thread Ronnie Sahlberg
Update receive-pack to use an atomic transaction iff the client negotiated
that it wanted atomic-push.
This leaves the default behavior to be the old non-atomic one ref at a
time update. This is to cause as little disruption as possible to existing
clients. It is unknown if there are client scripts that depend on the old
non-atomic behavior so we make it opt-in for now.

Later patch in this series also adds a configuration variable where you can
override the atomic push behavior on the receiving repo and force it
to use atomic updates always.

If it turns out over time that there are no client scripts that depend on the
old behavior we can change git to default to use atomic pushes and instead
offer an opt-out argument for people that do not want atomic pushes.

Change-Id: Ice9739aa2676f76d2e7fab2d54f37047b2eb277e
Signed-off-by: Ronnie Sahlberg 
---
 builtin/receive-pack.c | 73 +++---
 1 file changed, 58 insertions(+), 15 deletions(-)

diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index b8ffd9e..6991d22 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -67,6 +67,8 @@ static const char *NONCE_SLOP = "SLOP";
 static const char *nonce_status;
 static long nonce_stamp_slop;
 static unsigned long nonce_stamp_slop_limit;
+struct strbuf err = STRBUF_INIT;
+struct transaction *transaction;
 
 static enum deny_action parse_deny_action(const char *var, const char *value)
 {
@@ -827,33 +829,55 @@ static const char *update(struct command *cmd, struct 
shallow_info *si)
cmd->did_not_exist = 1;
}
}
-   if (delete_ref(namespaced_name, old_sha1, 0)) {
-   rp_error("failed to delete %s", name);
-   return "failed to delete";
+   if (!use_atomic_push) {
+   if (delete_ref(namespaced_name, old_sha1, 0)) {
+   rp_error("failed to delete %s", name);
+   return "failed to delete";
+   }
+   } else {
+   if (transaction_delete_ref(transaction,
+  namespaced_name,
+  old_sha1,
+  0, old_sha1 != NULL,
+  "push", &err)) {
+   rp_error("%s", err.buf);
+   strbuf_release(&err);
+   return "failed to delete";
+   }
}
return NULL; /* good */
}
else {
-   struct strbuf err = STRBUF_INIT;
-   struct transaction *transaction;
-
if (shallow_update && si->shallow_ref[cmd->index] &&
update_shallow_ref(cmd, si))
return "shallow error";
 
-   transaction = transaction_begin(&err);
-   if (!transaction ||
-   transaction_update_ref(transaction, namespaced_name,
-  new_sha1, old_sha1, 0, 1, "push",
-  &err) ||
-   transaction_commit(transaction, &err)) {
-   transaction_free(transaction);
+   if (!use_atomic_push) {
+   transaction = transaction_begin(&err);
+   if (!transaction) {
+   rp_error("%s", err.buf);
+   strbuf_release(&err);
+   return "failed to start transaction";
+   }
+   }
+   if (transaction_update_ref(transaction,
+  namespaced_name,
+  new_sha1, old_sha1,
+  0, 1, "push",
+  &err)) {
rp_error("%s", err.buf);
strbuf_release(&err);
return "failed to update ref";
}
-
-   transaction_free(transaction);
+   if (!use_atomic_push) {
+   if (transaction_commit(transaction, &err)) {
+   transaction_free(transaction);
+   rp_error("%s", err.buf);
+   strbuf_release(&err);
+   return "failed to update ref";
+   }
+   transaction_free(transaction);
+   }
strbuf_release(&err);
return NULL; /* good */
}
@@ -1053,6 +1077,16 @@ static void execute_commands(struct command *commands,
return;
}
 
+   if (use_atomic_push) {
+   transacti

Re: [PATCH] git-quiltimport.sh: disallow fuzz

2014-10-21 Thread Junio C Hamano
Junio C Hamano  writes:

> Things might have been different if this were mid 2006 or early
> 2007, but I am afraid that "the spirit of git" with a quote from
> Linus no longer carries much weight on this particular issue.  A
> backward incompatible change is backward incompatible change that
> breaks existing users no matter how loudly you (and I) shout that it
> is the right thing to do in the long run.
>
> Let's have it the other way around, keep the same behaviour for
> those who run the command without the new option, while allowing
> people who know better and are aligned with the spirit of git to
> pass the parameter, at least for now, with a note in the
> documentation to warn that the default may change in the future to
> allow no fuzz, or something.

I was waiting to hear an Ack or some comments and then forgot about
this topic.

I'll send two patches, one is essentially yours *but* does not
flip the default (i.e. those who want to be safe have to be explicit
about it), and then the other is to flip the default but more gently.

Here is the first one.  I'll send the "default flipping" as a reply
to this message.

-- >8 --
From: Joern Engel 
Date: Thu, 25 Sep 2014 18:08:31 -0400
Subject: [PATCH 1/2] git-quiltimport.sh: allow declining fuzz with --exact 
option

git-quiltimport unconditionally passes "-C1" to "git apply",
supposedly to roughly match the quilt default of --fuzz 2.  Allow
users to pass --exact option to disable it, requiring the patch to
apply without any fuzz.

Also note that -C1 and fuzz=2 is not identical.  Most patches have
three lines of context, so fuzz=2 leaves one relevant line of
context.  But for any patches with more or less context this is not
true.  git-apply has no option for fuzz, so any emulation will
always be best-effort.

Signed-off-by: Joern Engel 
Signed-off-by: Junio C Hamano 
---
 Documentation/git-quiltimport.txt | 12 
 git-quiltimport.sh| 17 -
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/Documentation/git-quiltimport.txt 
b/Documentation/git-quiltimport.txt
index a356196..109918d 100644
--- a/Documentation/git-quiltimport.txt
+++ b/Documentation/git-quiltimport.txt
@@ -49,6 +49,18 @@ The default for the patch directory is patches
 or the value of the $QUILT_PATCHES environment
 variable.
 
+-C ::
+   Pass `-C` to underlying `git apply` when applying
+   the patch, to reduce number of context lines to be matched.
+   By default, `-C1` is passed to `git apply` to emulate the
+   `--fuzz=2` behaviour of quilt (assuming the standard 3
+   context lines).
+
+--exact::
+   Do not pass any `-C` option to `git apply` when
+   applying the patch, to require context lines to fully match.
+
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/git-quiltimport.sh b/git-quiltimport.sh
index 167d79f..929365f 100755
--- a/git-quiltimport.sh
+++ b/git-quiltimport.sh
@@ -6,6 +6,8 @@ git quiltimport [options]
 --
 n,dry-run dry run
 author=   author name and email address for patches without any
+C=minimum context (see git apply)
+exact allow no-fuzz
 patches=  path to the quilt series and patches
 "
 SUBDIRECTORY_ON=Yes
@@ -13,6 +15,7 @@ SUBDIRECTORY_ON=Yes
 
 dry_run=""
 quilt_author=""
+cflag=-C1
 while test $# != 0
 do
case "$1" in
@@ -20,6 +23,18 @@ do
shift
quilt_author="$1"
;;
+   -C)
+   shift
+   # ensure numerical parameter
+   case "$1" in
+   ''|*[!0-9]*) usage;;
+   *) ;;
+   esac
+   cflag="-C$1"
+   ;;
+   --exact)
+   cflag=
+   ;;
-n|--dry-run)
dry_run=1
;;
@@ -130,7 +145,7 @@ do
fi
 
if [ -z "$dry_run" ] ; then
-   git apply --index -C1 ${level:+"$level"} "$tmp_patch" &&
+   git apply --index $cflag ${level:+"$level"} "$tmp_patch" &&
tree=$(git write-tree) &&
commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git 
commit-tree $tree -p $commit) &&
git update-ref -m "quiltimport: $patch_name" HEAD $commit || 
exit 4
-- 
2.1.2-583-g325e495

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] git-quiltimport: flip the default not to allow fuzz

2014-10-21 Thread Junio C Hamano
Trying to be as strict as possible when applying the patch may be a
good discipline, so let's flip the default but we can be helpful to
those who do rely on the original behaviour thanks to the previous
change to add -C$n option.

Suggest using -C1 when (and only when):

 - "git apply" without fuzz fails to apply; and
 - the user did not specify a -C$n or --exact option; and
 - "git apply -C1" (old behaviour) would have succeeded.

Signed-off-by: Junio C Hamano 
---

 * And this is the "flipping of the default"

 git-quiltimport.sh | 26 --
 1 file changed, 24 insertions(+), 2 deletions(-)

diff --git a/git-quiltimport.sh b/git-quiltimport.sh
index 929365f..1190eb9 100755
--- a/git-quiltimport.sh
+++ b/git-quiltimport.sh
@@ -15,7 +15,8 @@ SUBDIRECTORY_ON=Yes
 
 dry_run=""
 quilt_author=""
-cflag=-C1
+cflag=
+fuzz_specified=
 while test $# != 0
 do
case "$1" in
@@ -31,9 +32,11 @@ do
*) ;;
esac
cflag="-C$1"
+   fuzz_specified=yes
;;
--exact)
cflag=
+   fuzz_specified=yes
;;
-n|--dry-run)
dry_run=1
@@ -74,6 +77,25 @@ tmp_msg="$tmp_dir/msg"
 tmp_patch="$tmp_dir/patch"
 tmp_info="$tmp_dir/info"
 
+# Helper to warn about -C$n option
+do_apply () {
+   if git apply --index ${cflag+"$cflag"} "$@"
+   then
+   return
+   fi
+   if test -z "$fuzz_specified" &&
+  git apply --check --index -C1 "$@" >/dev/null 2>&1
+   then
+   cat >&2 <<-\EOM
+   'git quiltimport' by default no longer attempts to apply
+   patches with reduced context lines to allow fuzz; if you
+   want the old 'unsafe' behaviour, run the command with -C1
+   option.
+   EOM
+
+   fi
+   return 1
+}
 
 # Find the initial commit
 commit=$(git rev-parse HEAD)
@@ -145,7 +167,7 @@ do
fi
 
if [ -z "$dry_run" ] ; then
-   git apply --index $cflag ${level:+"$level"} "$tmp_patch" &&
+   do_apply ${level:+"$level"} "$tmp_patch" &&
tree=$(git write-tree) &&
commit=$( (echo "$SUBJECT"; echo; cat "$tmp_msg") | git 
commit-tree $tree -p $commit) &&
git update-ref -m "quiltimport: $patch_name" HEAD $commit || 
exit 4
-- 
2.1.2-583-g325e495

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] doc: fix 'git status --help' character quoting

2014-10-21 Thread Philip Oakley

From: "Junio C Hamano" 

Junio C Hamano  writes:


"Philip Oakley"  writes:


From: "Junio C Hamano" 
...

I think it is just the font. I just opened the above page with
Chrome and futzed the text from '0' to '0123456789' to see how it
look.  That round thing is consistent with how other digits are
rendered.

https://plus.google.com/u/0/+JunioCHamano/posts/dzNXV2FwP6K

(sorry for a URL to plus)


https://www.kernel.org/pub/software/scm/git/docs/git-status.html
(which IIUC is out of date) has an unformatted 0.

--


I've just had a look at how it formats when the zero is back-tick
quoted s /ASCII 0/ASCII `0`/ and it looks OK with both Chromium and
Firefox on my hack Ubuntu laptop - the character is colourised and
full sized, and the --man page output looks unchanged and clearly a
zero.

my hacky attempt at an in-line patch (squash in?) below:


You'd need a matching change to 34 in the same document to preserve
the consistency the original patch sought, though ;-)


Not that I think such a change makes much sense.

If there was a way to force use of a font whose numerals and I/O are
more clearly distinguishable and we do so for all HTML documents we
generate, that would be a good change that is not limited to these
places, though.

I've generated a patch for the 'git status --help' that can act as a 
reference. (to follow)


For me it's only those pages that have a lone zero that cause problems 
due to lack of context. It'll still be a slow burner problem as lone 
zeros are spotted.


Philip 


--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] doc: 'git status' quote the zero (NUL) character

2014-10-21 Thread Philip Oakley
Newer web rendering of 'git status --help --web' shows the zero in
"NUL (ASCII 0)" as if it is a small 'o' character. Back-tick quote the
zero to ensure it is displayed as a full size mono-spaced font. Also
display the "double quote (ASCII 34)" in the same manner.

Signed-off-by: Philip Oakley 
---
 Documentation/git-status.txt | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-status.txt b/Documentation/git-status.txt
index 4d8d530..24390d6 100644
--- a/Documentation/git-status.txt
+++ b/Documentation/git-status.txt
@@ -122,7 +122,7 @@ status code.
 The fields (including the `->`) are separated from each other by a
 single space. If a filename contains whitespace or other nonprintable
 characters, that field will be quoted in the manner of a C string
-literal: surrounded by ASCII double quote (34) characters, and with
+literal: surrounded by double quote (ASCII `34`) characters, and with
 interior special characters backslash-escaped.
 
 For paths with merge conflicts, `X` and `Y` show the modification
@@ -189,7 +189,7 @@ There is also an alternate -z format recommended for 
machine parsing. In
 that format, the status field is the same, but some other things
 change.  First, the '\->' is omitted from rename entries and the field
 order is reversed (e.g 'from \-> to' becomes 'to from'). Second, a NUL
-(ASCII 0) follows each filename, replacing space as a field separator
+(ASCII `0`) follows each filename, replacing space as a field separator
 and the terminating newline (but a space still separates the status
 field from the first filename).  Third, filenames containing special
 characters are not specially formatted; no quoting or
-- 
1.9.4.msysgit.0

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git reflog --date

2014-10-21 Thread Junio C Hamano
Junio C Hamano  writes:

> John Tapsell  writes:
>
>> For me, writing "git reflog @{now}"  is a lot less intuitive than "git
>> reflog --date"
>>
>> Currently the top google search for this question is here:
>>
>> http://stackoverflow.com/questions/17369254/is-there-a-way-to-cause-git-reflog-to-show-a-date-alongside-each-entry
>>
>> Which doesn't mention "@{now}"   at all.
>
> I would say that a site where cluelesses attempt to lead other
> cluelesses is not the best source of information ;-), but that tells
> us that either our docs are not read by people or they do not give
> necessary information to them clearly enough.

And it turns out it is a little bit of both.  We have this shown in
"git log --help":

-g::
--walk-reflogs::
...
By default, 'commit@\{Nth}' notation is
used in the output.  When the starting commit is specified as
'commit@\{now}', output also uses 'commit@\{timestamp}' notation
instead.

and "git reflog --help" says that "It is an alias for git log -g
--abbrev-commit --pretty=oneline; see git-log(1)." in fairly early
part of its description.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] grep: fix match highlighting for combined patterns with context lines

2014-10-21 Thread Junio C Hamano
Junio C Hamano  writes:

> If your goal is to stop colouring words on context and other kinds
> of lines, do you still need the "while (next_match(...))" loop for
> them?  Can't you make the resulting code clearer by restructuring
> the inside of the whole "if (opt->color)" block further, something
> along the lines of...
> Hmm?

It turns out that the result of such a change becomes more readable
than the original, in that it makes it clear that reinspection of
the lines are done only for matched ones and not context lines.

The diff looks unnecessarily noisy because it indents the while ()
loop that is only needed for sign == ':', though.

 grep.c | 42 ++
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/grep.c b/grep.c
index c668034..b363a94 100644
--- a/grep.c
+++ b/grep.c
@@ -1112,31 +1112,33 @@ static void show_line(struct grep_opt *opt, char *bol, 
char *eol,
output_sep(opt, sign);
}
if (opt->color) {
-   regmatch_t match;
-   enum grep_context ctx = GREP_CONTEXT_BODY;
-   int ch = *eol;
-   int eflags = 0;
+   if (sign == ':') {
+   /* paint the hits on matched lines */
+   regmatch_t match;
+   enum grep_context ctx = GREP_CONTEXT_BODY;
+   int ch = *eol;
+   int eflags = 0;
 
-   if (sign == ':')
line_color = opt->color_selected;
-   else if (sign == '-')
+   *eol = '\0';
+   while (next_match(opt, bol, eol, ctx, &match, eflags)) {
+   if (match.rm_so == match.rm_eo)
+   break;
+
+   output_color(opt, bol, match.rm_so, line_color);
+   output_color(opt, bol + match.rm_so,
+match.rm_eo - match.rm_so,
+opt->color_match);
+   bol += match.rm_eo;
+   rest -= match.rm_eo;
+   eflags = REG_NOTBOL;
+   }
+   *eol = ch;
+   } else if (sign == '-') {
line_color = opt->color_context;
-   else if (sign == '=')
+   } else if (sign == '=') {
line_color = opt->color_function;
-   *eol = '\0';
-   while (next_match(opt, bol, eol, ctx, &match, eflags)) {
-   if (match.rm_so == match.rm_eo)
-   break;
-
-   output_color(opt, bol, match.rm_so, line_color);
-   output_color(opt, bol + match.rm_so,
-match.rm_eo - match.rm_so,
-opt->color_match);
-   bol += match.rm_eo;
-   rest -= match.rm_eo;
-   eflags = REG_NOTBOL;
}
-   *eol = ch;
}
output_color(opt, bol, rest, line_color);
opt->output(opt, "\n", 1);
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: git reflog --date

2014-10-21 Thread Junio C Hamano
John Tapsell  writes:

> On 21 October 2014 19:06, Junio C Hamano  wrote:
>> John Tapsell  writes:
>>
>>> For me, writing "git reflog @{now}"  is a lot less intuitive than "git
>>> reflog --date"
>>>
>>> Currently the top google search for this question is here:
>>>
>>> http://stackoverflow.com/questions/17369254/is-there-a-way-to-cause-git-reflog-to-show-a-date-alongside-each-entry
>>>
>>> Which doesn't mention "@{now}"   at all.
>>
>> I would say that a site where cluelesses attempt to lead other
>> cluelesses is not the best source of information ;-), but that tells
>> us that either our docs are not read by people or they do not give
>> necessary information to them clearly enough.
>>
>>> My opinion:
>>>
>>> 1. Add --date   as an option to reflog.  Perhaps using the log.date
>>> format as the default.
>>> 2. Document --date in the man page for "git reflog"
>>> 3. Document @{now}  in the man page for "git reflog"
>>>
>>> Sound good?
>>
>> The order of changes is questionable, but other than that, I think
>> that would be a good way forward.
>
> Great - now I just need to persuade someone very nice nicely.. :-)

You should note that #1 is unworkable, as it would make:

$ git log -g --date default

ambiguous.  Is it asking the timed reflog output using log.date
format on the "default" branch, or is it asking the timed reflog
output using the "default" time format on the HEAD?

You would need to disambiguate by

$ git log -g --date -- default ;# on default branch
$ git log -g --date default -- ;# using default time format

or something, which means --date can be the last dashed option on
the command line, and also you close the door for us to ever add
another dashed command line option that takes an optional argument.

So the best you could do is

1. Add document commit@{timestamp} vs commit@{count} notation
   we have for "git log" also to "git reflog", perhaps?

2. Document --date=

RE: Urgent Order

2014-10-21 Thread Parker Nick
Hello,

Please send me a price list and quotation for your products we want to import 
from your country this is a very large order for long term import and urgent 
request.

Thank you in advance for your prompt confirmation.
Regards,

Parker Nick

Equipos de Elevaci n , S.A. de C.V.Av. Texcoco #35,
54070 Tlalnepantla , Edo . de M xico
M xico
Tels.+27840117769
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] grep: fix match highlighting for combined patterns with context lines

2014-10-21 Thread Zoltan Klinger
> Junio C Hamano  writes:
>
> It turns out that the result of such a change becomes more readable
> than the original, in that it makes it clear that reinspection of
> the lines are done only for matched ones and not context lines.
>
>
Agree, it looks much clearer now. Happy if you squashed your
change (commit da736e6) in zk/grep-color-words branch.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Git Help needed

2014-10-21 Thread brian m. carlson
On Tue, Oct 21, 2014 at 12:31:55PM +, ravikirangoud_palpano...@vfc.com 
wrote:
> Hi Brian,
> My Open SSL vendor is IBM. In fact I am using AIX OS from IBM. When we
> (Myself and Frank. Frank is cc'ed in this email)  discussed with IBM
> team, they asked some details on what flag settings need to be used to
> recompile, what parameter settings they need to do, etc.  IBM team
> told it is easy to recompile if they have provided with the details.
> 
> Could you please help us to provide additional details for
> compilation. Thanks in advance.

I don't have any more information than this, but I believe Debian and
Red Hat have patched that check out.  Any reasonable developer should be
able to discover the check and remove it.

This is getting off-topic for the list, so I recommend you discuss it
with IBM or simply recompile Git for the new version of OpenSSL, as this
really isn't a Git issue.
-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


[PATCH] rebase: convert revert to squash on autosquash

2014-10-21 Thread Michael S. Tsirkin
Reverts can typically be treated like squash.  Eliminating both the
original commit and the revert would be even nicer, but this seems a bit
harder to implement.

Signed-off-by: Michael S. Tsirkin 
---
 git-rebase--interactive.sh | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 86edac7..a82bbdf 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -745,7 +745,7 @@ rearrange_squash () {
while read -r pick sha1 message
do
case "$message" in
-   "squash! "*|"fixup! "*|"ack! "*)
+   "squash! "*|"fixup! "*|"ack! "*|"Revert \""*)
action="${message%%!*}"
rest=$message
prefix=
@@ -757,6 +757,12 @@ rearrange_squash () {
prefix="$prefix${rest%%!*},"
rest="${rest#*! }"
;;
+   "Revert \""*\")
+   action="squash"
+   prefix="Revert,"
+   rest="${rest#Revert \"}"
+   rest="${rest%%\"}"
+   ;;
*)
break
;;
-- 
MST
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html