* Re: FFmpeg considering GIT
From: Junio C Hamano @ 2007-05-06 7:49 UTC (permalink / raw)
To: Linus Torvalds
Cc: Karl Hasselstr?m, Paul Mackerras, Carl Worth, Michael Niedermayer,
Git Mailing List
In-Reply-To: <alpine.LFD.0.98.0705051524300.17381@woody.linux-foundation.org>
Linus Torvalds <torvalds@linux-foundation.org> writes:
>> and have the commits colored appropriately. That would be cool, but it
>> might need more tcl/tk knowledge than I actually possess).
>
> Ok, that turned out to be the case.
>
> Here's an updated patch to gitk, which at least *parses* the
> "--left-right" data properly, it just doesn't use it.
This on top of yours makes it use it.
gitk | 31 ++++++++++++++++++++++++++-----
1 files changed, 26 insertions(+), 5 deletions(-)
diff --git a/gitk b/gitk
index 0bf00ee..a6e762d 100755
--- a/gitk
+++ b/gitk
@@ -74,7 +74,7 @@ proc getcommits {} {
proc getcommitlines {fd view} {
global commitlisted nextupdate
global leftover commfd
- global displayorder commitidx commitrow commitdata
+ global displayorder commitidx commitrow commitdata commitside
global parentlist childlist children curview hlview
global vparentlist vchildlist vdisporder vcmitlisted
@@ -178,6 +178,7 @@ proc getcommitlines {fd view} {
}
set commitdata($id) [string range $cmit [expr {$j + 1}] end]
set commitrow($view,$id) $commitidx($view)
+ set commitside($id) $leftright
incr commitidx($view)
if {$view == $curview} {
lappend parentlist $olds
@@ -2986,7 +2987,7 @@ proc drawlines {id} {
proc drawcmittext {id row col rmx} {
global linespc canv canv2 canv3 canvy0 fgcolor
- global commitlisted commitinfo rowidlist
+ global commitlisted commitinfo commitside rowidlist
global rowtextx idpos idtags idheads idotherrefs
global linehtag linentag linedtag
global mainfont canvxmax boldrows boldnamerows fgcolor
@@ -2995,9 +2996,29 @@ proc drawcmittext {id row col rmx} {
set x [xc $row $col]
set y [yc $row]
set orad [expr {$linespc / 3}]
- set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
- [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
- -fill $ofill -outline $fgcolor -width 1 -tags circle]
+
+ if {[info exists commitside($id)]} {
+ set leftright $commitside($id)
+ } else {
+ set leftright 0
+ }
+ if {$leftright == 0} {
+ set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
+ [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
+ -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ } elseif {$leftright < 0} {
+ set t [$canv create polygon \
+ [expr {$x - $orad}] $y \
+ [expr {$x + $orad - 1}] [expr {$y - $orad}] \
+ [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
+ -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ } else {
+ set t [$canv create polygon \
+ [expr {$x + $orad - 1}] $y \
+ [expr {$x - $orad}] [expr {$y - $orad}] \
+ [expr {$x - $orad}] [expr {$y + $orad - 1}] \
+ -fill $ofill -outline $fgcolor -width 1 -tags circle]
+ }
$canv raise $t
$canv bind $t <1> {selcanvline {} %x %y}
set xt [xc $row [llength [lindex $rowidlist $row]]]
^ permalink raw reply related
* Re: Anyone running GIT on native Windows
From: Aaron Gray @ 2007-05-06 7:39 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7vejlufmhd.fsf@assigned-by-dhcp.cox.net>
> "Aaron Gray" <angray@beeb.net> writes:
>
>> I want to use GIT on Windows without Cygwin or MinGW.
>>
>> Has anyone tried this with GNU sh and utils compiled under Windows ?
>
> Call me Windoze uninitiated, but isn't that pretty much what
> MinGW is about?
MinGW still runs in its own directory tree and uses Unix paths.
What I want is to be able to work in Windows CMD and envoke .sh scripts by
association (unfortunately you have to add the .sh on the command name
though).
Ideally the .sh scripts would be converted or rewritten in C, this would be
the best solution.
Anyway best to get someone else take on the problem.
Aaron
^ permalink raw reply
* Re: 'upstream' branches.
From: David Woodhouse @ 2007-05-06 7:35 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Alex Riesen, git
In-Reply-To: <7v3b2ah30f.fsf@assigned-by-dhcp.cox.net>
On Sat, 2007-05-05 at 23:36 -0700, Junio C Hamano wrote:
> I think David's use of linus ref is bogus. What is he really
> trying to "track"? If he is trying to track where the tip of
> Linus's tree is, he should not let fetch from mtd to muck with
> that remote tracking ref that he uses to track Linus's tree.
I'm trying to track "the latest commit in this tree which comes from
Linus, either directly or indirectly".
So that 'git-diff linus..' or 'git-log linus..' will show me what's
outstanding against the master('s) tree. And scripts feeding the commits
list can ignore those commits, etc.
> On the other hand, I think it is perfectly reasonable thing to
> want to track where the tip of Linus's tree is "from mtd tree's
> point of view". Then diff between "mtd's idea of Linus's tip"
> and "mtd's tip" would represent what mtd people did, regardless
> of what Linus did in his tree, before mtd people had a chance to
> sync again with Linus.
Right. That's what I'm trying to track. And that 'idea of Linus' tip'
needs to get updated whenever we pull from Linus' tree into our
mtd-2.6.git tree on the server -- by whatever route, even if it's
indirectly through another repo.
Obviously we never actually _work_ on the tree on the server; we only
ever push to it from a working repo somewhere.
So those working repositories need to have this 'linus' branch which is
updated when they pull directly from kernel.org, and which is pushed to
the mtd tree when they push.
Furthermore, when unprivileged users create their own clone with commits
they want me to push, and if _they_ also pull from Linus' tree for some
reason, that information should also make it into my working repo when I
pull, and then into the mtd-2.6.git tree when I push. Those unprivileged
users will probably want an 'mtd' branch too, to keep track of their
_own_ outstanding changes.
And when we do other things like the olpc-2.6.git tree ,which pulls from
various other repositories (mtd, mmc, etc.), it should use the 'linus'
branches of each of those repositories we pull from.
Is that possible? I'm fairly sure it used to be.
--
dwmw2
^ permalink raw reply
* Re: Anyone running GIT on native Windows
From: Junio C Hamano @ 2007-05-06 7:19 UTC (permalink / raw)
To: Aaron Gray; +Cc: Git Mailing List
In-Reply-To: <2b6901c78faa$cf9aa7e0$0200a8c0@AMD2500>
"Aaron Gray" <angray@beeb.net> writes:
> I want to use GIT on Windows without Cygwin or MinGW.
>
> Has anyone tried this with GNU sh and utils compiled under Windows ?
Call me Windoze uninitiated, but isn't that pretty much what
MinGW is about?
^ permalink raw reply
* Re: git cvsimport fails
From: Thomas Hühn @ 2007-05-06 7:04 UTC (permalink / raw)
To: git
In-Reply-To: <87lkg2v4ha.fsf@mid.deneb.enyo.de>
Florian Weimer <fw@deneb.enyo.de> writes:
> * Thomas Hühn:
>
>> HEAD contains "ref: refs/heads/master", but refs/heads contains no
>> "master", just other files.
>>
>> Can I find out, which hash master should point at?
>
> After the initial checkout, it should point to "origin"; this is the
> HEAD of the CVS repository. Of course, if your main development line
> resides on another branch, you should use that.
Okay, thanks. I'll enter that.
Thomas
^ permalink raw reply
* Anyone running GIT on native Windows
From: Aaron Gray @ 2007-05-06 6:50 UTC (permalink / raw)
To: Git Mailing List
I want to use GIT on Windows without Cygwin or MinGW.
Has anyone tried this with GNU sh and utils compiled under Windows ?
I looked for a sh to c converter but no such luck :(
Aaron
^ permalink raw reply
* Re: [PATCH] git-config: read remote config files over HTTP
From: Junio C Hamano @ 2007-05-06 6:55 UTC (permalink / raw)
To: Sven Verdoolaege; +Cc: git
In-Reply-To: <11782757671933-git-send-email-skimo@liacs.nl>
Sven Verdoolaege <skimo@liacs.nl> writes:
> diff --git a/Makefile b/Makefile
> index 0185386..b782111 100644
> --- a/Makefile
> +++ b/Makefile
Very nicely done.
> diff --git a/config.c b/config.c
> index 0da74e0..36e3b97 100644
> --- a/config.c
> +++ b/config.c
> @@ -7,6 +7,7 @@
> */
> #include "cache.h"
> #include "pkt-line.h"
> +#include "http_config.h"
>
> #define MAXNAME (256)
>
> @@ -395,6 +396,16 @@ int git_config_from_file(config_fn_t fn, const char *filename)
> return ret;
> }
>
> +static int config_from_http(config_fn_t fn, char *dest)
> +{
> + static char *config_temp = "config.temp";
> + if (git_http_fetch_config(dest, config_temp))
> + return 1;
> + git_config_from_file(fn, config_temp);
> + unlink(config_temp);
> + return 0;
> +}
Not mkstemp()?
> @@ -403,6 +414,9 @@ int git_config_from_remote(config_fn_t fn, char *dest)
> static char var[MAXNAME];
> static char value[1024];
>
> + if (!prefixcmp(dest, "http://"))
> + return config_from_http(fn, dest);
> +
Shouldn't this also work for other protocols we handle via curl?
> diff --git a/http.c b/http.c
> index ae27e0c..3e1ccce 100644
> --- a/http.c
> +++ b/http.c
> @@ -25,6 +25,10 @@ long curl_low_speed_limit = -1;
> long curl_low_speed_time = -1;
> int curl_ftp_no_epsv = 0;
>
> +#ifdef USE_CURL_MULTI
> +void (*fill_active_slots)(void) = NULL;
> +#endif
> +
I wonder if we could lose USE_CURL_MULTI around this one,...
> struct curl_slist *pragma_header;
>
> struct active_request_slot *active_queue_head = NULL;
> @@ -394,7 +398,8 @@ void step_active_slots(void)
> } while (curlm_result == CURLM_CALL_MULTI_PERFORM);
> if (num_transfers < active_requests) {
> process_curl_messages();
> - fill_active_slots();
> + if (fill_active_slots)
> + fill_active_slots();
> }
> }
> #endif
> @@ -459,7 +464,8 @@ void release_active_slot(struct active_request_slot *slot)
> slot->curl = NULL;
> }
> #ifdef USE_CURL_MULTI
> - fill_active_slots();
> + if (fill_active_slots)
> + fill_active_slots();
> #endif
> }
... and especially this one.
The fill_active_slots variable may happen to stay at NULL under
!USE_CURL_MULTI, because the only code that sets the variable
would be in #ifdef USE_CURL_MULTI.
^ permalink raw reply
* Re: [PATCH] Have git-revert, git-cherry-pick cleanup ./.msg upon successful completion.
From: Junio C Hamano @ 2007-05-06 6:49 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Gerrit Pape, git, Alex Riesen
In-Reply-To: <20070505034615.GE16538@spearce.org>
"Shawn O. Pearce" <spearce@spearce.org> writes:
> What about this change instead? We make cherry-pick/revert
> use the same temporary file as merge, which is under .git/
> (something Alex mentioned he wanted). I think the use of ".msg"
> in cherry-pick/revert has always just been a bug, and not a feature,
> so I'm really not against changing things around like this.
While I would not say this is not an improvement, this makes
MERGE_MSG even less about merges and pushes us away from a
sensible "git whatnow".
^ permalink raw reply
* Re: git cvsimport fails
From: Florian Weimer @ 2007-05-06 6:41 UTC (permalink / raw)
To: git
In-Reply-To: <87abwomtdl.fsf@mid.thomas-huehn.de>
* Thomas Hühn:
> HEAD contains "ref: refs/heads/master", but refs/heads contains no
> "master", just other files.
>
> Can I find out, which hash master should point at?
After the initial checkout, it should point to "origin"; this is the
HEAD of the CVS repository. Of course, if your main development line
resides on another branch, you should use that.
^ permalink raw reply
* Re: [PATCH v3] Support ent:relative_path
From: Junio C Hamano @ 2007-05-06 6:38 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Dana How, Git Mailing List, Shawn O. Pearce
In-Reply-To: <Pine.LNX.4.64.0705051637450.4015@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>> (a) In a bare repository, I believe setup.c:setup_git_directory_gently()
>> determines the prefix to be NULL. This means my patch will see
>> ALL paths as absolute, except :../path which will result in an error.
>
> My point was that it feels inconsistent to take the current path into
> account in one case, but not in the other.
I do not understand your reasoning. In a bare repository you
cannot even be in a subdirectory to begin with.
^ permalink raw reply
* Re: 'upstream' branches.
From: Junio C Hamano @ 2007-05-06 6:36 UTC (permalink / raw)
To: Alex Riesen; +Cc: David Woodhouse, git
In-Reply-To: <20070505225249.GE2898@steel.home>
Alex Riesen <raa.lkml@gmail.com> writes:
> David Woodhouse, Sat, May 05, 2007 19:50:28 +0200:
>> > >
>> > > Is there a better way?
>> >
>> > I would just remove the pluses. git-fetch will say that the branch is
>> > already up-to-date, if the local branch already has everything the
>> > remote has.
>>
>> Then after I pull from Linus' tree, I can't pull from the mtd tree -- it
>> complains that the 'linus' branch there can't be fast-forwarded, and
>> refuses to pull the 'master' branch.
>
> Which got me by surprise (just tried). I though it'd notice that all
> the commits are already present...
>
> Experts, is it really supposed to be that way?
I am not sure what the issue is here. If the copy of Linus's
tip mtd tree has is behind the current Linus's tip, after you
fetch from Linus's tree to obtain its tip, if you allowed the
fetch from mtd tree to update the remote tracking ref that you
use to keep track of where Linus is, it would _rewind_ it, so I
think it is natural to warn/prevent that mistake.
I think David's use of linus ref is bogus. What is he really
trying to "track"? If he is trying to track where the tip of
Linus's tree is, he should not let fetch from mtd to muck with
that remote tracking ref that he uses to track Linus's tree.
On the other hand, I think it is perfectly reasonable thing to
want to track where the tip of Linus's tree is "from mtd tree's
point of view". Then diff between "mtd's idea of Linus's tip"
and "mtd's tip" would represent what mtd people did, regardless
of what Linus did in his tree, before mtd people had a chance to
sync again with Linus.
^ permalink raw reply
* Re: Git branch bug
From: Junio C Hamano @ 2007-05-06 6:30 UTC (permalink / raw)
To: Daniel Barkalow; +Cc: Johannes Schindelin, Guido Ostkamp, git
In-Reply-To: <Pine.LNX.4.64.0705051253380.28708@iabervon.org>
Daniel Barkalow <barkalow@iabervon.org> writes:
> This leaves open the question of how you make your initial commit in a
> branch that isn't master. I think the answer should be:
>
> $ git checkout -b experimental
> warning: You appear to be on a branch yet to be born.
> warning: Forcing checkout of HEAD.
> fatal: just how do you expect me to merge 0 trees?
>
> Which should probably be:
>
> $ git checkout -b experimental
> warning: You appear to be on a branch yet to be born.
> warning: Putting you on a new branch yet to be born.
>
> And leaving .git/HEAD pointing to refs/heads/experimental instead of
> refs/heads/master, with refs/heads/ still empty.
While I agree that is probably correct, it would not be useful
in real-life that much. When you do not even have 'master', I
do not think there is much point of being able to create two
useless, yet-to-be-born branches.
Also, once you make a commit on 'master', you would not be able
to create a new disconnected root with your suggestion alone. I
am not convinced that being able to start a disconnected root is
useful to begin with, but it is a different matter. We allow
fetching and merging from a different repository to cause
disconnected roots to exist in a repository anyway, so I do not
see any reason to disallow it either.
Assuming that the ability to switch to a new yet-to-be-born
branch is useful, I think the right thing to do is:
- Regardless of your HEAD state, you may want to have a way to
create a yet-to-be-born branch and switch to it. Perhaps
"git checkout -e new" make HEAD point at refs/heads/new
without creating one (I picked -e randomly for "empty").
- When you are on a yet-to-be-born branch, "git checkout -b
new" and "git checkout -b new HEAD" makes HEAD point at
refs/heads/new without creating one. I happen to consider
this a not so useful corner case, but that is to make things
consistent.
- When you are on a yet-to-be-born branch, "git branch new" and
"git branch new HEAD" is a nonsense operation. We should
clearly state that it is nonsense (I am agreeing with the
last point in your message).
^ permalink raw reply
* Re: [PATCH] Documentation: fix typo in git-remote.txt
From: Junio C Hamano @ 2007-05-06 6:11 UTC (permalink / raw)
To: James Bowes; +Cc: git
In-Reply-To: <11783893924046-git-send-email-jbowes@dangerouslyinc.com>
Thanks.
^ permalink raw reply
* [PATCH 2/3] blame: -C -C -C
From: Junio C Hamano @ 2007-05-06 6:02 UTC (permalink / raw)
To: git
In-Reply-To: <11784313631165-git-send-email-junkio@cox.net>
Existing "blame -C -C" would not find that the latter half of
the file2 came from the existing file1:
... both file1 and file2 are tracked ...
$ cat file1 >>file2
$ git add file1 file2
$ git commit
This is because we avoid the expensive find-copies-harder code
that makes unchanged file (in this case, file1) as a candidate
for copy & paste source when annotating an existing file
(file2). The third -C now allows it. However, this obviously
makes the process very expensive. We've actually seen this
patch before, but I dismissed it because it covers such a narrow
(and arguably stupid) corner case.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
builtin-blame.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/builtin-blame.c b/builtin-blame.c
index f8843e6..65d029a 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -55,6 +55,7 @@ static int num_commits;
#define PICKAXE_BLAME_MOVE 01
#define PICKAXE_BLAME_COPY 02
#define PICKAXE_BLAME_COPY_HARDER 04
+#define PICKAXE_BLAME_COPY_HARDEST 010
/*
* blame for a blame_entry with score lower than these thresholds
@@ -1079,8 +1080,9 @@ static int find_copy_in_parent(struct scoreboard *sb,
* and this code needs to be after diff_setup_done(), which
* usually makes find-copies-harder imply copy detection.
*/
- if ((opt & PICKAXE_BLAME_COPY_HARDER) &&
- (!porigin || strcmp(target->path, porigin->path)))
+ if ((opt & PICKAXE_BLAME_COPY_HARDEST)
+ || ((opt & PICKAXE_BLAME_COPY_HARDER)
+ && (!porigin || strcmp(target->path, porigin->path))))
diff_opts.find_copies_harder = 1;
if (is_null_sha1(target->commit->object.sha1))
@@ -2127,6 +2129,15 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
blame_move_score = parse_score(arg+2);
}
else if (!prefixcmp(arg, "-C")) {
+ /*
+ * -C enables copy from removed files;
+ * -C -C enables copy from existing files, but only
+ * when blaming a new file;
+ * -C -C -C enables copy from existing files for
+ * everybody
+ */
+ if (opt & PICKAXE_BLAME_COPY_HARDER)
+ opt |= PICKAXE_BLAME_COPY_HARDEST;
if (opt & PICKAXE_BLAME_COPY)
opt |= PICKAXE_BLAME_COPY_HARDER;
opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE;
--
1.5.2.rc1.709.g9462
^ permalink raw reply related
* [PATCH 3/3] Add test for blame corner cases.
From: Junio C Hamano @ 2007-05-06 6:02 UTC (permalink / raw)
To: git
In-Reply-To: <11784313631165-git-send-email-junkio@cox.net>
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
t/t8003-blame.sh | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 132 insertions(+), 0 deletions(-)
create mode 100755 t/t8003-blame.sh
diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh
new file mode 100755
index 0000000..db51b3a
--- /dev/null
+++ b/t/t8003-blame.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+test_description='git blame corner cases'
+. ./test-lib.sh
+
+pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/'
+
+test_expect_success setup '
+
+ echo A A A A A >one &&
+ echo B B B B B >two &&
+ echo C C C C C >tres &&
+ echo ABC >mouse &&
+ git add one two tres mouse &&
+ test_tick &&
+ GIT_AUTHOR_NAME=Initial git commit -m Initial &&
+
+ cat one >uno &&
+ mv two dos &&
+ cat one >>tres &&
+ echo DEF >>mouse
+ git add uno dos tres mouse &&
+ test_tick &&
+ GIT_AUTHOR_NAME=Second git commit -a -m Second &&
+
+ echo GHIJK >>mouse &&
+ git add mouse &&
+ test_tick &&
+ GIT_AUTHOR_NAME=Third git commit -m Third &&
+
+ cat mouse >cow &&
+ git add cow &&
+ test_tick &&
+ GIT_AUTHOR_NAME=Fourth git commit -m Fourth &&
+
+ {
+ echo ABC
+ echo DEF
+ echo XXXX
+ echo GHIJK
+ } >cow &&
+ git add cow &&
+ test_tick &&
+ GIT_AUTHOR_NAME=Fifth git commit -m Fifth
+'
+
+test_expect_success 'straight copy without -C' '
+
+ git blame uno | grep Second
+
+'
+
+test_expect_success 'straight move without -C' '
+
+ git blame dos | grep Initial
+
+'
+
+test_expect_success 'straight copy with -C' '
+
+ git blame -C1 uno | grep Second
+
+'
+
+test_expect_success 'straight move with -C' '
+
+ git blame -C1 dos | grep Initial
+
+'
+
+test_expect_success 'straight copy with -C -C' '
+
+ git blame -C -C1 uno | grep Initial
+
+'
+
+test_expect_success 'straight move with -C -C' '
+
+ git blame -C -C1 dos | grep Initial
+
+'
+
+test_expect_success 'append without -C' '
+
+ git blame -L2 tres | grep Second
+
+'
+
+test_expect_success 'append with -C' '
+
+ git blame -L2 -C1 tres | grep Second
+
+'
+
+test_expect_success 'append with -C -C' '
+
+ git blame -L2 -C -C1 tres | grep Second
+
+'
+
+test_expect_success 'append with -C -C -C' '
+
+ git blame -L2 -C -C -C1 tres | grep Initial
+
+'
+
+test_expect_success 'blame wholesale copy' '
+
+ git blame -f -C -C1 HEAD^ -- cow | sed -e "$pick_fc" >current &&
+ {
+ echo mouse-Initial
+ echo mouse-Second
+ echo mouse-Third
+ } >expected &&
+ diff -u expected current
+
+'
+
+test_expect_success 'blame wholesale copy and more' '
+
+ git blame -f -C -C1 HEAD -- cow | sed -e "$pick_fc" >current &&
+ {
+ echo mouse-Initial
+ echo mouse-Second
+ echo cow-Fifth
+ echo mouse-Third
+ } >expected &&
+ diff -u expected current
+
+'
+
+test_done
--
1.5.2.rc1.709.g9462
^ permalink raw reply related
* [PATCH 1/3] blame: handle the tail-match correctly in -C/-M
From: Junio C Hamano @ 2007-05-06 6:02 UTC (permalink / raw)
To: git
The -C/-M option to blame tries to find a section of a preimage
file by running diff against the lines whose origin is still
unknown, and excluding the different parts. The code however
did not cover the case where the tail part of the section
matched, which we handle for the normal non-move/copy codepath.
This breakage was most visible when preimage file matches in its
entirety and failed to pass blame in such a case.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
builtin-blame.c | 52 ++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 40 insertions(+), 12 deletions(-)
diff --git a/builtin-blame.c b/builtin-blame.c
index 8919b02..f8843e6 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -891,6 +891,39 @@ static void copy_split_if_better(struct scoreboard *sb,
}
/*
+ * We are looking at a part of the final image represented by
+ * ent (tlno and same are offset by ent->s_lno).
+ * tlno is where we are looking at in the final image.
+ * up to (but not including) same match preimage.
+ * plno is where we are looking at in the preimage.
+ *
+ * <-------------- final image ---------------------->
+ * <------ent------>
+ * ^tlno ^same
+ * <---------preimage----->
+ * ^plno
+ *
+ * All line numbers are 0-based.
+ */
+static void handle_split(struct scoreboard *sb,
+ struct blame_entry *ent,
+ int tlno, int plno, int same,
+ struct origin *parent,
+ struct blame_entry *split)
+{
+ if (ent->num_lines <= tlno)
+ return;
+ if (tlno < same) {
+ struct blame_entry this[3];
+ tlno += ent->s_lno;
+ same += ent->s_lno;
+ split_overlap(this, ent, tlno, plno, same, parent);
+ copy_split_if_better(sb, split, this);
+ decref_split(this);
+ }
+}
+
+/*
* Find the lines from parent that are the same as ent so that
* we can pass blames to it. file_p has the blob contents for
* the parent.
@@ -922,26 +955,21 @@ static void find_copy_in_blob(struct scoreboard *sb,
patch = compare_buffer(file_p, &file_o, 1);
+ /*
+ * file_o is a part of final image we are annotating.
+ * file_p partially may match that image.
+ */
memset(split, 0, sizeof(struct blame_entry [3]));
plno = tlno = 0;
for (i = 0; i < patch->num; i++) {
struct chunk *chunk = &patch->chunks[i];
- /* tlno to chunk->same are the same as ent */
- if (ent->num_lines <= tlno)
- break;
- if (tlno < chunk->same) {
- struct blame_entry this[3];
- split_overlap(this, ent,
- tlno + ent->s_lno, plno,
- chunk->same + ent->s_lno,
- parent);
- copy_split_if_better(sb, split, this);
- decref_split(this);
- }
+ handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
plno = chunk->p_next;
tlno = chunk->t_next;
}
+ /* remainder, if any, all match the preimage */
+ handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
free_patch(patch);
}
--
1.5.2.rc1.709.g9462
^ permalink raw reply related
* Re: git-blame not tracking copies
From: Junio C Hamano @ 2007-05-06 6:02 UTC (permalink / raw)
To: Andy Parkins; +Cc: git
In-Reply-To: <200705022033.25885.andyparkins@gmail.com>
Andy Parkins <andyparkins@gmail.com> writes:
> The issues are
>
> - Blame2 says all the lines come from commit 4, when actually they
> come from commits 1, 2 and 3. It was pointed out that this is
> particularly annoying because the file is an exact copy and so the
> copy has the same hash as the original so should be easy to spot
>
> - The output isn't stable, even if blame2 had a good reason for not
> assigning lines 1 and 2 to their correct commits, why isn't the same
> true in blame3?
>
> - Blame3 incorrectly ascribes line 4 to commit 4, when it should have
> remained as it was in blame1 - to commit 3.
This turns out to be a simple and stupid boundary error.
The algorithm passes the blame by (ab)using diff to find the
common section. We run an equivalent of "diff -u0", notice the
lines that come out of it -- the lines that do not appear are
common ones. Simply put, if we have this hunk at the beginning:
@@ -4,1 +4,2 @@
-a
+A
+B
the only information we are interested in this hunk are (1) that
the hunk begins at line 4 in the postimage, so lines 1,2,3 in
the postimage are the same as the preimage; and (2) that the
different part ends just before line 6 (the hunk has two lines
in the postimage which we know do not match the preimage). So
if the next hunk from the diff look like this...
@@ -6,1 +8,1 @@
-e
+E
then we know lines 6 and 7 in the postimage are the same as the
preimage.
We need to use the information (2) from the last hunk in the
patch and blame all the remaining lines to the parent.
When we are assigning blame from one file in the "current"
commit down to one (possibly different) file in its parent
commit in pass_blame_to_parent() function, we grab patch between
the two, and we have the final "the rest are the same" call to
blame_chunk(). However, the code to assign blame for only part
of a file to unrelated file in its parent (i.e. -M/-C), the
corresponding code in find_copy_in_blob() to use the diff output
was missing this "the rest are the same" handling.
A 3-patch series follows.
^ permalink raw reply
* Re: Initial support for cloning submodules
From: Alon Ziv @ 2007-05-06 4:13 UTC (permalink / raw)
To: skimo; +Cc: Junio C Hamano, git
In-Reply-To: <20070505081404.GR955MdfPADPa@greensroom.kotnet.org>
On Sat, 2007-05-05 at 10:14 +0200, Sven Verdoolaege wrote:
> We could easily have dump-config only dump a predefined "known safe"
> set of config options, although that would mean you have to upgrade
> the server side each time you add a new dumpable config option.
> Or we could do the preselection only when called from git-daemon.
>
Or we could have the set of dumpable options itself in the config file;
a bit more cumbersome, but leaves all flexibility (including the
shoot-yourself-in-the-foot kind) in the hands of the users :)
-az
^ permalink raw reply
* (unknown),
From: Aaron Gray @ 2007-05-06 3:51 UTC (permalink / raw)
To: Git Mailing List
subscribe git
^ permalink raw reply
* subscriibe
From: Aaron Gray @ 2007-05-06 3:16 UTC (permalink / raw)
To: Git Mailing List
subscribe git
^ permalink raw reply
* Re: [PATCH v3] Support ent:relative_path
From: Johannes Schindelin @ 2007-05-06 0:59 UTC (permalink / raw)
To: Martin Waitz; +Cc: Junio C Hamano, Shawn O. Pearce, Dana How, Git Mailing List
In-Reply-To: <20070505211857.GE30511@admingilde.org>
Hi,
On Sat, 5 May 2007, Martin Waitz wrote:
> hoi :)
>
> On Sat, May 05, 2007 at 01:17:35PM -0700, Junio C Hamano wrote:
> > > we could also introduce "<tree-ish>/<path>" for absolute path entries.
> >
> > When you name the tree-ish with usual "branch name", where does
> > the branch name end and pathname start? What happens when there
> > is an ambiguity, and how costly to detect such an ambiguity to
> > begin with?
>
> well, if you know that it starts with a tree-ish there is no
> ambiguity [...]
Wrong. For example, mw/submodules~10 _is_ a tree-ish (if you have a branch
named "mw/submodules").
Hth,
Dscho
^ permalink raw reply
* Re: 'upstream' branches.
From: Alex Riesen @ 2007-05-05 22:52 UTC (permalink / raw)
To: David Woodhouse; +Cc: git, Junio C Hamano
In-Reply-To: <1178387429.17680.35.camel@shinybook.infradead.org>
David Woodhouse, Sat, May 05, 2007 19:50:28 +0200:
> > >
> > > Is there a better way?
> >
> > I would just remove the pluses. git-fetch will say that the branch is
> > already up-to-date, if the local branch already has everything the
> > remote has.
>
> Then after I pull from Linus' tree, I can't pull from the mtd tree -- it
> complains that the 'linus' branch there can't be fast-forwarded, and
> refuses to pull the 'master' branch.
Which got me by surprise (just tried). I though it'd notice that all
the commits are already present...
Experts, is it really supposed to be that way?
^ permalink raw reply
* Yet another Perforce importer
From: Alex Riesen @ 2007-05-05 22:48 UTC (permalink / raw)
To: git
I was unhappy with the existing importer because it did not allow to
commit the current state of a client, and did not allow to find out
how this client state was produced. This script does this and also
allows for updating git repo incrementally (so that the files which
"officially" did not change will not be reupdated. Active by default,
but can be switched off to do a complete import, see --full).
It is a perl script again, sorry. This one is developed and tested
with ActiveState Perl (which explains the binmode after each and every
open), so use with caution. If you're lucky to use Perforce in a POSIX
environment - remove the binmodes and windows-related hack to detect
case-sensitivity problems in filenames. I have no idea what would they
break there.
The script has some provisions for Windows Maloperating System:
it tries to figure out the conflicts caused by disability in its
filesystems with regard to case insensitivity. It is enabled
automatically for ActiveState Perl. If you see warnings about some
conflicts it usually means that the state in the working directory
cannot be trusted anymore (and is a fairly typical error in
environments contaminated with windows). The script does not reread
the files from p4 server (I admit being lazy), it just trusts the
working directory and will do in such a case an untrustworthy commit.
(the reason behind this is that at work, where I have to use perforce,
I had to give up arguing with everyone about this problem. The people
who could do something about it just don't care about the fact that
the stupid thing they've chosen has very non-windows rules regarding
filenames. Either they are deaf, or dumb, or both).
The client definition, the state and the information how you got the
state are saved in a side branch (refs/p4import/<client-name>), which
references the previous imported state (if any) and the git commit
just made (if --yes passed). The result looks funny in gitk but works
good enough for incremental imports (see the first while in git_p4_init).
"The information how you got the client state" must be given and is
expected to be a file which will be stored on the side branch under
the name "spec". The story behind this is that Perforce was so bad for
the workflow we have here at work, that direct use of the system is
discouraged (like in "made impossible") and IT&Tooling Department
"provided" us with a program which can take a configuration file which
has mapping and revision information. So now you can bind the history
of a project in one place: the linear history of this configuration
file. Good idea, if you're stuck with Perforce (and good job by
Perforce to have us stuck with them), if implemented rightly. It
wasn't of course, but this is another long and depressing story.
Remote-to-local mapping and the revisions of files are stored in "have",
and the client definition - in "client" on that side branch.
Being work in progress, the script does not commit anything by
default (use -y|--yes to commit), just updates the index.
Probably, wont work without initial commit. Can't remember testing
that.
Does not touch your Perforce client (except for reading). Don't forget
to log in, though. I found that environment variables (P4SERVER or
P4PASSWD) sometimes work (they stopped recently).
Expects to find P4 and Git tools in path (p4 and git, specifically).
Not tested in POSIX environment (I'm not allowed to have any at work,
and I promise to kill anyone who tries to install Perforce in my home
network).
Quite memory hungry. Slow (but Git works so much faster than perforce
so I really couldn't care less: I sync with central server one-two
times a day).
On windows: will have problems with long pathnames (can break on w2k,
try using wxp).
On windows: avoid Ctrl-C or closing the console window while the
script is running. Interrupted script shouldn't corrupt anything but
the act can take your whole system down (happened to me twice or
trice).
The script:
#!/usr/bin/perl -w
local $VERBOSE = 0;
local $DRYRUN = 0;
local $AUTO_COMMIT = 0;
local $JUST_COMMIT = 0;
local $P4CLIENT = undef;
local @EDIT_COMMIT = 0;
local @FULL_IMPORT = 0;
local @DESC = ();
local $SPEC = undef;
local @P4ARGS = ();
local $P4HAVE_FILE = undef;
push(@P4ARGS, '-P', $ENV{P4PASSWD})
if defined($ENV{P4PASSWD}) and length($ENV{P4PASSWD});
use Cwd;
local $start_dir = cwd();
sub read_args {
my ($in_client, $in_cl, $in_fi, $in_p4) = (0,0,0,0);
foreach my $f ( @_ ) {
if ($in_client) { $in_client = 0; $P4CLIENT = $f; next }
if ($in_cl) { $in_cl=0; push(@DESC,"c$f"); next }
if ($in_fi) { $in_fi=0; push(@DESC,"f$f"); next }
if ($in_p4) { $in_p4=0; push(@DESC,"4$f"); next }
$DRYRUN=1, next if $f eq '-n' or $f eq '--dry-run';
$AUTO_COMMIT=1, next if $f eq '-y' or $f eq '--yes';
$JUST_COMMIT=1, next if $f eq '--just-commit';
$EDIT_COMMIT=1, next if ($f eq '-e') or ($f eq '--edit');
$FULL_IMPORT=1, next if $f eq '--full';
$VERBOSE++, next if $f eq '-v' or $f eq '--verbose';
$in_client = 1, next if $f eq '--client';
$in_cl = 1, next if $f eq '-C';
$in_fi = 1, next if $f eq '-F';
$in_p4 = 1, next if ($f eq '--ptr') or ($f eq '--p4');
if ($f eq '--help' or $f eq '-h') {
print <<EOF;
$0 <specification> [-n|--dry-run] [-y|--yes] [--client <client-name>] \
[-e|--edit] [--just-commit] [--full] [-v|--verbose] [-C <change-number>] \
[-F <filename>] [--ptr|--p4 <p4-path-and/or-revision>]
Perforce client state importer. Creates a git commit on the current
branch from a state the given p4 client and working directory hold.
<specification> must be given and is expected to be a file which will be
stored on the side branch under the name "spec".
Remote-to-local mapping and the revisions of files are stored in "have",
and the client definition - in "client".
--client client Specify client name (saved in .git/p4/client for the next time)
--full Perform full import, don't even try to figure out what changed
-y|--yes Commit automatically (by default only index updated)
--just-commit To be used after you forgot to run with --yes first time
-n|--dry-run Do not update the index and do not commit
-e|--edit Edit commit description before committing
-v|--verbose Be more verbose. Can be given many times, increases verbosity
-F file Take description for the commit from a file in the
next parameter
-C change Take description for the commit from this p4 change
--p4|--ptr p4-path-and/or-revision Take description for the commit from the p4
change described by this p4 path, possibly including revision
specification
The descriptions taken from p4 changes given by -C and --p4 will
be concatenated if the options given multiple times.
EOF
exit(0);
}
warn("$0: spec already set, $f ignored\n"),next if defined($SPEC);
$SPEC = $f;
}
}
read_args(@ARGV);
local ($GIT_DIR) = qx{git rev-parse --git-dir};
$GIT_DIR =~ s/\r?\n$//s if defined($GIT_DIR);
die "$0: git directory not found\n" if !defined($GIT_DIR) or !-d $GIT_DIR;
$ENV{VISUAL} = 'vim' unless defined($ENV{VISUAL});
local $editor = $ENV{VISUAL};
$editor = $ENV{EDITOR} unless defined($editor);
die "$0: no editor defined\n" unless defined($editor);
# P4 client was given in command-line. Store it
if ( defined($P4CLIENT) ) {
mkdir "$GIT_DIR/p4", 0777;
if ( open(F, '>', "$GIT_DIR/p4/client") ) {
print F "$P4CLIENT\n";
close(F);
} else {
die "$0: cannot store client name: $!\n"
}
} else {
if ( open(F, '<', "$GIT_DIR/p4/client") ) {
($P4CLIENT) = <F>;
close(F);
$P4CLIENT =~ s/^\s*//,$P4CLIENT =~ s/\s*$// if defined($P4CLIENT);
}
}
die "P4 client not defined\n" if !defined($P4CLIENT) or !length($P4CLIENT);
print "reading P4 client $P4CLIENT\n" if $VERBOSE;
local ($P4ROOT, $p4clnt, $P4HOST);
open(my $fdo, '>', "$GIT_DIR/p4/client.def") or die "p4/client.def: $!\n";
binmode($fdo);
open(my $fdi, '-|', "p4 client -o $P4CLIENT") or die "p4 client: $!\n";
binmode($fdi);
my $last_line_len = 0;
while (<$fdi>) {
next if /^#/o;
if ( m/^\s*Root:\s*(\S+)[\\\/]*\s*$/so ) { $P4ROOT = $1 }
elsif ( m/^\s*Client:\s*(\S+)/o ) { $p4clnt = $1 }
elsif ( m/^\s*Host:\s*(\S+)/o ) { $P4HOST = $1 }
($VERBOSE and print), next if /^(Access|Update):/;
s/\r?\n$//so;
my $len = length($_);
print $fdo "$_\n" if $len or $len != $last_line_len;
$last_line_len = $len;
}
close($fdi);
close($fdo);
die "Client root not defined\n" unless defined($P4ROOT);
if ( $VERBOSE ) {
print "GIT_DIR: $GIT_DIR\n";
print "Root: $P4ROOT (cwd: $start_dir)\n";
print "Host: $P4HOST\n";
print "Client: $p4clnt\n" if $p4clnt ne $P4CLIENT;
}
my ($git_head,$git_p4_head,$git_p4_have) = &git_p4_init;
if ($JUST_COMMIT) {
git_p4_commit($git_head, $git_p4_head);
exit 0;
}
local %gitignore_dirs = ();
$gitignore_dirs{'/'} = read_filter_file("$GIT_DIR/info/exclude");
push(@{$gitignore_dirs{'/'}}, @{read_filter_file('.gitignore')});
my %git_index = ();
$/ = "\0";
my @git_X = ();
print "Reading git file list(git ls-files @git_X --cached -z)...\n" if $VERBOSE;
foreach ( qx{git ls-files @git_X --cached -z} ) {
chop; # chop \0
next if m/^\.gitignore$/o;
next if m/\/\.gitignore$/o;
next if filtered($_);
$git_index{$_} = 1;
}
my @git_add = ();
my @git_addx = ();
my @git_del = ();
my @git_upd = ();
print "Reading P4 file list...\n" if $VERBOSE;
local ($Conflicts,$Ignored,$Added,$Deleted,$Updated) = (0,0,0,0,0);
$/ = "\n";
my $in_name = 0;
my @root = split(/[\/\\]+/, $P4ROOT);
my %p4_index = ();
my %p4_a_lc = ();
my %lnames = ();
my %lconflicts = ();
if (opendir(DIR, '.')) {
$lnames{'.'} = [grep {$_ ne '.' and $_ ne '..'} readdir(DIR)];
closedir(DIR);
#print "read $start_dir (",scalar(@{$lnames{'.'}}),")\n";
}
open(my $have, "p4 -G @P4ARGS -c $P4CLIENT -H $P4HOST -d $P4ROOT have |") or
die "$0: failed to start p4: $!\n";
binmode($have);
$P4HAVE_FILE = "$GIT_DIR/p4/have";
open(my $storedhave, '>', $P4HAVE_FILE) or die "$P4HAVE_FILE: $!\n";
binmode($storedhave);
my $ent;
while (defined($ent=read_pydict_entry($have))) {
next if !defined($ent->{depotFile}) or !defined($ent->{clientFile});
my $a = $ent->{depotFile};
$ent->{clientFile} =~ m!^//[^/]+/(.*)!o;
my $b = $1;
my @bb = split(/\/+/, $b);
print $storedhave "$a\0$ent->{clientFile}\0$ent->{haveRev}\0\n";
if ( $^O eq 'MSWin32' ) {
# stupid windows, daft activestate, dumb P4
# This piece below is checking for file name conflicts
# which happen on windows because of it mangling the names.
my $blc = lc $b;
if ( $#bb > 0 ) {
my $path = '.';
foreach my $n (@bb[0 .. $#bb -1]) {
my @conflicts =
grep {lc $_ eq lc $n and $_ ne $n} @{$lnames{$path}};
if (@conflicts and !exists($lconflicts{"$path/$n"})) {
warn "warning: $a -> $b\n".
"warning: conflict between path \"$path/$n\" and ".
"local filesystem in \"@conflicts\"\n";
$Conflicts++;
$lconflicts{"$path/$n"} = 1;
}
$path .= "/$n";
if (!exists($lnames{$path})) {
if (opendir(DIR, $path)) {
$lnames{$path} =
[grep {$_ ne '.' and $_ ne '..'} readdir(DIR)];
closedir(DIR);
#print "read $path (",scalar(@{$lnames{$path}}),")\n";
}
}
}
}
if (!exists($p4_a_lc{$blc})) {
$p4_a_lc{$blc} = [$a, $b];
} else {
warn("warning: $a -> $b\n".
"warning: conflicts with ".
$p4_a_lc{$blc}->[0]." -> ".
$p4_a_lc{$blc}->[1]."\n");
$Conflicts++;
next;
}
}
my $i;
for ($i = 0; $i < $#bb; ++$i) {
my $bdir = join('/',@bb[0 .. $i]) . '/';
if ( !exists($gitignore_dirs{$bdir}) ) {
$gitignore_dirs{$bdir} = read_filter_file("$bdir.gitignore");
}
}
if (filtered($b)) {
print " i $b\n" if $VERBOSE > 3;
$Ignored++;
next
}
$p4_index{$b} = $a;
if ( exists($git_index{$b}) ) {
my $needup = 1;
if (defined($git_p4_have)) {
$prev = $git_p4_have->{$a};
if (defined($prev)) {
$prev->[0] =~ m!^//[^/]+/(.*)!o;
$needup = 0 if ($b eq $1) and ($prev->[1] eq $ent->{haveRev});
if ($needup and $VERBOSE > 1) {
my $reason;
$reason = 'local file' if $b ne $1;
$reason = 'revision' if $prev->[1] ne $ent->{haveRev};
print "$a ($reason changed)\n";
}
}
}
if ($needup) {
$Updated++;
push(@git_upd, $b);
}
} else {
$Added++;
if ( $b =~ m/\.(bat|cmd|pl|sh|exe|dll)$/io )
{ push(@git_addx, $b) } else { push(@git_add, $b) }
}
}
close($storedhave);
close($have);
undef %p4_a_lc;
@git_del = grep { !exists($p4_index{$_}) } keys %git_index;
$Deleted = $#git_del + 1;
#foreach (keys %git_index)
#{ push(@git_del, $_) if !exists($p4_index{$_}) }
if ( $DRYRUN ) {
print($#git_add+$#git_addx+ 2," files to add\n") if $VERBOSE;
print map {" a $_\n"} @git_add if $VERBOSE > 2;
print map {" a $_\n"} @git_addx if $VERBOSE > 2;
print($#git_del+1," files to unreg\n") if $VERBOSE;
print map {" d $_\n"} @git_del if $VERBOSE > 2;
print($#git_upd+1," files to update\n") if $VERBOSE;
print map {" u $_\n"} @git_upd if $VERBOSE > 2;
print "added: $Added, unregd: $Deleted, updated: $Updated, ignored: $Ignored";
print ", conflicts: $Conflicts" if $Conflicts;
print "\n";
} else {
if (@git_add || @git_addx) {
print($#git_add+$#git_addx+ 2,
" files | git update-index --add -z --stdin\n")
if $VERBOSE;
if (@git_add) {
open(GIT, '| git update-index --add --chmod=-x -z --stdin') or
die "$0 git-update-index(add): $!\n";
print GIT map {print " a $_\n" if $VERBOSE > 1; "$_\0"} @git_add;
close(GIT);
}
if (@git_addx) {
open(GIT, '| git update-index --add --chmod=+x -z --stdin') or
die "$0 git-update-index(add): $!\n";
print GIT map {print " a $_\n" if $VERBOSE > 1; "$_\0"} @git_addx;
close(GIT);
}
}
if (@git_del) {
print($#git_del+1," files | git update-index --remove -z --stdin\n")
if $VERBOSE;
open(GIT, '| git update-index --force-remove -z --stdin') or
die "$0 git-update-index(del): $!\n";
print GIT map {print " d $_\n" if $VERBOSE > 1; "$_\0"} @git_del;
close(GIT);
}
if (@git_upd) {
print($#git_upd+1," files | git update-index -z --stdin\n")
if $VERBOSE;
open(GIT, '| git update-index -z --stdin') or
die "$0 git-update-index(upd): $!\n";
print GIT map {print " u $_\n" if $VERBOSE > 1; "$_\0"} @git_upd;
close(GIT);
}
print "added: $Added, unregd: $Deleted, updated: $Updated, ignored: $Ignored";
print ", conflicts: $Conflicts" if $Conflicts;
print "\n";
git_p4_commit($git_head, $git_p4_head) if $AUTO_COMMIT;
}
exit 0;
sub filtered {
my $name = shift;
study($name);
my @path = split(/\/+/o, $name);
my $dir = '';
$name = '';
foreach my $d (@path) {
$name .= $d;
# print STDERR "$dir: $name $d\n" if $v;
foreach my $re (@{$gitignore_dirs{'/'}}) {
return 1 if $name =~ m/$re/;
return 1 if $d =~ m/$re/;
}
if ( length($dir) and exists($gitignore_dirs{$dir}) ) {
foreach my $re (@{$gitignore_dirs{$dir}}) {
return 1 if $name =~ m/$re/;
return 1 if $d =~ m/$re/;
}
}
$name .= '/';
$dir = $name;
}
# print STDERR "$name not filtered\n" if $v;
return 0;
}
sub read_filter_file {
my @filts = ();
my $file = shift;
if ( open(my $if, '<', $file) ) {
print "added ignore file $file\n" if $VERBOSE;
$/ = "\n";
while (my $l = <$if>) {
next if $l =~ /^\s*#/o;
next if $l =~ /^\s*$/o;
$l =~ s/[\r\n]+$//so;
$l =~ s/\./\\./go;
$l =~ s/\*/.*/go;
if ( $l =~ m/\// ) {
$l = "^$l($|/)";
} else {
$l = "(^|/)$l\$";
}
print " filter $l\n" if $VERBOSE > 1;
push(@filts, qr/$l/);
}
close($if);
}
return \@filts;
}
sub r_pystr
{
my $fd = shift;
my ($len,$str)=('','');
my ($c,$rd,$b) = (4,0,'');
while ($c > 0) {
$rd = sysread($fd,$b,$c);
warn("failed to read len: $!"), return undef if !defined($rd);
warn("not enough data for len"), return undef if !$rd;
$len .= $b;
$c -= $rd;
}
$len = unpack('V',$len);
while ($len > 0) {
$rd = sysread($fd,$b,$len);
warn("failed to read data: $!"), return undef if !defined($rd);
warn("not enough data"), return undef if !$rd;
$str .= $b;
$len -= $rd;
}
return $str;
}
sub read_pydict_entry
{
my $f = shift;
my ($buf,$rd);
FIL: while (1) {
# object type identifier
$rd = sysread($f, $buf, 1);
last FIL if $rd == 0;
warn("object type: $!\n"),last if $rd != 1;
# '{' is a python marshalled dict
warn("object type: not {\n"),last if $buf ne '{';
my $ent = {};
PAIR: while (1) {
my ($b,$key);
# key type identifier
$rd = sysread($f, $b, 1);
warn("key type: $!\n"),last FIL if $rd != 1;
if ($b eq 's') { # length-prefixed string
$key = r_pystr($f);
warn("key: $!\n"),last FIL if !defined($b);
} elsif ($b eq '0') { # NULL-element, end of entry
last PAIR;
} else {
warn("key type: not s");
last FIL;
}
# value type identifier
$rd = sysread($f, $b, 1);
warn("$key value type: $!\n"),last FIL if $rd != 1;
if ($b eq 's') { # length-prefixed string
$b = r_pystr($f);
warn("$key value: $!"),last FIL if !defined($b);
$ent->{$key} = $b;
} else {
warn("$key value type: not s ($b)");
last FIL;
}
}
return $ent;
}
return undef;
}
sub cl2msg {
my $cl = shift;
my($o1,$o2,$i);
if(!open($o1, '>>', "$GIT_DIR/p4/msg")) {
warn "p4/msg: $!\n";
return;
}
binmode($o1);
if(!open($o2, '>>', "$GIT_DIR/p4/p4msg")) {
warn "p4/p4msg: $!\n";
close($o1);
return
}
binmode($o2);
if(!open($i, '-|', "p4 describe -s $cl")){
warn "p4 describe: $!\n";
close($o1);
close($o2);
return
}
binmode($i);
print $o1 "$cl: ";
print $o2 "$cl: ";
my @a;
while (my $l = <$i>) {
last if $l =~ /^\s*Affected files \.{3}\s*$/so;
$l =~ s/\r?\n$//so;
push @a, $l;
}
close($i);
print $o2 substr($a[2],1),"\n";
close($o2);
print $o1 map {"$_\n"} (substr($a[2],1),"\n",@a);
close($o1);
}
sub git_p4_init {
my ($commit,$parent,$p4commit,$p4parent);
my ($HEAD, $p4head) = qx{git rev-parse HEAD refs/p4import/$P4CLIENT};
$HEAD = $p4head = '' if $?;
s/\r?\n//gs for ($HEAD, $p4head);
if (length($p4head)) {
($commit,$p4parent) =
grep { s/^parent (.{40}).*/$1/s }
qx{git cat-file commit $p4head};
$commit = $p4parent = '' if $?;
} else {
$commit = $p4parent = '';
}
while (($commit ne $HEAD) and length($p4parent)) {
$p4head = $p4parent;
($commit,$p4parent) =
grep { s/^parent (.{40}).*/$1/s }
qx{git cat-file commit $p4head};
$commit = $p4parent = '' if $?;
if ($VERBOSE and $HEAD eq $commit) {
print "found p4 import commit ";
system('git','name-rev',$p4head);
}
}
warn "Current HEAD was not imported from $P4CLIENT\n" if $HEAD ne $commit;
my $p4have = undef;
if (!$FULL_IMPORT and $HEAD eq $commit) {
if (open(my $f, '-|', "git cat-file -p $p4head:have")) {
my $old = $/;
$/ = "\0";
my $cnt = 0;
while(1) {
my $p4name = <$f>;
last if !defined($p4name);
$p4name =~ s/^.//so if $cnt; # remove \n
my $name = <$f>;
my $rev = <$f>;
last if !defined($name) or !defined($rev);
chop($p4name,$name,$rev);
++$cnt;
if (defined($p4have)) {
$p4have->{$p4name} = [$name,$rev];
} else {
$p4have = {$p4name=>[$name,$rev]};
}
}
$/ = $old;
close($f);
print "loaded $cnt revisions from $p4head\n" if $VERBOSE;
}
}
return ($HEAD, $p4head, $p4have);
}
sub git_p4_commit {
my ($HEAD, $p4head) = @_;
my ($commit,$parent,$p4commit,$p4parent);
my ($fdo,$fdi,$rc);
$rc = system('git','diff-index','--exit-code','--quiet','--cached','HEAD');
if ($rc == 0) {
warn("No changes\n");
return;
}
return if $DRYRUN;
my $p4x = "$GIT_DIR/p4/idx.tmp";
unlink($p4x);
my $oldidx = $ENV{GIT_INDEX_FILE};
$ENV{PAGER} = 'cat';
$ENV{GIT_INDEX_FILE} = $p4x;
open(STDIN, '<', $SPEC) or die "$SPEC: $!\n";
my ($p4spec) = qx{git hash-object -t blob -w --stdin};
die "Failed to store $SPEC in git repo\n" if $?;
open(STDIN, '<', "$GIT_DIR/p4/client.def") or die "cldef: $!\n";
my ($p4clnt) = qx{git hash-object -t blob -w --stdin};
die "Failed to save mappings of $P4CLIENT in git repo" if $?;
if (!defined($P4HAVE_FILE)) {
print "reading state of $P4CLIENT\n" if $VERBOSE;
$P4HAVE_FILE = "$GIT_DIR/p4/have";
open($fdo, '>', $P4HAVE_FILE) or die "p4/have: $!\n";
binmode($fdo);
open($fdi, "p4 -G @P4ARGS -c $P4CLIENT -H $P4HOST -d $P4ROOT have|") or
die "p4 have: $!\n";
binmode($fdi);
my $ent;
while (defined($ent=read_pydict_entry($fdi))) {
next if !defined($ent->{depotFile});
next if !defined($ent->{clientFile});
print $fdo "$ent->{depotFile}\0",
"$ent->{clientFile}\0",
"$ent->{haveRev}\0\n";
}
close($fdi);
close($fdo);
}
open(STDIN, '<', $P4HAVE_FILE) or die "$P4HAVE_FILE: $!\n";
my ($p4have) = qx{git hash-object -t blob -w --stdin};
die "Failed to save state of $P4CLIENT in git repo" if $?;
unlink("$GIT_DIR/p4/msg", "$GIT_DIR/p4/p4msg");
foreach my $i (@DESC) {
$i =~ s/^(.)//o;
if ('c' eq $1) {
print "reading changes for $i\n" if $VERBOSE;
cl2msg($i);
} elsif ('f' eq $1) {
my($o1,$o2,$i);
if (open($o1, '>>', "$GIT_DIR/p4/msg")) {
if (open($o2, '>>', "$GIT_DIR/p4/p4msg")) {
if (open($i, '<', $i)) {
my $n = 0;
while(<$i>) {
$n++;
print $o1 $_;
print $o2 $_ if $n == 1;
}
close($i);
}
close($o2);
}
close($o1);
}
} elsif ('4' eq $1) {
print "reading changes for $i\n" if $VERBOSE;
my ($change)=qx{p4 changes -m1 $i};
if (!defined($change) or $change !~ m/\s+(\d+)\s/) {
die "$i does not resolve into a change number\n";
}
cl2msg($1);
}
}
system($editor, "$GIT_DIR/p4/msg") if $EDIT_COMMIT;
#
# Store the imported file data
#
if (defined($oldidx)) { $ENV{GIT_INDEX_FILE} = $oldidx }
else { delete $ENV{GIT_INDEX_FILE} }
if ( $^O eq 'MSWin32' ) { open(STDERR, "NUL") }
else { open(STDERR, "/dev/null") }
my ($tree) = qx{git write-tree};
die "Failed to write current tree\n" if $?;
$parent = length($HEAD) ? "-p $HEAD": '';
open(STDIN, '<', "$GIT_DIR/p4/msg") or die "p4/msg: $!\n";
$tree =~ s/\r?\n//gs;
($commit)=qx{git commit-tree $tree $parent};
die "failed to commit current tree\n" if $?;
s/\r?\n//gs for ($commit);
#
# Storing import control data
#
$ENV{GIT_INDEX_FILE} = $p4x;
open($fdo, '|-', 'git update-index --add --index-info') or
die "could not start git update-index\n";
binmode($fdo);
s/\r?\n//gs for ($p4spec,$p4clnt,$p4have);
print $fdo "100644 $p4spec\tspec\n";
print $fdo "100644 $p4clnt\tclient\n";
print $fdo "100644 $p4have\thave\n";
close($fdo);
if($?) {
die "Failed to store $SPEC in p4import index and git repo\n".
"Failed to save mappings of $P4CLIENT in p4import index and git repo\n".
"Failed to save state of $P4CLIENT in p4import index and git repo\n"
}
my ($p4tree)=qx{git write-tree};
die "Failed to store $SPEC (tree) in git repo\n" if $?;
# Bind import control data to the file data
$p4parent="-p $commit";
$p4parent="$p4parent -p $p4head" if length($p4head);
open(STDIN, '<', "$GIT_DIR/p4/p4msg") or die "p4/p4msg: $!\n";
$p4tree =~ s/\r?\n//gs;
($p4commit)=qx{git commit-tree $p4tree $p4parent};
die "Failed to store $SPEC (commit) in git repo\n" if $?;
$p4commit =~ s/\r?\n//gs;
# Finishing touches: update references
$rc = system('git','update-ref','-m','data of p4import','HEAD',$commit);
die "Failed to update HEAD\n" if $rc;
$rc = system('git','update-ref','-m','p4import',"refs/p4import/$P4CLIENT",$p4commit);
die "Failed to store $SPEC (reference) in git repo\n" if $rc;
print STDOUT (grep {s/\r?\n//gs;s/.*?\s//} qx{git name-rev refs/p4import/$P4CLIENT}), ":\n";
system('git','log','--max-count=1','--pretty=format:%h %s%n',$p4commit);
print STDOUT (grep {s/\r?\n//gs;s/.*?\s//} qx{git name-rev HEAD}), ":\n";
system('git','log','--max-count=1','--pretty=format:%h %s%n',$commit);
}
^ permalink raw reply
* Re: FFmpeg considering GIT
From: Linus Torvalds @ 2007-05-05 22:30 UTC (permalink / raw)
To: Karl Hasselstr?m, Paul Mackerras, Junio C Hamano
Cc: Carl Worth, Michael Niedermayer, Git Mailing List
In-Reply-To: <alpine.LFD.0.98.0705051511020.17381@woody.linux-foundation.org>
On Sat, 5 May 2007, Linus Torvalds wrote:
>
> (It also shows that my "gitk" patch was incorrectly getting the commit
> name from character 6 onward, even though it should have been 7, but I'll
> also try to make gitk understand the "<" and ">" markers, and make it
> possible to say
>
> gitk --left-right a...b
>
> and have the commits colored appropriately. That would be cool, but it
> might need more tcl/tk knowledge than I actually possess).
Ok, that turned out to be the case.
Here's an updated patch to gitk, which at least *parses* the
"--left-right" data properly, it just doesn't use it. But with the fix to
"git log" I just posted, and this, you at least have the same capabilities
gitk used to have, and it should be fairly easy for somebody who knows
tcltk to squirrel away the "leftright" data per commit and use that to
color the commit lines in the top-most pane.
I'm also sure the "if first character is one of '-'/'<'/'>'" test can be
written more prettily, rather than have three if-statements on it.
Finally, it realy _should_ check that the first 7 characters of the commit
log (the ones it ignores by just asking for substring 7..) are actually
the exact characters "commit ", but I'll blame my lack of comfort with the
language again.
Somebody? Please? It really should be pretty cool. Do
gitk --left-right commit^1...commit^2
for an appropriate 'commit' that is a merge, and the two sides getting
merged should show up with different colors!
Linus
----
gitk | 18 ++++++++++++++----
1 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/gitk b/gitk
index b1c65d7..0bf00ee 100755
--- a/gitk
+++ b/gitk
@@ -33,8 +33,8 @@ proc start_rev_list {view} {
set order "--date-order"
}
if {[catch {
- set fd [open [concat | git rev-list --header $order \
- --parents --boundary --default HEAD $args] r]
+ set fd [open [concat | git log -z --pretty=raw $order \
+ --parents --boundary $args] r]
} err]} {
puts stderr "Error executing git rev-list: $err"
exit 1
@@ -127,13 +127,23 @@ proc getcommitlines {fd view} {
set start [expr {$i + 1}]
set j [string first "\n" $cmit]
set ok 0
+ set leftright 0
set listed 1
if {$j >= 0} {
- set ids [string range $cmit 0 [expr {$j - 1}]]
+ # start with 'commit '
+ set ids [string range $cmit 7 [expr {$j - 1}]]
if {[string range $ids 0 0] == "-"} {
set listed 0
set ids [string range $ids 1 end]
}
+ if {[string range $ids 0 0] == "<"} {
+ set leftright -1
+ set ids [string range $ids 1 end]
+ }
+ if {[string range $ids 0 0] == ">"} {
+ set leftright 1
+ set ids [string range $ids 1 end]
+ }
set ok 1
foreach id $ids {
if {[string length $id] != 40} {
@@ -147,7 +157,7 @@ proc getcommitlines {fd view} {
if {[string length $shortcmit] > 80} {
set shortcmit "[string range $shortcmit 0 80]..."
}
- error_popup "Can't parse git rev-list output: {$shortcmit}"
+ error_popup "Can't parse git git log output: {$shortcmit}"
exit 1
}
set id [lindex $ids 0]
^ permalink raw reply related
* Re: FFmpeg considering GIT
From: Linus Torvalds @ 2007-05-05 22:18 UTC (permalink / raw)
To: Karl Hasselstr?m, Paul Mackerras, Junio C Hamano
Cc: Carl Worth, Michael Niedermayer, Git Mailing List
In-Reply-To: <alpine.LFD.0.98.0705051019580.3819@woody.linux-foundation.org>
On Sat, 5 May 2007, Linus Torvalds wrote:
>
> This patch may be worth applying regardless, since there is really no real
> reason to use "git rev-list". In fact, I really like the ability to say
>
> gitk --stat
>
> and have the diffstat output visible in the commit window automatically ;)
Btw, testing this a bit more actually shows what I would consider a real
buglet in "git log --boundary": the option would be honoured only if
"left-right" was enabled.
This patch fixes "git log --boundary" to actually show the "-" in front of
a commit name regardless of whether you _also_ asked for left-right.
(It also shows that my "gitk" patch was incorrectly getting the commit
name from character 6 onward, even though it should have been 7, but I'll
also try to make gitk understand the "<" and ">" markers, and make it
possible to say
gitk --left-right a...b
and have the commits colored appropriately. That would be cool, but it
might need more tcl/tk knowledge than I actually possess).
Linus
---
diff --git a/log-tree.c b/log-tree.c
index c679324..4bef909 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -244,10 +244,10 @@ void show_log(struct rev_info *opt, const char *sep)
stdout);
if (opt->commit_format != CMIT_FMT_ONELINE)
fputs("commit ", stdout);
- if (opt->left_right) {
- if (commit->object.flags & BOUNDARY)
- putchar('-');
- else if (commit->object.flags & SYMMETRIC_LEFT)
+ if (commit->object.flags & BOUNDARY)
+ putchar('-');
+ else if (opt->left_right) {
+ if (commit->object.flags & SYMMETRIC_LEFT)
putchar('<');
else
putchar('>');
^ 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