Git development
 help / color / mirror / Atom feed
* Re: git-rev-list bug?
From: Linus Torvalds @ 2006-03-10 18:31 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Catalin Marinas
In-Reply-To: <7vslpqy4u7.fsf@assigned-by-dhcp.cox.net>



On Fri, 10 Mar 2006, Junio C Hamano wrote:
> 
> So we would need a combination of both, something like this?

Looks good to me.

As does the 'revs.prune_fn' abstraction by Fredrik Kuivinen, for that 
matter. Ack to both.

		Linus

^ permalink raw reply

* Re: bug?: stgit creates (unneccessary?) conflicts when pulling
From: Shawn Pearce @ 2006-03-10 16:23 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git
In-Reply-To: <b0943d9e0603091400o2cd0291h@mail.gmail.com>

Catalin Marinas <catalin.marinas@gmail.com> wrote:
> On 01/03/06, Shawn Pearce <spearce@spearce.org> wrote:
> > Speaking of making StGIT faster: earlier we were talking about how
> > git-diff|git-apply is faster than a 3 way git-read-tree on large
> > merges when there are many structural changes in the tree due to
> > the smaller number of process spawns required.
> >
> > You might want to take a look at pg--merge-all: This is sort of based
> > on git-merge-recursive, but I've gotten it down to just a handful
> > of process spawns, aside from the stupidity of git-checkout-index.
> 
> Trying to implement this, I've just noticed that git-read-tree has a
> --aggressive option which takes care of the file removals. Adding this
> option lowered the pushing time in StGIT from ~2 min to under 2
> seconds (merges between 2.6.14 and the latest kernel). There's
> probably no need to deal with file removals in pg--merge-all anymore.


Thanks for the heads up.  I'll have to add that in.  In case you
didn't notice the list traffic I have added a --stage=all switch to
git-checkout-index to grab into temporary files all unmerged stages.

I'm still working on integrating that into pg--merge-all but the
idea is to save on the fork/exec of git-unpack-file when I get into
the diff portion of the merge process.  At least on Cygwin (a place
where I'm really using pg) it will save time as the forks are so
expensive there.  Linux users may not see any improvement from it.

I also added --stdin to git-checkout-index but pg--merge-all is
still using xargs.  I just haven't had time to convert it over and
push it up to my public repo.  Hopefully I'll get both of those
done this weekend.

I've started to get busy with an Eclipse plugin for GIT so my work
with pg is likely going to slow down a little (besides its doing
most of what I need at this point).  But the next thing I was going
to try to add to GIT to boost pg's performance was to integrate
a diff library, so we aren't forking out a diff process for every
file we need to extract a diff for.

-- 
Shawn.

^ permalink raw reply

* [PATCH 4/4] Add quick reference
From: Jonas Fonseca @ 2006-03-10 14:48 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20060310144106.GA7920@diku.dk>

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

---

 If someone wants to have a look, I've put it here:
 http://www.diku.dk/hjemmesider/studerende/fonseca/cg-ref.pdf

 Documentation/Makefile             |    9 ++-
 Documentation/asciidoc.conf        |    4 +
 Documentation/make-cg-ref-asciidoc |   61 +++++++++++++++++++
 Documentation/quick-reference.txt  |  114 ++++++++++++++++++++++++++++++++++++
 4 files changed, 185 insertions(+), 3 deletions(-)

diff --git a/Documentation/Makefile b/Documentation/Makefile
index d316a14..439d20f 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -4,14 +4,14 @@ CG_SRC=$(filter-out $(CG_IGNORE), $(wild
 PACKAGE=cogito
 
 MAN1_TXT=$(patsubst ../cg%,cg%.1.txt,$(CG_SRC))
-MAN7_TXT=$(PACKAGE).7.txt
+MAN7_TXT=$(PACKAGE).7.txt cg-ref.7.txt
 
-DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) introduction.html
+DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) quick-reference.html introduction.html
 
 DOC_MAN1=$(patsubst %.txt,%,$(MAN1_TXT))
 DOC_MAN7=$(patsubst %.txt,%,$(MAN7_TXT))
 
-DOC_PDF=$(patsubst %.txt,%.pdf,$(MAN1_TXT) $(MAN7_TXT)) introduction.pdf
+DOC_PDF=$(patsubst %.txt,%.pdf,$(MAN1_TXT) $(MAN7_TXT)) quick-reference.pdf introduction.pdf
 
 prefix=$(HOME)
 bin=$(prefix)/bin
@@ -100,6 +100,9 @@ introduction.xml: ../README
 $(PACKAGE).7.txt : make-$(PACKAGE)-asciidoc
 	./make-$(PACKAGE)-asciidoc > $@
 
+cg-ref.7.txt : quick-reference.txt make-cg-ref-asciidoc
+	CGPACKAGE=$(PACKAGE) ./make-cg-ref-asciidoc $< > $@
+
 # It seems that cg%.txt won't match this so use an explicit rule
 cg.1.txt : ../cg make-cg-asciidoc
 	CGPACKAGE=$(PACKAGE) ./make-cg-asciidoc $< > $@
diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf
index baefb2f..69f1646 100644
--- a/Documentation/asciidoc.conf
+++ b/Documentation/asciidoc.conf
@@ -19,3 +19,7 @@ ifdef::backend-xhtml11[]
 [gitlink-inlinemacro]
 <a href="{target}.html">{target}{0?({0})}</a>
 endif::backend-xhtml11[]
+
+[attributes]
+# Five non breaking spaces used for option indentation in the quick reference
+cg-refopt=&#160;&#160;&#160;&#160;&#160;
diff --git a/Documentation/make-cg-ref-asciidoc b/Documentation/make-cg-ref-asciidoc
new file mode 100755
index 0000000..7fd60ca
--- /dev/null
+++ b/Documentation/make-cg-ref-asciidoc
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+#
+# Generate asciidoc manpage markup from Cogito quick reference file.
+# Copyright (c) Jonas Fonseca, 2006
+#
+# Takes the path to the reference file. Prints the manpage to stdout.
+
+PACKAGE=${CGPACKAGE:-cogito}
+
+ref=$1
+
+cat <<__END__
+cg-ref(7)
+=========
+
+NAME
+----
+cg-ref - Cogito quick reference
+
+SYNOPSIS
+--------
+A list of frequently used commands grouped with related commands.
+
+DESCRIPTION
+-----------
+
+__END__
+
+sed '0,/^$/d' < "$ref" | \
+sed '/^`/d' | \
+sed 's/--/../g' | \
+sed '/frame="none"/,1d' | \
+sed 's/\\$//' | \
+while read line; do
+	if echo "$line" | grep -q '^.*:$'; then
+		echo "$line"
+		echo "$line" | sed "s/[^~]/~/g"
+		echo
+		echo "[verse]"
+	else
+		entry=$(echo "$line" | sed "s/^\([^	]*\)	/\1/")
+		space=$(echo "$entry" | sed "s/[^*']//g" | sed "s/[*']/ /g")
+
+		echo "$line" | sed "s/^\([^	]*\)	/\1$space	/"
+	fi
+done | \
+sed 's/.*cg-refopt} \(-[^	]*\)/    \1        /' | \
+sed "s/[*]\([^*]*\)[*]/\1/g" | \
+sed "s/[']\([^']*\)[']/\1/g"
+
+cat << __END__
+
+COPYRIGHT
+---------
+Copyright (C) Jonas Fonseca, 2006.
+
+SEE ALSO
+--------
+gitlink:cg-ref[7] is part of gitlink:${PACKAGE}[7],
+a toolkit for managing gitlink:git[7] trees.
+__END__
diff --git a/Documentation/quick-reference.txt b/Documentation/quick-reference.txt
new file mode 100644
index 0000000..11c0a13
--- /dev/null
+++ b/Documentation/quick-reference.txt
@@ -0,0 +1,114 @@
+Cogito Quick Reference
+======================
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Getting help:
+------------------------------------------------------------------------------
+*cg help* 'command'		Show help for a command
+*cg* 'command' -h		Show usage summary for a command
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Repository creation:
+------------------------------------------------------------------------------
+*cg init*			Create a repository in the current directory
+*cg clone* 'url'		Clone a remote repository
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+File operations:
+------------------------------------------------------------------------------
+*cg add* 'file'			Add file to the working tree
+*cg add* -r 'directory'		Recursively add files in directory
+*cg rm* 'file'			Remove file or directory from the working tree
+*cg rm* -r 'directory'		Recursively remove files in directory
+{cg-refopt} -f			Delete file from disk
+*cg mv* 'file' 'dest'		Move file or directory to new location
+{cg-refopt} -f			Overwrite existing destination files
+*cg restore* 'file'		Restore file
+{cg-refopt} -r 'rev'		Bring back file from revision (and add it)
+{cg-refopt} -f			Overwrite uncommitted changes
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Examining History:
+------------------------------------------------------------------------------
+*cg log* '[file]'		View commit log
+{cg-refopt} -r 'rev'		Limit to revision range
+{cg-refopt} -f			List affected files
+{cg-refopt} -s			Summarize commits to one line
+*cg diff* '[file]'		Show diff of changes
+{cg-refopt} -r 'rev'		Diff revision instead of working tree
+{cg-refopt} -p			Diff against parent
+{cg-refopt} -s			Show diff stat
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Working tree:
+------------------------------------------------------------------------------
+*cg status* '[file]'		Show branches and status of the working tree
+*cg commit*			Commit the working tree
+{cg-refopt} -m 'message'	Append message to commit log
+*cg admin-uncommit*		Undo commit
+*cg reset*			Reset the working treeUndo commit
+*cg seek* 'rev'			Temporarily switch the working tree
+*cg clean*			Remove file not under revision control
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Remote branches:
+------------------------------------------------------------------------------
+*cg branch-ls*			List remote branches
+*cg branch-add* 'branch' 'url'	Add remote branch
+*cg branch-chg* 'branch' 'url'	Change URL of existing branch
+*cg fetch* 'branch'		Fetch changes from a remote branch
+*cg update* 'branch'		Fetch and merge changes from a remote branch
+*cg push* 'branch'		Push changes to a remote branch
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Local branches:
+------------------------------------------------------------------------------
+*cg merge* 'branch'		Merge changes from branch
+*cg switch* 'branch'		Switch the working tree to branch
+{cg-refopt} -r 'rev'		Create branch from revision
+{cg-refopt} -f			Overwrite existing branch
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Exporting and importing:
+------------------------------------------------------------------------------
+*cg patch*			Apply patch
+*cg mkpatch*			Format a patch with log message and diffstat
+{cg-refopt} -r 'rev'		Limit to revision range
+*cg export* 'directory'		Export "snapshot" to directory
+{cg-refopt} -r 'rev'			
+------------------------------------------------------------------------------
+
+[frame="none"]
+`-------------------------------`---------------------------------------------
+Tags:
+------------------------------------------------------------------------------
+*cg tag* 'name' 'rev'		Create tag for a given revision
+{cg-refopt} -s			Sign tag with your private key using GPG
+*cg tag-ls*			Show name and revision for all tags
+------------------------------------------------------------------------------
+
+`-------------------------------`---------------------------------------------
+File status flags:
+------------------------------------------------------------------------------
+?				file is unknown
+A				file has been added.
+D				file has been deleted.
+!				file is not in working tree
+M				file has been touched or modified
+m				file has been touched or modified (during merge)
+------------------------------------------------------------------------------

-- 
Jonas Fonseca

^ permalink raw reply related

* [PATCH 3/4] Generate PDF documents using docbook2pdf
From: Jonas Fonseca @ 2006-03-10 14:44 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20060310144106.GA7920@diku.dk>

Unfortunately xmlto cannot be used for this,

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

---

 Documentation/Makefile |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/Documentation/Makefile b/Documentation/Makefile
index 00e9276..d316a14 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -11,6 +11,8 @@ DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_
 DOC_MAN1=$(patsubst %.txt,%,$(MAN1_TXT))
 DOC_MAN7=$(patsubst %.txt,%,$(MAN7_TXT))
 
+DOC_PDF=$(patsubst %.txt,%.pdf,$(MAN1_TXT) $(MAN7_TXT)) introduction.pdf
+
 prefix=$(HOME)
 bin=$(prefix)/bin
 mandir=$(prefix)/man
@@ -35,15 +37,17 @@ all: html man txt
 
 html: $(DOC_HTML)
 
-
 man: man1 man7
 man1: $(DOC_MAN1)
 man7: $(DOC_MAN7)
 
+pdf: $(DOC_PDF)
+
 txt: txt1 txt7
 txt1: $(MAN1_TXT)
 txt7: $(MAN7_TXT)
 
+
 install: man txt
 	$(INSTALL) -m755 -d $(DESTDIR)/$(txtdir)
 	$(INSTALL) $(MAN1_TXT) $(MAN7_TXT) $(DESTDIR)/$(txtdir)
@@ -56,13 +60,16 @@ install-html: html
 	$(INSTALL) $(DOC_HTML) $(DESTDIR)/$(htmldir)
 
 clean:
-	rm -f *.xml *.html *.1 *.7 cg*.[17].txt $(PACKAGE).7.txt
+	rm -f *.xml *.html *.pdf *.1 *.7 cg*.[17].txt $(PACKAGE).7.txt
 
 .PRECIOUS: cg%.txt
 
 introduction.html: ../README
 	asciidoc -b xhtml11 -d article -f asciidoc.conf -o $@ $<
 
+introduction.xml: ../README
+	asciidoc -b docbook -d article -f asciidoc.conf -o $@ $<
+
 %.1.html : %.1.txt
 	asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
 
@@ -87,6 +94,9 @@ introduction.html: ../README
 %.7 : %.7.xml
 	xmlto man $<
 
+%.pdf : %.xml
+	docbook2pdf $<
+
 $(PACKAGE).7.txt : make-$(PACKAGE)-asciidoc
 	./make-$(PACKAGE)-asciidoc > $@
 
-- 
Jonas Fonseca

^ permalink raw reply related

* [PATCH 2/4] Encode the manpage section in the file name
From: Jonas Fonseca @ 2006-03-10 14:43 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20060310144106.GA7920@diku.dk>

This makes it easier to handle other document types.

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

---

 Documentation/Makefile |   39 +++++++++++++++++++++++++++------------
 1 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/Documentation/Makefile b/Documentation/Makefile
index 661c259..00e9276 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -3,13 +3,13 @@ CG_SRC=$(filter-out $(CG_IGNORE), $(wild
 
 PACKAGE=cogito
 
-MAN1_TXT=$(patsubst ../cg%,cg%.txt,$(CG_SRC))
-MAN7_TXT=$(PACKAGE).txt
+MAN1_TXT=$(patsubst ../cg%,cg%.1.txt,$(CG_SRC))
+MAN7_TXT=$(PACKAGE).7.txt
 
 DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT) $(MAN7_TXT)) introduction.html
 
-DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
-DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
+DOC_MAN1=$(patsubst %.txt,%,$(MAN1_TXT))
+DOC_MAN7=$(patsubst %.txt,%,$(MAN7_TXT))
 
 prefix=$(HOME)
 bin=$(prefix)/bin
@@ -56,28 +56,43 @@ install-html: html
 	$(INSTALL) $(DOC_HTML) $(DESTDIR)/$(htmldir)
 
 clean:
-	rm -f *.xml *.html *.1 *.7 cg*.txt $(PACKAGE).txt
+	rm -f *.xml *.html *.1 *.7 cg*.[17].txt $(PACKAGE).7.txt
 
 .PRECIOUS: cg%.txt
 
 introduction.html: ../README
 	asciidoc -b xhtml11 -d article -f asciidoc.conf -o $@ $<
 
-%.html : %.txt
+%.1.html : %.1.txt
 	asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
 
-%.1 %.7 : %.xml
-	xmlto man $<
+%.7.html : %.7.txt
+	asciidoc -b xhtml11 -d manpage -f asciidoc.conf $<
 
-%.xml : %.txt
+%.html : %.txt
+	asciidoc -b xhtml11 -d article -f asciidoc.conf -o $@ $<
+
+%.1.xml : %.1.txt
 	asciidoc -b docbook -d manpage -f asciidoc.conf $<
 
-$(PACKAGE).txt : make-$(PACKAGE)-asciidoc
+%.7.xml : %.7.txt
+	asciidoc -b docbook -d manpage -f asciidoc.conf $<
+
+%.xml : %.txt
+	asciidoc -b docbook -d article -f asciidoc.conf $<
+
+%.1 : %.1.xml
+	xmlto man $<
+
+%.7 : %.7.xml
+	xmlto man $<
+
+$(PACKAGE).7.txt : make-$(PACKAGE)-asciidoc
 	./make-$(PACKAGE)-asciidoc > $@
 
 # It seems that cg%.txt won't match this so use an explicit rule
-cg.txt : ../cg make-cg-asciidoc
+cg.1.txt : ../cg make-cg-asciidoc
 	CGPACKAGE=$(PACKAGE) ./make-cg-asciidoc $< > $@
 
-cg-%.txt : ../cg-% make-cg-asciidoc
+cg-%.1.txt : ../cg-% make-cg-asciidoc
 	CGPACKAGE=$(PACKAGE) ./make-cg-asciidoc $< > $@

-- 
Jonas Fonseca

^ permalink raw reply related

* [PATCH 1/4] Simplify wildcards for match files to be ignored
From: Jonas Fonseca @ 2006-03-10 14:43 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git
In-Reply-To: <20060310144106.GA7920@diku.dk>

Signed-off-by: Jonas Fonseca <fonseca@diku.dk>

---

 Documentation/Makefile |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/Documentation/Makefile b/Documentation/Makefile
index 3aad2fb..661c259 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,4 +1,4 @@
-CG_IGNORE=$(wildcard ../cg-X* ../cg-*.orig ../cg-*.rej ../cg-*.in)
+CG_IGNORE=$(wildcard ../cg-X* ../cg-*.*)
 CG_SRC=$(filter-out $(CG_IGNORE), $(wildcard ../cg*))
 
 PACKAGE=cogito

-- 
Jonas Fonseca

^ permalink raw reply related

* Cogito: Cleanup documentation building and add quick reference
From: Jonas Fonseca @ 2006-03-10 14:41 UTC (permalink / raw)
  To: Petr Baudis; +Cc: git

Hi,

Here are a few patches that makes it possible to build documentation as
PDF using docbook2pdf (chosen because xmlto doesn't seem to be able to
generate PDFs).

All the patches leads up to adding a quick reference with often used
Cogito commands and associated option. It is inspired by svn-ref and the
goal is to have the PDF version under two pages long. The grouping of
commands could need some more comments.

The quick reference can be translated into HTML, PDF and cg-ref(7)
manpage. The last one is achieved by stripping much of the markup from
the 'default' version since manpages cannot have table layout. Note the
HTML and PDF versions are generated as quick-reference.{html,pdf}. We
might want to generate cg-ref.{html,pdf} instead.

-- 
Jonas Fonseca

^ permalink raw reply

* [PATCH] fetch,parse-remote,fmt-merge-msg: refs/remotes/* support
From: Eric Wong @ 2006-03-10 12:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vzmjz5y6o.fsf@assigned-by-dhcp.cox.net>

Note: This replaces the previous patch to fetch and parse-remote.

We can now easily fetch and merge things from heads in the
refs/remotes/ hierarchy in remote repositories.

The refs/remotes/ hierarchy is likely to become the standard for
tracking foreign SCMs, as well as the location of Pull: targets
for non-master heads of newly cloned repositories.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 git-fetch.sh           |    8 +++++++-
 git-fmt-merge-msg.perl |    8 ++++++++
 git-parse-remote.sh    |    8 ++++----
 3 files changed, 19 insertions(+), 5 deletions(-)

6697c83da96b26739c3fe33c8526da6124cea909
diff --git a/git-fetch.sh b/git-fetch.sh
index 0346d4a..11e9a9d 100755
--- a/git-fetch.sh
+++ b/git-fetch.sh
@@ -94,6 +94,9 @@ append_fetch_head () {
     # remote-nick is the URL given on the command line (or a shorthand)
     # remote-name is the $GIT_DIR relative refs/ path we computed
     # for this refspec.
+
+    # the $note_ variable will be fed to git-fmt-merge-msg for further
+    # processing.
     case "$remote_name_" in
     HEAD)
 	note_= ;;
@@ -103,6 +106,9 @@ append_fetch_head () {
     refs/tags/*)
 	note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')"
 	note_="tag '$note_' of " ;;
+    refs/remotes/*)
+	note_="$(expr "$remote_name_" : 'refs/\(remotes/.*\)')"
+	note_="remote branch '$note_' of " ;;
     *)
 	note_="$remote_name of " ;;
     esac
@@ -150,7 +156,7 @@ fast_forward_local () {
 	git-update-ref "$1" "$2" 
 	;;
 
-    refs/heads/*)
+    refs/heads/* | refs/remotes/*)
 	# $1 is the ref being updated.
 	# $2 is the new value for the ref.
 	local=$(git-rev-parse --verify "$1^0" 2>/dev/null)
diff --git a/git-fmt-merge-msg.perl b/git-fmt-merge-msg.perl
index afe80e6..5986e54 100755
--- a/git-fmt-merge-msg.perl
+++ b/git-fmt-merge-msg.perl
@@ -75,6 +75,7 @@ while (<>) {
 		$src{$src} = {
 			BRANCH => [],
 			TAG => [],
+			R_BRANCH => [],
 			GENERIC => [],
 			# &1 == has HEAD.
 			# &2 == has others.
@@ -91,6 +92,11 @@ while (<>) {
 		push @{$src{$src}{TAG}}, $1;
 		$src{$src}{HEAD_STATUS} |= 2;
 	}
+	elsif (/^remote branch (.*)$/) {
+		$origin = $1;
+		push @{$src{$src}{R_BRANCH}}, $1;
+		$src{$src}{HEAD_STATUS} |= 2;
+	}
 	elsif (/^HEAD$/) {
 		$origin = $src;
 		$src{$src}{HEAD_STATUS} |= 1;
@@ -123,6 +129,8 @@ for my $src (@src) {
 	}
 	push @this, andjoin("branch ", "branches ",
 			   $src{$src}{BRANCH});
+	push @this, andjoin("remote branch ", "remote branches ",
+			   $src{$src}{R_BRANCH});
 	push @this, andjoin("tag ", "tags ",
 			   $src{$src}{TAG});
 	push @this, andjoin("commit ", "commits ",
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
index 5f158c6..63f2281 100755
--- a/git-parse-remote.sh
+++ b/git-parse-remote.sh
@@ -86,14 +86,14 @@ canon_refs_list_for_fetch () {
 		local=$(expr "$ref" : '[^:]*:\(.*\)')
 		case "$remote" in
 		'') remote=HEAD ;;
-		refs/heads/* | refs/tags/*) ;;
-		heads/* | tags/* ) remote="refs/$remote" ;;
+		refs/heads/* | refs/tags/* | refs/remotes/*) ;;
+		heads/* | tags/* | remotes/* ) remote="refs/$remote" ;;
 		*) remote="refs/heads/$remote" ;;
 		esac
 		case "$local" in
 		'') local= ;;
-		refs/heads/* | refs/tags/*) ;;
-		heads/* | tags/* ) local="refs/$local" ;;
+		refs/heads/* | refs/tags/* | refs/remotes/*) ;;
+		heads/* | tags/* | remotes/* ) local="refs/$local" ;;
 		*) local="refs/heads/$local" ;;
 		esac
 
-- 
1.2.4.gbe2d

^ permalink raw reply related

* Re: What's in git.git
From: Martin Langhoff @ 2006-03-10 11:59 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Fredrik Kuivinen, Junio C Hamano, git
In-Reply-To: <Pine.LNX.4.63.0603101215100.25810@wbgn013.biozentrum.uni-wuerzburg.de>

On 3/11/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> The history is linearized, and the commits are ordered accordingly, then
> to be passed to git-annotate/-blame.

Exactly.

If a process has already done the costly git-rev-list for other
purposes (say, grab logentries of the relevant commits), and wants to
also run annotate/blame, it should be able to reuse it cheaply, by
passing -S filename. Possibly an IDE (or gitk/qgit) would want to do
this.

Now, what I use it for in git-cvsserver is to "flatten" merges. CVS
clients don't really understand that we know about parallel history,
so every time we have a merge the view that the CVS client gets is of
a "merge commit" with a merge summary. And I sweep the merged commits
under the carpet.

(there's some arbitrary nondeterministic magic in how I pick what side
to track and what side to merge. let's not think about that too much.
but I just want git-blame to see a somewhat simplified git-rev-list).

does that help?

cheers,


m

^ permalink raw reply

* Re: What's in git.git
From: Johannes Schindelin @ 2006-03-10 11:17 UTC (permalink / raw)
  To: Fredrik Kuivinen; +Cc: Martin Langhoff, Junio C Hamano, git
In-Reply-To: <20060310104443.GA4491@c165.ib.student.liu.se>

Hi,

On Fri, 10 Mar 2006, Fredrik Kuivinen wrote:

> On Mon, Mar 06, 2006 at 10:05:41PM +1300, Martin Langhoff wrote:
> > On 3/6/06, Junio C Hamano <junkio@cox.net> wrote:
> > > - The deathmatch between annotate/blame (Ryan Anderson, Fredrik
> > >   Kuivinen, me cheerleading)
> > 
> > Add fuel to the fire  ;-) Can git-blame take cached git-rev-list
> > output like annotate does with -S?
> > 
> 
> Currently it cannot do that. How is that option used?

The history is linearized, and the commits are ordered accordingly, then 
to be passed to git-annotate/-blame.

> If you want to make annotate/blame faster for certain files you might as 
> well cache the output of annotate/blame instead of the git-rev-list 
> output, no?
> 
> What am I missing?

Two things:

- the history is growing, and
- it would be inefficient/error-prone to save the annotates for files 

Hth,
Dscho
  

^ permalink raw reply

* Re: bug?: stgit creates (unneccessary?) conflicts when pulling
From: Catalin Marinas @ 2006-03-10 11:13 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Shawn Pearce
In-Reply-To: <7vslpr2ojz.fsf@assigned-by-dhcp.cox.net>

On 09/03/06, Junio C Hamano <junkio@cox.net> wrote:
> "Catalin Marinas" <catalin.marinas@gmail.com> writes:
>
> > Trying to implement this, I've just noticed that git-read-tree has a
> > --aggressive option which takes care of the file removals. Adding this
> > option lowered the pushing time in StGIT from ~2 min to under 2
> > seconds (merges between 2.6.14 and the latest kernel). There's
> > probably no need to deal with file removals in pg--merge-all anymore.
>
> Yup, it was originally done to improve the performance of
> resolve merge strategy, but I am glad somebody else has found
> use for it.

Actually, I asked for it about 6 months ago:

http://marc.theaimsgroup.com/?l=git&m=112677889118711&w=2

and I got the reply from you :-):

http://marc.theaimsgroup.com/?l=git&m=112690084826630&w=2

Anyway, it's good we have it, it saved me some time with implementing
Shawn's merging algorithm.

--
Catalin

^ permalink raw reply

* Re: git-rev-list bug?
From: Catalin Marinas @ 2006-03-10 11:01 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Linus Torvalds, git
In-Reply-To: <7vslpqy4u7.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> wrote:
> Junio C Hamano <junkio@cox.net> writes:
>
>> It however has a side effect -- uninteresting commits were never
>> parsed here, but now they get parsed.  I am not sure if there
>> are correctness implications...
>
> Actually there is.  If a merge with an uninteresting side branch
> was the only thing that brought changes to paths we are
> interested in, we do not want TREE_SAME logic to remove other
> parents (i.e. the branches we are interested in) from the merge
> commit.  
>
> So we would need a combination of both, something like this?

I can confirm that it "stg patches" works fine with this patch for
git-rev-list.

Thanks.

-- 
Catalin

^ permalink raw reply

* Re: What's in git.git
From: Fredrik Kuivinen @ 2006-03-10 10:44 UTC (permalink / raw)
  To: Martin Langhoff; +Cc: Junio C Hamano, git
In-Reply-To: <46a038f90603060105m29595745ke64d4a623506c0b0@mail.gmail.com>

On Mon, Mar 06, 2006 at 10:05:41PM +1300, Martin Langhoff wrote:
> On 3/6/06, Junio C Hamano <junkio@cox.net> wrote:
> > - The deathmatch between annotate/blame (Ryan Anderson, Fredrik
> >   Kuivinen, me cheerleading)
> 
> Add fuel to the fire  ;-) Can git-blame take cached git-rev-list
> output like annotate does with -S?
> 

Currently it cannot do that. How is that option used? If you want to
make annotate/blame faster for certain files you might as well cache
the output of annotate/blame instead of the git-rev-list output, no?

What am I missing?

- Fredrik

^ permalink raw reply

* Re: git-rev-list bug?
From: Junio C Hamano @ 2006-03-10 10:25 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git, Catalin Marinas
In-Reply-To: <7v4q26zklx.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> It however has a side effect -- uninteresting commits were never
> parsed here, but now they get parsed.  I am not sure if there
> are correctness implications...

Actually there is.  If a merge with an uninteresting side branch
was the only thing that brought changes to paths we are
interested in, we do not want TREE_SAME logic to remove other
parents (i.e. the branches we are interested in) from the merge
commit.  

So we would need a combination of both, something like this?

---
diff --git a/revision.c b/revision.c
index 713f27e..c8d93ff 100644
--- a/revision.c
+++ b/revision.c
@@ -282,6 +282,7 @@ static int same_tree_as_empty(struct tre
 static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
 {
 	struct commit_list **pp, *parent;
+	int tree_changed = 0;
 
 	if (!commit->tree)
 		return;
@@ -296,14 +297,19 @@ static void try_to_simplify_commit(struc
 	while ((parent = *pp) != NULL) {
 		struct commit *p = parent->item;
 
-		if (p->object.flags & UNINTERESTING) {
-			pp = &parent->next;
-			continue;
-		}
-
 		parse_commit(p);
 		switch (compare_tree(p->tree, commit->tree)) {
 		case TREE_SAME:
+			if (p->object.flags & UNINTERESTING) {
+				/* Even if a merge with an uninteresting
+				 * side branch brought the entire change
+				 * we are interested in, we do not want
+				 * to lose the other branches of this
+				 * merge, so we just keep going.
+				 */
+				pp = &parent->next;
+				continue;
+			}
 			parent->next = NULL;
 			commit->parents = parent;
 			return;
@@ -315,12 +321,14 @@ static void try_to_simplify_commit(struc
 			}
 		/* fallthrough */
 		case TREE_DIFFERENT:
+			tree_changed = 1;
 			pp = &parent->next;
 			continue;
 		}
 		die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
 	}
-	commit->object.flags |= TREECHANGE;
+	if (tree_changed)
+		commit->object.flags |= TREECHANGE;
 }
 
 static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)

^ permalink raw reply related

* Re: git-rev-list bug?
From: Junio C Hamano @ 2006-03-10  9:59 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git, Catalin Marinas
In-Reply-To: <7virqmzlhb.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> I am wondering why try_to_simplify_commit() skips parents marked
> with UNINTERESTING.  I think this is causing a problem Catalin
> found with rev-list.
> ...
> The attached patch seems to fix it (without losing the logic to
> omit tree comparison with UNINTERESTING parent, which I do not
> quite understand).

Actually the previous patch is not right either.  If I ask "what
changes path B between commit#1..commit#4", it would still omit
commit#2.

It should not matter if the parent is uninteresting while
checking if a commit touches the specified path.  The attached
patch which replaces the previous botched one does exactly that.

It however has a side effect -- uninteresting commits were never
parsed here, but now they get parsed.  I am not sure if there
are correctness implications...

---
diff --git a/revision.c b/revision.c
index 713f27e..9d0934a 100644
--- a/revision.c
+++ b/revision.c
@@ -296,11 +296,6 @@ static void try_to_simplify_commit(struc
 	while ((parent = *pp) != NULL) {
 		struct commit *p = parent->item;
 
-		if (p->object.flags & UNINTERESTING) {
-			pp = &parent->next;
-			continue;
-		}
-
 		parse_commit(p);
 		switch (compare_tree(p->tree, commit->tree)) {
 		case TREE_SAME:

^ permalink raw reply related

* Re: git-rev-list bug?
From: Junio C Hamano @ 2006-03-10  9:40 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git, Catalin Marinas
In-Reply-To: <7vmzfy1zjb.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> To my surprise, it turns out that this regression was not very
> recent.  Bisecting points at this commite:
>...
> I haven't had time to dig into this deeper yet...


I am wondering why try_to_simplify_commit() skips parents marked
with UNINTERESTING.  I think this is causing a problem Catalin
found with rev-list.

If you have (time flows from top to bottom):

	commit#1	(it does not matter what this does)
        commit#2        change file B only
        commit#3	change file A only
        commit#4	change file B only

"git-rev-list commit#1..commit#4 -- A" shows commit#3 (correct)
and commit#2 (incorrect).

It pushes commit#1 (UNINTERESTING) and commit#4 (~UNINTERESTING)
and starts traversing.  try-to-simplify(commit#4) says "no tree
change between #3 and #4" and it returns without marking
commit#4 with TREECHANGE flag.  But when looking at commit#2 and
trying to simplify it, it says "Ah, its parent is uninteresting,
so I would not do compare_tree()".  Iteration over parents of
commit#2 leaves the while() loop and at the end of function the
commit is marked with TREECHANGE and is shown.

The attached patch seems to fix it (without losing the logic to
omit tree comparison with UNINTERESTING parent, which I do not
quite understand).



---
diff --git a/revision.c b/revision.c
index 713f27e..23c9b9d 100644
--- a/revision.c
+++ b/revision.c
@@ -282,6 +282,7 @@ static int same_tree_as_empty(struct tre
 static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
 {
 	struct commit_list **pp, *parent;
+	int changed = 0;
 
 	if (!commit->tree)
 		return;
@@ -315,12 +316,14 @@ static void try_to_simplify_commit(struc
 			}
 		/* fallthrough */
 		case TREE_DIFFERENT:
+			changed = 1;
 			pp = &parent->next;
 			continue;
 		}
 		die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
 	}
-	commit->object.flags |= TREECHANGE;
+	if (changed)
+		commit->object.flags |= TREECHANGE;
 }
 
 static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list)

^ permalink raw reply related

* [PATCH 3/3] blame: Rename detection (take 2)
From: Fredrik Kuivinen @ 2006-03-10  9:21 UTC (permalink / raw)
  To: git; +Cc: junkio
In-Reply-To: <20060310092135.24015.26510.stgit@c165>




Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>

---

 blame.c |  239 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 199 insertions(+), 40 deletions(-)

diff --git a/blame.c b/blame.c
index 90338af..ac57e10 100644
--- a/blame.c
+++ b/blame.c
@@ -14,6 +14,7 @@
 #include "tree.h"
 #include "blob.h"
 #include "diff.h"
+#include "diffcore.h"
 #include "revision.h"
 
 #define DEBUG 0
@@ -34,7 +35,9 @@ struct util_info {
 	char *buf;
 	unsigned long size;
 	int num_lines;
-//    const char* path;
+	const char* pathname;
+
+	void* topo_data;
 };
 
 struct chunk {
@@ -342,25 +345,34 @@ static int map_line(struct commit *commi
 	return info->line_map[line];
 }
 
-static int fill_util_info(struct commit *commit, const char *path)
+static struct util_info* get_util(struct commit *commit)
 {
-	struct util_info *util;
-	if (commit->object.util)
-		return 0;
+	struct util_info *util = commit->object.util;
+
+	if (util)
+		return util;
 
 	util = xmalloc(sizeof(struct util_info));
+	util->buf = NULL;
+	util->size = 0;
+	util->line_map = NULL;
+	util->num_lines = -1;
+	util->pathname = NULL;
+	commit->object.util = util;
+	return util;
+}
 
-	if (get_blob_sha1(commit->tree, path, util->sha1)) {
-		free(util);
+static int fill_util_info(struct commit *commit)
+{
+	struct util_info *util = commit->object.util;
+
+	assert(util);
+	assert(util->pathname);
+	
+	if (get_blob_sha1(commit->tree, util->pathname, util->sha1))
 		return 1;
-	} else {
-		util->buf = NULL;
-		util->size = 0;
-		util->line_map = NULL;
-		util->num_lines = -1;
-		commit->object.util = util;
+	else
 		return 0;
-	}
 }
 
 static void alloc_line_map(struct commit *commit)
@@ -389,10 +401,11 @@ static void alloc_line_map(struct commit
 
 static void init_first_commit(struct commit* commit, const char* filename)
 {
-	struct util_info* util;
+	struct util_info* util = commit->object.util;
 	int i;
 
-	if (fill_util_info(commit, filename))
+	util->pathname = filename;
+	if (fill_util_info(commit))
 		die("fill_util_info failed");
 
 	alloc_line_map(commit);
@@ -453,7 +466,7 @@ static void process_commits(struct rev_i
 		if(num_parents == 0)
 			*initial = commit;
 
-		if(fill_util_info(commit, path))
+		if (fill_util_info(commit))
 			continue;
 
 		alloc_line_map(commit);
@@ -471,7 +484,7 @@ static void process_commits(struct rev_i
 				printf("parent: %s\n",
 				       sha1_to_hex(parent->object.sha1));
 
-			if(fill_util_info(parent, path)) {
+			if (fill_util_info(parent)) {
 				num_parents--;
 				continue;
 			}
@@ -511,6 +524,135 @@ static void process_commits(struct rev_i
 	} while ((commit = get_revision(rev)) != NULL);
 }
 
+
+static int compare_tree_path(struct rev_info* revs,
+			     struct commit* c1, struct commit* c2)
+{
+	const char* paths[2];
+	struct util_info* util = c2->object.util;
+	paths[0] = util->pathname;
+	paths[1] = NULL;
+
+	diff_tree_setup_paths(get_pathspec(revs->prefix, paths));
+	return rev_compare_tree(c1->tree, c2->tree);
+}
+
+
+static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1,
+				   const char* path)
+{
+	const char* paths[2];
+	paths[0] = path;
+	paths[1] = NULL;
+
+	diff_tree_setup_paths(get_pathspec(revs->prefix, paths));
+	return rev_same_tree_as_empty(t1);
+}
+
+static const char* find_rename(struct commit* commit, struct commit* parent)
+{
+	struct util_info* cutil = commit->object.util;
+	struct diff_options diff_opts;
+	const char *paths[1];
+	int i;
+
+	if (DEBUG) {
+		printf("find_rename commit: %s ",
+		       sha1_to_hex(commit->object.sha1));
+		puts(sha1_to_hex(parent->object.sha1));
+	}
+
+	diff_setup(&diff_opts);
+	diff_opts.recursive = 1;
+	diff_opts.detect_rename = DIFF_DETECT_RENAME;
+	paths[0] = NULL;
+	diff_tree_setup_paths(paths);
+	if (diff_setup_done(&diff_opts) < 0)
+		die("diff_setup_done failed");
+
+	diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1,
+		       "", &diff_opts);
+	diffcore_std(&diff_opts);
+
+	for (i = 0; i < diff_queued_diff.nr; i++) {
+		struct diff_filepair *p = diff_queued_diff.queue[i];
+
+		if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) {
+			if (DEBUG)
+				printf("rename %s -> %s\n", p->one->path, p->two->path);
+			return p->two->path;
+		}
+	}
+
+	return 0;
+}
+
+static void simplify_commit(struct rev_info *revs, struct commit *commit)
+{
+	struct commit_list **pp, *parent;
+
+	if (!commit->tree)
+		return;
+
+	if (!commit->parents) {
+		struct util_info* util = commit->object.util;
+		if (!same_tree_as_empty_path(revs, commit->tree,
+					     util->pathname))
+			commit->object.flags |= TREECHANGE;
+		return;
+	}
+
+	pp = &commit->parents;
+	while ((parent = *pp) != NULL) {
+		struct commit *p = parent->item;
+
+		if (p->object.flags & UNINTERESTING) {
+			pp = &parent->next;
+			continue;
+		}
+
+		parse_commit(p);
+		switch (compare_tree_path(revs, p, commit)) {
+		case REV_TREE_SAME:
+			parent->next = NULL;
+			commit->parents = parent;
+			get_util(p)->pathname = get_util(commit)->pathname;
+			return;
+
+		case REV_TREE_NEW:
+		{
+			
+			struct util_info* util = commit->object.util;
+			if (revs->remove_empty_trees &&
+			    same_tree_as_empty_path(revs, p->tree,
+						    util->pathname)) {
+				const char* new_name = find_rename(commit, p);
+				if (new_name) {
+					struct util_info* putil = get_util(p);
+					if (!putil->pathname)
+						putil->pathname = strdup(new_name);
+				} else {
+					*pp = parent->next;
+					continue;
+				}
+			}
+		}
+
+		/* fallthrough */
+		case REV_TREE_DIFFERENT:
+			pp = &parent->next;
+			if (!get_util(p)->pathname)
+				get_util(p)->pathname =
+					get_util(commit)->pathname;
+			continue;
+		}
+		die("bad tree compare for commit %s",
+		    sha1_to_hex(commit->object.sha1));
+	}
+	commit->object.flags |= TREECHANGE;
+}
+
+
 struct commit_info
 {
 	char* author;
@@ -569,6 +711,18 @@ static const char* format_time(unsigned 
 	return time_buf;
 }
 
+static void topo_setter(struct commit* c, void* data)
+{
+	struct util_info* util = c->object.util;
+	util->topo_data = data;
+}
+
+static void* topo_getter(struct commit* c)
+{
+	struct util_info* util = c->object.util;
+	return util->topo_data;
+}
+
 int main(int argc, const char **argv)
 {
 	int i;
@@ -580,8 +734,8 @@ int main(int argc, const char **argv)
 	int sha1_len = 8;
 	int compability = 0;
 	int options = 1;
+	struct commit* start_commit;
 
-	int num_args;
 	const char* args[10];
 	struct rev_info rev;
 
@@ -634,28 +788,29 @@ int main(int argc, const char **argv)
 		strcpy(filename_buf, filename);
 	filename = filename_buf;
 
-	{
-		struct commit* c;
-		if (get_sha1(commit, sha1))
-			die("get_sha1 failed, commit '%s' not found", commit);
-		c = lookup_commit_reference(sha1);
-
-		if (fill_util_info(c, filename)) {
-			printf("%s not found in %s\n", filename, commit);
-			return 1;
-		}
+	if (get_sha1(commit, sha1))
+		die("get_sha1 failed, commit '%s' not found", commit);	
+	start_commit = lookup_commit_reference(sha1);
+	get_util(start_commit)->pathname = filename;
+	if (fill_util_info(start_commit)) {
+		printf("%s not found in %s\n", filename, commit);
+		return 1;
 	}
 
-	num_args = 0;
-	args[num_args++] = NULL;
-	args[num_args++] = "--topo-order";
-	args[num_args++] = "--remove-empty";
-	args[num_args++] = commit;
-	args[num_args++] = "--";
-	args[num_args++] = filename;
-	args[num_args] = NULL;
 
-	setup_revisions(num_args, args, &rev, "HEAD");
+	init_revisions(&rev);	
+	rev.remove_empty_trees = 1;
+	rev.topo_order = 1;
+	rev.prune_fn = simplify_commit;
+	rev.topo_setter = topo_setter;
+	rev.topo_getter = topo_getter;
+	rev.limited = 1;
+
+	commit_list_insert(start_commit, &rev.commits);
+	
+	args[0] = filename;
+	args[1] = NULL;
+	diff_tree_setup_paths(args);
 	prepare_revision_walk(&rev);
 	process_commits(&rev, filename, &initial);
 
@@ -665,17 +820,21 @@ int main(int argc, const char **argv)
 
 	for (i = 0; i < num_blame_lines; i++) {
 		struct commit *c = blame_lines[i];
+		struct util_info* u;
+
 		if (!c)
 			c = initial;
 
+		u = c->object.util;
 		get_commit_info(c, &ci);
 		fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout);
 		if(compability)
 			printf("\t(%10s\t%10s\t%d)", ci.author,
 			       format_time(ci.author_time, ci.author_tz), i+1);
 		else
-			printf(" (%-15.15s %10s %*d) ", ci.author,
-			       format_time(ci.author_time, ci.author_tz),
+			printf(" %s (%-15.15s %10s %*d) ", u->pathname,
+			       ci.author, format_time(ci.author_time,
+						      ci.author_tz),
 			       max_digits, i+1);
 
 		if(i == num_blame_lines - 1) {

^ permalink raw reply related

* [PATCH 2/3] rev-lib: Make it easy to do rename tracking (take 2)
From: Fredrik Kuivinen @ 2006-03-10  9:21 UTC (permalink / raw)
  To: git; +Cc: junkio
In-Reply-To: <20060310092135.24015.26510.stgit@c165>


prune_fn in the rev_info structure is called in place of
try_to_simplify_commit. This makes it possible to do rename tracking
with a custom try_to_simplify_commit-like function.

This commit also introduces init_revisions which initialises the rev_info
structure with default values.

Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>

---

 rev-list.c |    6 ++--
 revision.c |  100 ++++++++++++++++++++++++++++++++++--------------------------
 revision.h |   18 ++++++++++-
 3 files changed, 76 insertions(+), 48 deletions(-)

diff --git a/rev-list.c b/rev-list.c
index 8e4d83e..812d237 100644
--- a/rev-list.c
+++ b/rev-list.c
@@ -190,7 +190,7 @@ static int count_distance(struct commit_
 
 		if (commit->object.flags & (UNINTERESTING | COUNTED))
 			break;
-		if (!revs.paths || (commit->object.flags & TREECHANGE))
+		if (!revs.prune_fn || (commit->object.flags & TREECHANGE))
 			nr++;
 		commit->object.flags |= COUNTED;
 		p = commit->parents;
@@ -224,7 +224,7 @@ static struct commit_list *find_bisectio
 	nr = 0;
 	p = list;
 	while (p) {
-		if (!revs.paths || (p->item->object.flags & TREECHANGE))
+		if (!revs.prune_fn || (p->item->object.flags & TREECHANGE))
 			nr++;
 		p = p->next;
 	}
@@ -234,7 +234,7 @@ static struct commit_list *find_bisectio
 	for (p = list; p; p = p->next) {
 		int distance;
 
-		if (revs.paths && !(p->item->object.flags & TREECHANGE))
+		if (revs.prune_fn && !(p->item->object.flags & TREECHANGE))
 			continue;
 
 		distance = count_distance(p);
diff --git a/revision.c b/revision.c
index 2a33637..b41f961 100644
--- a/revision.c
+++ b/revision.c
@@ -197,31 +197,27 @@ static int everybody_uninteresting(struc
 	return 1;
 }
 
-#define TREE_SAME	0
-#define TREE_NEW	1
-#define TREE_DIFFERENT	2
-static int tree_difference = TREE_SAME;
+static int tree_difference = REV_TREE_SAME;
 
 static void file_add_remove(struct diff_options *options,
 		    int addremove, unsigned mode,
 		    const unsigned char *sha1,
 		    const char *base, const char *path)
 {
-	int diff = TREE_DIFFERENT;
+	int diff = REV_TREE_DIFFERENT;
 
 	/*
-	 * Is it an add of a new file? It means that
-	 * the old tree didn't have it at all, so we
-	 * will turn "TREE_SAME" -> "TREE_NEW", but
-	 * leave any "TREE_DIFFERENT" alone (and if
-	 * it already was "TREE_NEW", we'll keep it
-	 * "TREE_NEW" of course).
+	 * Is it an add of a new file? It means that the old tree
+	 * didn't have it at all, so we will turn "REV_TREE_SAME" ->
+	 * "REV_TREE_NEW", but leave any "REV_TREE_DIFFERENT" alone
+	 * (and if it already was "REV_TREE_NEW", we'll keep it
+	 * "REV_TREE_NEW" of course).
 	 */
 	if (addremove == '+') {
 		diff = tree_difference;
-		if (diff != TREE_SAME)
+		if (diff != REV_TREE_SAME)
 			return;
-		diff = TREE_NEW;
+		diff = REV_TREE_NEW;
 	}
 	tree_difference = diff;
 }
@@ -232,7 +228,7 @@ static void file_change(struct diff_opti
 		 const unsigned char *new_sha1,
 		 const char *base, const char *path)
 {
-	tree_difference = TREE_DIFFERENT;
+	tree_difference = REV_TREE_DIFFERENT;
 }
 
 static struct diff_options diff_opt = {
@@ -241,19 +237,19 @@ static struct diff_options diff_opt = {
 	.change = file_change,
 };
 
-static int compare_tree(struct tree *t1, struct tree *t2)
+int rev_compare_tree(struct tree *t1, struct tree *t2)
 {
 	if (!t1)
-		return TREE_NEW;
+		return REV_TREE_NEW;
 	if (!t2)
-		return TREE_DIFFERENT;
-	tree_difference = TREE_SAME;
+		return REV_TREE_DIFFERENT;
+	tree_difference = REV_TREE_SAME;
 	if (diff_tree_sha1(t1->object.sha1, t2->object.sha1, "", &diff_opt) < 0)
-		return TREE_DIFFERENT;
+		return REV_TREE_DIFFERENT;
 	return tree_difference;
 }
 
-static int same_tree_as_empty(struct tree *t1)
+int rev_same_tree_as_empty(struct tree *t1)
 {
 	int retval;
 	void *tree;
@@ -285,7 +281,7 @@ static void try_to_simplify_commit(struc
 		return;
 
 	if (!commit->parents) {
-		if (!same_tree_as_empty(commit->tree))
+		if (!rev_same_tree_as_empty(commit->tree))
 			commit->object.flags |= TREECHANGE;
 		return;
 	}
@@ -300,19 +296,20 @@ static void try_to_simplify_commit(struc
 		}
 
 		parse_commit(p);
-		switch (compare_tree(p->tree, commit->tree)) {
-		case TREE_SAME:
+		switch (rev_compare_tree(p->tree, commit->tree)) {
+		case REV_TREE_SAME:
 			parent->next = NULL;
 			commit->parents = parent;
 			return;
 
-		case TREE_NEW:
-			if (revs->remove_empty_trees && same_tree_as_empty(p->tree)) {
+		case REV_TREE_NEW:
+			if (revs->remove_empty_trees &&
+			    rev_same_tree_as_empty(p->tree)) {
 				*pp = parent->next;
 				continue;
 			}
 		/* fallthrough */
-		case TREE_DIFFERENT:
+		case REV_TREE_DIFFERENT:
 			pp = &parent->next;
 			continue;
 		}
@@ -358,8 +355,8 @@ static void add_parents_to_list(struct r
 	 * simplify the commit history and find the parent
 	 * that has no differences in the path set if one exists.
 	 */
-	if (revs->paths)
-		try_to_simplify_commit(revs, commit);
+	if (revs->prune_fn)
+		revs->prune_fn(revs, commit);
 
 	parent = commit->parents;
 	while (parent) {
@@ -381,9 +378,6 @@ static void limit_list(struct rev_info *
 	struct commit_list *newlist = NULL;
 	struct commit_list **p = &newlist;
 
-	if (revs->paths)
-		diff_tree_setup_paths(revs->paths);
-
 	while (list) {
 		struct commit_list *entry = list;
 		struct commit *commit = list->item;
@@ -435,6 +429,23 @@ static void handle_all(struct rev_info *
 	for_each_ref(handle_one_ref);
 }
 
+void init_revisions(struct rev_info *revs)
+{
+	memset(revs, 0, sizeof(*revs));
+	revs->lifo = 1;
+	revs->dense = 1;
+	revs->prefix = setup_git_directory();
+	revs->max_age = -1;
+	revs->min_age = -1;
+	revs->max_count = -1;
+
+	revs->prune_fn = NULL;
+	revs->prune_data = NULL;
+
+	revs->topo_setter = topo_sort_default_setter;
+	revs->topo_getter = topo_sort_default_getter;
+}
+
 /*
  * Parse revision information, filling in the "rev_info" structure,
  * and removing the used arguments from the argument list.
@@ -448,14 +459,8 @@ int setup_revisions(int argc, const char
 	const char **unrecognized = argv + 1;
 	int left = 1;
 
-	memset(revs, 0, sizeof(*revs));
-	revs->lifo = 1;
-	revs->dense = 1;
-	revs->prefix = setup_git_directory();
-	revs->max_age = -1;
-	revs->min_age = -1;
-	revs->max_count = -1;
-
+	init_revisions(revs);
+	
 	/* First, search for "--" */
 	seen_dashdash = 0;
 	for (i = 1; i < argc; i++) {
@@ -464,7 +469,7 @@ int setup_revisions(int argc, const char
 			continue;
 		argv[i] = NULL;
 		argc = i;
-		revs->paths = get_pathspec(revs->prefix, argv + i + 1);
+		revs->prune_data = get_pathspec(revs->prefix, argv + i + 1);
 		seen_dashdash = 1;
 		break;
 	}
@@ -628,7 +633,7 @@ int setup_revisions(int argc, const char
 				if (lstat(argv[j], &st) < 0)
 					die("'%s': %s", arg, strerror(errno));
 			}
-			revs->paths = get_pathspec(revs->prefix, argv + i);
+			revs->prune_data = get_pathspec(revs->prefix, argv + i);
 			break;
 		}
 		commit = get_commit_reference(revs, arg, sha1, flags ^ local_flags);
@@ -642,8 +647,13 @@ int setup_revisions(int argc, const char
 		commit = get_commit_reference(revs, def, sha1, 0);
 		add_one_commit(commit, revs);
 	}
-	if (revs->paths)
+
+	if (revs->prune_data) {
+		diff_tree_setup_paths(revs->prune_data);
+		revs->prune_fn = try_to_simplify_commit;
 		revs->limited = 1;
+	}
+
 	return left;
 }
 
@@ -653,7 +663,9 @@ void prepare_revision_walk(struct rev_in
 	if (revs->limited)
 		limit_list(revs);
 	if (revs->topo_order)
-		sort_in_topological_order(&revs->commits, revs->lifo);
+		sort_in_topological_order_fn(&revs->commits, revs->lifo,
+					     revs->topo_setter,
+					     revs->topo_getter);
 }
 
 static int rewrite_one(struct commit **pp)
@@ -709,7 +721,7 @@ struct commit *get_revision(struct rev_i
 			return NULL;
 		if (revs->no_merges && commit->parents && commit->parents->next)
 			goto next;
-		if (revs->paths && revs->dense) {
+		if (revs->prune_fn && revs->dense) {
 			if (!(commit->object.flags & TREECHANGE))
 				goto next;
 			rewrite_parents(commit);
diff --git a/revision.h b/revision.h
index 31e8f61..6c2beca 100644
--- a/revision.h
+++ b/revision.h
@@ -7,6 +7,10 @@
 #define SHOWN		(1u<<3)
 #define TMP_MARK	(1u<<4) /* for isolated cases; clean after use */
 
+struct rev_info;
+
+typedef void (prune_fn_t)(struct rev_info *revs, struct commit *commit);
+
 struct rev_info {
 	/* Starting list */
 	struct commit_list *commits;
@@ -14,7 +18,8 @@ struct rev_info {
 
 	/* Basic information */
 	const char *prefix;
-	const char **paths;
+	void *prune_data;
+	prune_fn_t *prune_fn;
 
 	/* Traversal flags */
 	unsigned int	dense:1,
@@ -33,9 +38,20 @@ struct rev_info {
 	int max_count;
 	unsigned long max_age;
 	unsigned long min_age;
+
+	topo_sort_set_fn_t topo_setter;
+	topo_sort_get_fn_t topo_getter;
 };
 
+#define REV_TREE_SAME		0
+#define REV_TREE_NEW		1
+#define REV_TREE_DIFFERENT	2
+
 /* revision.c */
+extern int rev_same_tree_as_empty(struct tree *t1);
+extern int rev_compare_tree(struct tree *t1, struct tree *t2);
+
+extern void init_revisions(struct rev_info *revs);
 extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);
 extern void prepare_revision_walk(struct rev_info *revs);
 extern struct commit *get_revision(struct rev_info *revs);

^ permalink raw reply related

* [PATCH 1/3] Make it possible to not clobber object.util in sort_in_topological_order (take 2)
From: Fredrik Kuivinen @ 2006-03-10  9:21 UTC (permalink / raw)
  To: git; +Cc: junkio
In-Reply-To: <20060310092135.24015.26510.stgit@c165>




Signed-off-by: Fredrik Kuivinen <freku045@student.liu.se>

---

 commit.c |   30 ++++++++++++++++++++++++------
 commit.h |   16 +++++++++++++++-
 2 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/commit.c b/commit.c
index 06d5439..013683a 100644
--- a/commit.c
+++ b/commit.c
@@ -569,11 +569,29 @@ int count_parents(struct commit * commit
         return count;
 }
 
+void topo_sort_default_setter(struct commit *c, void *data)
+{
+	c->object.util = data;
+}
+
+void *topo_sort_default_getter(struct commit *c)
+{
+	return c->object.util;
+}
+
 /*
  * Performs an in-place topological sort on the list supplied.
  */
 void sort_in_topological_order(struct commit_list ** list, int lifo)
 {
+	sort_in_topological_order_fn(list, lifo, topo_sort_default_setter,
+				     topo_sort_default_getter);
+}
+
+void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
+				  topo_sort_set_fn_t setter,
+				  topo_sort_get_fn_t getter)
+{
 	struct commit_list * next = *list;
 	struct commit_list * work = NULL, **insert;
 	struct commit_list ** pptr = list;
@@ -596,7 +614,7 @@ void sort_in_topological_order(struct co
 	next=*list;
 	while (next) {
 		next_nodes->list_item = next;
-		next->item->object.util = next_nodes;
+		setter(next->item, next_nodes);
 		next_nodes++;
 		next = next->next;
 	}
@@ -606,7 +624,7 @@ void sort_in_topological_order(struct co
 		struct commit_list * parents = next->item->parents;
 		while (parents) {
 			struct commit * parent=parents->item;
-			struct sort_node * pn = (struct sort_node *)parent->object.util;
+			struct sort_node * pn = (struct sort_node *) getter(parent);
 			
 			if (pn)
 				pn->indegree++;
@@ -624,7 +642,7 @@ void sort_in_topological_order(struct co
 	next=*list;
 	insert = &work;
 	while (next) {
-		struct sort_node * node = (struct sort_node *)next->item->object.util;
+		struct sort_node * node = (struct sort_node *) getter(next->item);
 
 		if (node->indegree == 0) {
 			insert = &commit_list_insert(next->item, insert)->next;
@@ -637,12 +655,12 @@ void sort_in_topological_order(struct co
 		sort_by_date(&work);
 	while (work) {
 		struct commit * work_item = pop_commit(&work);
-		struct sort_node * work_node = (struct sort_node *)work_item->object.util;
+		struct sort_node * work_node = (struct sort_node *) getter(work_item);
 		struct commit_list * parents = work_item->parents;
 
 		while (parents) {
 			struct commit * parent=parents->item;
-			struct sort_node * pn = (struct sort_node *)parent->object.util;
+			struct sort_node * pn = (struct sort_node *) getter(parent);
 			
 			if (pn) {
 				/* 
@@ -667,7 +685,7 @@ void sort_in_topological_order(struct co
 		*pptr = work_node->list_item;
 		pptr = &(*pptr)->next;
 		*pptr = NULL;
-		work_item->object.util = NULL;
+		setter(work_item, NULL);
 	}
 	free(nodes);
 }
diff --git a/commit.h b/commit.h
index 70a7c75..15c798a 100644
--- a/commit.h
+++ b/commit.h
@@ -65,15 +65,29 @@ int count_parents(struct commit * commit
 /*
  * Performs an in-place topological sort of list supplied.
  *
- * Pre-conditions:
+ * Pre-conditions for sort_in_topological_order:
  *   all commits in input list and all parents of those
  *   commits must have object.util == NULL
  *        
+ * Pre-conditions for sort_in_topological_order_fn:
+ *   all commits in input list and all parents of those
+ *   commits must have getter(commit) == NULL
+ *
  * Post-conditions: 
  *   invariant of resulting list is:
  *      a reachable from b => ord(b) < ord(a)
  *   in addition, when lifo == 0, commits on parallel tracks are
  *   sorted in the dates order.
  */
+
+typedef void (*topo_sort_set_fn_t)(struct commit*, void *data);
+typedef void* (*topo_sort_get_fn_t)(struct commit*);
+
+void topo_sort_default_setter(struct commit *c, void *data);
+void *topo_sort_default_getter(struct commit *c);
+
 void sort_in_topological_order(struct commit_list ** list, int lifo);
+void sort_in_topological_order_fn(struct commit_list ** list, int lifo,
+				  topo_sort_set_fn_t setter,
+				  topo_sort_get_fn_t getter);
 #endif /* COMMIT_H */

^ permalink raw reply related

* [PATCH 0/3] Teach git-blame about renames (take 2)
From: Fredrik Kuivinen @ 2006-03-10  9:21 UTC (permalink / raw)
  To: git; +Cc: junkio


Changes since the previous version:

* Fix the things pointed out by Junio.
* Some other minor clean-ups

---

This patch series teaches git-blame about renames. To do this I have
changed the revision.h interface a bit. In particular, it is now
possible for the user of revision.h to specify a
try_to_simply_commit-like function. That function can then do the
rename tracking.

I have also made a small change to sort_in_topological_order to make
it possible to use the object.util field at the same time as a
topological sort is done. Previously the object.util field was
clobbered by the topological sort. In the new interface the auxiliary
data that the topological sort needs to store for each commit object
is stored with a setter function and retrieved by a getter. Pointers
to those functions are passed to sort_in_topological_order_fn.

- Fredrik

^ permalink raw reply

* Re: git-rev-list bug?
From: Junio C Hamano @ 2006-03-10  8:20 UTC (permalink / raw)
  To: Catalin Marinas; +Cc: git, Linus Torvalds
In-Reply-To: <7vacc0iten.fsf@assigned-by-dhcp.cox.net>

Junio C Hamano <junkio@cox.net> writes:

> "Catalin Marinas" <catalin.marinas@gmail.com> writes:
>
>> Sorry if this was previously discussed. I ran git-rev-list on a linear
>> graph and tried to filter the results by a file name:
>>
>>   git rev-list since.. path/to/file
>>
>> but it always shows the child commit of "since" even if it didn't
>> touch the file. The same behaviour is for git-log (since it uses
>> git-rev-list) but git-whatchanged seems to be fine.
>>
>> Is this the intended behaviour? The "stg patches" command based on
>> git-rev-list used to work fine a few weeks ago but now it is always
>> reporting the bottom patch in the stack as modifying a given file.
>
> I can confirm that this is a recent breakage, but since it is
> unfortunately my day-job day the more detailed analysis and fix
> needs to wait.  Sorry.

To my surprise, it turns out that this regression was not very
recent.  Bisecting points at this commite:

diff-tree 461cf59... (from 6b94f1e...)
Author: Linus Torvalds <torvalds@osdl.org>
Date:   Wed Jan 18 14:47:30 2006 -0800

    rev-list: stop when the file disappears
    
    The one thing I've considered doing (I really should) is to add a "stop
    when you don't find the file" option to "git-rev-list". This patch does
    some of the work towards that: it removes the "parent" thing when the
    file disappears, so a "git annotate" could do do something like
    
    	git-rev-list --remove-empty --parents HEAD -- "$filename"
    
    and it would get a good graph that stops when the filename disappears
    (it's not perfect though: it won't remove all the unintersting commits).
    
    It also simplifies the logic of finding tree differences a bit, at the
    cost of making it a tad less efficient.
    
    The old logic was two-phase: it would first simplify _only_ merges tree as
    it traversed the tree, and then simplify the linear parts of the remainder
    independently. That was pretty optimal from an efficiency standpoint
    because it avoids doing any comparisons that we can see are unnecessary,
    but it made it much harder to understand than it really needed to be.
    
    The new logic is a lot more straightforward, and compares the trees as it
    traverses the graph (ie everything is a single phase). That makes it much
    easier to stop graph traversal at any point where a file disappears.
    

I haven't had time to dig into this deeper yet...

^ permalink raw reply

* Re: Make test broken w/ 180b0d7483711120e28289ff7d9fa346eddd5cb7
From: Junio C Hamano @ 2006-03-10  6:42 UTC (permalink / raw)
  To: gitzilla; +Cc: git, Petr Baudis
In-Reply-To: <441119DB.3020207@gmail.com>

A Large Angry SCM <gitzilla@gmail.com> writes:

> *** t1200-tutorial.sh ***
> *   ok 1: blob
> *   ok 2: blob 557db03
> *   ok 3: git-diff-files -p
> *   ok 4: git diff
> *   ok 5: tree
> *   ok 6: commit
> *   ok 7: git-diff-index -p HEAD
> *   ok 8: git diff HEAD
> *   ok 9: git-whatchanged -p --root
> *   ok 10: git tag my-first-tag
> *   ok 11: git checkout -b mybranch
> *   ok 12: git branch
> *   ok 13: git resolve now fails
> *   ok 14: git show-branch
> * FAIL 15: git resolve
>         cmp resolve.expect resolve.output
> *   ok 16: git show-branch
> *   ok 17: git repack
> *   ok 18: git prune-packed
> *   ok 19: -> only packed objects
> * failed 1 among 19 test(s)

Thanks.  Will push out a fix but it should be trivial.

---

diff --git a/t/t1200-tutorial.sh b/t/t1200-tutorial.sh
index c8a85f9..1002413 100755
--- a/t/t1200-tutorial.sh
+++ b/t/t1200-tutorial.sh
@@ -128,7 +128,7 @@ test_expect_success 'git show-branch' 'c
 git checkout mybranch
 
 cat > resolve.expect << EOF
-Updating from VARIABLE to VARIABLE.
+Updating from VARIABLE to VARIABLE
  example |    1 +
  hello   |    1 +
  2 files changed, 2 insertions(+), 0 deletions(-)

^ permalink raw reply related

* Make test broken w/ 180b0d7483711120e28289ff7d9fa346eddd5cb7
From: A Large Angry SCM @ 2006-03-10  6:16 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

*** t1200-tutorial.sh ***
*   ok 1: blob
*   ok 2: blob 557db03
*   ok 3: git-diff-files -p
*   ok 4: git diff
*   ok 5: tree
*   ok 6: commit
*   ok 7: git-diff-index -p HEAD
*   ok 8: git diff HEAD
*   ok 9: git-whatchanged -p --root
*   ok 10: git tag my-first-tag
*   ok 11: git checkout -b mybranch
*   ok 12: git branch
*   ok 13: git resolve now fails
*   ok 14: git show-branch
* FAIL 15: git resolve
         cmp resolve.expect resolve.output
*   ok 16: git show-branch
*   ok 17: git repack
*   ok 18: git prune-packed
*   ok 19: -> only packed objects
* failed 1 among 19 test(s)

^ permalink raw reply

* Re: git-applymbox fails to extract patch.
From: Dave Jones @ 2006-03-10  5:47 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0603092130030.18022@g5.osdl.org>

On Thu, Mar 09, 2006 at 09:35:11PM -0800, Linus Torvalds wrote:
 > 
 > 
 > On Fri, 10 Mar 2006, Dave Jones wrote:
 > > 
 > > What am I missing ?
 > 
 > Do you have "Content-Type:" headers with a multi-part boundary? That can 
 > cause it.

ahhh.
I was sent a MIME mail, and saved the attachment, then deleted
the junk from the body, and inlined it.
Never crossed my mind to check the headers.  That'll be it.

Now I remember why I hate hand-munging mails.


*snip snip*


$ git-applymbox -k ~/Mail/mbox
1 patch(es) to process.

Applying '[CPUFREQ] Fix the p4-clockmod N60 errata workaround.'

Wrote tree 6d7d2dfd2309675446f727a6b4b2a6ff475835fb
Committed: 6d373ea012b2974e627b9ee830e75cf3bf3c4c24

Sweet. I'm happy again.

Thanks,

		Dave
-- 
http://www.codemonkey.org.uk

^ permalink raw reply

* Re: git-applymbox fails to extract patch.
From: Linus Torvalds @ 2006-03-10  5:35 UTC (permalink / raw)
  To: Dave Jones; +Cc: git
In-Reply-To: <20060310050446.GA20764@redhat.com>



On Fri, 10 Mar 2006, Dave Jones wrote:
> 
> What am I missing ?

Do you have "Content-Type:" headers with a multi-part boundary? That can 
cause it.

Also, empty X-IMAP messages at the beginning of a mbox (pine does those, 
others probably do too) will cause things like that. The extra "email" 
will have no patch in it..

		Linus

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox