* Re: [PATCH] [GITK] use "git <command>" instead of "git-<command>"
From: Junio C Hamano @ 2006-01-25 9:52 UTC (permalink / raw)
To: Uwe Zeisberger; +Cc: git
In-Reply-To: <20060125075635.GB2768@informatik.uni-freiburg.de>
Uwe Zeisberger <zeisberg@informatik.uni-freiburg.de> writes:
> Otherwise gitk is not able to work with installations using a gitexecdir
> different from bindir.
For something like gitk that lives for some time and spawns git
number of times, it is considered a good practice to:
(1) Run "git --exec-path" at the beginning, to learn
GIT_EXEC_PATH;
(2) Prepend that to PATH;
(3) And invoke "git-foo" commands in the rest of the script.
This saves an extra fork/exec (gitk -> git -> git-foo). I was
told qgit already does this.
Note that we may end up leaving some git-* commands in /usr/bin
while moving the rest to elsewhere (e.g. /usr/lib/git-core/exec/),
so (2) and (3) cannot be safely substituted with
(BAD) invoke "$GIT_EXEC_PATH/git-foo" instead.
I usually prefer patches to gitk to come through paulus, so
please CC: when sending patches to gitk ("git whatchanged gitk"
would give you the e-mail address).
^ permalink raw reply
* Re: [QUESTION] What is a tag for?
From: Andreas Ericsson @ 2006-01-25 9:02 UTC (permalink / raw)
Cc: git
In-Reply-To: <7vbqy13vq9.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano wrote:
> Andreas Ericsson <ae@op5.se> writes:
>
>
>>I'll apply (and test) Linus suggestions of new refs and re-send it
>>when I'm done watching King-Kong and stuffing my face with popcorn.
>
>
> It appears you have not finished watching the movie yet, so I
> took the liberty of adding this on top of your patch myself
> ;-).
>
Sorry about that. I started adding stuff to it to disallow creating
branches that have no unique commits, and then thought of some other fun
stuff that's a bit specific to the place I work so I never got around to it.
Somehow the phb's never grow tired of coming up with new ways to waste
my time just when I've found a way to save some, forcing me to find a
way to find some more. Anyways, if anybody wants an update-hook to
update a project-management tool with worked time, gimme a holler. It's
quite neat but completely flawed in a good way. :)
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply
* [PATCH] [GITK] use "git <command>" instead of "git-<command>"
From: Uwe Zeisberger @ 2006-01-25 7:56 UTC (permalink / raw)
To: git
Otherwise gitk is not able to work with installations using a gitexecdir
different from bindir.
Signed-off-by: Uwe Zeisberger <zeisberg@informatik.uni-freiburg.de>
---
gitk | 32 ++++++++++++++++----------------
1 files changed, 16 insertions(+), 16 deletions(-)
05f2a8c2fb8811bb78dd3c81c204e8635ca0fd83
diff --git a/gitk b/gitk
index f12b3ce..6aa340d 100755
--- a/gitk
+++ b/gitk
@@ -21,7 +21,7 @@ proc parse_args {rargs} {
if [catch {
set parse_args [concat --default HEAD $rargs]
- set parsed_args [split [eval exec git-rev-parse $parse_args] "\n"]
+ set parsed_args [split [eval exec git rev-parse $parse_args] "\n"]
}] {
# if git-rev-parse failed for some reason...
if {$rargs == {}} {
@@ -40,7 +40,7 @@ proc start_rev_list {rlargs} {
set nextupdate [expr {$startmsecs + 100}]
set ncmupdate 1
if [catch {
- set commfd [open [concat | git-rev-list --header --topo-order \
+ set commfd [open [concat | git rev-list --header --topo-order \
--parents $rlargs] r]
} err] {
puts stderr "Error executing git-rev-list: $err"
@@ -181,7 +181,7 @@ proc doupdate {reading} {
}
proc readcommit {id} {
- if [catch {set contents [exec git-cat-file commit $id]}] return
+ if [catch {set contents [exec git cat-file commit $id]}] return
parsecommit $id $contents 0 {}
}
@@ -242,7 +242,7 @@ proc updatecommits {rargs} {
set phase updatecommits
set oldcommits $commits
set commits {}
- set removed_commits [split [eval exec git-rev-list $ignorenew] "\n" ]
+ set removed_commits [split [eval exec git rev-list $ignorenew] "\n" ]
if {[llength $removed_commits] > 0} {
allcanvs delete all
foreach c $removed_commits {
@@ -359,7 +359,7 @@ proc readrefs {} {
foreach v {tagids idtags headids idheads otherrefids idotherrefs} {
catch {unset $v}
}
- set refd [open [list | git-ls-remote [gitdir]] r]
+ set refd [open [list | git ls-remote [gitdir]] r]
while {0 <= [set n [gets $refd line]]} {
if {![regexp {^([0-9a-f]{40}) refs/([^^]*)$} $line \
match id path]} {
@@ -376,14 +376,14 @@ proc readrefs {} {
set type {}
set tag {}
catch {
- set commit [exec git-rev-parse "$id^0"]
+ set commit [exec git rev-parse "$id^0"]
if {"$commit" != "$id"} {
set tagids($name) $commit
lappend idtags($commit) $name
}
}
catch {
- set tagcontents($name) [exec git-cat-file tag "$id"]
+ set tagcontents($name) [exec git cat-file tag "$id"]
}
} elseif { $type == "heads" } {
set headids($name) $id
@@ -1855,7 +1855,7 @@ proc findpatches {} {
}
if {[catch {
- set f [open [list | git-diff-tree --stdin -s -r -S$findstring \
+ set f [open [list | git diff-tree --stdin -s -r -S$findstring \
<< $inputids] r]
} err]} {
error_popup "Error starting search process: $err"
@@ -1958,7 +1958,7 @@ proc findfiles {} {
# start off a git-diff-tree process if needed
if {$diffsneeded ne {}} {
if {[catch {
- set df [open [list | git-diff-tree -r --stdin << $diffsneeded] r]
+ set df [open [list | git diff-tree -r --stdin << $diffsneeded] r]
} err ]} {
error_popup "Error starting search process: $err"
return
@@ -2382,7 +2382,7 @@ proc findgca {ids} {
set gca $id
} else {
if {[catch {
- set gca [exec git-merge-base $gca $id]
+ set gca [exec git merge-base $gca $id]
} err]} {
return {}
}
@@ -2470,7 +2470,7 @@ proc showmergediff {} {
catch {unset grouphunks}
set groupfilelast -1
foreach p $parents($diffmergeid) {
- set cmd [list | git-diff-tree -p $p $diffmergeid]
+ set cmd [list | git diff-tree -p $p $diffmergeid]
set cmd [concat $cmd $mergefilelist($diffmergeid)]
if {[catch {set f [open $cmd r]} err]} {
error_popup "Error getting diffs: $err"
@@ -2912,7 +2912,7 @@ proc gettreediffs {ids} {
global treediff parents treepending
set treepending $ids
set treediff {}
- if [catch {set gdtf [open [concat | git-diff-tree --no-commit-id -r $ids] r]}] return
+ if [catch {set gdtf [open [concat | git diff-tree --no-commit-id -r $ids] r]}] return
fconfigure $gdtf -blocking 0
fileevent $gdtf readable [list gettreediffline $gdtf $ids]
}
@@ -2946,7 +2946,7 @@ proc getblobdiffs {ids} {
global difffilestart nextupdate diffinhdr treediffs
set env(GIT_DIFF_OPTS) $diffopts
- set cmd [concat | git-diff-tree --no-commit-id -r -p -C $ids]
+ set cmd [concat | git diff-tree --no-commit-id -r -p -C $ids]
if {[catch {set bdf [open $cmd r]} err]} {
puts "error getting diffs: $err"
return
@@ -3524,7 +3524,7 @@ proc mkpatchgo {} {
set oldid [$patchtop.fromsha1 get]
set newid [$patchtop.tosha1 get]
set fname [$patchtop.fname get]
- if {[catch {exec git-diff-tree -p $oldid $newid >$fname &} err]} {
+ if {[catch {exec git diff-tree -p $oldid $newid >$fname &} err]} {
error_popup "Error creating patch: $err"
}
catch {destroy $patchtop}
@@ -4090,11 +4090,11 @@ proc tcl_encoding {enc} {
# defaults...
set datemode 0
set diffopts "-U 5 -p"
-set wrcomcmd "git-diff-tree --stdin -p --pretty"
+set wrcomcmd "git diff-tree --stdin -p --pretty"
set gitencoding {}
catch {
- set gitencoding [exec git-repo-config --get i18n.commitencoding]
+ set gitencoding [exec git repo-config --get i18n.commitencoding]
}
if {$gitencoding == ""} {
set gitencoding "utf-8"
--
1.1.4.g2eaa
--
Uwe Zeisberger
dd if=/proc/self/exe bs=1 skip=1 count=3 2>/dev/null
^ permalink raw reply related
* git describe fails without tags
From: Uwe Zeisberger @ 2006-01-25 7:47 UTC (permalink / raw)
To: git
Hello,
using git describe on Linus' sparse repo results in:
uzeisberger@io:~/gsrc/sparse$ git describe
fatal: cannot describe '62ac6c16058aba8693fd5827379debc5f57b60f5'
The reason is, that there exist no tags at all, so right, there is no
"most recent tag that is reachable from HEAD".
I wonder if it would be sane to assume an implicit tag for the empty
repository, s.t. git describe results in
<empty>-62ac6c16
(whatever name is choosen for <empty>).
Any opinions?
Best regards
Uwe
--
Uwe Zeisberger
http://www.google.com/search?q=1+degree+celsius+in+kelvin
^ permalink raw reply
* Re: Caching directories
From: Pavel Roskin @ 2006-01-25 7:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vvew8zwfe.fsf@assigned-by-dhcp.cox.net>
On Tue, 2006-01-24 at 21:52 -0800, Junio C Hamano wrote:
> Pavel Roskin <proski@gnu.org> writes:
>
> > Maybe it's time to start caching directories in git? I mean,
> > directories corresponding to tree objects could have their stats
> > recorded in the cache. This would allow to distinguish between tracked
> > and untracked directories without scanning them recursively.
>
> I do not understand the above logic.
>
> Given a directory path, finding out if the directory has
> something tracked in it is an O(log n) operation in the current
> index that does not "cache directory". Your message implies
> that you feel we could use the index file to list "untracked
> directories" without recursively scanning the directory tree,
> but to me, the only way to do that is to record a new directory
> in the index file every time somebody (either Makefile or the
> user) creates a junk directory. That does not make much sense
> to me, so I am probably misreading what you really meant.
Sorry, it looks like my post was based on incorrect assumptions. The
new --directory option to git-ls-files seems to be exactly what I want.
It allowed me to simplify cg-clean immensely. Further simplification
will be possible once the support for .gitignore in parent directories
is fixed.
> I have no idea what 'clean' does, so would not comment on that
> part of your message.
It means removing untracked files and directories.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: [PATCH] Parametrize asciidoc and add --unsafe
From: Pavel Roskin @ 2006-01-25 6:52 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmll2h5h.fsf@assigned-by-dhcp.cox.net>
On Tue, 2006-01-24 at 18:08 -0800, Junio C Hamano wrote:
> Pavel Roskin <proski@gnu.org> writes:
>
> > Including files from the parent directory is considered unsafe by
> > asciidoc 7.1.0. This is used in git.txt, which includes ../README.
>
> Is copying/linking README down when we build documentation a
> more conservative option, I wonder?
I considered this possibility. I don't have a strong preference. The
argument in favor of "--unsafe" is that adding a make target is more
intrusive that adding a switch. Besides, we may want to include more
files from other directories.
> Does asciidoc prior to 7.1.0 do sensible thing given an --unsafe
> option? If not, how does one override ASCIIDOC from the command
> line to the toplevel "make"?
Good question. I misunderstood the asciidoc changelog. Older versions
(before 7.0.4) understand "--safe", but not "--unsafe". Since version
7.0.4 is less than 2 months old, it would be reasonable not to go ahead
with my patch right now.
Let's make a copy for now. Symbolic linking doesn't work - asciidoc
recognizes and rejects symlinks.
---
[PATCH] Don't include ../README in git.txt - make a local copy
asciidoc 7.0.4 and newer considers such includes from parent directory
unsafe.
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
Documentation/.gitignore | 1 +
Documentation/Makefile | 9 ++++++---
Documentation/git.txt | 2 +-
3 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/Documentation/.gitignore b/Documentation/.gitignore
index 9fef490..c87c61a 100644
--- a/Documentation/.gitignore
+++ b/Documentation/.gitignore
@@ -4,3 +4,4 @@
*.7
howto-index.txt
doc.dep
+README
diff --git a/Documentation/Makefile b/Documentation/Makefile
index a65fb1b..a3bca86 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -62,11 +62,14 @@ doc.dep : $(wildcard *.txt) build-docdep
-include doc.dep
-git.7: ../README
+git.7: README
+
+README: ../README
+ cp $< $@
clean:
- rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep
+ rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep README
%.html : %.txt
asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
@@ -77,7 +80,7 @@ clean:
%.xml : %.txt
asciidoc -b docbook -d manpage -f asciidoc.conf $<
-git.html: git.txt ../README
+git.html: git.txt README
glossary.html : glossary.txt sort_glossary.pl
cat $< | \
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 25bcb84..e8ef3ef 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -586,7 +586,7 @@ git Diffs
Discussion[[Discussion]]
------------------------
-include::../README[]
+include::README[]
Authors
-------
--
Regards,
Pavel Roskin
^ permalink raw reply related
* Re: [PATCH] rev-{list,parse}: allow -<n> as shorthand for --max-count=<n>
From: Eric Wong @ 2006-01-25 6:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git list
In-Reply-To: <7vd5iicauh.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <junkio@cox.net> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
>
> > Some versions of head(1) and tail(1) allow their line limits to be
> > parsed this way. I find --max-count to be a commonly used option,
> > and also similar in spirit to head/tail, so I decided to make life
> > easier on my worn out (and lazy :) fingers with this patch.
>
> As an old timer, I personally am very used to "head -4", but
> also have been training my fingers to say "head -n 4" for the
> past few years, because the former is not POSIXly correct.
I don't agree with POSIX on this point, and I don't see why git should
be bound to POSIX, especially at the UI level just because it's POSIX.
Fwiw, head/tail in coreutils distributed by Debian still supports -<n>
alongside -n <n> and -n<n>.
> At the same time, I agree that --max-count *was* a mistake. We
> should maybe say "-n <n>" perhaps?
Then, -n<n> (w/o the space) should be supported as well. Heck, I've
been wanting GNU getopt_long() option parsing in git for a while. Not
sure if I'll have time to implement it myself any time soon, though.
--
Eric Wong
^ permalink raw reply
* Re: git-ls-files in subdirectories ignore higher-up .gitignore
From: Sam Ravnborg @ 2006-01-25 6:11 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <1138125570.24415.11.camel@dv>
On Tue, Jan 24, 2006 at 12:59:30PM -0500, Pavel Roskin wrote:
> Hello!
>
> git-ls-files appears to behave in a way that may be unexpected to the
> users. When run in a subdirectory, git-ls-files never reads .gitignore
> or whatever is specified by --exclude-per-directory in the parent
> directories.
>
> This can be demonstrated in git's own repository:
>
> $ touch t/test.o
> $ git-ls-files --others --exclude-per-directory=.gitignore
> $ cd t
> $ git-ls-files --others --exclude-per-directory=.gitignore
> test.o
> $
>
> Before I attempt to fix it, I'd like to make sure it's a bug, not a
> feature.
I for one consider it a bug.
I expect exactly same output if I do
git ls-files t/
or
cd t; git ls-files
Very usefull when I limit grep to some part of the kernel tree for
example.
Sam
^ permalink raw reply
* Re: Caching directories
From: Junio C Hamano @ 2006-01-25 5:52 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <1138076423.15105.36.camel@dv>
Pavel Roskin <proski@gnu.org> writes:
> Maybe it's time to start caching directories in git? I mean,
> directories corresponding to tree objects could have their stats
> recorded in the cache. This would allow to distinguish between tracked
> and untracked directories without scanning them recursively.
I do not understand the above logic.
Given a directory path, finding out if the directory has
something tracked in it is an O(log n) operation in the current
index that does not "cache directory". Your message implies
that you feel we could use the index file to list "untracked
directories" without recursively scanning the directory tree,
but to me, the only way to do that is to record a new directory
in the index file every time somebody (either Makefile or the
user) creates a junk directory. That does not make much sense
to me, so I am probably misreading what you really meant.
I've been meaning to explore the possibility of recording 0{40}
SHA1 in the index file to mean "I do not want to place anything
on this path when I write the index out to a tree yet, but keep
an eye on the path in the working tree for me".
You can consider this as an "intent to add"; for example, with
such an index file, you could do something like this:
$ git update-index --intent-to-add foo
This would record 0^{40} SHA1 with the 0 mode in the index at
"foo". Then:
$ git diff-files -p
diff --git a/foo b/foo
new file mode 100644
index 0000000..6690023
--- /dev/null
+++ b/foo
@@ -0,0 +1,24 @@
+...
+....
...
The index has heard about it, but does not actually have it, so
it reports an addition. Since we currently do not have such,
after a "git add", the index not just has heard about it, but
actually has it, and as a consequence, there is no way to get
"new file" out of diff-files.
$ git diff-index --cached HEAD ;# nothing
The index has heard about it, but does not have it. If the HEAD
commit did not have it, diff-index --cached would report
nothing.
$ git diff-index HEAD
diff --git a/foo b/foo
new file mode 100644
index 0000000..6690023
--- /dev/null
+++ b/foo
@@ -0,0 +1,24 @@
+...
+....
...
The index has heard about it, and without --cached it uses the
working tree file, so if HEAD did not have it you would see "new
file" out of diff-index. If the comparison were with a tree
that has "foo" in it, diff-index using an index that does not
have "foo" would not say anything in the current system, but
with "intent to add", it would say "Oh, your index knows about
it so let me look in the working tree; ah, you have something
there. Let me compare it with the version in the tree in
question".
One interesting thing the "intent to add" entries would do is
this:
$ git diff-files --abbrev foo
:000000 100644 0000... 0000...
Note that two "0^{40}" mean quite different things. The one on
the LHS means "we've heard about it but we do not have it". On
the other hand, the one on the RHS means "we do not cache the
SHA1 --- go look at the working tree file".
We might want to represent the existence of a tree that does not
have anything under using 0^{40} as well. Or it might be better
kept out of the main index entries list, and become extra data
just like we have been discussing how to store "bind" entries in
the "Subprojects" thread. I dunno.
I have no idea what 'clean' does, so would not comment on that
part of your message.
^ permalink raw reply
* Re: [PATCH] diff-tree -c: show a merge commit a bit more sensibly.
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0601241655090.10804@evo.osdl.org>
Linus Torvalds <torvalds@osdl.org> writes:
> On Tue, 24 Jan 2006, Junio C Hamano wrote:
>>
>> A new option '-c' to diff-tree changes the way a merge commit is
>> displayed when generating a patch output. It shows a "combined
>> diff" (hence the option letter 'c'), which looks like this:
>
> Can you make this the default for "git-whatchanged" too? That way, merges
> that have manual fixups will actually show up in the whatchanged output.
One problem with that I see is that it would mean making the
patch output as the default for whatchanged, since I made '-c'
to imply '-p' (I did not think of a reasonable 'combined diff'
behaviour for the diff-raw output).
I suspect many people are now used to the current default of
showing an abbreviated diff-raw and use it to quickly sanity
check the list of paths touched by each commit, so I am not so
sure that '-c' would be a good default for whatchanged.
For now, please do "git-repo-config whatchanged.difftree" ;-).
BTW, one feature that might be interesting is to tell either
rev-list or diff-tree to show _only_ merges. My debugging
session went like this:
$ git rev-list --all --parents |
sed -ne 's/\([^ ]*\) [^ ]* [^ ].*/\1/p' |
git diff-tree -c --stdin --pretty
I doubt such a flag would be of any practical value other than
curiosity, though.
> Also, it would be perhaps even nicer if it had a "dense" version, which
> only showed the chunks that had differences from more than one parent.
> Chunks that have diffs from just one parent obviously had no conflicts in
> that chunk, so they are much less interesting than a chunk that was
> different from more than one parent..
I agree that would be useful. The logic to cull "uninteresting"
commit comes much earlier than the combined diff is split into
hunks, so it is probably not trivial (but I suspect not hard) to
arrange. For now, I output the "diff --combined" header along
with the commit log even if "dense" ends up removing all hunks
as not-so-interesting. An updated version is currently in the
"pu" branch.
I think the current output can be enhanced to have "-line,count"
for all parents to make the output machine applicable (i.e. we
could teach git-apply to take such a patch, which is somewhat
yucky) but I suspect dense mode would make that inpractical. I
personally think combined diff is purely for human consumption,
so the machine applicability may not be an issue.
^ permalink raw reply
* [PATCH 2/2] diff-tree --cc: denser combined diff output for a merge commit.
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: git
Building on the previous '-c' (combined) option, '--cc' option
squelches the output further by omitting hunks that consist of
difference with solely one parent.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* I am not particularly happy about the option name, but I
wanted to avoid --dense, because it would make it hard to use
in the context of 'whatchanged' (rev-list wants that flag).
Even without '-m' flag, the command outputs the commit log if
the removal of not so interesting hunks results in an empty
patch, along with 'diff --combined' header. This might be
considered a feature to remind the user that there were some
file-level merges, just like diff-files shows empty diffs on
cache-dirty paths.
combine-diff.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
diff-tree.c | 10 ++++++--
diff.h | 2 +-
3 files changed, 73 insertions(+), 8 deletions(-)
ceba1d2a70929c0c89c4dcddb1e1b4dd38d8494c
diff --git a/combine-diff.c b/combine-diff.c
index 6690023..062ed8a 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -278,7 +278,25 @@ static int interesting(struct sline *sli
return ((sline->flag & all_mask) != all_mask || sline->lost_head);
}
-static void make_hunks(struct sline *sline, unsigned long cnt, int num_parent)
+static unsigned long line_diff_parents(struct sline *sline, unsigned long all_mask)
+{
+ /*
+ * Look at the line and see from which parents we have difference.
+ * Lower bits of sline->flag records if the parent had this line,
+ * so XOR with all_mask gives us on-bits for parents we have
+ * differences with.
+ */
+ unsigned long parents = (sline->flag ^ all_mask);
+ if (sline->lost_head) {
+ struct lline *ll;
+ for (ll = sline->lost_head; ll; ll = ll->next)
+ parents |= ll->parent_map;
+ }
+ return parents & all_mask;
+}
+
+static void make_hunks(struct sline *sline, unsigned long cnt,
+ int num_parent, int dense)
{
unsigned long all_mask = (1UL<<num_parent) - 1;
unsigned long mark = (1UL<<num_parent);
@@ -302,6 +320,45 @@ static void make_hunks(struct sline *sli
}
i++;
}
+ if (!dense)
+ return;
+
+ /* Look at each hunk, and if it contains changes from only
+ * one parent, mark that uninteresting.
+ */
+ i = 0;
+ while (i < cnt) {
+ int j, hunk_end, diffs;
+ unsigned long parents;
+ while (i < cnt && !(sline[i].flag & mark))
+ i++;
+ if (cnt <= i)
+ break; /* No more interesting hunks */
+ for (hunk_end = i + 1; hunk_end < cnt; hunk_end++)
+ if (!(sline[hunk_end].flag & mark))
+ break;
+ /* [i..hunk_end) are interesting. Now is it from
+ * only one parent?
+ * If lost lines are only from one parent and
+ * remaining lines existed in parents other than
+ * that parent, then the hunk is not that interesting.
+ */
+ parents = 0;
+ diffs = 0;
+ for (j = i; j < hunk_end; j++)
+ parents |= line_diff_parents(sline + j, all_mask);
+ /* Now, how many bits from [0..num_parent) are on? */
+ for (j = 0; j < num_parent; j++) {
+ if (parents & (1UL<<j))
+ diffs++;
+ }
+ if (diffs < 2) {
+ /* This hunk is not that interesting after all */
+ for (j = i; j < hunk_end; j++)
+ sline[j].flag &= ~mark;
+ }
+ i = hunk_end;
+ }
}
static void dump_sline(struct sline *sline, int cnt, int num_parent)
@@ -351,7 +408,8 @@ static void dump_sline(struct sline *sli
}
}
-static void show_combined_diff(struct path_list *elem, int num_parent)
+static void show_combined_diff(struct path_list *elem, int num_parent,
+ int dense)
{
unsigned long size, cnt, lno;
char *result, *cp, *ep;
@@ -390,7 +448,7 @@ static void show_combined_diff(struct pa
for (i = 0; i < num_parent; i++)
combine_diff(elem->parent_sha1[i], ourtmp, sline, cnt, i);
- make_hunks(sline, cnt, num_parent);
+ make_hunks(sline, cnt, num_parent, dense);
dump_sline(sline, cnt, num_parent);
unlink(ourtmp);
@@ -410,7 +468,8 @@ static void show_combined_diff(struct pa
}
int diff_tree_combined_merge(const unsigned char *sha1,
- const char *header, int show_empty_merge)
+ const char *header,
+ int show_empty_merge, int dense)
{
struct commit *commit = lookup_commit(sha1);
struct diff_options diffopts;
@@ -455,7 +514,7 @@ int diff_tree_combined_merge(const unsig
else
printf("%s", p->path);
putchar('\n');
- show_combined_diff(p, num_parent);
+ show_combined_diff(p, num_parent, dense);
}
}
diff --git a/diff-tree.c b/diff-tree.c
index 0c68936..99c580c 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -8,6 +8,7 @@ static int verbose_header = 0;
static int ignore_merges = 1;
static int show_empty_combined = 0;
static int combine_merges = 0;
+static int dense_combined_merges = 0;
static int read_stdin = 0;
static const char *header = NULL;
@@ -121,7 +122,8 @@ static int diff_tree_commit(const unsign
header = generate_header(sha1, sha1,
commit->buffer);
return diff_tree_combined_merge(sha1, header,
- show_empty_combined);
+ show_empty_combined,
+ dense_combined_merges);
}
}
@@ -168,7 +170,7 @@ static int diff_tree_stdin(char *line)
}
static const char diff_tree_usage[] =
-"git-diff-tree [--stdin] [-m] [-c] [-s] [-v] [--pretty] [-t] [-r] [--root] "
+"git-diff-tree [--stdin] [-m] [-c] [--cc] [-s] [-v] [--pretty] [-t] [-r] [--root] "
"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
" -r diff recursively\n"
" --root include the initial commit as diff against /dev/null\n"
@@ -235,6 +237,10 @@ int main(int argc, const char **argv)
combine_merges = 1;
continue;
}
+ if (!strcmp(arg, "--cc")) {
+ dense_combined_merges = combine_merges = 1;
+ continue;
+ }
if (!strcmp(arg, "-v")) {
verbose_header = 1;
header_prefix = "diff-tree ";
diff --git a/diff.h b/diff.h
index 081234c..ab0d47b 100644
--- a/diff.h
+++ b/diff.h
@@ -56,7 +56,7 @@ extern int diff_tree(struct tree_desc *t
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
const char *base, struct diff_options *opt);
-extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int);
+extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int, int);
extern void diff_addremove(struct diff_options *,
int addremove,
--
1.1.4.g869a
^ permalink raw reply related
* [PATCH 1/2] diff-tree -c: show a merge commit a bit more sensibly.
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: git
A new option '-c' to diff-tree changes the way a merge commit is
displayed when generating a patch output. It shows a "combined
diff" (hence the option letter 'c'), which looks like this:
$ git-diff-tree --pretty -c -p fec9ebf1 | head -n 18
diff-tree fec9ebf... (from parents)
Merge: 0620db3... 8a263ae...
Author: Junio C Hamano <junkio@cox.net>
Date: Sun Jan 15 22:25:35 2006 -0800
Merge fixes up to GIT 1.1.3
diff --combined describe.c
@@@ +98,7 @@@
return (a_date > b_date) ? -1 : (a_date == b_date) ? 0 : 1;
}
- static void describe(char *arg)
- static void describe(struct commit *cmit, int last_one)
++ static void describe(char *arg, int last_one)
{
+ unsigned char sha1[20];
+ struct commit *cmit;
There are a few things to note about this feature:
- The '-c' option implies '-p'. It also implies '-m' halfway
in the sense that "interesting" merges are shown, but not all
merges.
- When a blob matches one of the parents, we do not show a diff
for that path at all. For a merge commit, this option shows
paths with real file-level merge (aka "interesting things").
- As a concequence of the above, an "uninteresting" merge is
not shown at all. You can use '-m' in addition to '-c' to
show the commit log for such a merge, but there will be no
combined diff output.
- Unlike "gitk", the output is monochrome.
A '-' character in the nth column means the line is from the nth
parent and does not appear in the merge result (i.e. removed
from that parent's version).
A '+' character in the nth column means the line appears in the
merge result, and the nth parent does not have that line
(i.e. added by the merge itself or inherited from another
parent).
The above example output shows that the function signature was
changed from either parents (hence two "-" lines and a "++"
line), and "unsigned char sha1[20]", prefixed by a " +", was
inherited from the first parent.
The code as sent to the list was buggy in few corner cases,
which I have fixed since then.
It does not bother to keep track of and show the line numbers
from parent commits, which it probably should.
Signed-off-by: Junio C Hamano <junkio@cox.net>
---
* This is a replacement for the previous one, and is in the
"pu" branch.
Makefile | 2
combine-diff.c | 469 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff-tree.c | 36 ++++
diff.h | 2
4 files changed, 502 insertions(+), 7 deletions(-)
create mode 100644 combine-diff.c
8085b27b67d0c4ccec206699f4292e6aed94f36b
diff --git a/Makefile b/Makefile
index 3046056..552b20f 100644
--- a/Makefile
+++ b/Makefile
@@ -182,7 +182,7 @@ LIB_H = \
DIFF_OBJS = \
diff.o diffcore-break.o diffcore-order.o diffcore-pathspec.o \
- diffcore-pickaxe.o diffcore-rename.o tree-diff.o
+ diffcore-pickaxe.o diffcore-rename.o tree-diff.o combine-diff.o
LIB_OBJS = \
blob.o commit.o connect.o count-delta.o csum-file.o \
diff --git a/combine-diff.c b/combine-diff.c
new file mode 100644
index 0000000..6690023
--- /dev/null
+++ b/combine-diff.c
@@ -0,0 +1,469 @@
+#include "cache.h"
+#include "commit.h"
+#include "diff.h"
+#include "diffcore.h"
+#include "quote.h"
+
+struct path_list {
+ struct path_list *next;
+ int len;
+ char *path;
+ unsigned char sha1[20];
+ unsigned char parent_sha1[FLEX_ARRAY][20];
+};
+
+static int uninteresting(struct diff_filepair *p)
+{
+ if (diff_unmodified_pair(p))
+ return 1;
+ if (!S_ISREG(p->one->mode) || !S_ISREG(p->two->mode))
+ return 1;
+ return 0;
+}
+
+static struct path_list *intersect_paths(struct path_list *curr,
+ int n, int num_parent)
+{
+ struct diff_queue_struct *q = &diff_queued_diff;
+ struct path_list *p;
+ int i;
+
+ if (!n) {
+ struct path_list *list = NULL, *tail = NULL;
+ for (i = 0; i < q->nr; i++) {
+ int len;
+ const char *path;
+ if (uninteresting(q->queue[i]))
+ continue;
+ path = q->queue[i]->two->path;
+ len = strlen(path);
+
+ p = xmalloc(sizeof(*p) + len + 1 + num_parent * 20);
+ p->path = (char*) &(p->parent_sha1[num_parent][0]);
+ memcpy(p->path, path, len);
+ p->path[len] = 0;
+ p->len = len;
+ p->next = NULL;
+ memcpy(p->sha1, q->queue[i]->two->sha1, 20);
+ memcpy(p->parent_sha1[n], q->queue[i]->one->sha1, 20);
+ if (!tail)
+ list = tail = p;
+ else {
+ tail->next = p;
+ p = tail;
+ }
+ }
+ return list;
+ }
+
+ for (p = curr; p; p = p->next) {
+ int found = 0;
+ if (!p->len)
+ continue;
+ for (i = 0; i < q->nr; i++) {
+ const char *path;
+ int len;
+
+ if (uninteresting(q->queue[i]))
+ continue;
+ path = q->queue[i]->two->path;
+ len = strlen(path);
+ if (len == p->len && !memcmp(path, p->path, len)) {
+ found = 1;
+ memcpy(p->parent_sha1[n],
+ q->queue[i]->one->sha1, 20);
+ break;
+ }
+ }
+ if (!found)
+ p->len = 0;
+ }
+ return curr;
+}
+
+struct lline {
+ struct lline *next;
+ int len;
+ unsigned long parent_map;
+ char line[FLEX_ARRAY];
+};
+
+struct sline {
+ struct lline *lost_head, **lost_tail;
+ char *bol;
+ int len;
+ unsigned long flag;
+};
+
+static char *grab_blob(const unsigned char *sha1, unsigned long *size)
+{
+ char *blob;
+ char type[20];
+ if (!memcmp(sha1, null_sha1, 20)) {
+ /* deleted blob */
+ *size = 0;
+ return xcalloc(1, 1);
+ }
+ blob = read_sha1_file(sha1, type, size);
+ if (strcmp(type, "blob"))
+ die("object '%s' is not a blob!", sha1_to_hex(sha1));
+ return blob;
+}
+
+#define TMPPATHLEN 50
+#define MAXLINELEN 10240
+
+static void write_to_temp_file(char *tmpfile, void *blob, unsigned long size)
+{
+ int fd = git_mkstemp(tmpfile, TMPPATHLEN, ".diff_XXXXXX");
+ if (fd < 0)
+ die("unable to create temp-file");
+ if (write(fd, blob, size) != size)
+ die("unable to write temp-file");
+ close(fd);
+}
+
+static void write_temp_blob(char *tmpfile, const unsigned char *sha1)
+{
+ unsigned long size;
+ void *blob;
+ blob = grab_blob(sha1, &size);
+ write_to_temp_file(tmpfile, blob, size);
+ free(blob);
+}
+
+static int parse_num(char **cp_p, unsigned int *num_p)
+{
+ char *cp = *cp_p;
+ unsigned int num = 0;
+ int read_some;
+
+ while ('0' <= *cp && *cp <= '9')
+ num = num * 10 + *cp++ - '0';
+ if (!(read_some = cp - *cp_p))
+ return -1;
+ *cp_p = cp;
+ *num_p = num;
+ return 0;
+}
+
+static int parse_hunk_header(char *line, int len,
+ unsigned int *ob, unsigned int *on,
+ unsigned int *nb, unsigned int *nn)
+{
+ char *cp;
+ cp = line + 4;
+ if (parse_num(&cp, ob)) {
+ bad_line:
+ return error("malformed diff output: %s", line);
+ }
+ if (*cp == ',') {
+ cp++;
+ if (parse_num(&cp, on))
+ goto bad_line;
+ }
+ else
+ *on = 1;
+ if (*cp++ != ' ' || *cp++ != '+')
+ goto bad_line;
+ if (parse_num(&cp, nb))
+ goto bad_line;
+ if (*cp == ',') {
+ cp++;
+ if (parse_num(&cp, nn))
+ goto bad_line;
+ }
+ else
+ *nn = 1;
+ return -!!memcmp(cp, " @@", 3);
+}
+
+static void append_lost(struct sline *sline, int n, const char *line)
+{
+ struct lline *lline;
+ int len = strlen(line);
+ unsigned long this_mask = (1UL<<n);
+ if (line[len-1] == '\n')
+ len--;
+
+ /* Check to see if we can squash things */
+ if (sline->lost_head) {
+ struct lline *last_one = NULL;
+ /* We cannot squash it with earlier one */
+ for (lline = sline->lost_head;
+ lline;
+ lline = lline->next)
+ if (lline->parent_map & this_mask)
+ last_one = lline;
+ lline = last_one ? last_one->next : sline->lost_head;
+ while (lline) {
+ if (lline->len == len &&
+ !memcmp(lline->line, line, len)) {
+ lline->parent_map |= this_mask;
+ return;
+ }
+ lline = lline->next;
+ }
+ }
+
+ lline = xmalloc(sizeof(*lline) + len + 1);
+ lline->len = len;
+ lline->next = NULL;
+ lline->parent_map = this_mask;
+ memcpy(lline->line, line, len);
+ lline->line[len] = 0;
+ if (sline->lost_head)
+ *(sline->lost_tail) = lline;
+ else
+ sline->lost_head = lline;
+ sline->lost_tail = &lline->next;
+}
+
+static void combine_diff(const unsigned char *parent, const char *ourtmp,
+ struct sline *sline, int cnt, int n)
+{
+ FILE *in;
+ char parent_tmp[TMPPATHLEN];
+ char cmd[TMPPATHLEN * 2 + 1024];
+ char line[MAXLINELEN];
+ unsigned int lno, ob, on, nb, nn;
+ unsigned long pmask = ~(1UL << n);
+ struct sline *lost_bucket = NULL;
+
+ write_temp_blob(parent_tmp, parent);
+ sprintf(cmd, "diff --unified=0 -La/x -Lb/x '%s' '%s'",
+ parent_tmp, ourtmp);
+ in = popen(cmd, "r");
+ if (!in)
+ return;
+
+ lno = 1;
+ while (fgets(line, sizeof(line), in) != NULL) {
+ int len = strlen(line);
+ if (5 < len && !memcmp("@@ -", line, 4)) {
+ if (parse_hunk_header(line, len,
+ &ob, &on, &nb, &nn))
+ break;
+ lno = nb;
+ if (!nb) {
+ /* @@ -1,2 +0,0 @@ to remove the
+ * first two lines...
+ */
+ nb = 1;
+ }
+ lost_bucket = &sline[nb-1]; /* sline is 0 based */
+ continue;
+ }
+ if (!lost_bucket)
+ continue;
+ switch (line[0]) {
+ case '-':
+ append_lost(lost_bucket, n, line+1);
+ break;
+ case '+':
+ sline[lno-1].flag &= pmask;
+ lno++;
+ break;
+ }
+ }
+ fclose(in);
+ unlink(parent_tmp);
+}
+
+static unsigned long context = 3;
+static char combine_marker = '@';
+
+static int interesting(struct sline *sline, unsigned long all_mask)
+{
+ return ((sline->flag & all_mask) != all_mask || sline->lost_head);
+}
+
+static void make_hunks(struct sline *sline, unsigned long cnt, int num_parent)
+{
+ unsigned long all_mask = (1UL<<num_parent) - 1;
+ unsigned long mark = (1UL<<num_parent);
+ unsigned long i;
+
+ i = 0;
+ while (i < cnt) {
+ if (interesting(&sline[i], all_mask)) {
+ unsigned long j = (context < i) ? i - context : 0;
+ while (j <= i)
+ sline[j++].flag |= mark;
+ while (++i < cnt) {
+ if (!interesting(&sline[i], all_mask))
+ break;
+ sline[i].flag |= mark;
+ }
+ j = (i + context < cnt) ? i + context : cnt;
+ while (i < j)
+ sline[i++].flag |= mark;
+ continue;
+ }
+ i++;
+ }
+}
+
+static void dump_sline(struct sline *sline, int cnt, int num_parent)
+{
+ unsigned long mark = (1UL<<num_parent);
+ int i;
+ int lno = 0;
+
+ while (1) {
+ struct sline *sl = &sline[lno];
+ int hunk_end;
+ while (lno < cnt && !(sline[lno].flag & mark))
+ lno++;
+ if (cnt <= lno)
+ break;
+ for (hunk_end = lno + 1; hunk_end < cnt; hunk_end++)
+ if (!(sline[hunk_end].flag & mark))
+ break;
+ for (i = 0; i <= num_parent; i++) putchar(combine_marker);
+ printf(" +%d,%d ", lno+1, hunk_end-lno);
+ for (i = 0; i <= num_parent; i++) putchar(combine_marker);
+ putchar('\n');
+ while (lno < hunk_end) {
+ struct lline *ll;
+ int j;
+ sl = &sline[lno++];
+ ll = sl->lost_head;
+ while (ll) {
+ for (j = 0; j < num_parent; j++) {
+ if (ll->parent_map & (1UL<<j))
+ putchar('-');
+ else
+ putchar(' ');
+ }
+ putchar(' ');
+ puts(ll->line);
+ ll = ll->next;
+ }
+ for (j = 0; j < num_parent; j++) {
+ if ((1UL<<j) & sl->flag)
+ putchar(' ');
+ else
+ putchar('+');
+ }
+ printf(" %.*s\n", sl->len, sl->bol);
+ }
+ }
+}
+
+static void show_combined_diff(struct path_list *elem, int num_parent)
+{
+ unsigned long size, cnt, lno;
+ char *result, *cp, *ep;
+ struct sline *sline; /* survived lines */
+ int i;
+ char ourtmp[TMPPATHLEN];
+
+ /* Read the result of merge first */
+ result = grab_blob(elem->sha1, &size);
+ write_to_temp_file(ourtmp, result, size);
+
+ for (cnt = 0, cp = result; cp - result < size; cp++) {
+ if (*cp == '\n')
+ cnt++;
+ }
+ if (result[size-1] != '\n')
+ cnt++; /* incomplete line */
+
+ sline = xcalloc(cnt, sizeof(*sline));
+ ep = result;
+ sline[0].bol = result;
+ for (lno = 0, cp = result; cp - result < size; cp++) {
+ if (*cp == '\n') {
+ sline[lno].len = cp - sline[lno].bol;
+ sline[lno].flag = (1UL<<num_parent) - 1;
+ lno++;
+ if (lno < cnt)
+ sline[lno].bol = cp + 1;
+ }
+ }
+ if (result[size-1] != '\n') {
+ sline[cnt-1].len = size - (sline[cnt-1].bol - result);
+ sline[cnt-1].flag = (1UL<<num_parent) - 1;
+ }
+
+ for (i = 0; i < num_parent; i++)
+ combine_diff(elem->parent_sha1[i], ourtmp, sline, cnt, i);
+
+ make_hunks(sline, cnt, num_parent);
+
+ dump_sline(sline, cnt, num_parent);
+ unlink(ourtmp);
+ free(result);
+
+ for (i = 0; i < cnt; i++) {
+ if (sline[i].lost_head) {
+ struct lline *ll = sline[i].lost_head;
+ while (ll) {
+ struct lline *tmp = ll;
+ ll = ll->next;
+ free(tmp);
+ }
+ }
+ }
+ free(sline);
+}
+
+int diff_tree_combined_merge(const unsigned char *sha1,
+ const char *header, int show_empty_merge)
+{
+ struct commit *commit = lookup_commit(sha1);
+ struct diff_options diffopts;
+ struct commit_list *parents;
+ struct path_list *p, *paths = NULL;
+ int num_parent, i, num_paths;
+
+ diff_setup(&diffopts);
+ diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
+ diffopts.recursive = 1;
+
+ /* count parents */
+ for (parents = commit->parents, num_parent = 0;
+ parents;
+ parents = parents->next, num_parent++)
+ ; /* nothing */
+
+ /* find set of paths that everybody touches */
+ for (parents = commit->parents, i = 0;
+ parents;
+ parents = parents->next, i++) {
+ struct commit *parent = parents->item;
+ diff_tree_sha1(parent->object.sha1, commit->object.sha1, "",
+ &diffopts);
+ paths = intersect_paths(paths, i, num_parent);
+ diff_flush(&diffopts);
+ }
+
+ /* find out surviving paths */
+ for (num_paths = 0, p = paths; p; p = p->next) {
+ if (p->len)
+ num_paths++;
+ }
+ if (num_paths || show_empty_merge) {
+ puts(header);
+ for (p = paths; p; p = p->next) {
+ if (!p->len)
+ continue;
+ printf("diff --combined ");
+ if (quote_c_style(p->path, NULL, NULL, 0))
+ quote_c_style(p->path, NULL, stdout, 0);
+ else
+ printf("%s", p->path);
+ putchar('\n');
+ show_combined_diff(p, num_parent);
+ }
+ }
+
+ /* Clean things up */
+ while (paths) {
+ struct path_list *tmp = paths;
+ paths = paths->next;
+ free(tmp);
+ }
+ return 0;
+}
diff --git a/diff-tree.c b/diff-tree.c
index efa2b94..0c68936 100644
--- a/diff-tree.c
+++ b/diff-tree.c
@@ -6,6 +6,8 @@ static int show_root_diff = 0;
static int no_commit_id = 0;
static int verbose_header = 0;
static int ignore_merges = 1;
+static int show_empty_combined = 0;
+static int combine_merges = 0;
static int read_stdin = 0;
static const char *header = NULL;
@@ -79,9 +81,13 @@ static const char *generate_header(const
offset = sprintf(this_header, "%s%s ",
header_prefix,
diff_unique_abbrev(commit_sha1, abbrev));
- offset += sprintf(this_header + offset, "(from %s)\n",
- parent_sha1 ?
- diff_unique_abbrev(parent_sha1, abbrev) : "root");
+ if (commit_sha1 != parent_sha1)
+ offset += sprintf(this_header + offset, "(from %s)\n",
+ parent_sha1
+ ? diff_unique_abbrev(parent_sha1, abbrev)
+ : "root");
+ else
+ offset += sprintf(this_header + offset, "(from parents)\n");
offset += pretty_print_commit(commit_format, msg, len,
this_header + offset,
sizeof(this_header) - offset);
@@ -108,8 +114,16 @@ static int diff_tree_commit(const unsign
}
/* More than one parent? */
- if (ignore_merges && commit->parents && commit->parents->next)
- return 0;
+ if (commit->parents && commit->parents->next) {
+ if (ignore_merges)
+ return 0;
+ else if (combine_merges) {
+ header = generate_header(sha1, sha1,
+ commit->buffer);
+ return diff_tree_combined_merge(sha1, header,
+ show_empty_combined);
+ }
+ }
for (parents = commit->parents; parents; parents = parents->next) {
struct commit *parent = parents->item;
@@ -154,7 +168,7 @@ static int diff_tree_stdin(char *line)
}
static const char diff_tree_usage[] =
-"git-diff-tree [--stdin] [-m] [-s] [-v] [--pretty] [-t] [-r] [--root] "
+"git-diff-tree [--stdin] [-m] [-c] [-s] [-v] [--pretty] [-t] [-r] [--root] "
"[<common diff options>] <tree-ish> [<tree-ish>] [<path>...]\n"
" -r diff recursively\n"
" --root include the initial commit as diff against /dev/null\n"
@@ -217,6 +231,10 @@ int main(int argc, const char **argv)
ignore_merges = 0;
continue;
}
+ if (!strcmp(arg, "-c")) {
+ combine_merges = 1;
+ continue;
+ }
if (!strcmp(arg, "-v")) {
verbose_header = 1;
header_prefix = "diff-tree ";
@@ -245,6 +263,12 @@ int main(int argc, const char **argv)
if (diff_options.output_format == DIFF_FORMAT_PATCH)
diff_options.recursive = 1;
+ if (combine_merges) {
+ diff_options.output_format = DIFF_FORMAT_PATCH;
+ show_empty_combined = !ignore_merges;
+ ignore_merges = 0;
+ }
+
diff_tree_setup_paths(get_pathspec(prefix, argv));
diff_setup_done(&diff_options);
diff --git a/diff.h b/diff.h
index 5696f2a..081234c 100644
--- a/diff.h
+++ b/diff.h
@@ -56,6 +56,8 @@ extern int diff_tree(struct tree_desc *t
extern int diff_tree_sha1(const unsigned char *old, const unsigned char *new,
const char *base, struct diff_options *opt);
+extern int diff_tree_combined_merge(const unsigned char *sha1, const char *, int);
+
extern void diff_addremove(struct diff_options *,
int addremove,
unsigned mode,
--
1.1.4.g869a
^ permalink raw reply related
* Re: [PATCH] Parametrize asciidoc and add --unsafe
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <1138140946.19065.2.camel@dv>
Pavel Roskin <proski@gnu.org> writes:
> Including files from the parent directory is considered unsafe by
> asciidoc 7.1.0. This is used in git.txt, which includes ../README.
Is copying/linking README down when we build documentation a
more conservative option, I wonder?
Does asciidoc prior to 7.1.0 do sensible thing given an --unsafe
option? If not, how does one override ASCIIDOC from the command
line to the toplevel "make"?
^ permalink raw reply
* Re: [QUESTION] What is a tag for?
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: Andreas Ericsson; +Cc: git
In-Reply-To: <43CE8DFB.9070004@op5.se>
Andreas Ericsson <ae@op5.se> writes:
> I'll apply (and test) Linus suggestions of new refs and re-send it
> when I'm done watching King-Kong and stuffing my face with popcorn.
It appears you have not finished watching the movie yet, so I
took the liberty of adding this on top of your patch myself
;-).
^ permalink raw reply
* Re: [PATCH] use "git <command>" instead of "git-<command>"
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: Uwe Zeisberger; +Cc: git
In-Reply-To: <20060124105224.GA6765@informatik.uni-freiburg.de>
Uwe Zeisberger <zeisberg@informatik.uni-freiburg.de> writes:
> Otherwise installations with gitexecdir != bindir are not able
> to determine the right version.
True, but this part
> -VN=$(git-describe --abbrev=4 HEAD 2>/dev/null | sed -e 's/-/./g') ||
> +VN=$(git describe --abbrev=4 HEAD 2>/dev/null | sed -e 's/-/./g') ||
>...
has a subtle issue, which the commit 026351a addresses, which
will hopefully become a non-issue given enough time. Then it
would be safe to make this change.
Of course, if/when I change the main Makefile to have different
gitexecdir and bindir by default, it would become "my problem",
but until then...
> -dirty=$(sh -c 'git-diff-index --name-only HEAD' 2>/dev/null) || dirty=
> +dirty=$(sh -c 'git diff-index --name-only HEAD' 2>/dev/null) || dirty=
On the other hand, your patch is correct for this part. The
issue 026351a commit addressed does not apply. An ancient 'git'
that did not have 'diff-index' (it was called 'diff-cache')
would have hit a breakage early on since 'describe' did not
exist back then.
^ permalink raw reply
* Re: git-ls-files in subdirectories ignore higher-up .gitignore
From: Junio C Hamano @ 2006-01-25 2:08 UTC (permalink / raw)
To: Pavel Roskin; +Cc: git
In-Reply-To: <1138125570.24415.11.camel@dv>
Pavel Roskin <proski@gnu.org> writes:
> This can be demonstrated in git's own repository:
>
> $ touch t/test.o
> $ git-ls-files --others --exclude-per-directory=.gitignore
> $ cd t
> $ git-ls-files --others --exclude-per-directory=.gitignore
> test.o
> $
>
> Before I attempt to fix it, I'd like to make sure it's a bug, not a
> feature.
I am not sure if that is a bug or a feature, but you are right.
We do not bother to go uplevel and look for .gitignore in the
current code.
It would probably be a welcome addition if your fix made these
two sequences work similarly modulo leading paths from the
command output. I think it is natural to expect they are moral
equivalents:
(Sequence 1)
$ touch t/test.o t/garbage
$ git-ls-files -o --exclude-per-directory=.gitignore t/
(Sequence 2)
$ touch t/test.o t/garbage
$ cd t
$ git-ls-files -o --exclude-per-directory=.gitignore
^ permalink raw reply
* Re: [PATCH] diff-tree -c: show a merge commit a bit more sensibly.
From: Linus Torvalds @ 2006-01-24 22:15 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vwtgqas0y.fsf@assigned-by-dhcp.cox.net>
On Tue, 24 Jan 2006, Junio C Hamano wrote:
>
> A new option '-c' to diff-tree changes the way a merge commit is
> displayed when generating a patch output. It shows a "combined
> diff" (hence the option letter 'c'), which looks like this:
Thank you!
Can you make this the default for "git-whatchanged" too? That way, merges
that have manual fixups will actually show up in the whatchanged output.
Also, it would be perhaps even nicer if it had a "dense" version, which
only showed the chunks that had differences from more than one parent.
Chunks that have diffs from just one parent obviously had no conflicts in
that chunk, so they are much less interesting than a chunk that was
different from more than one parent..
Linus
^ permalink raw reply
* [PATCH] Parametrize asciidoc and add --unsafe
From: Pavel Roskin @ 2006-01-24 22:15 UTC (permalink / raw)
To: git
Including files from the parent directory is considered unsafe by
asciidoc 7.1.0. This is used in git.txt, which includes ../README.
Since git is developed openly, we shouldn't be afraid of exploits
lurking in the docs. Create a make variable ASCIIDOC and use it to
always call asciidoc with the --unsafe option.
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
Documentation/Makefile | 12 +++++++-----
1 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/Documentation/Makefile b/Documentation/Makefile
index a65fb1b..391f583 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -28,6 +28,8 @@ man7=$(mandir)/man7
INSTALL?=install
+ASCIIDOC = asciidoc --unsafe
+
#
# Please note that there is a minor bug in asciidoc.
# The version after 6.0.3 _will_ include the patch found here:
@@ -69,20 +71,20 @@ clean:
rm -f *.xml *.html *.1 *.7 howto-index.txt howto/*.html doc.dep
%.html : %.txt
- asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
+ $(ASCIIDOC) -b xhtml11 -d manpage -f asciidoc.conf $<
%.1 %.7 : %.xml
xmlto man $<
%.xml : %.txt
- asciidoc -b docbook -d manpage -f asciidoc.conf $<
+ $(ASCIIDOC) -b docbook -d manpage -f asciidoc.conf $<
git.html: git.txt ../README
glossary.html : glossary.txt sort_glossary.pl
cat $< | \
perl sort_glossary.pl | \
- asciidoc -b xhtml11 - > glossary.html
+ $(ASCIIDOC) -b xhtml11 - > glossary.html
howto-index.txt: howto-index.sh $(wildcard howto/*.txt)
rm -f $@+ $@
@@ -90,13 +92,13 @@ howto-index.txt: howto-index.sh $(wildca
mv $@+ $@
$(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt
- asciidoc -b xhtml11 $*.txt
+ $(ASCIIDOC) -b xhtml11 $*.txt
WEBDOC_DEST = /pub/software/scm/git/docs
$(patsubst %.txt,%.html,$(wildcard howto/*.txt)): %.html : %.txt
rm -f $@+ $@
- sed -e '1,/^$$/d' $? | asciidoc -b xhtml11 - >$@+
+ sed -e '1,/^$$/d' $? | $(ASCIIDOC) -b xhtml11 - >$@+
mv $@+ $@
install-webdoc : html
--
Regards,
Pavel Roskin
^ permalink raw reply related
* [PATCH] stg export: check if there are any patches to export
From: Pavel Roskin @ 2006-01-24 21:25 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git
Otherwise, stg export fails with "list index out of range"
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
stgit/commands/export.py | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/stgit/commands/export.py b/stgit/commands/export.py
index 096fb68..b8ca133 100644
--- a/stgit/commands/export.py
+++ b/stgit/commands/export.py
@@ -124,6 +124,9 @@ def func(parser, options, args):
patches = applied[start_idx:stop_idx]
num = len(patches)
+ if num == 0:
+ raise CmdException, 'No patches applied'
+
zpadding = len(str(num))
if zpadding < 2:
zpadding = 2
--
Regards,
Pavel Roskin
^ permalink raw reply related
* Re: StGIT: "stg new" vs "stg new --force"
From: Catalin Marinas @ 2006-01-24 21:23 UTC (permalink / raw)
To: Pavel Roskin; +Cc: J. Bruce Fields, Yann Dirson, git, Charles Lever
In-Reply-To: <1138126671.24415.28.camel@dv>
On 24/01/06, Pavel Roskin <proski@gnu.org> wrote:
> Seriously, it would be nice to have an editor that would allow to edit
> the patch and see the resulting file and vice versa. Maybe emacs could
> be hacked to do it.
I think emacs has some basic support via ediff-merge or smerge but
it's difficult to integrate it with StGIT. Refreshing a patch with
StGIT means updating the GIT index files with the latest changes in
the working directory, save the index and create a commit object
pointing to it.
--
Catalin
^ permalink raw reply
* StGIT: defaults for authname, authemail
From: Andrey Borzenkov @ 2006-01-24 19:13 UTC (permalink / raw)
To: git
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Would be nice if StGIT honored GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL if they are
set and took them as default. Would be more plug'n'play, I was rather
surprised why stg export gave me From: <>.
I have zero python knowledge to make a patch, sorry.
regards
- -andrey
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFD1nxgR6LMutpd94wRAkQ5AJ0ZU3bc1mCu7Cx3XsNYoAleZU9E0wCfXyVF
VM310OOCMkiXEe0HWsE1CtI=
=tfhC
-----END PGP SIGNATURE-----
^ permalink raw reply
* Re: StGIT: "stg new" vs "stg new --force"
From: Pavel Roskin @ 2006-01-24 18:17 UTC (permalink / raw)
To: J. Bruce Fields; +Cc: Yann Dirson, Catalin Marinas, git, Charles Lever
In-Reply-To: <20060124175443.GA29670@fieldses.org>
On Tue, 2006-01-24 at 12:54 -0500, J. Bruce Fields wrote:
> On Tue, Jan 24, 2006 at 12:30:23AM -0500, Pavel Roskin wrote:
> > On Fri, 2006-01-20 at 13:22 -0500, J. Bruce Fields wrote:
> > > I tend to use stg refresh -es as a quick (well, not quite as quick as
> > > I'd like) way to look at the current patch. Often I leave it up while
> > > I'm working (editing the patched files). So if exiting from stg refresh
> > > -es suddenly started overwriting my working files, I'd be very
> > > unhappy....
> >
> > If I understand correctly, "stg refresh" only modifies the repository,
> > not the files in the local directory.
>
> Well, yeah, but the reason that makes sense is that it's modifying the
> repository to bring it up to date with the working directory.
Yes. As it stands now, the update is made using the local state after
editing. If the patch becomes editable, the update will use the local
state before editing. It would still fit the original semantic as you
described it.
> > This shouldn't change.
>
> So after you hand-edit the diff and exit "stg refresh -es", the top of
> the current patch will no longer agree with the state of the working
> directory. What are you going to do on the next refresh?
Put remaining changes to the repository.
> Or on the
> next push or pop?
Right now - protest loudly about local changes. In the future - proceed
cautiously if there are no conflicts.
> This seems a little confusing.
Try removing the whole repository while "stg refresh" is running. THAT
would be confusing :-)
Seriously, it would be nice to have an editor that would allow to edit
the patch and see the resulting file and vice versa. Maybe emacs could
be hacked to do it.
--
Regards,
Pavel Roskin
^ permalink raw reply
* git-ls-files in subdirectories ignore higher-up .gitignore
From: Pavel Roskin @ 2006-01-24 17:59 UTC (permalink / raw)
To: git
Hello!
git-ls-files appears to behave in a way that may be unexpected to the
users. When run in a subdirectory, git-ls-files never reads .gitignore
or whatever is specified by --exclude-per-directory in the parent
directories.
This can be demonstrated in git's own repository:
$ touch t/test.o
$ git-ls-files --others --exclude-per-directory=.gitignore
$ cd t
$ git-ls-files --others --exclude-per-directory=.gitignore
test.o
$
Before I attempt to fix it, I'd like to make sure it's a bug, not a
feature.
--
Regards,
Pavel Roskin
^ permalink raw reply
* Re: StGIT: "stg new" vs "stg new --force"
From: J. Bruce Fields @ 2006-01-24 17:54 UTC (permalink / raw)
To: Pavel Roskin; +Cc: Yann Dirson, Catalin Marinas, git, Charles Lever
In-Reply-To: <1138080623.15105.51.camel@dv>
On Tue, Jan 24, 2006 at 12:30:23AM -0500, Pavel Roskin wrote:
> On Fri, 2006-01-20 at 13:22 -0500, J. Bruce Fields wrote:
> > I tend to use stg refresh -es as a quick (well, not quite as quick as
> > I'd like) way to look at the current patch. Often I leave it up while
> > I'm working (editing the patched files). So if exiting from stg refresh
> > -es suddenly started overwriting my working files, I'd be very
> > unhappy....
>
> If I understand correctly, "stg refresh" only modifies the repository,
> not the files in the local directory.
Well, yeah, but the reason that makes sense is that it's modifying the
repository to bring it up to date with the working directory.
> This shouldn't change.
So after you hand-edit the diff and exit "stg refresh -es", the top of
the current patch will no longer agree with the state of the working
directory. What are you going to do on the next refresh? Or on the
next push or pop? This seems a little confusing.
--b.
^ permalink raw reply
* [PATCH] cg-clean shouldn't clean untracked directories without -d
From: Pavel Roskin @ 2006-01-24 17:17 UTC (permalink / raw)
To: Petr Baudis, git
Use the new squashdirs argument in list_untracked_files() to treat
untracked directories and their contents as a whole. Remove a separate
pass to find untracked directories. Adjust the testsuite accordingly.
Don't change IFS - it's no longer needed.
Signed-off-by: Pavel Roskin <proski@gnu.org>
---
cg-clean | 103 +++++++++++++-----------------------------------------
t/t9400-clean.sh | 3 +-
2 files changed, 25 insertions(+), 81 deletions(-)
diff --git a/cg-clean b/cg-clean
index b40b41b..fc6767d 100755
--- a/cg-clean
+++ b/cg-clean
@@ -53,88 +53,33 @@ done
[ ${#ARGS[*]} = 0 ] || usage
+list_untracked_files "$noexclude" squashdirs | tr '\0' '\n' |
+(cd "${_git_relpath-.}" &&
+while read -r file; do
+ if [ -z "$_git_relpath" ] || [ x"${file#$_git_relpath}" != x"$file" ]; then
+ file="${file#$_git_relpath}"
+ else
+ continue
+ fi
-clean_dirs()
-{
- dirlist="$(mktemp -t gitlsfiles.XXXXXX)"
- git-ls-files --cached |
- sed -n 's|/[^/]*$||p' |
- while IFS=$'\n' read -r dir; do
- while true; do
- echo "$dir"
- updir="${dir%/*}"
- [ "$dir" = "$updir" ] && break
- dir="$updir"
- done
- done |
- sort -u >"$dirlist"
-
- save_IFS="$IFS"
- IFS=$'\n'
-
- find ./ -type d -print |
- sed 's/^\.\///;/^$/d;/^\.git$/d;/^\.git\//d' |
- cat - "$dirlist" | sort -u |
- diff - "$dirlist" |
- sed -n 's/< //p' |
- while read -r dir; do
- if [ ! -d "$dir" ]; then
- # Perhaps directory was removed with its parent
- continue
- fi
+ if [ -d "$file" -a ! -L "$file" ]; then
if [ -z "$cleandir" ]; then
- echo "Not removing $dir/"
+ echo "Not removing $file/"
continue
fi
- [ "$quiet" ] || echo "Removing $dir/"
+ [ "$quiet" ] || echo "Removing $file/"
if [ "$cleandirhard" ]; then
- chmod -R 700 "$dir"
- fi
- $rm -rf "$dir"
- if [ -e "$dir" -o -L "$dir" ]; then
- echo "Cannot remove $dir/"
- fi
- done
-
- IFS="$save_IFS"
- rm "$dirlist"
-}
-
-clean_files()
-{
- save_IFS="$IFS"
- IFS=$'\n'
-
- list_untracked_files "$noexclude" nosquashdirs | tr '\0' '\n' |
- (cd "${_git_relpath-.}" &&
- while read -r file; do
- if [ -z "$_git_relpath" ] || [ x"${file#$_git_relpath}" != x"$file" ]; then
- file="${file#$_git_relpath}"
- else
- continue
- fi
-
- if [ -d "$file" -a ! -L "$file" ]; then
- # Sanity check, shouldn't happen
- echo "FATAL: cg-status reports directories (internal error)" >&2
- exit 1
- elif [ -e "$file" -o -L "$file" ]; then
- [ "$quiet" ] || echo "Removing $file"
- "$rm" -f "$file"
- # rm would complain itself on failure
- else
- echo "File $file has disappeared!"
+ chmod -R 700 "$file"
fi
- done)
-
- IFS="$save_IFS"
-}
-
-
-# Even if -d or -D is not specified, we want to tell user about
-# directories that are not removed
-if [ -z "$quiet" -o "$cleandir" ]; then
- ( cd "${_git_relpath-.}" && clean_dirs )
-fi
-
-clean_files
+ $rm -rf "$file"
+ if [ -e "$file" -o -L "$file" ]; then
+ echo "Cannot remove $file/"
+ fi
+ elif [ -e "$file" -o -L "$file" ]; then
+ [ "$quiet" ] || echo "Removing $file"
+ "$rm" -f "$file"
+ # rm would complain itself on failure
+ else
+ echo "File $file has disappeared!"
+ fi
+done)
diff --git a/t/t9400-clean.sh b/t/t9400-clean.sh
index 47ae0dc..98801c5 100755
--- a/t/t9400-clean.sh
+++ b/t/t9400-clean.sh
@@ -84,10 +84,8 @@ echo "ign file 3" >"repo dir/ign file 3.
echo "ign file 4" >"repo dir/ign file 4.ign1"
mklist init
-# FIXME: cg-clean shouldn't clean unknown directories without "-d"
loss='extra file 1
ign file 2.ign1
-extra dir 1/extra file 3
repo dir/extra file 2'
test_expect_success 'cg-clean in top-level dir' \
"(cg-clean && check_loss)"
@@ -99,6 +97,7 @@ test_expect_success 'cg-clean -x in top-
"(cg-clean -x && check_loss)"
loss='extra dir 1
+extra dir 1/extra file 3
repo dir/extra dir 2'
test_expect_success 'cg-clean -d in top-level dir' \
"(cg-clean -d && check_loss)"
--
Regards,
Pavel Roskin
^ 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