* Re: Cherry-picking to remote branches
From: VMiklos @ 2007-07-06 15:01 UTC (permalink / raw)
To: Sean Kelley; +Cc: Johannes Schindelin, git
In-Reply-To: <a2e879e50707060739s4c8e751dj494618d3d545277b@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1346 bytes --]
Na Fri, Jul 06, 2007 at 09:39:47AM -0500, Sean Kelley <svk.sweng@gmail.com> pisal(a):
>> > git checkout -b stable linux-stable/master
>> >
>> > git cherry-pick b3b1eea69a (a commit from linux-devel)
>> >
>> > git push linux-stable
>> >
>> > error: remote 'refs/heads/master' is not a strict subset of local ref
>> > 'refs/heads/master'. maybe you are not up-to-date and need to pull
>> > first?
>> > error: failed to push to 'git://mysite.com/data/git/linux-stable.git'
>>
>> Since you are obviously only interested in pushing the stable branch, why
>> don't you
>>
>> git push linux-stable stable
>>
>> Hm?
>>
>> If you do not specify which branches to push, "git push" will find all
>> refnames which are present both locally and remotely, and push those.
>> Evidently, however, your local "master" disagrees with the remote
>> "master".
>
> It is not entirely clear to me from the documentation. So I was
> trying to cobble together something that seemed to make sense. I want
> to work from the devel clone. On occasion I want to cherry-pick
> changesets and push those to the stable branch. I don't want
> everything that goes into devel to go into stable.
what about this?
git push linux-stable stable:master
VMiklos
--
developer of Frugalware Linux - http://frugalware.org
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [PATCH] Fix guilt to work correctly even if the refs are packed
From: Theodore Ts'o @ 2007-07-06 14:57 UTC (permalink / raw)
To: Josef 'Jeff' Sipek; +Cc: git
Explicitly referencing .git/refs/heads/$branch is bad; use git
show-ref -h instead.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
---
guilt | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/guilt b/guilt
index 814f755..54f9087 100755
--- a/guilt
+++ b/guilt
@@ -247,7 +247,7 @@ head_check()
# if the expected hash is empty, just return
[ -z "$1" ] && return 0
- if [ "`cat "$GIT_DIR/refs/heads/$branch"`" != "$1" ]; then
+ if [ "`git show-ref -s "refs/heads/$branch"`" != "$1" ]; then
echo "Expected HEAD commit $1" >&2
echo " got `cat "$GIT_DIR/refs/heads/$branch"`" >&2
return 1
--
1.5.3.rc0.11.ge2b1a
^ permalink raw reply related
* [PATCH] git-gui: Allow users to set commit.signoff from options.
From: Gerrit Pape @ 2007-07-06 14:46 UTC (permalink / raw)
To: Shawn O. Pearce, git
Users may want to automatically sign-off any commit for a specific
repository. If they are mostly a git-gui user they should be able to
view/set this option from within the git-gui environment, rather than
needing to edit a raw text file on their local filesystem.
This was noticed and requested by Josh Triplett through
http://bugs.debian.org/412776
Signed-off-by: Gerrit Pape <pape@smarden.org>
---
git-gui.sh | 1 +
lib/option.tcl | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/git-gui.sh b/git-gui.sh
index 0096f49..5ded736 100755
--- a/git-gui.sh
+++ b/git-gui.sh
@@ -1295,6 +1295,7 @@ set default_config(merge.summary) false
set default_config(merge.verbosity) 2
set default_config(user.name) {}
set default_config(user.email) {}
+set default_config(commit.signoff) false
set default_config(gui.pruneduringfetch) false
set default_config(gui.trustmtime) false
diff --git a/lib/option.tcl b/lib/option.tcl
index ae19a8f..28208ce 100644
--- a/lib/option.tcl
+++ b/lib/option.tcl
@@ -188,6 +188,7 @@ proc do_options {} {
{b merge.summary {Summarize Merge Commits}}
{i-1..5 merge.verbosity {Merge Verbosity}}
{b merge.diffstat {Show Diffstat After Merge}}
+ {b commit.signoff {Automatically Sign-off}}
{b gui.trustmtime {Trust File Modification Timestamps}}
{b gui.pruneduringfetch {Prune Tracking Branches During Fetch}}
--
1.5.2.1
^ permalink raw reply related
* [PATCH] git-commit: add commit.signoff config option
From: Gerrit Pape @ 2007-07-06 14:45 UTC (permalink / raw)
To: Junio C Hamano, git
In-Reply-To: <20070706144227.11736.qmail@046ba2bc1a0185.315fe32.mid.smarden.org>
Have the commit.signoff boolean config option automatically add a
Signed-off-by: by git-commit, without giving the -s switch explicitly.
Signed-off-by: Gerrit Pape <pape@smarden.org>
---
git-commit.sh | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/git-commit.sh b/git-commit.sh
index 7a7d19a..b493820 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -275,6 +275,7 @@ $1"
esac
done
case "$edit_flag" in t) no_edit= ;; esac
+test "$(git config --bool commit.signoff)" != true || signoff=t
################################################################
# Sanity check options
--
1.5.2.1
^ permalink raw reply related
* [PATCH] git-commit: don't add multiple Signed-off-by: from the same identity
From: Gerrit Pape @ 2007-07-06 14:42 UTC (permalink / raw)
To: Junio C Hamano, git
If requested to signoff a commit, don't add another Signed-off-by: line
to the commit message if the exact same line is already there.
This was noticed and requested by Josh Triplett through
http://bugs.debian.org/430851
Signed-off-by: Gerrit Pape <pape@smarden.org>
---
git-commit.sh | 20 +++++++++++---------
1 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/git-commit.sh b/git-commit.sh
index f866f95..7a7d19a 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -458,16 +458,18 @@ fi | git stripspace >"$GIT_DIR"/COMMIT_EDITMSG
case "$signoff" in
t)
- need_blank_before_signoff=
+ sign=$(git-var GIT_COMMITTER_IDENT | sed -e '
+ s/>.*/>/
+ s/^/Signed-off-by: /
+ ')
+ blank_before_signoff=
tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
- grep 'Signed-off-by:' >/dev/null || need_blank_before_signoff=yes
- {
- test -z "$need_blank_before_signoff" || echo
- git-var GIT_COMMITTER_IDENT | sed -e '
- s/>.*/>/
- s/^/Signed-off-by: /
- '
- } >>"$GIT_DIR"/COMMIT_EDITMSG
+ grep 'Signed-off-by:' >/dev/null || blank_before_signoff='
+'
+ tail -n 1 "$GIT_DIR"/COMMIT_EDITMSG |
+ grep "$sign"$ >/dev/null ||
+ printf '%s%s\n' "$blank_before_signoff" "$sign" \
+ >>"$GIT_DIR"/COMMIT_EDITMSG
;;
esac
--
1.5.2.1
^ permalink raw reply related
* Re: Cherry-picking to remote branches
From: Sean Kelley @ 2007-07-06 14:39 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0707061524180.4093@racer.site>
Hi
On 7/6/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Hi,
>
> On Fri, 6 Jul 2007, Sean Kelley wrote:
>
> > [...]
> >
> > git checkout -b stable linux-stable/master
> >
> > git cherry-pick b3b1eea69a (a commit from linux-devel)
> >
> > git push linux-stable
> >
> > error: remote 'refs/heads/master' is not a strict subset of local ref
> > 'refs/heads/master'. maybe you are not up-to-date and need to pull
> > first?
> > error: failed to push to 'git://mysite.com/data/git/linux-stable.git'
>
> Since you are obviously only interested in pushing the stable branch, why
> don't you
>
> git push linux-stable stable
>
> Hm?
>
> If you do not specify which branches to push, "git push" will find all
> refnames which are present both locally and remotely, and push those.
> Evidently, however, your local "master" disagrees with the remote
> "master".
It is not entirely clear to me from the documentation. So I was
trying to cobble together something that seemed to make sense. I want
to work from the devel clone. On occasion I want to cherry-pick
changesets and push those to the stable branch. I don't want
everything that goes into devel to go into stable.
Sean
>
> Hth,
> Dscho
>
>
^ permalink raw reply
* Re: Cherry-picking to remote branches
From: Johannes Schindelin @ 2007-07-06 14:26 UTC (permalink / raw)
To: Sean Kelley; +Cc: git
In-Reply-To: <a2e879e50707060709oc9fe8b3k8e594f1cb6e10437@mail.gmail.com>
Hi,
On Fri, 6 Jul 2007, Sean Kelley wrote:
> [...]
>
> git checkout -b stable linux-stable/master
>
> git cherry-pick b3b1eea69a (a commit from linux-devel)
>
> git push linux-stable
>
> error: remote 'refs/heads/master' is not a strict subset of local ref
> 'refs/heads/master'. maybe you are not up-to-date and need to pull
> first?
> error: failed to push to 'git://mysite.com/data/git/linux-stable.git'
Since you are obviously only interested in pushing the stable branch, why
don't you
git push linux-stable stable
Hm?
If you do not specify which branches to push, "git push" will find all
refnames which are present both locally and remotely, and push those.
Evidently, however, your local "master" disagrees with the remote
"master".
Hth,
Dscho
^ permalink raw reply
* Cherry-picking to remote branches
From: Sean Kelley @ 2007-07-06 14:09 UTC (permalink / raw)
To: git
I have been having trouble with the following workflow. I am trying
to push changes to a remote from a branch that is tracking it.
git clone git://mysite.com/data/git/linux-devel.git linux-devel
cd linux-devel
git remote add -m master -f linux-stable
git://mysite.com/data/git/linux-stable.git
git branch -r
linux-stable/HEAD
linux-stable/master
origin/HEAD
origin/master
git checkout -b stable linux-stable/master
git cherry-pick b3b1eea69a (a commit from linux-devel)
git push linux-stable
error: remote 'refs/heads/master' is not a strict subset of local ref
'refs/heads/master'. maybe you are not up-to-date and need to pull
first?
error: failed to push to 'git://mysite.com/data/git/linux-stable.git'
Thanks for your help,
Sean
^ permalink raw reply
* Re: Update local tracking refs when pushing- no way to disable
From: Dan McGee @ 2007-07-06 13:20 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.64.0707052320090.14638@iabervon.org>
On 7/5/07, Daniel Barkalow <barkalow@iabervon.org> wrote:
> On Thu, 5 Jul 2007, Dan McGee wrote:
>
> > In this commit:
> > b516968ff62ec153e008d033c153affd7ba9ddc6
> >
> > I don't know if anyone else has the same way of working as I do, but I
> > tend to set the "remote.<name>.skipDefaultUpdate" property to true for
> > my publicly visible repository, just so I don't have duplicate branch
> > heads lying around in my local repository. Call this peculiar, but I
> > like it that way. However, git-push does not respect this property,
> > meaning I know have these branches whether I want them or not. In a
> > tool such as qgit or even 'git branch -a' output, it starts to get
> > awful cluttered.
>
> What git-fetch and git-push care about is whether you have an entry
> "remote.<name>.fetch" with a colon and stuff on the right of it. If so,
> this is a pattern that is used to generate the duplicate branch heads that
> you don't want. git clone sets it up to a default pattern
> (refs/remotes/origin/*), and I don't think there's any way to make it not
> do that, but you can just reconfigure it afterwards if you don't like it.
Wow, my bad here on this one. Didn't even think about the default config line:
[remote "toofishes.net"]
url = toofishes.net:~/gitprojects/shoepolish.git/
fetch = +refs/heads/*:refs/remotes/toofishes.net/*
push = +refs/heads/*:refs/heads/*
Getting rid of that fetch line makes it work as intended. And not to
hijack my own thread, but did behavior change between 1.5.2.3 and
1.5.3 wrt non-subset pushes?
$ git push toofishes.net
error: remote 'refs/heads/alpm_list_speed' is not a strict subset of
local ref 'refs/heads/alpm_list_speed'. maybe you are not up-to-date
and need to pull first?
error: remote 'refs/heads/asciidoc' is not a strict subset of local
ref 'refs/heads/asciidoc'. maybe you are not up-to-date and need to
pull first?
error: remote 'refs/heads/color' is not a strict subset of local ref
'refs/heads/color'. maybe you are not up-to-date and need to pull
first?
error: remote 'refs/heads/permissions' is not a strict subset of local
ref 'refs/heads/permissions'. maybe you are not up-to-date and need to
pull first?
error: remote 'refs/heads/pkgname_check' is not a strict subset of
local ref 'refs/heads/pkgname_check'. maybe you are not up-to-date and
need to pull first?
updating 'refs/heads/working'
from 59d9ccf48d84fd1e59f78cb4dcf428e53d1c6911
to 6b7b9743181078aa7152daffdfc1eaeb46304c0f
Generating pack...
Done counting 0 objects.
Writing 0 objects...
Total 0 (delta 0), reused 0 (delta 0)
refs/heads/working: 59d9ccf48d84fd1e59f78cb4dcf428e53d1c6911 ->
6b7b9743181078aa7152daffdfc1eaeb46304c0f
I thought the '+' sign in the push refspec would supress these errors,
but it doesn't seem to. Running 'git push -f' works but that was never
necessary before after doing some rebasing of these branches.
-Dan
^ permalink raw reply
* Re: git-apply{,mbox,patch} should default to --unidiff-zero
From: Johannes Schindelin @ 2007-07-06 12:49 UTC (permalink / raw)
To: Adrian Bunk; +Cc: Junio C Hamano, Linus Torvalds, git
In-Reply-To: <20070706121441.GM3492@stusta.de>
Hi,
On Fri, 6 Jul 2007, Adrian Bunk wrote:
> On Thu, Jul 05, 2007 at 10:41:51PM -0700, Junio C Hamano wrote:
> > Linus Torvalds <torvalds@linux-foundation.org> writes:
> >...
> > > Adrian has a point in that if there are lines to be deleted, that in
> > > itself is context, and then the strict behaviour of "git-apply" is
> > > arguably unnecessaily strict.
> >
> > Not really. That is true, unless you have two identical instances of
> > the group of lines being deleted, in which case you cannot safely tell
> > which instance is to be removed.
> >...
>
> The interesting thing is that you can never safely tell it for any
> amount of context - I've seen patches with three lines of context being
> applied at the wrong place simply because there were several matching
> contexts.
Yes, that is right. You can never safely tell. But now you want to allow
even less context by default. In which you can even "more neverer" safely
tell. That is why I am disagreeing with that change.
Ciao,
Dscho
^ permalink raw reply
* Re: Update local tracking refs when pushing- no way to disable
From: Johannes Schindelin @ 2007-07-06 12:46 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Dan McGee, git
In-Reply-To: <Pine.LNX.4.64.0707052320090.14638@iabervon.org>
Hi,
On Thu, 5 Jul 2007, Daniel Barkalow wrote:
> What git-fetch and git-push care about is whether you have an entry
> "remote.<name>.fetch" with a colon and stuff on the right of it. If so,
> this is a pattern that is used to generate the duplicate branch heads
> that you don't want. git clone sets it up to a default pattern
> (refs/remotes/origin/*), and I don't think there's any way to make it
> not do that, but you can just reconfigure it afterwards if you don't
> like it.
Related, but not identical, is the problem illustrated in
http://thread.gmane.org/gmane.comp.version-control.git/49888
IMHO there is a bug. IIUC git push first looks for common ref names on the
local and remote side (yes, refs/remotes are excluded since v1.5.3-rc0~9,
but the underlying problem is still there). Then it pushes them. But here,
something seems to have gone wrong: refs/remotes/origin/HEAD is a symref.
And the corresponding ref is updated. Should git-push not just _not_
update symrefs?
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] Per-path attribute based hunk header selection.
From: Johannes Schindelin @ 2007-07-06 12:38 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7v8x9uexji.fsf_-_@assigned-by-dhcp.cox.net>
Hi,
On Fri, 6 Jul 2007, Junio C Hamano wrote:
> diff --git a/diff.c b/diff.c
> @@ -1143,6 +1154,82 @@ int diff_filespec_is_binary(struct diff_filespec *one)
> return one->is_binary;
> }
>
> +static struct hunk_header_regexp {
> + char *name;
> + char *regexp;
> + struct hunk_header_regexp *next;
> +} *hunk_header_regexp_list, **hunk_header_regexp_tail;
> +
> +static int hunk_header_config(const char *var, const char *value)
> +{
> + static const char funcname[] = "funcname.";
> + struct hunk_header_regexp *hh;
> +
> + if (prefixcmp(var, funcname))
> + return 0;
> + var += strlen(funcname);
> + for (hh = hunk_header_regexp_list; hh; hh = hh->next)
> + if (!strcmp(var, hh->name)) {
> + free(hh->regexp);
> + hh->regexp = xstrdup(value);
> + return 0;
> + }
Heh. By reordering your code, you could say
if ((hh = hunk_header_regexp(var))) {
free(hh->regexp);
hh->regexp = xstrdup(value);
return 0;
}
> + hh = xcalloc(1, sizeof(*hh));
> + hh->name = xstrdup(var);
> + hh->regexp = xstrdup(value);
> + hh->next = NULL;
> + *hunk_header_regexp_tail = hh;
> + return 0;
> +}
Is that tail expansion not overly complex? Why not just set "hh->next =
hunk_header_regexp_list; hunk_header_regexp_list = hh";
Yes, your code seems correct, but I took some extra cycles to get at that
impression. A "static int parsed_config_for_hunk_headers" would have
helped, instead of reusing _tail for two purposes. And this variable could
be set at the beginning of hunk_header_config(), so that
hunk_header_regexp() is usable from inside hunk_header_config().
> +static const char *hunk_header_regexp(const char *ident)
> +{
> + struct hunk_header_regexp *hh;
> +
> + if (!hunk_header_regexp_tail) {
> + hunk_header_regexp_tail = &hunk_header_regexp_list;
> + git_config(hunk_header_config);
> + }
> + for (hh = hunk_header_regexp_list; hh; hh = hh->next)
> + if (!strcmp(ident, hh->name))
> + return hh->regexp;
> + return NULL;
> +}
Another thing. These long names are a bit inconsistent. In the config, you
name it "funcname". In xdiff, we name them "FUNCNAMES". Yes, here they are
hunk_headers.
Also, since the expressions are not strictly regular expressions, but
lists of them, and with your idea they are even more different, why not
just go for "funcname_list"? It's easier to read, and static anyway.
Rest looks fine to me...
Ciao,
Dscho
^ permalink raw reply
* Re: being nice to patch(1)
From: David Kastrup @ 2007-07-06 12:38 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.64.0707031303130.4071@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> > >
>> > > I guess the second choice generally isn't an option, but dammit,
>> > > "git-apply" really is the better program here.
>> >
>> > Why not? git-apply works outside of a git repo ;-)
>>
>> I was more thinking that people are not necessarily willing to install git
>> just to get the "git-apply" program..
>
> But maybe they would be willing to install git to get that wonderful
> git-apply program, and that wonderful rename-and-mode-aware
> git-diff, and the git-merge-file program, all of which can operate
> outside of a git repository. (Take that, hg!)
Well, hmph! I just rewrote my git-diff-using script to not check
stuff into a throw-away git repository, and guess what: with real-life
use cases (diffing trees of about 500MB size), git-diff runs out of
memory (the machine probably has something like 1.5GB of virtual memory
size) when operating outside of a git repository.
So the usefulness still seems limited, even now that the output format
of --name-status has been fixed.
Any idea whether this is a bug, sloppy programming, or an inherent
restriction/necessity?
Also an idea which of the following scenarios would be best for
catching all of moves/renames/deletes/adds? Note: any repository is
strictly throw-away.
Experiments are somewhat time-consuming, so every hunch helps.
a) diff directories outside of git (works, but fatal memory footprint
for large cases)
b) diff index against work directory
c) diff revision against work directory
d) diff revision against index
e) diff revision against revision (works, but high disk footprint and
likely slower than alternatives)
Thanks,
--
David Kastrup
^ permalink raw reply
* Re: [PATCH 1/3] Introduce diff_filespec_is_binary()
From: Johannes Schindelin @ 2007-07-06 12:20 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vejjmexm0.fsf_-_@assigned-by-dhcp.cox.net>
Hi,
On Fri, 6 Jul 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > It is quite cute to hide this in the funcname patch...
>
> So this is the proper refactoring _before_ any of your topics.
Thanks. And sorry for bugging you.
Ciao,
Dscho
^ permalink raw reply
* [PATCH] git-cvsserver: detect/diagnose write failure, etc.
From: Jim Meyering @ 2007-07-06 12:18 UTC (permalink / raw)
To: git
Currently I maintain a CVS repository that mirrors
the primary git repository for the GNU coreutils.
It is kept in sync via a relatively fragile "update" (push) hook
that runs git-cvsexportcommit every time I push to the git repository.
Since it'd be nice to keep cvs support (so as not to *require*
everyone to switch to git right away), without the actual CVS
repository, I'm considering using git-cvsserver.
However, before I switch, I'd like to have a little more
confidence that it is reliable. I've included a patch below
that makes it more likely to report if/when something goes wrong,
usually just write errors.
Beware: in some contexts (when running as server), one must
not "die", but rather return an "error" indicator to the client.
I did that in the second hunk. However, I haven't carefully
audited the others, and so, some of the "die" calls I added may
end up killing the server, when a gentler failure is required.
I've just looked, and can confirm that my change to req_Modified
(first hunk) is wrong. It should not die. Rather, it should probably
do something like the "print "E ... in hunk#2. Ideally, someone
would write a test to exercise code like this, to make sure it works.
Jim
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 5cbf27e..8d8d6f5 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -644,7 +644,7 @@ sub req_Modified
$bytesleft -= $blocksize;
}
- close $fh;
+ close $fh or die "Failed to write temporary, $filename: $!";
# Ensure we have something sensible for the file mode
if ( $mode =~ /u=(\w+)/ )
@@ -901,8 +901,13 @@ sub req_update
# projects (heads in this case) to checkout.
#
if ($state->{module} eq '') {
+ my $heads_dir = $state->{CVSROOT} . '/refs/heads';
+ if (!opendir HEADS, $heads_dir) {
+ print "E [server aborted]: Failed to open directory, $heads_dir: $!\n"
+ . "error\n";
+ return 0;
+ }
print "E cvs update: Updating .\n";
- opendir HEADS, $state->{CVSROOT} . '/refs/heads';
while (my $head = readdir(HEADS)) {
if (-f $state->{CVSROOT} . '/refs/heads/' . $head) {
print "E cvs update: New directory `$head'\n";
@@ -1754,7 +1759,9 @@ sub req_annotate
# git-jsannotate telling us about commits we are hiding
# from the client.
- open(ANNOTATEHINTS, ">$tmpdir/.annotate_hints") or die "Error opening > $tmpdir/.annotate_hints $!";
+ my $a_hints = "$tmpdir/.annotate_hints";
+ open(ANNOTATEHINTS, '>', $a_hints)
+ or die "Failed to open '$a_hints' for writing: $!";
for (my $i=0; $i < @$revisions; $i++)
{
print ANNOTATEHINTS $revisions->[$i][2];
@@ -1765,11 +1772,11 @@ sub req_annotate
}
print ANNOTATEHINTS "\n";
- close ANNOTATEHINTS;
+ close ANNOTATEHINTS or die "Failed to write $a_hints: $!";
- my $annotatecmd = 'git-annotate';
- open(ANNOTATE, "-|", $annotatecmd, '-l', '-S', "$tmpdir/.annotate_hints", $filename)
- or die "Error invoking $annotatecmd -l -S $tmpdir/.annotate_hints $filename : $!";
+ my @cmd = (qw(git-annotate -l -S), $a_hints, $filename);
+ open(ANNOTATE, "-|", @cmd)
+ or die "Error invoking ". join(' ',@cmd) .": $!";
my $metadata = {};
print "E Annotations for $filename\n";
print "E ***************\n";
@@ -1996,12 +2003,12 @@ sub transmitfile
{
open NEWFILE, ">", $targetfile or die("Couldn't open '$targetfile' for writing : $!");
print NEWFILE $_ while ( <$fh> );
- close NEWFILE;
+ close NEWFILE or die("Failed to write '$targetfile': $!");
} else {
print "$size\n";
print while ( <$fh> );
}
- close $fh or die ("Couldn't close filehandle for transmitfile()");
+ close $fh or die ("Couldn't close filehandle for transmitfile(): $!");
} else {
die("Couldn't execute git-cat-file");
}
@@ -2501,17 +2508,14 @@ sub update
if ($parent eq $lastpicked) {
next;
}
- open my $p, 'git-merge-base '. $lastpicked . ' '
- . $parent . '|';
- my @output = (<$p>);
- close $p;
- my $base = join('', @output);
+ my $base = safe_pipe_capture('git-merge-base',
+ $lastpicked, $parent);
chomp $base;
if ($base) {
my @merged;
# print "want to log between $base $parent \n";
open(GITLOG, '-|', 'git-log', "$base..$parent")
- or die "Cannot call git-log: $!";
+ or die "Cannot call git-log: $!";
my $mergedhash;
while (<GITLOG>) {
chomp;
--
1.5.3.rc0.11.ge2b1a-dirty
^ permalink raw reply related
* Re: git-apply{,mbox,patch} should default to --unidiff-zero
From: Adrian Bunk @ 2007-07-06 12:14 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Linus Torvalds, Johannes Schindelin, git
In-Reply-To: <7vd4z6gkbk.fsf@assigned-by-dhcp.cox.net>
On Thu, Jul 05, 2007 at 10:41:51PM -0700, Junio C Hamano wrote:
> Linus Torvalds <torvalds@linux-foundation.org> writes:
>...
> > Adrian has a point in that if there are lines to be deleted, that in
> > itself is context, and then the strict behaviour of "git-apply" is
> > arguably unnecessaily strict.
>
> Not really. That is true, unless you have two identical
> instances of the group of lines being deleted, in which case you
> cannot safely tell which instance is to be removed.
>...
The interesting thing is that you can never safely tell it for any
amount of context - I've seen patches with three lines of context being
applied at the wrong place simply because there were several matching
contexts.
cu
Adrian
--
"Is there not promise of rain?" Ling Tan asked suddenly out
of the darkness. There had been need of rain for many days.
"Only a promise," Lao Er said.
Pearl S. Buck - Dragon Seed
^ permalink raw reply
* [PATCH] Enable "git rerere" by the config variable rerere.enabled
From: Johannes Schindelin @ 2007-07-06 12:05 UTC (permalink / raw)
To: git, gitster, Shawn O. Pearce
Earlier, "git rerere" was enabled by creating the directory
.git/rr-cache. That is definitely not in line with most other
features, which are enabled by a config variable.
So, check the config variable "rerere.enabled". If it is set
to "false" explicitely, do not activate rerere, even if
.git/rr-cache exists. This should help when you want to disable
rerere temporarily.
If "rerere.enabled" is not set at all, fall back to detection
of the directory .git/rr-cache.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Touches quite some parts, doesn't it?
And yeah, the git-gui part should be factored out, I guess. Shawn?
Documentation/config.txt | 5 +++++
Documentation/git-rerere.txt | 4 ++--
builtin-rerere.c | 31 +++++++++++++++++++++++++++----
contrib/emacs/git.el | 3 +--
git-am.sh | 15 +++------------
git-commit.sh | 5 +----
git-gui/lib/commit.tcl | 4 +---
git-merge.sh | 5 +----
git-rebase.sh | 12 +++---------
t/t4200-rerere.sh | 23 ++++++++++++++++++++---
10 files changed, 64 insertions(+), 43 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 66a55b0..4b67f0a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -448,6 +448,11 @@ gc.rerereunresolved::
kept for this many days when `git rerere gc` is run.
The default is 15 days. See gitlink:git-rerere[1].
+rerere.enabled::
+ Activate recording of resolved conflicts, so that identical
+ conflict hunks can be resolved automatically, should they
+ be encountered again. See gitlink:git-rerere[1].
+
gitcvs.enabled::
Whether the cvs server interface is enabled for this repository.
See gitlink:git-cvsserver[1].
diff --git a/Documentation/git-rerere.txt b/Documentation/git-rerere.txt
index 7ff9b05..c4d4263 100644
--- a/Documentation/git-rerere.txt
+++ b/Documentation/git-rerere.txt
@@ -23,7 +23,7 @@ initial manual merge, and later by noticing the same automerge
results and applying the previously recorded hand resolution.
[NOTE]
-You need to create `$GIT_DIR/rr-cache` directory to enable this
+You need to set the config variable rerere.enabled to enable this
command.
@@ -171,7 +171,7 @@ records it if it is a new conflict, or reuses the earlier hand
resolve when it is not. `git-commit` also invokes `git-rerere`
when recording a merge result. What this means is that you do
not have to do anything special yourself (Note: you still have
-to create `$GIT_DIR/rr-cache` directory to enable this command).
+to set the config variable rerere.enabled to enable this command).
In our example, when you did the test merge, the manual
resolution is recorded, and it will be reused when you do the
diff --git a/builtin-rerere.c b/builtin-rerere.c
index 29fb075..af4d35a 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -12,6 +12,9 @@ static const char git_rerere_usage[] =
static int cutoff_noresolve = 15;
static int cutoff_resolve = 60;
+/* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
+static int rerere_enabled = -1;
+
static char *merge_rr_path;
static const char *rr_path(const char *name, const char *file)
@@ -387,21 +390,40 @@ static int git_rerere_config(const char *var, const char *value)
cutoff_resolve = git_config_int(var, value);
else if (!strcmp(var, "gc.rerereunresolved"))
cutoff_noresolve = git_config_int(var, value);
+ else if (!strcmp(var, "rerere.enabled"))
+ rerere_enabled = git_config_bool(var, value);
else
return git_default_config(var, value);
return 0;
}
-int cmd_rerere(int argc, const char **argv, const char *prefix)
+int is_rerere_enabled(void)
{
- struct path_list merge_rr = { NULL, 0, 0, 1 };
- int i, fd = -1;
struct stat st;
+ const char *rr_cache = git_path("rr-cache");
+ int rr_cache_exists;
- if (stat(git_path("rr-cache"), &st) || !S_ISDIR(st.st_mode))
+ if (!rerere_enabled)
return 0;
+ rr_cache_exists = !stat(rr_cache, &st) && S_ISDIR(st.st_mode);
+ if (rerere_enabled < 0)
+ return rr_cache_exists;
+
+ if (!rr_cache_exists && (mkdir(rr_cache, 0777) ||
+ adjust_shared_perm(rr_cache)))
+ die("Could not create directory %s", rr_cache);
+ return 1;
+}
+
+int cmd_rerere(int argc, const char **argv, const char *prefix)
+{
+ struct path_list merge_rr = { NULL, 0, 0, 1 };
+ int i, fd = -1;
+
git_config(git_rerere_config);
+ if (!is_rerere_enabled())
+ return 0;
merge_rr_path = xstrdup(git_path("rr-cache/MERGE_RR"));
fd = hold_lock_file_for_update(&write_lock, merge_rr_path, 1);
@@ -411,6 +433,7 @@ int cmd_rerere(int argc, const char **argv, const char *prefix)
return do_plain_rerere(&merge_rr, fd);
else if (!strcmp(argv[1], "clear")) {
for (i = 0; i < merge_rr.nr; i++) {
+ struct stat st;
const char *name = (const char *)merge_rr.items[i].util;
if (!stat(git_path("rr-cache/%s", name), &st) &&
S_ISDIR(st.st_mode) &&
diff --git a/contrib/emacs/git.el b/contrib/emacs/git.el
index f600179..457f95f 100644
--- a/contrib/emacs/git.el
+++ b/contrib/emacs/git.el
@@ -681,8 +681,7 @@ and returns the process output as a string."
(condition-case nil (delete-file ".git/MERGE_MSG") (error nil))
(with-current-buffer buffer (erase-buffer))
(git-set-files-state files 'uptodate)
- (when (file-directory-p ".git/rr-cache")
- (git-run-command nil nil "rerere"))
+ (git-run-command nil nil "rerere")
(git-refresh-files)
(git-refresh-ewoc-hf git-status)
(message "Committed %s." commit)
diff --git a/git-am.sh b/git-am.sh
index d57a3e2..e5e6f2c 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -95,10 +95,7 @@ It does not apply to blobs recorded in its index."
eval GITHEAD_$his_tree='"$SUBJECT"'
export GITHEAD_$his_tree
git-merge-recursive $orig_tree -- HEAD $his_tree || {
- if test -d "$GIT_DIR/rr-cache"
- then
- git rerere
- fi
+ git rerere
echo Failed to merge in the changes.
exit 1
}
@@ -252,10 +249,7 @@ last=`cat "$dotest/last"`
this=`cat "$dotest/next"`
if test "$skip" = t
then
- if test -d "$GIT_DIR/rr-cache"
- then
- git rerere clear
- fi
+ git rerere clear
this=`expr "$this" + 1`
resume=
fi
@@ -420,10 +414,7 @@ do
stop_here_user_resolve $this
fi
apply_status=0
- if test -d "$GIT_DIR/rr-cache"
- then
- git rerere
- fi
+ git rerere
;;
esac
diff --git a/git-commit.sh b/git-commit.sh
index f866f95..9106a74 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -610,10 +610,7 @@ rm -f "$GIT_DIR/COMMIT_MSG" "$GIT_DIR/COMMIT_EDITMSG" "$GIT_DIR/SQUASH_MSG"
cd_to_toplevel
-if test -d "$GIT_DIR/rr-cache"
-then
- git rerere
-fi
+git rerere
if test "$ret" = 0
then
diff --git a/git-gui/lib/commit.tcl b/git-gui/lib/commit.tcl
index f9791f6..578bef8 100644
--- a/git-gui/lib/commit.tcl
+++ b/git-gui/lib/commit.tcl
@@ -331,9 +331,7 @@ A rescan will be automatically started now.
# -- Let rerere do its thing.
#
- if {[file isdirectory [gitdir rr-cache]]} {
- catch {git rerere}
- }
+ catch {git rerere}
# -- Run the post-commit hook.
#
diff --git a/git-merge.sh b/git-merge.sh
index 4852530..5ccf282 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -496,9 +496,6 @@ Conflicts:
sed -e 's/^[^ ]* / /' |
uniq
} >>"$GIT_DIR/MERGE_MSG"
- if test -d "$GIT_DIR/rr-cache"
- then
- git rerere
- fi
+ git rerere
die "Automatic merge failed; fix conflicts and then commit the result."
fi
diff --git a/git-rebase.sh b/git-rebase.sh
index 7a02f29..cbafa14 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -101,7 +101,7 @@ call_merge () {
return
;;
1)
- test -d "$GIT_DIR/rr-cache" && git rerere
+ git rerere
die "$RESOLVEMSG"
;;
2)
@@ -160,10 +160,7 @@ do
--skip)
if test -d "$dotest"
then
- if test -d "$GIT_DIR/rr-cache"
- then
- git rerere clear
- fi
+ git rerere clear
prev_head="`cat $dotest/prev_head`"
end="`cat $dotest/end`"
msgnum="`cat $dotest/msgnum`"
@@ -181,10 +178,7 @@ do
exit
;;
--abort)
- if test -d "$GIT_DIR/rr-cache"
- then
- git rerere clear
- fi
+ git rerere clear
if test -d "$dotest"
then
rm -r "$dotest"
diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh
index 71d364a..6f55ba0 100755
--- a/t/t4200-rerere.sh
+++ b/t/t4200-rerere.sh
@@ -39,15 +39,32 @@ sed -e 's/To die, t/To die! T/' > a1
echo "* END *" >>a1
git commit -q -a -m second
-# activate rerere
-mkdir .git/rr-cache
+test_expect_success 'nothing recorded without rerere' '
+ (rm -rf .git/rr-cache; git config rerere.enabled false) &&
+ ! git merge first &&
+ ! test -d .git/rr-cache
+'
-test_expect_failure 'conflicting merge' 'git pull . first'
+# activate rerere, old style
+test_expect_success 'conflicting merge' '
+ git reset --hard &&
+ mkdir .git/rr-cache &&
+ git config --unset rerere.enabled &&
+ ! git merge first
+'
sha1=$(sed -e 's/ .*//' .git/rr-cache/MERGE_RR)
rr=.git/rr-cache/$sha1
test_expect_success 'recorded preimage' "grep ======= $rr/preimage"
+test_expect_success 'rerere.enabled works, too' '
+ rm -rf .git/rr-cache &&
+ git config rerere.enabled true &&
+ git reset --hard &&
+ ! git merge first &&
+ grep ======= $rr/preimage
+'
+
test_expect_success 'no postimage or thisimage yet' \
"test ! -f $rr/postimage -a ! -f $rr/thisimage"
--
1.5.3.rc0.2689.g99ca2-dirty
^ permalink raw reply related
* Re: [PATCH] git init: activate rerere by default
From: Johannes Schindelin @ 2007-07-06 12:03 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Alex Riesen, git
In-Reply-To: <7v1wfmi090.fsf@assigned-by-dhcp.cox.net>
Hi,
On Thu, 5 Jul 2007, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> > .... I guess that many distros do not update their templates as often
> > as the core, because they are much more likely to be modified
> > distro-specifically.
>
> Can you back that up? Fedora and Debian seem to ship them unmodified.
No.
> > Further, there are some platforms which are insane enough that you
> > cannot trust the executable bit, and therefore the templates are
> > disabled by default.
But this still holds.
> If you truly want to have rerere enabled by default, it might make sense
> to:
>
> * Remove "if test -d "$GIT_DIR/rr-cache" tests we have in the
> existing users;
>
> * Implement a new test in builtin-rerere.c, as:
>
> - if rerere.enabled configuration does not exist, check
> $GIT_DIR/rr-cache as before;
>
> - if rerere.enabled configuration is true, do not bother
> checking $GIT_DIR/rr-cache, but just do it;
>
> - if rerere.enabled configuration is explicitly set to false,
> never use rerere.
>
> * Maybe later we might change the default value for
> rerere.enabled to "true", IOW, everybody except people who
> say "[rerere] enabled = false" in their configuration
> automatically gets rerere.
>
> Doing it in git-init, either your patch or by installing a new
> template, means existing old repository would never get the
> updated behaviour unless the user runs "git init" there, which
> is not a very intuitive thing to do to begin with.
Well, I finally bit the apple. Will post in a minute.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH] git init: activate rerere by default
From: Johannes Schindelin @ 2007-07-06 12:03 UTC (permalink / raw)
To: しらいしななこ; +Cc: Alex Riesen, git
In-Reply-To: <200707061112.l66BCb6w017186@mi1.bluebottle.com>
[-- Attachment #1: Type: TEXT/PLAIN, Size: 1195 bytes --]
Hi,
On Fri, 6 Jul 2007, しらいしななこ wrote:
> I am sorry, but I can't understand how [git rerere] works and how it is
> useful, after reading the manual page of git-rerere three times. Are
> there "rerere tutorial for stupid newbies" document somewhere? I
> earlier created .git/rr-cache folder but I have not seen anything
> interesting happened in my repository.
There is no tutorial. In fact, it should help your workflow seemlessly.
Suppose that you rebase a lot, on top of an upstream who has conflicting
changes, and refuses (at least for a long time) to merge your work.
What you usually do is work out the conflicts over and over again, often
identically. Basically for many conflicts (but not necessarily all!), you
say: "Yes, I have seen that. My version is better."
When rerere is enabled, it records the conflicting hunks (i.e. the parts
between <<<<<<< ... ======= ... >>>>>>>) together with how you resolved
it, and next time it sees the same conflicting hunks, it automatically
applies your resolution.
You should still inspect if it makes sense, and therefore the merge will
still fail, even if all conflicts were automatically resolved.
Hth,
Dscho
^ permalink raw reply
* Re: [PATCH] git init: activate rerere by default
From: しらいしななこ @ 2007-07-06 11:12 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Alex Riesen, git
In-Reply-To: <Pine.LNX.4.64.0707052018260.9789@racer.site>
Quoting Johannes Schindelin <Johannes.Schindelin@gmx.de>:
> All this means that the given patch would not hardly make rerere as
> widespread as I intended.
>
> Yes, templates are nice. But I don't think that templates are the way to
> go for introducing nice features as rr-cache.
I am sorry, but I can't understand how it works and how it is useful,
after reading the manual page of git-rerere three times. Are there
"rerere tutorial for stupid newbies" document somewhere? I earlier
created .git/rr-cache folder but I have not seen anything interesting
happened in my repository.
--
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/
----------------------------------------------------------------------
Free pop3 email with a spam filter.
http://www.bluebottle.com/tag/5
^ permalink raw reply
* Re: gitk doesn't start due to cygwin wish not following symlinks?
From: Jan Hudec @ 2007-07-06 9:33 UTC (permalink / raw)
To: Kees-Jan Dijkzeul; +Cc: git
In-Reply-To: <fa0b6e200707031202g4a1248d8na22fbf99b215804@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1290 bytes --]
On Tue, Jul 03, 2007 at 21:02:35 +0200, Kees-Jan Dijkzeul wrote:
> Hi,
>
> I'm using "stow" to manage several versions of git on my cygwin
> system. As a result, my /usr/local/bin contains a bunch of symlinks to
> the actual binaries in /usr/local/stow/git-1.5.2.2/bin.
>
> This works like a charm, except that gitk won't start up, claiming, in
> turn, that it is unable to start git itself. After some investigation,
> I found that the "wish" that is supplied with cygwin isn't a true
> cygwin one, and hence doesn't understand cygwin style simlinks, and
> thus cannot start the /usr/local/bin/git symlink. It needs the true
> binary.
>
> So for now, I've worked around this by updating the first few lines of
> the gitk script to read:
>
> #!/bin/sh
> # Tcl ignores the next line -*- tcl -*- \
> export PATH=$PATH:/usr/local/stow/git-1.5.2.2/bin
> # Tcl ignores the next line also \
> exec wish "$0" -- "$@"
>
> This works for me, but is admittedly butt-ugly. Any tips on how to
> handle this kind of situation?
Ask cygwin folks to teach their wish their symlinks?
You could also try putting a git.bat somewhere in path, that would set the
path and run true git from /usr/local/stow/git-1.5.2.2/bin.
--
Jan 'Bulb' Hudec <bulb@ucw.cz>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 2/2] filter-branch: fail gracefully when a filter fails
From: Jeff King @ 2007-07-06 9:31 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes.Schindelin, git
In-Reply-To: <7vir8yextt.fsf@assigned-by-dhcp.cox.net>
On Fri, Jul 06, 2007 at 01:33:02AM -0700, Junio C Hamano wrote:
> the purpose of updating this script, I would say a temporary
> file is much better than any of the alternatives around 1>&3.
As the one who originally mentioned the redirection trick, let me say
that I agree. I brought it up more as "yuck, this is the way you have
to do it" than a real suggestion. I think the tempfile, while ugly, is
less ugly.
-Peff
^ permalink raw reply
* Re: [Bug?] compiler warning with gcc >= 4.2
From: Jan Hudec @ 2007-07-06 8:55 UTC (permalink / raw)
To: Nicolas Pitre; +Cc: Frank Lichtenheld, Git Mailing List
In-Reply-To: <alpine.LFD.0.999.0707030957160.26459@xanadu.home>
[-- Attachment #1: Type: text/plain, Size: 2659 bytes --]
On Tue, Jul 03, 2007 at 10:18:52 -0400, Nicolas Pitre wrote:
> On Tue, 3 Jul 2007, Frank Lichtenheld wrote:
>
> > Hi,
> >
> > while testing for an (probably) unrelated miscompilation bug,
> > I got the following warning while compiling git:
> >
> > gcc-4.2 -o sha1_file.o -c -g -O2 -Wall -DSHA1_HEADER='<openssl/sha.h>'
> > -DETC_GITCONFIG='"/home/djpig/etc/gitconfig"' -DNO_STRLCPY sha1_file.c
> > sha1_file.c: In function ‘check_packed_git_idx’:
> > sha1_file.c:523: warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false
> > sha1_file.c:523: warning: assuming signed overflow does not occur when assuming that (X + c) < X is always false
> >
> > This comes from the new -Wstrict-overflow which warns about the fact
> > that with -fstrict-overflow, which is activated by default with -O2,
> > the if clause referenced in the warning will be optimised away.
> >
> > So I would be interested to know
> > a) if the compiler optimising this check away (which seems to be a check
> > about whether signed overflow can occour) can lead to unwanted results
>
> Of course it can if the compiler blindly optimizes the test away.
>
> In this particular case, the answer can be determined at compile time
> though, since all values to perform the test are constants. So in this
> case the warning is rather obnoxious.
>
> However it would be completely wrong if the compiler optimized away the
> if from index-pack.c on line 104, or from builtin-pack-objects.c on line
> 579. Even warning about it without actually optimizing it away would be
> bad in those cases.
The compiler *will* optimize it away according to the manual
(http://gcc.gnu.org/onlinedocs/gcc-4.2.0/gcc/Optimize-Options.html#index-fstrict_002doverflow-551).
Reasoning behind that is, that C standard does not define what will happen on
signed overflow and therefore the code should not depend on it. Gcc 4.2 has
an option to specify that signed overflow always wraps -- -fwrapv, in which
case the compiler will compute the result as intended (and should not produce
the warning).
> > b) if not a), if it would make sense trying to suppress that warning, so
> > that other people don't end up wondering the same as me
>
> I really wonder what's the point for gcc to warn about such things.
> Sure the warning should go away, but not by compromizing the test that
> we need performed on the actual definition of off_t.
Yes, there is. The expression is undefined according to the C specification,
(or at least GCC manual claims it).
--
Jan 'Bulb' Hudec <bulb@ucw.cz>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: Update local tracking refs when pushing- no way to disable
From: Shawn O. Pearce @ 2007-07-06 8:42 UTC (permalink / raw)
To: Marco Costalba; +Cc: Daniel Barkalow, Dan McGee, git
In-Reply-To: <e5bfff550707060126t781587aaxbe2f6eca1c282985@mail.gmail.com>
Marco Costalba <mcostalba@gmail.com> wrote:
> On 7/6/07, Daniel Barkalow <barkalow@iabervon.org> wrote:
> >
> >(AFAICT, the only additional stuff that -a shows with git branch is the
> >stuff that you're deleting; perhaps qgit should have an option to not show
> >remotes, or not show them by default or only show them if what they point
> >to isn't otherwise marked? Anyway, it shouldn't be necessary to avoid
> >having this information just so that it isn't shown in interfaces you
> >use.)
> >
>
> Probably an option "show remote branches" from a popup context menu
> (right click) is the more natural and predictable solution.
Recently I was faced with handling a repository that has over
200 local refs/heads and 200+ refs/remotes that the user might
be interested in working on. Yea, its fun to look at in gitk.
It is not fun to run `git fetch` when on Cygwin.
Anyway, the git-gui `pu` branch now has new UI to handle these
sorts of cases rather nicely. The revision selection mega-widget
that I recently wrote lets the user select which "class" of ref
(head, tracking branch, tag) they want and then filter them using
a substring glob filter. The trick works very well to let the user
weed the list of 400+ possible refs down to just a couple that they
can pick from with the keyboard, or the mouse.
The UI will be in 0.8.0. Which I'm hoping to go into an rc status
later this week.
Minor warning: currently the `pu` branch of git-gui probably
requires git 1.5.3-rc0 or later. It doesn't test for it and just
assumes your git is new enough. I do plan on fixing the couple of
spots that might matter to be conditional and fallback gracefully
if 1.5.3 isn't available. Just haven't done it yet. Those will
be fixed before they merge to `master`.
--
Shawn.
^ permalink raw reply
* [PATCH] Per-path attribute based hunk header selection.
From: Junio C Hamano @ 2007-07-06 8:39 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Linus Torvalds, git
In-Reply-To: <Pine.LNX.4.64.0707051223520.9789@racer.site>
This makes"diff -p" hunk headers customizable via gitattributes mechanism.
It is based on Johannes's earlier patch that allowed to define a single
regexp to be used for everything.
The mechanism to arrive at the regexp that is used to define hunk header
is the same as other use of gitattributes. You assign an attribute, funcname
(because "diff -p" typically uses the name of the function the patch is about
as the hunk header), a simple string value. This can be one of the names of
built-in pattern (currently, "java" is defined) or a custom pattern name, to
be looked up from the configuration file.
(in .gitattributes)
*.java funcname=java
*.perl funcname=perl
(in .git/config)
[funcname]
java = ... # ugly and complicated regexp to override the built-in one.
perl = ... # another ugly and complicated regexp to define a new one.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
This three patch series is lacking 2/3, as it is exactly the
same as the earlier "1/2 Future-proof source for changes in
xdemitconf_t" patch.
diff.c | 96 +++++++++++++++++++++++++++++++++++++++++++++-
diffcore.h | 1 +
t/t4018-diff-funcname.sh | 60 ++++++++++++++++++++++++++++
xdiff-interface.c | 71 ++++++++++++++++++++++++++++++++++
xdiff-interface.h | 2 +
xdiff/xdiff.h | 4 ++
xdiff/xemit.c | 37 +++++++++++-------
7 files changed, 256 insertions(+), 15 deletions(-)
create mode 100644 t/t4018-diff-funcname.sh
diff --git a/diff.c b/diff.c
index d10e848..04e7e91 100644
--- a/diff.c
+++ b/diff.c
@@ -1101,22 +1101,26 @@ static void emit_binary_diff(mmfile_t *one, mmfile_t *two)
static void setup_diff_attr_check(struct git_attr_check *check)
{
static struct git_attr *attr_diff;
+ static struct git_attr *attr_diff_func_name;
if (!attr_diff) {
attr_diff = git_attr("diff", 4);
+ attr_diff_func_name = git_attr("funcname", 8);
}
check[0].attr = attr_diff;
+ check[1].attr = attr_diff_func_name;
}
static void diff_filespec_check_attr(struct diff_filespec *one)
{
- struct git_attr_check attr_diff_check[1];
+ struct git_attr_check attr_diff_check[2];
if (one->checked_attr)
return;
setup_diff_attr_check(attr_diff_check);
one->is_binary = 0;
+ one->hunk_header_ident = NULL;
if (!git_checkattr(one->path, ARRAY_SIZE(attr_diff_check), attr_diff_check)) {
const char *value;
@@ -1127,6 +1131,13 @@ static void diff_filespec_check_attr(struct diff_filespec *one)
;
else if (ATTR_FALSE(value))
one->is_binary = 1;
+
+ /* hunk header ident */
+ value = attr_diff_check[1].value;
+ if (ATTR_TRUE(value) || ATTR_FALSE(value) || ATTR_UNSET(value))
+ ;
+ else
+ one->hunk_header_ident = value;
}
if (!one->data && DIFF_FILE_VALID(one))
@@ -1143,6 +1154,82 @@ int diff_filespec_is_binary(struct diff_filespec *one)
return one->is_binary;
}
+static struct hunk_header_regexp {
+ char *name;
+ char *regexp;
+ struct hunk_header_regexp *next;
+} *hunk_header_regexp_list, **hunk_header_regexp_tail;
+
+static int hunk_header_config(const char *var, const char *value)
+{
+ static const char funcname[] = "funcname.";
+ struct hunk_header_regexp *hh;
+
+ if (prefixcmp(var, funcname))
+ return 0;
+ var += strlen(funcname);
+ for (hh = hunk_header_regexp_list; hh; hh = hh->next)
+ if (!strcmp(var, hh->name)) {
+ free(hh->regexp);
+ hh->regexp = xstrdup(value);
+ return 0;
+ }
+ hh = xcalloc(1, sizeof(*hh));
+ hh->name = xstrdup(var);
+ hh->regexp = xstrdup(value);
+ hh->next = NULL;
+ *hunk_header_regexp_tail = hh;
+ return 0;
+}
+
+static const char *hunk_header_regexp(const char *ident)
+{
+ struct hunk_header_regexp *hh;
+
+ if (!hunk_header_regexp_tail) {
+ hunk_header_regexp_tail = &hunk_header_regexp_list;
+ git_config(hunk_header_config);
+ }
+ for (hh = hunk_header_regexp_list; hh; hh = hh->next)
+ if (!strcmp(ident, hh->name))
+ return hh->regexp;
+ return NULL;
+}
+
+static const char *diff_hunk_header_regexp(struct diff_filespec *one)
+{
+ const char *ident, *regexp;
+
+ diff_filespec_check_attr(one);
+ ident = one->hunk_header_ident;
+
+ if (!ident)
+ /*
+ * If the config file has "funcname.default" defined, that
+ * regexp is used; otherwise NULL is returned and xemit uses
+ * the built-in default.
+ */
+ return hunk_header_regexp("default");
+
+ /* Look up custom "funcname.$ident" regexp from config. */
+ regexp = hunk_header_regexp(ident);
+ if (regexp)
+ return regexp;
+
+ /*
+ * And define built-in fallback patterns here. Note that
+ * these can be overriden by the user's config settings.
+ */
+ if (!strcmp(ident, "java"))
+ return "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|"
+ "new\\|return\\|switch\\|throw\\|while\\)\n"
+ "^[ ]*\\(\\([ ]*"
+ "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}"
+ "[ ]*([^;]*$\\)";
+
+ return NULL;
+}
+
static void builtin_diff(const char *name_a,
const char *name_b,
struct diff_filespec *one,
@@ -1217,6 +1304,11 @@ static void builtin_diff(const char *name_a,
xdemitconf_t xecfg;
xdemitcb_t ecb;
struct emit_callback ecbdata;
+ const char *hunk_header_regexp;
+
+ hunk_header_regexp = diff_hunk_header_regexp(one);
+ if (!hunk_header_regexp)
+ hunk_header_regexp = diff_hunk_header_regexp(two);
memset(&xecfg, 0, sizeof(xecfg));
memset(&ecbdata, 0, sizeof(ecbdata));
@@ -1226,6 +1318,8 @@ static void builtin_diff(const char *name_a,
xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
xecfg.ctxlen = o->context;
xecfg.flags = XDL_EMIT_FUNCNAMES;
+ if (hunk_header_regexp)
+ xdiff_set_find_func(&xecfg, hunk_header_regexp);
if (!diffopts)
;
else if (!prefixcmp(diffopts, "--unified="))
diff --git a/diffcore.h b/diffcore.h
index dcab7e2..0598514 100644
--- a/diffcore.h
+++ b/diffcore.h
@@ -27,6 +27,7 @@ struct diff_filespec {
char *path;
void *data;
void *cnt_data;
+ const void *hunk_header_ident;
unsigned long size;
int xfrm_flags; /* for use by the xfrm */
unsigned short mode; /* file mode */
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
new file mode 100644
index 0000000..dc7a47b
--- /dev/null
+++ b/t/t4018-diff-funcname.sh
@@ -0,0 +1,60 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='Test custom diff function name patterns'
+
+. ./test-lib.sh
+
+LF='
+'
+
+cat > Beer.java << EOF
+public class Beer
+{
+ int special;
+ public static void main(String args[])
+ {
+ String s=" ";
+ for(int x = 99; x > 0; x--)
+ {
+ System.out.print(x + " bottles of beer on the wall "
+ + x + " bottles of beer\n"
+ + "Take one down, pass it around, " + (x - 1)
+ + " bottles of beer on the wall.\n");
+ }
+ System.out.print("Go to the store, buy some more,\n"
+ + "99 bottles of beer on the wall.\n");
+ }
+}
+EOF
+
+sed 's/beer\\/beer,\\/' < Beer.java > Beer-correct.java
+
+test_expect_success 'default behaviour' '
+ git diff Beer.java Beer-correct.java |
+ grep "^@@.*@@ public class Beer"
+'
+
+test_expect_success 'preset java pattern' '
+ echo "*.java funcname=java" >.gitattributes &&
+ git diff Beer.java Beer-correct.java |
+ grep "^@@.*@@ public static void main("
+'
+
+git config funcname.java '!static
+!String
+[^ ].*s.*'
+
+test_expect_success 'custom pattern' '
+ git diff Beer.java Beer-correct.java |
+ grep "^@@.*@@ int special;$"
+'
+
+test_expect_success 'last regexp must not be negated' '
+ git config diff.functionnameregexp "!static" &&
+ ! git diff Beer.java Beer-correct.java
+'
+
+test_done
diff --git a/xdiff-interface.c b/xdiff-interface.c
index e407cf1..be866d1 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -129,3 +129,74 @@ int buffer_is_binary(const char *ptr, unsigned long size)
size = FIRST_FEW_BYTES;
return !!memchr(ptr, 0, size);
}
+
+struct ff_regs {
+ int nr;
+ struct ff_reg {
+ regex_t re;
+ int negate;
+ } *array;
+};
+
+static long ff_regexp(const char *line, long len,
+ char *buffer, long buffer_size, void *priv)
+{
+ char *line_buffer = xstrndup(line, len); /* make NUL terminated */
+ struct ff_regs *regs = priv;
+ regmatch_t pmatch[2];
+ int result = 0, i;
+
+ for (i = 0; i < regs->nr; i++) {
+ struct ff_reg *reg = regs->array + i;
+ if (reg->negate ^ !!regexec(®->re,
+ line_buffer, 2, pmatch, 0)) {
+ free(line_buffer);
+ return -1;
+ }
+ }
+ i = pmatch[1].rm_so >= 0 ? 1 : 0;
+ line += pmatch[i].rm_so;
+ result = pmatch[i].rm_eo - pmatch[i].rm_so;
+ if (result > buffer_size)
+ result = buffer_size;
+ else
+ while (result > 0 && (isspace(line[result - 1]) ||
+ line[result - 1] == '\n'))
+ result--;
+ memcpy(buffer, line, result);
+ free(line_buffer);
+ return result;
+}
+
+void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value)
+{
+ int i;
+ struct ff_regs *regs;
+
+ xecfg->find_func = ff_regexp;
+ regs = xecfg->find_func_priv = xmalloc(sizeof(struct ff_regs));
+ for (i = 0, regs->nr = 1; value[i]; i++)
+ if (value[i] == '\n')
+ regs->nr++;
+ regs->array = xmalloc(regs->nr * sizeof(struct ff_reg));
+ for (i = 0; i < regs->nr; i++) {
+ struct ff_reg *reg = regs->array + i;
+ const char *ep = strchr(value, '\n'), *expression;
+ char *buffer = NULL;
+
+ reg->negate = (*value == '!');
+ if (reg->negate && i == regs->nr - 1)
+ die("Last expression must not be negated: %s", value);
+ if (*value == '!')
+ value++;
+ if (ep)
+ expression = buffer = xstrndup(value, ep - value);
+ else
+ expression = value;
+ if (regcomp(®->re, expression, 0))
+ die("Invalid regexp to look for hunk header: %s", expression);
+ if (buffer)
+ free(buffer);
+ value = ep + 1;
+ }
+}
diff --git a/xdiff-interface.h b/xdiff-interface.h
index 536f4e4..fb742db 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -20,4 +20,6 @@ int parse_hunk_header(char *line, int len,
int read_mmfile(mmfile_t *ptr, const char *filename);
int buffer_is_binary(const char *ptr, unsigned long size);
+extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line);
+
#endif
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 9402bb0..c00ddaa 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -73,9 +73,13 @@ typedef struct s_xdemitcb {
int (*outf)(void *, mmbuffer_t *, int);
} xdemitcb_t;
+typedef long (*find_func_t)(const char *line, long line_len, char *buffer, long buffer_size, void *priv);
+
typedef struct s_xdemitconf {
long ctxlen;
unsigned long flags;
+ find_func_t find_func;
+ void *find_func_priv;
} xdemitconf_t;
typedef struct s_bdiffparam {
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index 4b6e639..d3d9c84 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -69,7 +69,24 @@ static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
}
-static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) {
+static long def_ff(const char *rec, long len, char *buf, long sz, void *priv)
+{
+ if (len > 0 &&
+ (isalpha((unsigned char)*rec) || /* identifier? */
+ *rec == '_' || /* also identifier? */
+ *rec == '$')) { /* identifiers from VMS and other esoterico */
+ if (len > sz)
+ len = sz;
+ while (0 < len && isspace((unsigned char)rec[len - 1]))
+ len--;
+ memcpy(buf, rec, len);
+ return len;
+ }
+ return -1;
+}
+
+static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll,
+ find_func_t ff, void *ff_priv) {
/*
* Be quite stupid about this for now. Find a line in the old file
@@ -80,22 +97,12 @@ static void xdl_find_func(xdfile_t *xf, long i, char *buf, long sz, long *ll) {
const char *rec;
long len;
- *ll = 0;
while (i-- > 0) {
len = xdl_get_rec(xf, i, &rec);
- if (len > 0 &&
- (isalpha((unsigned char)*rec) || /* identifier? */
- *rec == '_' || /* also identifier? */
- *rec == '$')) { /* mysterious GNU diff's invention */
- if (len > sz)
- len = sz;
- while (0 < len && isspace((unsigned char)rec[len - 1]))
- len--;
- memcpy(buf, rec, len);
- *ll = len;
+ if ((*ll = ff(rec, len, buf, sz, ff_priv)) >= 0)
return;
- }
}
+ *ll = 0;
}
@@ -120,6 +127,7 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
xdchange_t *xch, *xche;
char funcbuf[80];
long funclen = 0;
+ find_func_t ff = xecfg->find_func ? xecfg->find_func : def_ff;
if (xecfg->flags & XDL_EMIT_COMMON)
return xdl_emit_common(xe, xscr, ecb, xecfg);
@@ -143,7 +151,8 @@ int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
if (xecfg->flags & XDL_EMIT_FUNCNAMES) {
xdl_find_func(&xe->xdf1, s1, funcbuf,
- sizeof(funcbuf), &funclen);
+ sizeof(funcbuf), &funclen,
+ ff, xecfg->find_func_priv);
}
if (xdl_emit_hunk_hdr(s1 + 1, e1 - s1, s2 + 1, e2 - s2,
funcbuf, funclen, ecb) < 0)
--
1.5.3.rc0.822.g38609
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox