* Re: [PATCH] push: Correctly initialize nonfastforward in do_push.
From: Matthieu Moy @ 2009-09-16 17:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vpr9q24oa.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Matthieu Moy <Matthieu.Moy@imag.fr> writes:
>
>> The variable is assigned unconditionally in print_push_status, but
>> print_push_status is not reached by all codepaths. In particular, this
>> fixes a bug where "git push ... nonexisting-branch" was complaining about
>> non-fast forward.
>
> Hmm, the patch looks correct but I am scratching my head to see how this
> is triggered. "git push ... nonexisting-branch" seems to get:
Short answer: trust me, without the patch, you get the non-fast
forward (and valgrind tells you about conditional jump on
uninitialized value), with, you don't ;-).
Longer one:
int transport_push(struct transport *transport,
int refspec_nr, const char **refspec, int flags,
int * nonfastforward)
{
[...]
if (match_refs(local_refs, &remote_refs,
refspec_nr, refspec, match_flags)) {
return -1; /* <------------------------------ you stop here */
}
[...]
if (!quiet || push_had_errors(remote_refs))
print_push_status(transport->url, remote_refs,
verbose | porcelain, porcelain,
nonfastforward); /* <----- you would have updated nonfastforward there */
[...]
}
Actually, my initial version probably had the condition of the second
if too. And with the first "return" statement in transport_push.
Writting this, I'm wondering if it wouldn't be a better coding style
to initialize nonfastforward to 0 within transport_push (in case other
callers to transport_push appear one day, they won't get the the same
bug). Second version of the patch is comming.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCH] push: Correctly initialize nonfastforward in do_push.
From: Junio C Hamano @ 2009-09-16 18:15 UTC (permalink / raw)
To: Matthieu Moy; +Cc: git
In-Reply-To: <vpqfxamby33.fsf@bauges.imag.fr>
Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
> Short answer: trust me, without the patch, you get the non-fast
> forward (and valgrind tells you about conditional jump on
> uninitialized value), with, you don't ;-).
I understand valgrind one; I can trace the codepath with eyeballs without
it, and that is why I said it looks correct to begin with.
My puzzlement was that the following in the log message did not seem to
reproduce for me:
... where "git push ... nonexisting-branch" was complaining about
non-fast forward.
I would be eventually writing an entry in the Release Notes about this
fix, and I do not want to say:
"git push $there no-such-ref" incorrectly said no-such-ref does not
fast forward; fixed.
when I know that command line would produce something entirely different
error.
^ permalink raw reply
* Re: [PATCH] push: Correctly initialize nonfastforward in do_push.
From: Matthieu Moy @ 2009-09-16 18:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvdjizrgg.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
>
>> Short answer: trust me, without the patch, you get the non-fast
>> forward (and valgrind tells you about conditional jump on
>> uninitialized value), with, you don't ;-).
>
> I understand valgrind one; I can trace the codepath with eyeballs without
> it, and that is why I said it looks correct to begin with.
(in case it wasn't clear, "you" in my message should have been read as
"one", no harm intended)
> My puzzlement was that the following in the log message did not seem to
> reproduce for me:
> ... where "git push ... nonexisting-branch" was complaining about
> non-fast forward.
It's comming from an uninitialized variable, so it may have worked
just "by chance". For me, it seems to do it reproducibly, with for
example:
$ mkdir repo
$ rm -rf repo/
$ git init repo
Initialized empty Git repository in /tmp/repo/.git/
$ cd repo; touch foo; git add .; git commit -m foo > /dev/null
$ git push . nonexisting-branch
error: src refspec nonexisting-branch does not match any.
error: failed to push some refs to '.'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again. See the 'non-fast forward'
section of 'git push --help' for details.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCH v2 3/4] reset: add option "--merge-safe" to "git reset"
From: Junio C Hamano @ 2009-09-16 18:37 UTC (permalink / raw)
To: Christian Couder
Cc: git, Johannes Schindelin, Stephan Beyer, Daniel Barkalow,
Jakub Narebski, Linus Torvalds, Paolo Bonzini
In-Reply-To: <20090916041443.3737.63217.chriscool@tuxfamily.org>
Christian Couder <chriscool@tuxfamily.org> writes:
> From: Stephan Beyer <s-beyer@gmx.net>
>
> This option is nearly like "--merge" except that it is
> safer. The table below show the differences between these
> options.
>
> working index HEAD target working index HEAD
> B B A A --m-s B A A
> --merge A A A
> B B A C --m-s (disallowed)
> --merge C C C
>
> In this table, A, B and C are some different states of
> a file. For example the first 2 lines of the table mean
> that if a file is in state B in the working tree and
> the index, and in a different state A in HEAD and in
> the target, then "git reset --merge-safe target" will
> put the file in state B in the working tree and in
> state A in the index and HEAD.
At first, I had to spend a few minutes guessing what you meant by "target"
in the table. All the other words are well known and do not need to be
explained, but you can make it even easier to understand by updating the
sentence before the table, perhaps like:
When running "git reset --option target" to reset the HEAD to another
commit (as a special case "target" could be the same as HEAD), here
is what happens to paths in various state.
As you mentioned in the proposed commit log message of the other entry,
you have a different behaviour for unmerged case. Can you add that case
to the table as well?
The original use case of Linus's "reset --merge" was:
$ edit ... ;# you may have some local changes to the work tree
$ git merge/pull ...
... (1) it merges cleanly;
... (2) you see conflicts and do not commit, or
... (3) you resolve conflicts and commit, while leaving the earlier
... modified paths alone.
... In any of the three cases, you inspect the result, and say
... "ah, crap!"
... You want to go back to the state before the merge, i.e.
... target = HEAD^ in (1) or (3) above and target = HEAD in (2).
$ git reset --merge $target
Recall that "git merge/pull ..." step does not even touch anything if you
have a dirty index (i.e. "diff --cached" is non-empty), so any difference
between the index and HEAD to reset the failed merge away must come from
the merge itself
Immediately before you run "reset --merge" in the above sequence, you can
categorize the paths in various states this way:
work index HEAD how that path got into this state...
A A A not involved in this merge.
B A A not involved in this merge, originally modified.
B B A cleanly merged.
B B B cleanly merged (and committed if (1) or (3)).
C U A merge left conflicts
where U denotes unmerged path in the index, and C is a file in the work
tree with conflict markers. The path had content A in HEAD before the
start of the merge that you are resetting away.
Note that the target is A in all cases in the above table.
We would want to go back to HEAD == index == target for all of these
cases, and discarding B in "cleanly merged" entries is absolutely the
right thing to do. Clearly, --merge-safe is _not_ designed to work in
this scenario.
Don't get me wrong. I am not saying --merge-safe is unsafe nor useless.
I am trying to show a way with an intended use-case (and the mechanical
notation you and Daniel wrote up, which is very nice to illustrate what
exactly happens) to explain how --merge works, and more importantly why
it works that way.
That is because I would like to see an intended use case of this new
feature in a bigger picture. With the table, I can see what it does (or
at least what you wanted it to do), but it does not clearly explain what
this new mode of operation is good for, in what context it is designed
to be used, and what problem it intends to solve. I think you find it
very clear, by reading my explanation above, what Linus's --merge is
intended to solve:
After a (possibly conflicted) merge modified my index and my work
tree, "reset --hard" to the commit before I started the merge will
discard the local modifications I had in the work tree before the
merge. "reset --merge" was invented to let me go back to the
state before the merge, without discarding such local changes I
had before the merge.
I want to be able to explain to others what --merge-safe is for in a
similar way myself before I have it in my tree, and I can't (yet).
^ permalink raw reply
* Behavior of 'git add \*.txt': bug or feature?
From: Matthieu Moy @ 2009-09-16 19:46 UTC (permalink / raw)
To: git
Hi,
I find the behavior of 'git add \*.txt' strange: for adding untracked
files, it considers \*.txt as a pattern to match, but for updating
existing file's staged content, it seems to consider it as a filename:
$ git status
# On branch master
# Changed but not updated:
#
# modified: three.txt
# modified: two.txt
#
# Untracked files:
#
# one.txt
no changes added to commit (use "git add" and/or "git commit -a")
$ git add -v '*.txt'
add 'one.txt'
$ git add -v '*.txt'
$
I would have expected this "git add -v '*.txt'" to update the staged
content of two.txt and three.txt too.
It this the intended behavior? If so, what's the rationale for this?
Thanks,
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* Re: [PATCH 04/15] Set _O_BINARY as default fmode for both MinGW and MSVC
From: Alexey Borzenkov @ 2009-09-16 20:00 UTC (permalink / raw)
To: Johannes Sixt
Cc: Marius Storm-Olsen, git, Johannes.Schindelin, msysgit, gitster,
j6t, lznuaa, raa.lkml, Marius Storm-Olsen
In-Reply-To: <4AB10F01.9010703@viscovery.net>
On Wed, Sep 16, 2009 at 8:14 PM, Johannes Sixt <j.sixt@viscovery.net> wrote:
>> MinGW set the _CRT_fmode to set both the default fmode and
>> _O_BINARY on stdin/stdout/stderr. Rather use the main()
>> define in mingw.h to set this for both MinGW and MSVC.
>>
>> This will ensure that a MinGW and MSVC build will handle
>> input and output identically.
> This one breaks t5302-pack-index.sh (test 15, "[index v1] 2) create a
> stealth corruption in a delta base reference") in my MinGW build. I have
> yet to find out what exactly goes wrong and how it could be fixed.
Looks like calling _setmode in main is too late for something. :-/
I tried defining int _fmode in mingw.c (which sets msvcrt's _fmode
early, without calling _setmode), and it didn't work either (i.e. the
bug was still happening). So the culprit must be in _setmode. I also
tried logging what index_obj_offset and index_obj_nr are showing, and
here are results:
/* with _CRT_fmode = _O_BINARY */
index_obj_offset: 844032
index_obj_nr: 205
/* without _CRT_fmode = _O_BINARY */
index_obj_offset: 844235
index_obj_nr: 298
I then tried to see what git show-index actually returns there, and
here are several top lines of the results:
/* with _CRT_fmode = _O_BINARY */
850186 0106e17481932f5c223fafadc1d26abc6adf40d6
203652 01179d82b18c252824e20e190543e0e84950d820
15576 0246ff570c396c37ff08c0f5f9d88c84fc21a297
851536 035e7e54cee9eb197af435b6b6dcced489c233f6
376062 03a6f56dbbb556425ef8c43c31519b32eb5629a4
39452 0471b3b8ab8da19f3968dc238e9555f4e48ce858
8230 0483297992ed4cd5ab3b5790912b1f03598ea660
72292 0508b858e01f0367552fb14722388ba48dbd36f7
/* without _CRT_fmode = _O_BINARY */
844235 01a8d3f6d063d48baf40ee656804aa58486a34b2
851754 035e7e54cee9eb197af435b6b6dcced489c233f6
851844 04ff7bd225fbb4842697af96c147a4ddecb6a657
848233 088ddcb945af72c47348b65a63992c71b6b9dbe8
849676 088e69e7ab273e35b4f63ecb1b915a3997f13dff
14825 09bd72201f82a0da14a52230e2ccd0e43529e779
9848 0a5916ad398380ba103d98bad6fa4f2b20b74e75
695905 0ae5469e687083bbf954262873ee8c0c7d017e75
As you can see the hashes are completely different! Unfortunately I
also can't pinpoint where this actually happens... :-/
*several minutes later*
Searching which executables set _fmode and which don't I found the
culprit. test-genrandom.c didn't include git-compat-util.h, so mingw.h
was never included. This caused different random data to be generated,
and as it seems more importantly, of different sizes. Can be fixed
with this patch:
diff --git a/test-genrandom.c b/test-genrandom.c
index 8ad276d..b3c28d9 100644
--- a/test-genrandom.c
+++ b/test-genrandom.c
@@ -4,8 +4,7 @@
* Copyright (C) 2007 by Nicolas Pitre, licensed under the GPL version 2.
*/
-#include <stdio.h>
-#include <stdlib.h>
+#include "git-compat-util.h"
int main(int argc, char *argv[])
{
Or maybe there's a hidden bug in git that gets uncovered with slightly
different random data, I don't know. I'm glad I could finally solve
this mindbending issue. :)
^ permalink raw reply related
* [PATCH] Exporter for code_swarm
From: Giuseppe Bilotta @ 2009-09-16 20:27 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano, Giuseppe Bilotta
This simple Perl script echoes the entire project history into a format
suitable for consumption from the organic project development visualizer
code_swarm http://vis.cs.ucdavis.edu/~ogawa/codeswarm/ and any other
software that expects a file event XML file in the same format.
Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
contrib/git-file-events.perl | 28 ++++++++++++++++++++++++++++
1 files changed, 28 insertions(+), 0 deletions(-)
create mode 100755 contrib/git-file-events.perl
I had actually considered writing a patch to add the format as a predefined
format for git log, but on second thoughts I decided it was not really worth
the effort. This script, although it's just a quick hack, serves the purpose
just as well, although it's obviously not suited for anything more than
contrib/, if for anything at all.
Enjoy.
diff --git a/contrib/git-file-events.perl b/contrib/git-file-events.perl
new file mode 100755
index 0000000..b5fd5e5
--- /dev/null
+++ b/contrib/git-file-events.perl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+# Output full repository log as a list of file events, in the format expected by
+# code_swarm http://vis.cs.ucdavis.edu/~ogawa/codeswarm/
+#
+# Usage: perl git-file-events.perl > events.xml
+
+open(LOG, 'git log --reverse --date-order --format="%x09%at000%x09%aN" --name-only|');
+
+my $date = undef;
+my $author = undef;
+
+print "<?xml version=\"1.0\" ?>\n<file_events>\n";
+while (<LOG>) {
+ chomp;
+ if (/^\t(\d+)\t(.*)/) {
+ $date = $1;
+ $author = $2;
+ } else {
+ next unless $_;
+ die "Malformed log: no author!\n'$_'\n" unless $author;
+ $file = $_;
+ $file =~ s/\n//g;
+ $file =~ s/"//g;
+ print "<event date=\"$date\" filename=\"$_\" author=\"$author\" />\n";
+ }
+}
+print "</file_events>\n";
--
1.6.4.1.345.ge2d8f
^ permalink raw reply related
* Re: Behavior of 'git add \*.txt': bug or feature?
From: Junio C Hamano @ 2009-09-16 20:30 UTC (permalink / raw)
To: Matthieu Moy; +Cc: git
In-Reply-To: <vpqljke7jv8.fsf@bauges.imag.fr>
Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
> It this the intended behavior? If so, what's the rationale for this?
I strongly suspect that it comes from the fact that we have two
definitions and three implementations of pathspec-aware tree traversal.
One family is unaware of shell-glob wildcards (they only do leading
directory path match) while the other know both leading directory path and
shell-glob.
It is on the list of long-term items to fix, as the change required is
quite involved.
^ permalink raw reply
* Re: [PATCH] gitk: restore wm state to normal before saving geometry information
From: Pat Thoyts @ 2009-09-16 21:07 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Alexey Borzenkov, git
In-Reply-To: <19120.48177.116508.251237@cargo.ozlabs.ibm.com>
Paul Mackerras <paulus@samba.org> writes:
>> patch fixes this issue by storing window geometry in normal state.
>
>Hmmm, shouldn't we be also saving the window state (zoomed/normal) and
>restoring that as well?
>
>Paul.
We do. That got added in c876dbad
--
Pat Thoyts http://www.patthoyts.tk/
PGP fingerprint 2C 6E 98 07 2C 59 C8 97 10 CE 11 E6 04 E0 B9 DD
^ permalink raw reply
* [PATCH] Update the usage bundle string.
From: Thiago Farina @ 2009-09-16 21:20 UTC (permalink / raw)
To: git; +Cc: Thiago Farina
Currently the usage bundle string is not well formatted.
Now it is formatted and the user can read the string much more easily.
Signed-off-by: Thiago Farina <tfransosi@gmail.com>
---
builtin-bundle.c | 12 +++++++++---
1 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/builtin-bundle.c b/builtin-bundle.c
index 9b58152..2e98907 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -11,6 +11,12 @@
static const char *bundle_usage="git bundle (create <bundle> <git rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
+static const char builtin_bundle_usage[] = "\
+ git bundle create <file> <git-rev-list args>\n\
+ git bundle verify <file>\n\
+ git bundle list-heads <file> [refname...]\n\
+ git bundle unbundle <file> [refname...]";
+
int cmd_bundle(int argc, const char **argv, const char *prefix)
{
struct bundle_header header;
@@ -19,8 +25,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
int bundle_fd = -1;
char buffer[PATH_MAX];
- if (argc < 3)
- usage(bundle_usage);
+ if (argc < 3)
+ usage(builtin_bundle_usage);
cmd = argv[1];
bundle_file = argv[2];
@@ -59,5 +65,5 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
return !!unbundle(&header, bundle_fd) ||
list_bundle_refs(&header, argc, argv);
} else
- usage(bundle_usage);
+ usage(builtin_bundle_usage);
}
--
1.6.5.rc0.dirty
^ permalink raw reply related
* Re: Behavior of 'git add \*.txt': bug or feature?
From: Matthieu Moy @ 2009-09-16 21:26 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbplazl7s.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
>
>> It this the intended behavior? If so, what's the rationale for this?
>
> I strongly suspect that it comes from the fact that we have two
> definitions and three implementations of pathspec-aware tree traversal.
> One family is unaware of shell-glob wildcards (they only do leading
> directory path match) while the other know both leading directory path and
> shell-glob.
>
> It is on the list of long-term items to fix, as the change required is
> quite involved.
OK, that answers my question.
Thanks,
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* [PATCH v2] Update the usage bundle string.
From: Thiago Farina @ 2009-09-16 21:32 UTC (permalink / raw)
To: git; +Cc: Thiago Farina
Currently the usage bundle string is not well formatted.
Now it is formatted and the user can read the string much more easily.
Signed-off-by: Thiago Farina <tfransosi@gmail.com>
---
builtin-bundle.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/builtin-bundle.c b/builtin-bundle.c
index 9b58152..9946592 100644
--- a/builtin-bundle.c
+++ b/builtin-bundle.c
@@ -9,7 +9,11 @@
* bundle supporting "fetch", "pull", and "ls-remote".
*/
-static const char *bundle_usage="git bundle (create <bundle> <git rev-list args> | verify <bundle> | list-heads <bundle> [refname]... | unbundle <bundle> [refname]... )";
+static const char builtin_bundle_usage[] = "\
+ git bundle create <file> <git-rev-list args>\n\
+ git bundle verify <file>\n\
+ git bundle list-heads <file> [refname...]\n\
+ git bundle unbundle <file> [refname...]";
int cmd_bundle(int argc, const char **argv, const char *prefix)
{
@@ -19,8 +23,8 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
int bundle_fd = -1;
char buffer[PATH_MAX];
- if (argc < 3)
- usage(bundle_usage);
+ if (argc < 3)
+ usage(builtin_bundle_usage);
cmd = argv[1];
bundle_file = argv[2];
@@ -59,5 +63,5 @@ int cmd_bundle(int argc, const char **argv, const char *prefix)
return !!unbundle(&header, bundle_fd) ||
list_bundle_refs(&header, argc, argv);
} else
- usage(bundle_usage);
+ usage(builtin_bundle_usage);
}
--
1.6.5.rc0.dirty
^ permalink raw reply related
* [StGit PATCH 4/5] Add the -p option to fold
From: Catalin Marinas @ 2009-09-16 21:41 UTC (permalink / raw)
To: Karl Hasselström, git
In-Reply-To: <20090916214049.6622.44662.stgit@toshiba-laptop>
This option was added to import, so it makes sense for fold to have it
as well.
Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---
stgit/commands/fold.py | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/stgit/commands/fold.py b/stgit/commands/fold.py
index 28e824c..ce0459e 100644
--- a/stgit/commands/fold.py
+++ b/stgit/commands/fold.py
@@ -39,6 +39,8 @@ options = [
short = 'Perform a three-way merge with the current patch'),
opt('-b', '--base', args = [argparse.commit],
short = 'Use BASE instead of HEAD when applying the patch'),
+ opt('-p', '--strip', type = 'int', metavar = 'N',
+ short = 'Remove N leading slashes from diff paths (default 1)'),
opt('--reject', action = 'store_true',
short = 'Leave the rejected hunks in corresponding *.rej files')]
@@ -75,11 +77,13 @@ def func(parser, options, args):
crt_patch = crt_series.get_patch(current)
bottom = crt_patch.get_bottom()
git.apply_patch(filename = filename, base = bottom,
- reject = options.reject)
+ strip = options.strip, reject = options.reject)
elif options.base:
git.apply_patch(filename = filename, reject = options.reject,
+ strip = options.strip,
base = git_id(crt_series, options.base))
else:
- git.apply_patch(filename = filename, reject = options.reject)
+ git.apply_patch(filename = filename, strip = options.strip,
+ reject = options.reject)
out.done()
^ permalink raw reply related
* [StGit PATCH 3/5] Do not create an empty patch if import failed without --reject
From: Catalin Marinas @ 2009-09-16 21:41 UTC (permalink / raw)
To: Karl Hasselström, git
In-Reply-To: <20090916214049.6622.44662.stgit@toshiba-laptop>
If the import failed, do not leave an empty patch on the stack. If this
is required, the --reject option should be passed. The patch also fixes
a lowercase typo in the --reject option description.
Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---
stgit/commands/imprt.py | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/stgit/commands/imprt.py b/stgit/commands/imprt.py
index aa75065..de77635 100644
--- a/stgit/commands/imprt.py
+++ b/stgit/commands/imprt.py
@@ -68,7 +68,7 @@ options = [
opt('-b', '--base', args = [argparse.commit],
short = 'Use BASE instead of HEAD for file importing'),
opt('--reject', action = 'store_true',
- short = 'leave the rejected hunks in corresponding *.rej files'),
+ short = 'Leave the rejected hunks in corresponding *.rej files'),
opt('-e', '--edit', action = 'store_true',
short = 'Invoke an editor for the patch description'),
opt('-d', '--showdiff', action = 'store_true',
@@ -154,8 +154,13 @@ def __create_patch(filename, message, author_name, author_email,
base = git_id(crt_series, options.base)
else:
base = None
- git.apply_patch(diff = diff, base = base, reject = options.reject,
- strip = options.strip)
+ try:
+ git.apply_patch(diff = diff, base = base, reject = options.reject,
+ strip = options.strip)
+ except git.GitException:
+ if not options.reject:
+ crt_series.delete_patch(patch)
+ raise
crt_series.refresh_patch(edit = options.edit,
show_patch = options.showdiff,
author_date = author_date,
^ permalink raw reply related
* [StGit PATCH 1/5] Remove the 'fail_dump' argument to git.apply_patch()
From: Catalin Marinas @ 2009-09-16 21:40 UTC (permalink / raw)
To: Karl Hasselström, git
In-Reply-To: <20090916214049.6622.44662.stgit@toshiba-laptop>
Since we have a 'reject' argument, there is no need for the failed diff
to be dumped.
Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---
stgit/git.py | 11 ++---------
1 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/stgit/git.py b/stgit/git.py
index 012e282..97b1e96 100644
--- a/stgit/git.py
+++ b/stgit/git.py
@@ -818,7 +818,7 @@ def repack():
GRun('repack', '-a', '-d', '-f').run()
def apply_patch(filename = None, diff = None, base = None,
- fail_dump = True, reject = False, strip = None):
+ reject = False, strip = None):
"""Apply a patch onto the current or given index. There must not
be any local changes in the tree, otherwise the command fails
"""
@@ -847,14 +847,7 @@ def apply_patch(filename = None, diff = None, base = None,
except GitRunException:
if base:
switch(orig_head)
- if fail_dump:
- # write the failed diff to a file
- f = file('.stgit-failed.patch', 'w+')
- f.write(diff)
- f.close()
- out.warn('Diff written to the .stgit-failed.patch file')
-
- raise
+ raise GitException('Diff does not apply cleanly')
if base:
top = commit(message = 'temporary commit used for applying a patch',
^ permalink raw reply related
* [StGit PATCH 5/5] Autosign imported patches
From: Catalin Marinas @ 2009-09-16 21:41 UTC (permalink / raw)
To: Karl Hasselström, git
In-Reply-To: <20090916214049.6622.44662.stgit@toshiba-laptop>
If stgit.autosign configuration is set, allow the automatic signing of
the imported patches, similar to the 'new' command.
Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---
stgit/commands/imprt.py | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/stgit/commands/imprt.py b/stgit/commands/imprt.py
index de77635..0f78490 100644
--- a/stgit/commands/imprt.py
+++ b/stgit/commands/imprt.py
@@ -141,6 +141,10 @@ def __create_patch(filename, message, author_name, author_email,
if options.authdate:
author_date = options.authdate
+ sign_str = options.sign_str
+ if not options.sign_str:
+ sign_str = config.get('stgit.autosign')
+
crt_series.new_patch(patch, message = message, can_edit = False,
author_name = author_name,
author_email = author_email,
@@ -164,8 +168,7 @@ def __create_patch(filename, message, author_name, author_email,
crt_series.refresh_patch(edit = options.edit,
show_patch = options.showdiff,
author_date = author_date,
- sign_str = options.sign_str,
- backup = False)
+ sign_str = sign_str, backup = False)
out.done()
def __mkpatchname(name, suffix):
^ permalink raw reply related
* [StGit PATCH 0/5] More UI clean-up
From: Catalin Marinas @ 2009-09-16 21:40 UTC (permalink / raw)
To: Karl Hasselström, git
The series adds makes the fold and import options consistent regarding
the -p and --reject options. The autosigning of new patches was extended
to the import command as well.
---
Catalin Marinas (5):
Remove the 'fail_dump' argument to git.apply_patch()
Add the --reject option to fold
Do not create an empty patch if import failed without --reject
Add the -p option to fold
Autosign imported patches
stgit/commands/fold.py | 15 +++++++++++----
stgit/commands/imprt.py | 18 +++++++++++++-----
stgit/git.py | 11 ++---------
3 files changed, 26 insertions(+), 18 deletions(-)
--
Catalin
^ permalink raw reply
* [StGit PATCH 2/5] Add the --reject option to fold
From: Catalin Marinas @ 2009-09-16 21:41 UTC (permalink / raw)
To: Karl Hasselström, git
In-Reply-To: <20090916214049.6622.44662.stgit@toshiba-laptop>
Signed-off-by: Catalin Marinas <catalin.marinas@gmail.com>
---
stgit/commands/fold.py | 11 +++++++----
1 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/stgit/commands/fold.py b/stgit/commands/fold.py
index 66a2dd9..28e824c 100644
--- a/stgit/commands/fold.py
+++ b/stgit/commands/fold.py
@@ -38,7 +38,9 @@ options = [
opt('-t', '--threeway', action = 'store_true',
short = 'Perform a three-way merge with the current patch'),
opt('-b', '--base', args = [argparse.commit],
- short = 'Use BASE instead of HEAD applying the patch')]
+ short = 'Use BASE instead of HEAD when applying the patch'),
+ opt('--reject', action = 'store_true',
+ short = 'Leave the rejected hunks in corresponding *.rej files')]
directory = DirectoryHasRepository(log = True)
@@ -72,11 +74,12 @@ def func(parser, options, args):
if options.threeway:
crt_patch = crt_series.get_patch(current)
bottom = crt_patch.get_bottom()
- git.apply_patch(filename = filename, base = bottom)
+ git.apply_patch(filename = filename, base = bottom,
+ reject = options.reject)
elif options.base:
- git.apply_patch(filename = filename,
+ git.apply_patch(filename = filename, reject = options.reject,
base = git_id(crt_series, options.base))
else:
- git.apply_patch(filename = filename)
+ git.apply_patch(filename = filename, reject = options.reject)
out.done()
^ permalink raw reply related
* Re: [RFC/PATCH 0/2] Speed up fetch with large number of tags
From: Julian Phillips @ 2009-09-16 22:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vbplb2pi7.fsf@alter.siamese.dyndns.org>
On Wed, 16 Sep 2009, Junio C Hamano wrote:
> Julian Phillips <julian@quantumfyre.co.uk> writes:
>
>> I have a repository at $dayjob where fetch was taking ~30s to tell me
>> that there were no updates.
>>
>> It turns out that I appear to have added a nasty linear search of all
>> remote refs for every commit (i.e. tag^{}) tag ref way back in the
>> original C implementation of fetch. This doesn't scale well to large
>> numbers of refs, so this replaces it with a hash table based lookup
>> instead, which brings the time down to a few seconds even for very large
>> ref counts.
>>
>> I haven't tested it with non-native transports, but there is no reason
>> to believe that the code should be transport specific.
>
> Very interesting.
>
> A few questions (not criticisms).
>
> * 1m50s to 4.5s is quite impressive, even if it is only in a repository
> with unusual refs-vs-commits ratio, but I personally think 10 refs per
> every commit is already on the borderline of being insane, and the
> normal ratio would be more like 1 refs per every 10-20 commits.
I noticed the problem with a real repository at $dayjob, and did enough
anaylsis to identiy the problem. I deliberately created a repository that
should emphasise the problem so that it was easy to get a handle on.
Having applied the ref-dict patches fetch on my $dayjob repo has gone from
~30s to ~4.5s, which may not be as impressive - but is much easier to live
with.
> What are possible downsides with the new code in repositories with more
> reasonable refs-vs-commits ratio? A hash table (with a sensible hash
> function) would almost always outperform linear search in an randomly
> ordered collection, so my gut tells me that there won't be performance
> downsides, but are there other potential issues we should worry about?
I guess that main thing would be the extra memory usage.
> * In an insanely large refs-vs-commits case, perhaps not 50000:1 but more
> like 100:1, but with a history with far more than one commit, what is
> the memory consumption? Judging from a cursory view, I think the way
> ref-dict re-uses struct ref might be quite suboptimal, as you are using
> only next (for hash-bucket link), old_sha1[] and its name field, and
> also your ref_dict_add() calls alloc_ref() which calls one calloc() per
> requested ref, instead of attempting any bulk allocation.
Yeah, I just reused struct for speed and convience of developing, to
veryify that ref-dict would give me the speed I wanted. A final patch
would want a more optimised version. Except that I've thrown the whole
hash table thing away anyway.
> * The outer loop is walking the list of refs from a transport, and the
> inner loop is walking a copy of the same list of refs from the same
> transport, looking for each refs/tags/X^{} what record, if any, existed
> for refs/tags/X.
>
> Would it make sense to further specialize your optimization? For
> example, something like...
I actually arrived at somthing similar to this myself, after realising
that I could use string_list as a basis.
> * It is tempting to use a hash table when you have to deal with an
> unordered collection, but in this case, wouldn't the refs obtained from
> the transport (it's essentially a ls-remote output, isn't it?) be
> sorted? Can't you take advantage of that fact to optimize the loop,
> without adding a specialized hash table implementation?
I wasn't sure if we could rely on the refs list being sorted. But I've
got a new version that uses an extra string_list instead that is actually
slightly faster. I'll post that shortly.
> We find refs/tags/v0.99 immediately followed by refs/tags/v0.99^{} in
> the ls-remote output. And the inefficient loop is about finding
> refs/tags/v0.99 when we see refs/tags/v0.99^{}, so if we remember the
> tag ref we saw in the previous round, we can check with that first to
> make sure our "sorted" assumption holds true, and optimize the loop out
> that way, no?
--
Julian
---
Bilbo's First Law:
You cannot count friends that are all packed up in barrels.
^ permalink raw reply
* Re: [RFC/PATCH 0/2] Speed up fetch with large number of tags
From: Shawn O. Pearce @ 2009-09-16 22:42 UTC (permalink / raw)
To: Julian Phillips; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.LNX.2.00.0909162141140.13697@reaper.quantumfyre.co.uk>
Julian Phillips <julian@quantumfyre.co.uk> wrote:
> On Wed, 16 Sep 2009, Junio C Hamano wrote:
>> * It is tempting to use a hash table when you have to deal with an
>> unordered collection, but in this case, wouldn't the refs obtained from
>> the transport (it's essentially a ls-remote output, isn't it?) be
>> sorted? Can't you take advantage of that fact to optimize the loop,
>> without adding a specialized hash table implementation?
>
> I wasn't sure if we could rely on the refs list being sorted. But I've
> got a new version that uses an extra string_list instead that is actually
> slightly faster. I'll post that shortly.
JGit depends on the fact that the refs list is sorted by the remote
peer, and that foo^{} immediately follows foo. I don't think this
has ever been documented, but all sane implementations[1] follow
this convention and it may be something we could simply codify as
part of the protocol standard.
[1] Sane implementations are defined to be what I consider to be
the two stable implementations in deployed use, git.git and JGit.
--
Shawn.
^ permalink raw reply
* Re: [RFC/PATCH 0/2] Speed up fetch with large number of tags
From: Shawn O. Pearce @ 2009-09-16 22:46 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Julian Phillips, git
In-Reply-To: <7vbplb2pi7.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
> A few questions (not criticisms).
>
> * 1m50s to 4.5s is quite impressive, even if it is only in a repository
> with unusual refs-vs-commits ratio, but I personally think 10 refs per
> every commit is already on the borderline of being insane, and the
> normal ratio would be more like 1 refs per every 10-20 commits.
Under Gerrit Code Review it is normaly to have 2-5 refs per commit,
every iteration of a patch is held as a commit and anchored by a
unique ref.
So we're borderline insane. :-)
--
Shawn.
^ permalink raw reply
* Re: [RFC/PATCH 0/2] Speed up fetch with large number of tags
From: Junio C Hamano @ 2009-09-16 22:52 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Julian Phillips, git
In-Reply-To: <20090916224253.GB14660@spearce.org>
"Shawn O. Pearce" <spearce@spearce.org> writes:
> JGit depends on the fact that the refs list is sorted by the remote
> peer, and that foo^{} immediately follows foo. I don't think this
> has ever been documented, but all sane implementations[1] follow
> this convention and it may be something we could simply codify as
> part of the protocol standard.
>
> [1] Sane implementations are defined to be what I consider to be
> the two stable implementations in deployed use, git.git and JGit.
There is no strong reason for ordering of refs between themselves
(i.e. refs/heads/master comes before refs/heads/next) other than the fact
that we sort and then walk due to packed-refs reasons.
But emitting tag X and then its peeled representation X^{} immediately
after it is quite fundamental in the way how anybody sane would implement
ls-remote. There is no reason to violate the established order other than
"I could do so", and in order not to show X and X^{} next to each other,
you would need _more_ processing.
So I would say it is very safe to assume this.
Also, you might not have noticed, but my illustration patch was merely
using it as a hint to optimize, and if the last ref we saw was not X when
it is turn to handle X^{}, it simply falled back to the original logic,
iow, the patch never compromised the correctness.
^ permalink raw reply
* [RFC/PATCH v2] fetch: Speed up fetch by rewriting find_non_local_tags
From: Julian Phillips @ 2009-09-16 22:53 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <alpine.LNX.2.00.0909162141140.13697@reaper.quantumfyre.co.uk>
When trying to get a list of remote tags to see if we need to fetch
any we were doing a linear search for the matching tag ref for the
tag^{} commit entries. This proves to be incredibly slow for large
numbers of tags. Rewrite the function so that we can do lookup in
string_lists instead.
For a repository with 50000 tags (and just a single commit on a single
branch), a fetch that does nothing goes from ~ 1m50s to ~4.2s.
Signed-off-by: Julian Phillips <julian@quantumfyre.co.uk>
---
Not only does this not require a custom hash table, it is also slightly
faster than the last version (~4.2s vs ~4.5s).
If nothing else, having rewritten it completely, at least I now
understand what the old find_non_local_tags function was actually doing
... ;)
builtin-fetch.c | 85 ++++++++++++++++++++++++++++++++++++++-----------------
1 files changed, 59 insertions(+), 26 deletions(-)
diff --git a/builtin-fetch.c b/builtin-fetch.c
index cb48c57..c9a2563 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -504,57 +504,90 @@ static int will_fetch(struct ref **head, const unsigned char *sha1)
return 0;
}
+struct tag_data {
+ struct ref **head;
+ struct ref ***tail;
+ struct string_list *refs;
+};
+
+static int add_to_tail(struct string_list_item *item, void *cb_data)
+{
+ struct tag_data *data = (struct tag_data *)cb_data;
+ unsigned char *commit = (unsigned char *)item->util;
+ struct ref *rm = NULL;
+ struct string_list_item *sli;
+
+ /* Tag objects will have the commit sha1 associated with the peeled
+ * ref, if there is not a peeled ref then the ref is probably a
+ * lightweight tag and so refers to a commit directly */
+ sli = string_list_lookup(item->string, data->refs);
+ if (sli)
+ commit = sli->util;
+
+ /* skip over tags that we don't have the commits for. */
+ if (!has_sha1_file(commit) && !will_fetch(data->head, commit))
+ return 0;
+
+ rm = alloc_ref(item->string);
+ rm->peer_ref = alloc_ref(item->string);
+ hashcpy(rm->old_sha1, item->util);
+
+ **data->tail = rm;
+ *data->tail = &rm->next;
+
+ return 0;
+}
+
static void find_non_local_tags(struct transport *transport,
struct ref **head,
struct ref ***tail)
{
struct string_list existing_refs = { NULL, 0, 0, 0 };
- struct string_list new_refs = { NULL, 0, 0, 1 };
+ struct string_list peeled_refs = { NULL, 0, 0, 1 };
+ struct string_list remote_refs = { NULL, 0, 0, 1 };
+ struct tag_data data = {head, tail, &peeled_refs};
+ struct string_list *refs;
char *ref_name;
int ref_name_len;
- const unsigned char *ref_sha1;
- const struct ref *tag_ref;
- struct ref *rm = NULL;
const struct ref *ref;
+ struct string_list_item *item;
for_each_ref(add_existing, &existing_refs);
for (ref = transport_get_remote_refs(transport); ref; ref = ref->next) {
if (prefixcmp(ref->name, "refs/tags"))
continue;
+ /* skip duplicates */
+ if (string_list_lookup(ref->name, &remote_refs))
+ continue;
+
+ refs = &remote_refs;
ref_name = xstrdup(ref->name);
ref_name_len = strlen(ref_name);
- ref_sha1 = ref->old_sha1;
+ /* we want to store peeled refs by the base ref name in the
+ * peeled_refs string list */
if (!strcmp(ref_name + ref_name_len - 3, "^{}")) {
ref_name[ref_name_len - 3] = 0;
- tag_ref = transport_get_remote_refs(transport);
- while (tag_ref) {
- if (!strcmp(tag_ref->name, ref_name)) {
- ref_sha1 = tag_ref->old_sha1;
- break;
- }
- tag_ref = tag_ref->next;
- }
+ refs = &peeled_refs;
}
- if (!string_list_has_string(&existing_refs, ref_name) &&
- !string_list_has_string(&new_refs, ref_name) &&
- (has_sha1_file(ref->old_sha1) ||
- will_fetch(head, ref->old_sha1))) {
- string_list_insert(ref_name, &new_refs);
-
- rm = alloc_ref(ref_name);
- rm->peer_ref = alloc_ref(ref_name);
- hashcpy(rm->old_sha1, ref_sha1);
-
- **tail = rm;
- *tail = &rm->next;
+ /* ignore refs that we already have */
+ if (!string_list_has_string(&existing_refs, ref_name)) {
+ item = string_list_insert(ref_name, refs);
+ item->util = (void *)ref->old_sha1;
}
+
free(ref_name);
}
+
+ /* For all the tags in the remote_refs string list, call add_to_tail to
+ * add them to the list of refs to be fetched */
+ for_each_string_list(add_to_tail, &remote_refs, &data);
+
string_list_clear(&existing_refs, 0);
- string_list_clear(&new_refs, 0);
+ string_list_clear(&peeled_refs, 0);
+ string_list_clear(&remote_refs, 0);
}
static void check_not_current_branch(struct ref *ref_map)
--
1.6.4.2
^ permalink raw reply related
* Re: [RFC/PATCH 0/2] Speed up fetch with large number of tags
From: Shawn O. Pearce @ 2009-09-16 23:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Julian Phillips, git
In-Reply-To: <7vtyz2wlhm.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
>
> > JGit depends on the fact that the refs list is sorted by the remote
> > peer, and that foo^{} immediately follows foo. I don't think this
> > has ever been documented, but all sane implementations[1] follow
> > this convention and it may be something we could simply codify as
> > part of the protocol standard.
> >
> > [1] Sane implementations are defined to be what I consider to be
> > the two stable implementations in deployed use, git.git and JGit.
>
> There is no strong reason for ordering of refs between themselves
> (i.e. refs/heads/master comes before refs/heads/next) other than the fact
> that we sort and then walk due to packed-refs reasons.
Sorry, I misspoke a bit above.
JGit does not care about the ordering between two refs, e.g. in your
master/next example above JGit would accept them in either order
just fine. Internally we enforce this by hashing the advertised
refs and walking the hash, callers presenting the data for a user
must copy to a list and sort by their desired sorting criteria
(usually name).
What I meant to say was this:
> But emitting tag X and then its peeled representation X^{} immediately
> after it is quite fundamental in the way how anybody sane would implement
> ls-remote. There is no reason to violate the established order other than
> "I could do so", and in order not to show X and X^{} next to each other,
> you would need _more_ processing.
and right, explicitly placing X^{} away from X means that the sender
has to do more work to buffer one of the two values and then show
them later. This is pointless other than to piss off any more
reasonable implementor.
I think we should formalize this rule of X^{} immediately follows
X if peeling is possible, and if not, then X^{} must not appear.
We already have a similar rule with packed-refs, although there it
is absolutely required by the format.
> Also, you might not have noticed, but my illustration patch was merely
> using it as a hint to optimize, and if the last ref we saw was not X when
> it is turn to handle X^{}, it simply falled back to the original logic,
> iow, the patch never compromised the correctness.
Oh, I missed that. JGit I think flat out panics and disconnects
if the remote does this to us. What is the incentive in supporting
a broken server with a slower client?
--
Shawn.
^ permalink raw reply
* [ANNOUNCE] Git User's Survey 2009 has been closed
From: Jakub Narebski @ 2009-09-16 23:13 UTC (permalink / raw)
To: git; +Cc: linux-kernel
Hi all,
Git User's Survey 2009 ended at the end of Wednesday, 16 October 2008,
around 23:45 CEST (GMT+0200).
Beginnings of survey summary should be available soon at
http://git.or.cz/gitwiki/GitSurvey2009
Currently you can get there raw data (individual responses) in CSV and
XLS formats (compressed). One can find there also link to online
analysis (on Survs.com) and beginnings of partial survey summaries
(send to git mailing list in the duration of the survey).
Thanks to all who participated in this survey!
--
Jakub Narebski
Poland
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox