Git development
 help / color / mirror / Atom feed
* Re: [RFC] Zit: the git-based single file content tracker
From: Giuseppe Bilotta @ 2008-10-25 10:30 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: David Lang, Junio C Hamano, Jean-Luc Herren, git
In-Reply-To: <200810251110.25704.jnareb@gmail.com>

On Sat, Oct 25, 2008 at 11:10 AM, Jakub Narebski <jnareb@gmail.com> wrote:
> On Sat, 25 Oct 2008, Giuseppe Bilotta wrote:
>
>> The user .zitignore file is probably the best approach: we can create
>> it ourselves (usually), and even if Git doesn't expand the pathname
>> itself, we can just use an absolute path. I'll go that way.
>
> First, absolute path to ~/.zitignore is a bit fragile: what if layout
> of home directories for users change, for example because of increasing
> number of users some fan-out is required (/home/nick -> /home/2/nick)?
> Second, ~/.zitignore looks like something that user can change; if
> you install zit, it can install libexec/zitignore somewhere... or just
> use ./zit/excludes (with 'do not edit' comment perhaps...).

(Actually, I just found another interesting thing about the config, in
that it stores the path to the work tree. This is not a problem,
though, because zit_setup() sets GIT_WORK_TREE.)

As I said, I don't like depending on stuff that needs to be installed.
For example, what about user (non-system) installs? the libexec (or
whatever) solution would have the same problem as the ~/.zitignore
solution, with the moving $HOME.

I guess this leaves the .zit/ solution as the most robust one,
although it's not the most space-effective, especially if you have
many directories, each with a single tracked file. On the plus side,
going for the .zit/ solution and dropping support for .somefile.git/
means some significant code semplification.

-- 
Giuseppe "Oblomov" Bilotta

^ permalink raw reply

* Re: [PATCH 3/7] gitk: Allow starting gui blame for a specific line.
From: Paul Mackerras @ 2008-10-25 11:57 UTC (permalink / raw)
  To: Alexander Gavrilov; +Cc: git
In-Reply-To: <200810241213.01337.angavrilov@gmail.com>

Alexander Gavrilov writes:

> Good point. How about this variant? I renamed the menu item, and
> changed the code to blame the current commit if:

Sounds good, just a couple of minor nits...

> +    # Now scan the lines to determine offset within the hunk
> +    set parent {}
> +    set dline 0
> +    set s_lno [lindex [split $s_lix "."] 0]
> +
> +    for {set i $line} {$i > $s_lno} {incr i -1} {
> +	set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
> +	# Determine if the line is removed
> +	set chunk [string range $c_line 0 [llength $base_lines]-2]

You need an [expr]:

set chunk [string range $c_line 0 [expr {[llength $base_lines] - 2}]]

> +	set removed_idx [string first "-" $chunk]
> +	# Choose a parent index
> +	if {$parent eq {}} {
> +	    if {$removed_idx >= 0} {
> +		set parent $removed_idx
> +		incr parent
> +	    } else {
> +		set unchanged_idx [string first " " $chunk]
> +		if {$unchanged_idx >= 0} {
> +		    set parent $unchanged_idx
> +		    incr parent
> +		} else {
> +		    # blame the current commit
> +		    set parent 0
> +		}
> +	    }
> +	}

I like this better than the previous version, but it would turn out a
bit simpler if you use parent = -1 to indicate that we're blaming the
current commit, and then increment it right at the end.

> +	# then count other lines that belong to it
> +	if {$parent > 0} {
> +	    set code [string index $c_line $parent-1]

Once again you need an [expr].

Apart from those things, it looks good.  If you like I will fix those
things and commit it.

Paul.

^ permalink raw reply

* [PATCH] gitk: Updated German translation.
From: Christian Stimming @ 2008-10-25 11:27 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git

[-- Attachment #1: Type: text/plain, Size: 125 bytes --]

Patch against today's master of gitk-gui.git at git.kernel.org. Attached to 
avoid whitespace problems.

Regards,

Christian

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-gitk-Update-German-translation.patch --]
[-- Type: text/x-diff; charset="us-ascii"; name="0001-gitk-Update-German-translation.patch", Size: 3493 bytes --]

From 627fc16459e43f5577c16851332bf02a9d40595e Mon Sep 17 00:00:00 2001
From: Christian Stimming <stimming@tuhh.de>
Date: Sat, 25 Oct 2008 13:25:35 +0200
Subject: [PATCH] gitk: Update German translation.

This takes into account the most recent po file merge. For future reference:
The German translator strongly preferes not to have po file merged by the
maintainer (thus causing tons of conflicts for already existing local translations),
but instead to run "make update-po" on his own.

Signed-off-by: Christian Stimming <stimming@tuhh.de>
---
 po/de.po |   51 +++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/po/de.po b/po/de.po
index c86cc2d..e0a6dee 100644
--- a/po/de.po
+++ b/po/de.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: git-gui\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-10-18 22:03+1100\n"
-"PO-Revision-Date: 2008-05-24 22:40+0200\n"
+"POT-Creation-Date: 2008-10-25 13:18+0200\n"
+"PO-Revision-Date: 2008-10-25 13:23+0200\n"
 "Last-Translator: Christian Stimming <stimming@tuhh.de>\n"
 "Language-Team: German\n"
 "MIME-Version: 1.0\n"
@@ -19,6 +19,14 @@ msgstr ""
 msgid "Couldn't get list of unmerged files:"
 msgstr "Liste der nicht-zusammengeführten Dateien nicht gefunden:"
 
+#: gitk:272
+msgid "Error parsing revisions:"
+msgstr "Fehler beim Laden der Versionen:"
+
+#: gitk:327
+msgid "Error executing --argscmd command:"
+msgstr "Fehler beim --argscmd Kommando:"
+
 #: gitk:340
 msgid "No files selected: --merge specified but no files are unmerged."
 msgstr ""
@@ -283,9 +291,9 @@ msgstr "Nur diesen hervorheben"
 msgid "External diff"
 msgstr "Externer Vergleich"
 
-#: gitk:2245
+#: gitk:2255
 msgid "Blame parent commit"
-msgstr ""
+msgstr "Annotieren der Elternversion"
 
 #: gitk:2488
 msgid ""
@@ -471,7 +479,33 @@ msgstr "<%s-Minus>\tSchriftgröße verkleinern"
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tAktualisieren"
 
-#: gitk:3200
+#: gitk:2979
+#, tcl-format
+msgid "Error getting \"%s\" from %s:"
+msgstr "Fehler beim Holen von »%s« von »%s«:"
+
+#: gitk:3036 gitk:3045
+#, tcl-format
+msgid "Error creating temporary directory %s:"
+msgstr "Fehler beim Erzeugen eines temporären Verzeichnisses »%s«:"
+
+#: gitk:3058
+msgid "command failed:"
+msgstr "Kommando fehlgeschlagen:"
+
+#: gitk:3078
+msgid "No such commit"
+msgstr "Version nicht gefunden"
+
+#: gitk:3083
+msgid "git gui blame: command failed:"
+msgstr "git gui blame: Kommando fehlgeschlagen:"
+
+#: gitk:3092
+msgid "External diff viewer failed:"
+msgstr "Externes Vergleich-(Diff-)Programm fehlgeschlagen:"
+
+#: gitk:3210
 msgid "Gitk view definition"
 msgstr "Gitk Ansichten"
 
@@ -692,9 +726,10 @@ msgstr "Bitte geben Sie einen Namen für den neuen Zweig an."
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
-"Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut eintragen?"
+"Version »%s« ist bereits im Zweig »%s« enthalten -- trotzdem erneut "
+"eintragen?"
 
-#: gitk:7708
+#: gitk:7718
 msgid "Cherry-picking"
 msgstr "Version pflücken"
 
@@ -836,7 +871,7 @@ msgstr "Vergleich nur für angezeigte Pfade"
 
 #: gitk:9414
 msgid "Support per-file encodings"
-msgstr ""
+msgstr "Zeichenkodierung pro Datei ermitteln"
 
 #: gitk:9421
 msgid "External diff tool"
-- 
1.6.0.rc1.34.g0fe8c


^ permalink raw reply related

* [PATCH 2/2] Fix git update-ref --no-deref -d.
From: Miklos Vajna @ 2008-10-25 12:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, Brandon Casey, git
In-Reply-To: <cover.1224939436.git.vmiklos@frugalware.org>

Till now --no-deref was just ignored when deleting refs, fix this.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 builtin-update-ref.c  |    8 +++++---
 t/t1400-update-ref.sh |    7 +++++++
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index d8f3142..378dc1b 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -13,7 +13,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 {
 	const char *refname, *oldval, *msg=NULL;
 	unsigned char sha1[20], oldsha1[20];
-	int delete = 0, no_deref = 0;
+	int delete = 0, no_deref = 0, flags = 0;
 	struct option options[] = {
 		OPT_STRING( 'm', NULL, &msg, "reason", "reason of the update"),
 		OPT_BOOLEAN('d', NULL, &delete, "deletes the reference"),
@@ -47,9 +47,11 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 	if (oldval && *oldval && get_sha1(oldval, oldsha1))
 		die("%s: not a valid old SHA1", oldval);
 
+	if (no_deref)
+		flags = REF_NODEREF;
 	if (delete)
-		return delete_ref(refname, oldval ? oldsha1 : NULL, 0);
+		return delete_ref(refname, oldval ? oldsha1 : NULL, flags);
 	else
 		return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
-				  no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
+				  flags, DIE_ON_ERR);
 }
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 04c2b16..8139cd6 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -75,6 +75,13 @@ test_expect_success "delete $m (by HEAD)" '
 '
 rm -f .git/$m
 
+cp -f .git/HEAD .git/HEAD.orig
+test_expect_success "delete symref without dereference" '
+	git update-ref --no-deref -d HEAD &&
+	! test -f .git/HEAD
+'
+cp -f .git/HEAD.orig .git/HEAD
+
 test_expect_success '(not) create HEAD with old sha1' "
 	test_must_fail git update-ref HEAD $A $B
 "
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH 0/2] Fixes for git branch -m / update-ref --no-deref -d
From: Miklos Vajna @ 2008-10-25 12:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, Brandon Casey, git
In-Reply-To: <7v63nh1sc7.fsf@gitster.siamese.dyndns.org>

On Fri, Oct 24, 2008 at 04:33:28PM -0700, Junio C Hamano <gitster@pobox.com> wrote:
> Hmm, remote_get() can read from all three supported places that you
> can
> define remotes.  Could you explain what happens if the old remote is
> read
> from say $GIT_DIR/remotes/origin and you are renaming it to "upstream"
> with "git remote rename origin upstream"?

While trying to answer your question, I noticed that
rename_ref()/delete_ref() did not really handled symrefs.

Regarding rename_ref() (for users: git branch -m) I think you can't
create symrefs in the refs/heads namespace without using plumbing, so
most users are not affected.

Regarding delete_ref() (for users: git update-ref --no-deref -d) in most
repos you just have HEAD as symref and you never want to delete it, but
in case the user asks for it, I think we just have to do so.

Here are two patches to fix these issues (and in fact they will be
required for git remote rename as well).

Miklos Vajna (2):
  Fix git branch -m for symrefs.
  Fix git update-ref --no-deref -d.

 builtin-branch.c       |    2 +-
 builtin-receive-pack.c |    2 +-
 builtin-remote.c       |    4 +-
 builtin-reset.c        |    2 +-
 builtin-send-pack.c    |    2 +-
 builtin-tag.c          |    2 +-
 builtin-update-ref.c   |    8 ++++--
 cache.h                |    2 +-
 refs.c                 |   56 ++++++++++++++++++++++++++++++------------------
 t/t1400-update-ref.sh  |    7 ++++++
 t/t3200-branch.sh      |    9 +++++++
 11 files changed, 64 insertions(+), 32 deletions(-)

^ permalink raw reply

* [PATCH 1/2] Fix git branch -m for symrefs.
From: Miklos Vajna @ 2008-10-25 12:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Jeff King, Brandon Casey, git
In-Reply-To: <cover.1224939436.git.vmiklos@frugalware.org>

This had two problems with symrefs. First, it copied the actual sha1
instead of the "pointer", second it failed to remove the old ref after a
successful rename.

Given that till now delete_ref() always dereferenced symrefs, a new
parameters has been introduced to delete_ref() to allow deleting refs
without a dereference.

Signed-off-by: Miklos Vajna <vmiklos@frugalware.org>
---
 builtin-branch.c       |    2 +-
 builtin-receive-pack.c |    2 +-
 builtin-remote.c       |    4 +-
 builtin-reset.c        |    2 +-
 builtin-send-pack.c    |    2 +-
 builtin-tag.c          |    2 +-
 builtin-update-ref.c   |    2 +-
 cache.h                |    2 +-
 refs.c                 |   56 ++++++++++++++++++++++++++++++------------------
 t/t3200-branch.sh      |    9 +++++++
 10 files changed, 53 insertions(+), 30 deletions(-)

diff --git a/builtin-branch.c b/builtin-branch.c
index 8d634ff..2b3613f 100644
--- a/builtin-branch.c
+++ b/builtin-branch.c
@@ -160,7 +160,7 @@ static int delete_branches(int argc, const char **argv, int force, int kinds)
 			continue;
 		}
 
-		if (delete_ref(name, sha1)) {
+		if (delete_ref(name, sha1, 0)) {
 			error("Error deleting %sbranch '%s'", remote,
 			       argv[i]);
 			ret = 1;
diff --git a/builtin-receive-pack.c b/builtin-receive-pack.c
index 45e3cd9..ab5fa1c 100644
--- a/builtin-receive-pack.c
+++ b/builtin-receive-pack.c
@@ -224,7 +224,7 @@ static const char *update(struct command *cmd)
 			warning ("Allowing deletion of corrupt ref.");
 			old_sha1 = NULL;
 		}
-		if (delete_ref(name, old_sha1)) {
+		if (delete_ref(name, old_sha1, 0)) {
 			error("failed to delete %s", name);
 			return "failed to delete";
 		}
diff --git a/builtin-remote.c b/builtin-remote.c
index a5883df..3f2113c 100644
--- a/builtin-remote.c
+++ b/builtin-remote.c
@@ -441,7 +441,7 @@ static int remove_branches(struct string_list *branches)
 		const char *refname = item->string;
 		unsigned char *sha1 = item->util;
 
-		if (delete_ref(refname, sha1))
+		if (delete_ref(refname, sha1, 0))
 			result |= error("Could not remove branch %s", refname);
 	}
 	return result;
@@ -669,7 +669,7 @@ static int prune(int argc, const char **argv)
 			const char *refname = states.stale.items[i].util;
 
 			if (!dry_run)
-				result |= delete_ref(refname, NULL);
+				result |= delete_ref(refname, NULL, 0);
 
 			printf(" * [%s] %s\n", dry_run ? "would prune" : "pruned",
 			       abbrev_ref(refname, "refs/remotes/"));
diff --git a/builtin-reset.c b/builtin-reset.c
index 16e6bb2..9514b77 100644
--- a/builtin-reset.c
+++ b/builtin-reset.c
@@ -279,7 +279,7 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
 		update_ref(msg, "ORIG_HEAD", orig, old_orig, 0, MSG_ON_ERR);
 	}
 	else if (old_orig)
-		delete_ref("ORIG_HEAD", old_orig);
+		delete_ref("ORIG_HEAD", old_orig, 0);
 	prepend_reflog_action("updating HEAD", msg, sizeof(msg));
 	update_ref_status = update_ref(msg, "HEAD", sha1, orig, 0, MSG_ON_ERR);
 
diff --git a/builtin-send-pack.c b/builtin-send-pack.c
index 910db92..bbf6e0a 100644
--- a/builtin-send-pack.c
+++ b/builtin-send-pack.c
@@ -234,7 +234,7 @@ static void update_tracking_ref(struct remote *remote, struct ref *ref)
 		if (args.verbose)
 			fprintf(stderr, "updating local tracking ref '%s'\n", rs.dst);
 		if (ref->deletion) {
-			delete_ref(rs.dst, NULL);
+			delete_ref(rs.dst, NULL, 0);
 		} else
 			update_ref("update by push", rs.dst,
 					ref->new_sha1, NULL, 0, 0);
diff --git a/builtin-tag.c b/builtin-tag.c
index b13fa34..1ff7b37 100644
--- a/builtin-tag.c
+++ b/builtin-tag.c
@@ -125,7 +125,7 @@ static int for_each_tag_name(const char **argv, each_tag_name_fn fn)
 static int delete_tag(const char *name, const char *ref,
 				const unsigned char *sha1)
 {
-	if (delete_ref(ref, sha1))
+	if (delete_ref(ref, sha1, 0))
 		return 1;
 	printf("Deleted tag '%s'\n", name);
 	return 0;
diff --git a/builtin-update-ref.c b/builtin-update-ref.c
index 56a0b1b..d8f3142 100644
--- a/builtin-update-ref.c
+++ b/builtin-update-ref.c
@@ -48,7 +48,7 @@ int cmd_update_ref(int argc, const char **argv, const char *prefix)
 		die("%s: not a valid old SHA1", oldval);
 
 	if (delete)
-		return delete_ref(refname, oldval ? oldsha1 : NULL);
+		return delete_ref(refname, oldval ? oldsha1 : NULL, 0);
 	else
 		return update_ref(msg, refname, sha1, oldval ? oldsha1 : NULL,
 				  no_deref ? REF_NODEREF : 0, DIE_ON_ERR);
diff --git a/cache.h b/cache.h
index b0edbf9..9951952 100644
--- a/cache.h
+++ b/cache.h
@@ -434,7 +434,7 @@ extern int commit_locked_index(struct lock_file *);
 extern void set_alternate_index_output(const char *);
 extern int close_lock_file(struct lock_file *);
 extern void rollback_lock_file(struct lock_file *);
-extern int delete_ref(const char *, const unsigned char *sha1);
+extern int delete_ref(const char *, const unsigned char *sha1, int flags);
 
 /* Environment bits from configuration mechanism */
 extern int trust_executable_bit;
diff --git a/refs.c b/refs.c
index 0a126fa..93a61e1 100644
--- a/refs.c
+++ b/refs.c
@@ -921,25 +921,32 @@ static int repack_without_ref(const char *refname)
 	return commit_lock_file(&packlock);
 }
 
-int delete_ref(const char *refname, const unsigned char *sha1)
+int delete_ref(const char *refname, const unsigned char *sha1, int flags)
 {
 	struct ref_lock *lock;
-	int err, i, ret = 0, flag = 0;
+	int err, i = 0, ret = 0, flag = 0;
+	char *path;
 
 	lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
 	if (!lock)
 		return 1;
 	if (!(flag & REF_ISPACKED)) {
 		/* loose */
-		i = strlen(lock->lk->filename) - 5; /* .lock */
-		lock->lk->filename[i] = 0;
-		err = unlink(lock->lk->filename);
+		if (!(flags & REF_NODEREF)) {
+			i = strlen(lock->lk->filename) - 5; /* .lock */
+			lock->lk->filename[i] = 0;
+			path = lock->lk->filename;
+		} else {
+			path = git_path(refname);
+		}
+		err = unlink(path);
 		if (err && errno != ENOENT) {
 			ret = 1;
 			error("unlink(%s) failed: %s",
-			      lock->lk->filename, strerror(errno));
+			      path, strerror(errno));
 		}
-		lock->lk->filename[i] = '.';
+		if (!(flags & REF_NODEREF))
+			lock->lk->filename[i] = '.';
 	}
 	/* removing the loose one could have resurrected an earlier
 	 * packed one.  Also, if it was not loose we need to repack
@@ -964,10 +971,15 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 	struct ref_lock *lock;
 	struct stat loginfo;
 	int log = !lstat(git_path("logs/%s", oldref), &loginfo);
+	const char *symref = NULL;
+	int is_symref = 0;
 
 	if (S_ISLNK(loginfo.st_mode))
 		return error("reflog for %s is a symlink", oldref);
 
+	symref = resolve_ref(oldref, orig_sha1, 0, &flag);
+	if (flag & REF_ISSYMREF)
+		is_symref = 1;
 	if (!resolve_ref(oldref, orig_sha1, 1, &flag))
 		return error("refname %s not found", oldref);
 
@@ -988,12 +1000,12 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 		return error("unable to move logfile logs/%s to tmp-renamed-log: %s",
 			oldref, strerror(errno));
 
-	if (delete_ref(oldref, orig_sha1)) {
+	if (delete_ref(oldref, orig_sha1, REF_NODEREF)) {
 		error("unable to delete old %s", oldref);
 		goto rollback;
 	}
 
-	if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1)) {
+	if (resolve_ref(newref, sha1, 1, &flag) && delete_ref(newref, sha1, REF_NODEREF)) {
 		if (errno==EISDIR) {
 			if (remove_empty_directories(git_path("%s", newref))) {
 				error("Directory not empty: %s", newref);
@@ -1031,18 +1043,20 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 	}
 	logmoved = log;
 
-	lock = lock_ref_sha1_basic(newref, NULL, 0, NULL);
-	if (!lock) {
-		error("unable to lock %s for update", newref);
-		goto rollback;
-	}
-
-	lock->force_write = 1;
-	hashcpy(lock->old_sha1, orig_sha1);
-	if (write_ref_sha1(lock, orig_sha1, logmsg)) {
-		error("unable to write current sha1 into %s", newref);
-		goto rollback;
-	}
+	if (!is_symref) {
+		lock = lock_ref_sha1_basic(newref, NULL, 0, NULL);
+		if (!lock) {
+			error("unable to lock %s for update", newref);
+			goto rollback;
+		}
+		lock->force_write = 1;
+		hashcpy(lock->old_sha1, orig_sha1);
+		if (write_ref_sha1(lock, orig_sha1, logmsg)) {
+			error("unable to write current sha1 into %s", newref);
+			goto rollback;
+		}
+	} else
+		create_symref(newref, symref, logmsg);
 
 	return 0;
 
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 2147eac..fdeb1f5 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -112,6 +112,15 @@ test_expect_success 'config information was renamed, too' \
 	"test $(git config branch.s.dummy) = Hello &&
 	 test_must_fail git config branch.s/s/dummy"
 
+test_expect_success 'renaming a symref' \
+'
+	git symbolic-ref refs/heads/master2 refs/heads/master &&
+	git branch -m master2 master3 &&
+	git symbolic-ref refs/heads/master3 &&
+	test -f .git/refs/heads/master &&
+	! test -f .git/refs/heads/master2
+'
+
 test_expect_success \
     'git branch -m u v should fail when the reflog for u is a symlink' '
      git branch -l u &&
-- 
1.6.0.2

^ permalink raw reply related

* [PATCH 1/5] blame: inline get_patch()
From: René Scharfe @ 2008-10-25 13:30 UTC (permalink / raw)
  To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>

Inline get_patch() to its only call site as a preparation for getting rid
of struct patch.  Also we don't need to check the ptr members because
fill_origin_blob() already did, and the caller didn't check for NULL
anyway, so drop the test.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
 builtin-blame.c |   31 +++++++++++--------------------
 1 files changed, 11 insertions(+), 20 deletions(-)

diff --git a/builtin-blame.c b/builtin-blame.c
index 48cc0c1..593b539 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -542,25 +542,6 @@ static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
 	return state.ret;
 }
 
-/*
- * Run diff between two origins and grab the patch output, so that
- * we can pass blame for lines origin is currently suspected for
- * to its parent.
- */
-static struct patch *get_patch(struct origin *parent, struct origin *origin)
-{
-	mmfile_t file_p, file_o;
-	struct patch *patch;
-
-	fill_origin_blob(parent, &file_p);
-	fill_origin_blob(origin, &file_o);
-	if (!file_p.ptr || !file_o.ptr)
-		return NULL;
-	patch = compare_buffer(&file_p, &file_o, 0);
-	num_get_patch++;
-	return patch;
-}
-
 static void free_patch(struct patch *p)
 {
 	free(p->chunks);
@@ -824,12 +805,22 @@ static int pass_blame_to_parent(struct scoreboard *sb,
 {
 	int i, last_in_target, plno, tlno;
 	struct patch *patch;
+	mmfile_t file_p, file_o;
 
 	last_in_target = find_last_in_target(sb, target);
 	if (last_in_target < 0)
 		return 1; /* nothing remains for this target */
 
-	patch = get_patch(parent, target);
+	/*
+	 * Run diff between two origins and grab the patch output, so that
+	 * we can pass blame for lines origin is currently suspected for
+	 * to its parent.
+	 */
+	fill_origin_blob(parent, &file_p);
+	fill_origin_blob(target, &file_o);
+	patch = compare_buffer(&file_p, &file_o, 0);
+	num_get_patch++;
+
 	plno = tlno = 0;
 	for (i = 0; i < patch->num; i++) {
 		struct chunk *chunk = &patch->chunks[i];
-- 
1.6.0.3.514.g2f91b

^ permalink raw reply related

* [PATCH 2/5] Always initialize xpparam_t to 0
From: René Scharfe @ 2008-10-25 13:30 UTC (permalink / raw)
  To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>

From: Brian Downing <bdowning@lavos.net>

We're going to be adding some parameters to this, so we can't have
any uninitialized data in it.

Signed-off-by: Brian Downing <bdowning@lavos.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Taken from pu.  This patch series doesn't add anything to the struct,
but it's a good idea to future-proof its initialization anyway.

 builtin-blame.c  |    1 +
 builtin-rerere.c |    1 +
 combine-diff.c   |    1 +
 diff.c           |    5 +++++
 merge-file.c     |    1 +
 5 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/builtin-blame.c b/builtin-blame.c
index 593b539..5ca7065 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -523,6 +523,7 @@ static struct patch *compare_buffer(mmfile_t
*file_p, mmfile_t *file_o,
 	xdemitconf_t xecfg;
 	xdemitcb_t ecb;

+	memset(&xpp, 0, sizeof(xpp));
 	xpp.flags = xdl_opts;
 	memset(&xecfg, 0, sizeof(xecfg));
 	xecfg.ctxlen = context;
diff --git a/builtin-rerere.c b/builtin-rerere.c
index dd4573f..d4dec6b 100644
--- a/builtin-rerere.c
+++ b/builtin-rerere.c
@@ -98,6 +98,7 @@ static int diff_two(const char *file1, const char *label1,

 	printf("--- a/%s\n+++ b/%s\n", label1, label2);
 	fflush(stdout);
+	memset(&xpp, 0, sizeof(xpp));
 	xpp.flags = XDF_NEED_MINIMAL;
 	memset(&xecfg, 0, sizeof(xecfg));
 	xecfg.ctxlen = 3;
diff --git a/combine-diff.c b/combine-diff.c
index 5aa1104..ec8df39 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -213,6 +213,7 @@ static void combine_diff(const unsigned char
*parent, mmfile_t *result_file,

 	parent_file.ptr = grab_blob(parent, &sz);
 	parent_file.size = sz;
+	memset(&xpp, 0, sizeof(xpp));
 	xpp.flags = XDF_NEED_MINIMAL;
 	memset(&xecfg, 0, sizeof(xecfg));
 	memset(&state, 0, sizeof(state));
diff --git a/diff.c b/diff.c
index e368fef..1918b73 100644
--- a/diff.c
+++ b/diff.c
@@ -400,6 +400,7 @@ static void diff_words_show(struct diff_words_data
*diff_words)
 	mmfile_t minus, plus;
 	int i;

+	memset(&xpp, 0, sizeof(xpp));
 	memset(&xecfg, 0, sizeof(xecfg));
 	minus.size = diff_words->minus.text.size;
 	minus.ptr = xmalloc(minus.size);
@@ -1416,6 +1417,7 @@ static void builtin_diff(const char *name_a,
 		if (!pe)
 			pe = diff_funcname_pattern(two);

+		memset(&xpp, 0, sizeof(xpp));
 		memset(&xecfg, 0, sizeof(xecfg));
 		memset(&ecbdata, 0, sizeof(ecbdata));
 		ecbdata.label_path = lbl;
@@ -1489,6 +1491,7 @@ static void builtin_diffstat(const char *name_a,
const char *name_b,
 		xdemitconf_t xecfg;
 		xdemitcb_t ecb;

+		memset(&xpp, 0, sizeof(xpp));
 		memset(&xecfg, 0, sizeof(xecfg));
 		xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts;
 		xdi_diff_outf(&mf1, &mf2, diffstat_consume, diffstat,
@@ -1535,6 +1538,7 @@ static void builtin_checkdiff(const char *name_a,
const char *name_b,
 		xdemitconf_t xecfg;
 		xdemitcb_t ecb;

+		memset(&xpp, 0, sizeof(xpp));
 		memset(&xecfg, 0, sizeof(xecfg));
 		xecfg.ctxlen = 1; /* at least one context line */
 		xpp.flags = XDF_NEED_MINIMAL;
@@ -2958,6 +2962,7 @@ static int diff_get_patch_id(struct diff_options
*options, unsigned char *sha1)
 		struct diff_filepair *p = q->queue[i];
 		int len1, len2;

+		memset(&xpp, 0, sizeof(xpp));
 		memset(&xecfg, 0, sizeof(xecfg));
 		if (p->status == 0)
 			return error("internal diff status error");
diff --git a/merge-file.c b/merge-file.c
index 2a939c9..3120a95 100644
--- a/merge-file.c
+++ b/merge-file.c
@@ -61,6 +61,7 @@ static int generate_common_file(mmfile_t *res,
mmfile_t *f1, mmfile_t *f2)
 	xdemitconf_t xecfg;
 	xdemitcb_t ecb;

+	memset(&xpp, 0, sizeof(xpp));
 	xpp.flags = XDF_NEED_MINIMAL;
 	memset(&xecfg, 0, sizeof(xecfg));
 	xecfg.ctxlen = 3;
-- 
1.6.0.3.514.g2f91b

^ permalink raw reply related

* [PATCH 3/5] Allow alternate "low-level" emit function from xdl_diff
From: René Scharfe @ 2008-10-25 13:30 UTC (permalink / raw)
  To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>

From: Brian Downing <bdowning@lavos.net>

For some users (e.g. git blame), getting textual patch output is just
extra work, as they can get all the information they need from the low-
level diff structures.  Allow for an alternate low-level emit function
to be defined to allow bypassing the textual patch generation; set
xemitconf_t's emit_func member to enable this.

The (void (*)()) type is pretty ugly, but the alternative would be to
include most of the private xdiff headers in xdiff.h to get the types
required for the "proper" function prototype.  Also, a (void *) won't
work, as ANSI C doesn't allow a function pointer to be cast to an
object pointer.

Signed-off-by: Brian Downing <bdowning@lavos.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
Taken from pu.

 xdiff/xdiff.h  |    1 +
 xdiff/xdiffi.c |    4 +++-
 xdiff/xemit.c  |    3 +--
 xdiff/xemit.h  |    3 +++
 4 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index deebe02..84fff58 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -87,6 +87,7 @@ typedef struct s_xdemitconf {
 	unsigned long flags;
 	find_func_t find_func;
 	void *find_func_priv;
+	void (*emit_func)();
 } xdemitconf_t;
 
 typedef struct s_bdiffparam {
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 1bad846..9d0324a 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -538,6 +538,8 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	     xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
 	xdchange_t *xscr;
 	xdfenv_t xe;
+	emit_func_t ef = xecfg->emit_func ?
+		(emit_func_t)xecfg->emit_func : xdl_emit_diff;
 
 	if (xdl_do_diff(mf1, mf2, xpp, &xe) < 0) {
 
@@ -551,7 +553,7 @@ int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 		return -1;
 	}
 	if (xscr) {
-		if (xdl_emit_diff(&xe, xscr, ecb, xecfg) < 0) {
+		if (ef(&xe, xscr, ecb, xecfg) < 0) {
 
 			xdl_free_script(xscr);
 			xdl_free_env(&xe);
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index d3d9c84..4625c1b 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -27,7 +27,6 @@
 
 static long xdl_get_rec(xdfile_t *xdf, long ri, char const **rec);
 static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *ecb);
-static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
 
 
 
@@ -58,7 +57,7 @@ static int xdl_emit_record(xdfile_t *xdf, long ri, char const *pre, xdemitcb_t *
  * Starting at the passed change atom, find the latest change atom to be included
  * inside the differential hunk according to the specified configuration.
  */
-static xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
+xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
 	xdchange_t *xch, *xchp;
 
 	for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
diff --git a/xdiff/xemit.h b/xdiff/xemit.h
index 440a739..c2e2e83 100644
--- a/xdiff/xemit.h
+++ b/xdiff/xemit.h
@@ -24,7 +24,10 @@
 #define XEMIT_H
 
 
+typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+			   xdemitconf_t const *xecfg);
 
+xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
 		  xdemitconf_t const *xecfg);
 
-- 
1.6.0.3.514.g2f91b

^ permalink raw reply related

* [PATCH 4/5] add xdi_diff_hunks() for callers that only need hunk lengths
From: René Scharfe @ 2008-10-25 13:31 UTC (permalink / raw)
  To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>

Based on a patch by Brian Downing, this uses the xdiff emit_func feature
to implement xdi_diff_hunks().  It's a function that calls a callback for
each hunk of a diff, passing its lengths.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
 xdiff-interface.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 xdiff-interface.h |    4 ++++
 2 files changed, 52 insertions(+), 1 deletions(-)

diff --git a/xdiff-interface.c b/xdiff-interface.c
index 49e06af..e8ef46d 100644
--- a/xdiff-interface.c
+++ b/xdiff-interface.c
@@ -1,6 +1,9 @@
 #include "cache.h"
 #include "xdiff-interface.h"
-#include "strbuf.h"
+#include "xdiff/xtypes.h"
+#include "xdiff/xdiffi.h"
+#include "xdiff/xemit.h"
+#include "xdiff/xmacros.h"
 
 struct xdiff_emit_state {
 	xdiff_emit_consume_fn consume;
@@ -153,6 +156,50 @@ int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
 	return ret;
 }
 
+struct xdiff_emit_hunk_state {
+	xdiff_emit_hunk_consume_fn consume;
+	void *consume_callback_data;
+};
+
+static int process_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
+			xdemitconf_t const *xecfg)
+{
+	long s1, s2, same, p_next, t_next;
+	xdchange_t *xch, *xche;
+	struct xdiff_emit_hunk_state *state = ecb->priv;
+	xdiff_emit_hunk_consume_fn fn = state->consume;
+	void *consume_callback_data = state->consume_callback_data;
+
+	for (xch = xscr; xch; xch = xche->next) {
+		xche = xdl_get_hunk(xch, xecfg);
+
+		s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
+		s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
+		same = s2 + XDL_MAX(xch->i1 - s1, 0);
+		p_next = xche->i1 + xche->chg1;
+		t_next = xche->i2 + xche->chg2;
+
+		fn(consume_callback_data, same, p_next, t_next);
+	}
+	return 0;
+}
+
+int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
+		   xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
+		   xpparam_t const *xpp, xdemitconf_t *xecfg)
+{
+	struct xdiff_emit_hunk_state state;
+	xdemitcb_t ecb;
+
+	memset(&state, 0, sizeof(state));
+	memset(&ecb, 0, sizeof(ecb));
+	state.consume = fn;
+	state.consume_callback_data = consume_callback_data;
+	xecfg->emit_func = (void (*)())process_diff;
+	ecb.priv = &state;
+	return xdi_diff(mf1, mf2, xpp, xecfg, &ecb);
+}
+
 int read_mmfile(mmfile_t *ptr, const char *filename)
 {
 	struct stat st;
diff --git a/xdiff-interface.h b/xdiff-interface.h
index eaf9cd3..7352b9a 100644
--- a/xdiff-interface.h
+++ b/xdiff-interface.h
@@ -4,12 +4,16 @@
 #include "xdiff/xdiff.h"
 
 typedef void (*xdiff_emit_consume_fn)(void *, char *, unsigned long);
+typedef void (*xdiff_emit_hunk_consume_fn)(void *, long, long, long);
 
 int xdi_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp, xdemitconf_t const *xecfg, xdemitcb_t *ecb);
 int xdi_diff_outf(mmfile_t *mf1, mmfile_t *mf2,
 		  xdiff_emit_consume_fn fn, void *consume_callback_data,
 		  xpparam_t const *xpp,
 		  xdemitconf_t const *xecfg, xdemitcb_t *xecb);
+int xdi_diff_hunks(mmfile_t *mf1, mmfile_t *mf2,
+		   xdiff_emit_hunk_consume_fn fn, void *consume_callback_data,
+		   xpparam_t const *xpp, xdemitconf_t *xecfg);
 int parse_hunk_header(char *line, int len,
 		      int *ob, int *on,
 		      int *nb, int *nn);
-- 
1.6.0.3.514.g2f91b

^ permalink raw reply related

* [PATCH 5/5] blame: use xdi_diff_hunks(), get rid of struct patch
From: René Scharfe @ 2008-10-25 13:31 UTC (permalink / raw)
  To: Brian Downing; +Cc: Junio C Hamano, git
In-Reply-To: <48BF0FBF.3010104@lsrfire.ath.cx>

Based on a patch by Brian Downing, this replaces the struct patch based
code for blame passing with calls to xdi_diff_hunks().  This way we
avoid generating and then parsing patches; we only let the interesting
infos be passed to our callbacks instead.  This makes blame a bit faster:

   $ blame="./git blame -M -C -C -p --incremental v1.6.0"

   # master
   $ /usr/bin/time $blame Makefile >/dev/null
   1.38user 0.14system 0:01.52elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
   0inputs+0outputs (0major+12226minor)pagefaults 0swaps
   $ /usr/bin/time $blame cache.h >/dev/null
   1.66user 0.13system 0:01.80elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
   0inputs+0outputs (0major+12262minor)pagefaults 0swaps

   # this patch series
   $ /usr/bin/time $blame Makefile >/dev/null
   1.27user 0.12system 0:01.40elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
   0inputs+0outputs (0major+11836minor)pagefaults 0swaps
   $ /usr/bin/time $blame cache.h >/dev/null
   1.52user 0.12system 0:01.70elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k
   0inputs+0outputs (0major+12052minor)pagefaults 0swaps

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
Brian, your numbers looked much more impressive.  Could you please clock
this code with your repository and the file server.c?  I wonder if this
callback mechanism is just too complicated or if your case simply benefits
lots more than the two files from git mentioned above.

The patch series ends here without adding xdiff caching, for two reasons.
It's quite easy to add it; patch 4 from your series applies unchanged and
patch 5 is just needs a few small changes to account for the absence of
compare_buffer().  More importantly, speed actually went down with caching
for the test case.  The common tail optimization (xdi_diff() vs. xdl_diff())
seems to beat caching for cache.h and Makefile..

 builtin-blame.c |  191 +++++++++++++++----------------------------------------
 1 files changed, 52 insertions(+), 139 deletions(-)

diff --git a/builtin-blame.c b/builtin-blame.c
index 5ca7065..b6bc5cf 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -443,113 +443,6 @@ static struct origin *find_rename(struct scoreboard *sb,
 }
 
 /*
- * Parsing of patch chunks...
- */
-struct chunk {
-	/* line number in postimage; up to but not including this
-	 * line is the same as preimage
-	 */
-	int same;
-
-	/* preimage line number after this chunk */
-	int p_next;
-
-	/* postimage line number after this chunk */
-	int t_next;
-};
-
-struct patch {
-	struct chunk *chunks;
-	int num;
-};
-
-struct blame_diff_state {
-	struct patch *ret;
-	unsigned hunk_post_context;
-	unsigned hunk_in_pre_context : 1;
-};
-
-static void process_u_diff(void *state_, char *line, unsigned long len)
-{
-	struct blame_diff_state *state = state_;
-	struct chunk *chunk;
-	int off1, off2, len1, len2, num;
-
-	num = state->ret->num;
-	if (len < 4 || line[0] != '@' || line[1] != '@') {
-		if (state->hunk_in_pre_context && line[0] == ' ')
-			state->ret->chunks[num - 1].same++;
-		else {
-			state->hunk_in_pre_context = 0;
-			if (line[0] == ' ')
-				state->hunk_post_context++;
-			else
-				state->hunk_post_context = 0;
-		}
-		return;
-	}
-
-	if (num && state->hunk_post_context) {
-		chunk = &state->ret->chunks[num - 1];
-		chunk->p_next -= state->hunk_post_context;
-		chunk->t_next -= state->hunk_post_context;
-	}
-	state->ret->num = ++num;
-	state->ret->chunks = xrealloc(state->ret->chunks,
-				      sizeof(struct chunk) * num);
-	chunk = &state->ret->chunks[num - 1];
-	if (parse_hunk_header(line, len, &off1, &len1, &off2, &len2)) {
-		state->ret->num--;
-		return;
-	}
-
-	/* Line numbers in patch output are one based. */
-	off1--;
-	off2--;
-
-	chunk->same = len2 ? off2 : (off2 + 1);
-
-	chunk->p_next = off1 + (len1 ? len1 : 1);
-	chunk->t_next = chunk->same + len2;
-	state->hunk_in_pre_context = 1;
-	state->hunk_post_context = 0;
-}
-
-static struct patch *compare_buffer(mmfile_t *file_p, mmfile_t *file_o,
-				    int context)
-{
-	struct blame_diff_state state;
-	xpparam_t xpp;
-	xdemitconf_t xecfg;
-	xdemitcb_t ecb;
-
-	memset(&xpp, 0, sizeof(xpp));
-	xpp.flags = xdl_opts;
-	memset(&xecfg, 0, sizeof(xecfg));
-	xecfg.ctxlen = context;
-	memset(&state, 0, sizeof(state));
-	state.ret = xmalloc(sizeof(struct patch));
-	state.ret->chunks = NULL;
-	state.ret->num = 0;
-
-	xdi_diff_outf(file_p, file_o, process_u_diff, &state, &xpp, &xecfg, &ecb);
-
-	if (state.ret->num) {
-		struct chunk *chunk;
-		chunk = &state.ret->chunks[state.ret->num - 1];
-		chunk->p_next -= state.hunk_post_context;
-		chunk->t_next -= state.hunk_post_context;
-	}
-	return state.ret;
-}
-
-static void free_patch(struct patch *p)
-{
-	free(p->chunks);
-	free(p);
-}
-
-/*
  * Link in a new blame entry to the scoreboard.  Entries that cover the
  * same line range have been removed from the scoreboard previously.
  */
@@ -795,6 +688,22 @@ static void blame_chunk(struct scoreboard *sb,
 	}
 }
 
+struct blame_chunk_cb_data {
+	struct scoreboard *sb;
+	struct origin *target;
+	struct origin *parent;
+	long plno;
+	long tlno;
+};
+
+static void blame_chunk_cb(void *data, long same, long p_next, long t_next)
+{
+	struct blame_chunk_cb_data *d = data;
+	blame_chunk(d->sb, d->tlno, d->plno, same, d->target, d->parent);
+	d->plno = p_next;
+	d->tlno = t_next;
+}
+
 /*
  * We are looking at the origin 'target' and aiming to pass blame
  * for the lines it is suspected to its parent.  Run diff to find
@@ -804,36 +713,28 @@ static int pass_blame_to_parent(struct scoreboard *sb,
 				struct origin *target,
 				struct origin *parent)
 {
-	int i, last_in_target, plno, tlno;
-	struct patch *patch;
+	int last_in_target;
 	mmfile_t file_p, file_o;
+	struct blame_chunk_cb_data d = { sb, target, parent, 0, 0 };
+	xpparam_t xpp;
+	xdemitconf_t xecfg;
 
 	last_in_target = find_last_in_target(sb, target);
 	if (last_in_target < 0)
 		return 1; /* nothing remains for this target */
 
-	/*
-	 * Run diff between two origins and grab the patch output, so that
-	 * we can pass blame for lines origin is currently suspected for
-	 * to its parent.
-	 */
 	fill_origin_blob(parent, &file_p);
 	fill_origin_blob(target, &file_o);
-	patch = compare_buffer(&file_p, &file_o, 0);
 	num_get_patch++;
 
-	plno = tlno = 0;
-	for (i = 0; i < patch->num; i++) {
-		struct chunk *chunk = &patch->chunks[i];
-
-		blame_chunk(sb, tlno, plno, chunk->same, target, parent);
-		plno = chunk->p_next;
-		tlno = chunk->t_next;
-	}
+	memset(&xpp, 0, sizeof(xpp));
+	xpp.flags = xdl_opts;
+	memset(&xecfg, 0, sizeof(xecfg));
+	xecfg.ctxlen = 0;
+	xdi_diff_hunks(&file_p, &file_o, blame_chunk_cb, &d, &xpp, &xecfg);
 	/* The rest (i.e. anything after tlno) are the same as the parent */
-	blame_chunk(sb, tlno, plno, last_in_target, target, parent);
+	blame_chunk(sb, d.tlno, d.plno, last_in_target, target, parent);
 
-	free_patch(patch);
 	return 0;
 }
 
@@ -925,6 +826,23 @@ static void handle_split(struct scoreboard *sb,
 	}
 }
 
+struct handle_split_cb_data {
+	struct scoreboard *sb;
+	struct blame_entry *ent;
+	struct origin *parent;
+	struct blame_entry *split;
+	long plno;
+	long tlno;
+};
+
+static void handle_split_cb(void *data, long same, long p_next, long t_next)
+{
+	struct handle_split_cb_data *d = data;
+	handle_split(d->sb, d->ent, d->tlno, d->plno, same, d->parent, d->split);
+	d->plno = p_next;
+	d->tlno = t_next;
+}
+
 /*
  * Find the lines from parent that are the same as ent so that
  * we can pass blames to it.  file_p has the blob contents for
@@ -939,8 +857,9 @@ static void find_copy_in_blob(struct scoreboard *sb,
 	const char *cp;
 	int cnt;
 	mmfile_t file_o;
-	struct patch *patch;
-	int i, plno, tlno;
+	struct handle_split_cb_data d = { sb, ent, parent, split, 0, 0 };
+	xpparam_t xpp;
+	xdemitconf_t xecfg;
 
 	/*
 	 * Prepare mmfile that contains only the lines in ent.
@@ -955,24 +874,18 @@ static void find_copy_in_blob(struct scoreboard *sb,
 	}
 	file_o.size = cp - file_o.ptr;
 
-	patch = compare_buffer(file_p, &file_o, 1);
-
 	/*
 	 * file_o is a part of final image we are annotating.
 	 * file_p partially may match that image.
 	 */
+	memset(&xpp, 0, sizeof(xpp));
+	xpp.flags = xdl_opts;
+	memset(&xecfg, 0, sizeof(xecfg));
+	xecfg.ctxlen = 1;
 	memset(split, 0, sizeof(struct blame_entry [3]));
-	plno = tlno = 0;
-	for (i = 0; i < patch->num; i++) {
-		struct chunk *chunk = &patch->chunks[i];
-
-		handle_split(sb, ent, tlno, plno, chunk->same, parent, split);
-		plno = chunk->p_next;
-		tlno = chunk->t_next;
-	}
+	xdi_diff_hunks(file_p, &file_o, handle_split_cb, &d, &xpp, &xecfg);
 	/* remainder, if any, all match the preimage */
-	handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split);
-	free_patch(patch);
+	handle_split(sb, ent, d.tlno, d.plno, ent->num_lines, parent, split);
 }
 
 /*
-- 
1.6.0.3.514.g2f91b

^ permalink raw reply related

* Re: Performance impact of a large number of commits
From: Samuel Abels @ 2008-10-25 15:12 UTC (permalink / raw)
  To: david; +Cc: git
In-Reply-To: <alpine.DEB.1.10.0810242219440.20238@asgard.lang.hm>

On Fri, 2008-10-24 at 22:29 -0700, david@lang.hm wrote:
> when git stores the copies of the files it does a sha1 hash of the file 
> contents and then stores the file in the directory
> .git/objects/<first two digits of the hash>/<hash>

> it would be a pretty minor change to git to have it use more directories 

Ah, I see how this works. Well, I'll think of a way to cope with this (I
might patch my Git installation, or see how well it performs on an
indexed file system). If all else fails we'll have to slash the number
of commits even if this means that some files are not added to the
history.

> my concern is that spending time creating the pack files will mean that 
> you don't have time to insert the new files.
> 
> that being said, there may be other ways of dealing with this data rather 
> than putting it into files and then adding it to the git repository.
> 
> Git has a fast-import streaming format that is designed for programs to 
> use that are converting repositories from other SCM systems.

I'm pretty sure that the streaming format won't do us much good, as the
files are re-created from scratch between commits.

Thanks a lot for the information, this was very helpful.

-Samuel

^ permalink raw reply

* [PATCH v2] Fixed git archive for bare repos
From: Deskin Miller @ 2008-10-25 15:38 UTC (permalink / raw)
  To: René Scharfe; +Cc: Charles Bailey, git, kenneth johansson, gitster
In-Reply-To: <49024A05.3090100@lsrfire.ath.cx>

From 8f0dce75427283e0333cce1f1e66f4eac9978ad4 Mon Sep 17 00:00:00 2001
From: Charles Bailey <charles@hashpling.org>

This moves the call to git_config to a place where it doesn't break the
logic for using git archive in a bare repository but retains the fix to
make git archive respect core.autocrlf.

Signed-off-by: Charles Bailey <charles@hashpling.org>
Tested-by: Deskin Miller <deskinm@umich.edu>
---
On Sat, Oct 25, 2008 at 12:19:49AM +0200, René Scharfe wrote:
> Charles Bailey schrieb:
> > This moves the call to git config to a place where it doesn't break
> > the logic for using git archive in a bare repository but retains the
> > fix to make git archive respect core.autocrlf.
> 
> If one combines your patch, Deskin's commit message and test and extends
> on the latter a bit then I think we have a winner. :)
> 
> Here are a few more tests which create a ZIP file in addition to a tar
> archive and compare them to their non-bare counterparts.
> 
> Care to resend?
> 
> Thanks,
> René

Here's a resend.  I've kept Charles's change and commit message, but added
René's tests and removed my test, since it was presupposed by the new tests.

Still needs a signoff from René.

 archive.c           |    2 ++
 builtin-archive.c   |    2 --
 t/t5000-tar-tree.sh |   21 +++++++++++++++++++++
 3 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/archive.c b/archive.c
index e2280df..45d242b 100644
--- a/archive.c
+++ b/archive.c
@@ -338,5 +338,7 @@ int write_archive(int argc, const char **argv, const char *prefix,
 	parse_treeish_arg(argv, &args, prefix);
 	parse_pathspec_arg(argv + 1, &args);
 
+	git_config(git_default_config, NULL);
+
 	return ar->write_archive(&args);
 }
diff --git a/builtin-archive.c b/builtin-archive.c
index 432ce2a..5ceec43 100644
--- a/builtin-archive.c
+++ b/builtin-archive.c
@@ -111,8 +111,6 @@ int cmd_archive(int argc, const char **argv, const char *prefix)
 {
 	const char *remote = NULL;
 
-	git_config(git_default_config, NULL);
-
 	remote = extract_remote_arg(&argc, argv);
 	if (remote)
 		return run_remote_archiver(remote, argc, argv);
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index e395ff4..0f27d73 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -58,6 +58,11 @@ test_expect_success \
      git commit-tree $treeid </dev/null)'
 
 test_expect_success \
+    'create bare clone' \
+    'git clone --bare . bare.git &&
+     cp .gitattributes bare.git/info/attributes'
+
+test_expect_success \
     'remove ignored file' \
     'rm a/ignored'
 
@@ -74,6 +79,14 @@ test_expect_success \
     'diff b.tar b2.tar'
 
 test_expect_success \
+    'git archive in a bare repo' \
+    '(cd bare.git && git archive HEAD) >b3.tar'
+
+test_expect_success \
+    'git archive vs. the same in a bare repo' \
+    'test_cmp b.tar b3.tar'
+
+test_expect_success \
     'validate file modification time' \
     'mkdir extract &&
      "$TAR" xf b.tar -C extract a/a &&
@@ -151,6 +164,14 @@ test_expect_success \
     'git archive --format=zip' \
     'git archive --format=zip HEAD >d.zip'
 
+test_expect_success \
+    'git archive --format=zip in a bare repo' \
+    '(cd bare.git && git archive --format=zip HEAD) >d1.zip'
+
+test_expect_success \
+    'git archive --format=zip vs. the same in a bare repo' \
+    'test_cmp d.zip d1.zip'
+
 $UNZIP -v >/dev/null 2>&1
 if [ $? -eq 127 ]; then
 	echo "Skipping ZIP tests, because unzip was not found"
-- 
1.6.0.3.515.g304f

^ permalink raw reply related

* Re: [PATCH 3/7] gitk: Allow starting gui blame for a specific line.
From: Alexander Gavrilov @ 2008-10-25 16:45 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: git
In-Reply-To: <18691.2467.601039.480382@cargo.ozlabs.ibm.com>

On Saturday 25 October 2008 15:57:23 Paul Mackerras wrote:
> > +    # Now scan the lines to determine offset within the hunk
> > +    set parent {}
> > +    set dline 0
> > +    set s_lno [lindex [split $s_lix "."] 0]
> > +
> > +    for {set i $line} {$i > $s_lno} {incr i -1} {
> > +	set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
> > +	# Determine if the line is removed
> > +	set chunk [string range $c_line 0 [llength $base_lines]-2]
> 
> You need an [expr]:
> 
> set chunk [string range $c_line 0 [expr {[llength $base_lines] - 2}]]

Ugh. I guess I'll have to install docs from Tcl 8.4...
 
> > +	set removed_idx [string first "-" $chunk]
> > +	# Choose a parent index
> > +	if {$parent eq {}} {
> > +	    if {$removed_idx >= 0} {
> > +		set parent $removed_idx
> > +		incr parent
> > +	    } else {
> > +		set unchanged_idx [string first " " $chunk]
> > +		if {$unchanged_idx >= 0} {
> > +		    set parent $unchanged_idx
> > +		    incr parent
> > +		} else {
> > +		    # blame the current commit
> > +		    set parent 0
> > +		}
> > +	    }
> > +	}
> 
> I like this better than the previous version, but it would turn out a
> bit simpler if you use parent = -1 to indicate that we're blaming the
> current commit, and then increment it right at the end.

Yes, it's probably better to apply the following fixup.

Alexander


diff --git a/gitk b/gitk
index 6fbd6bb..68f07c2 100755
--- a/gitk
+++ b/gitk
@@ -3160,33 +3160,32 @@ proc find_hunk_blamespec {base line} {
 
     # Now scan the lines to determine offset within the hunk
     set parent {}
+    set max_parent [expr {[llength $base_lines]-2}]
     set dline 0
     set s_lno [lindex [split $s_lix "."] 0]
 
     for {set i $line} {$i > $s_lno} {incr i -1} {
 	set c_line [$ctext get $i.0 "$i.0 + 1 lines"]
 	# Determine if the line is removed
-	set chunk [string range $c_line 0 [llength $base_lines]-2]
+	set chunk [string range $c_line 0 $max_parent]
 	set removed_idx [string first "-" $chunk]
 	# Choose a parent index
 	if {$parent eq {}} {
 	    if {$removed_idx >= 0} {
 		set parent $removed_idx
-		incr parent
 	    } else {
 		set unchanged_idx [string first " " $chunk]
 		if {$unchanged_idx >= 0} {
 		    set parent $unchanged_idx
-		    incr parent
 		} else {
 		    # blame the current commit
-		    set parent 0
+		    set parent -1
 		}
 	    }
 	}
 	# then count other lines that belong to it
-	if {$parent > 0} {
-	    set code [string index $c_line $parent-1]
+	if {$parent >= 0} {
+	    set code [string index $c_line $parent]
 	    if {$code eq "-" || ($removed_idx < 0 && $code ne "+")} {
 		incr dline
 	    }
@@ -3197,7 +3196,8 @@ proc find_hunk_blamespec {base line} {
 	}
     }
 
-    if {$parent eq {}} { set parent 0 }
+    if {$parent eq {}} { set parent -1 }
+    incr parent
     incr dline [lindex $base_lines $parent]
     return [list $parent $dline]
 }

^ permalink raw reply related

* Re: [PATCH 1/2] Fix git branch -m for symrefs.
From: Junio C Hamano @ 2008-10-25 18:31 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: Jeff King, Brandon Casey, git
In-Reply-To: <a96243124c555cbc4081f733b348252ac200bd53.1224939436.git.vmiklos@frugalware.org>

Miklos Vajna <vmiklos@frugalware.org> writes:

> -int delete_ref(const char *refname, const unsigned char *sha1)
> +int delete_ref(const char *refname, const unsigned char *sha1, int flags)
>  {
>  	struct ref_lock *lock;
> -	int err, i, ret = 0, flag = 0;
> +	int err, i = 0, ret = 0, flag = 0;
> +	char *path;
>  
>  	lock = lock_ref_sha1_basic(refname, sha1, 0, &flag);
>  	if (!lock)
>  		return 1;
>  	if (!(flag & REF_ISPACKED)) {

Two variables flag vs flags is a bit confusing, isn't it?  How about
naming the new one "delopt" or something?

The new variable "char *path" at the toplevel can be confined in the scope
of this if () {} block and probably can become "const char *", right?

> @@ -964,10 +971,15 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
>  	struct ref_lock *lock;
>  	struct stat loginfo;
>  	int log = !lstat(git_path("logs/%s", oldref), &loginfo);
> +	const char *symref = NULL;
> +	int is_symref = 0;
>  
>  	if (S_ISLNK(loginfo.st_mode))
>  		return error("reflog for %s is a symlink", oldref);

Possible bug in the context.  When there is no reflog for the ref being
renamed, lstat would fail; it doesn't feel right to have this S_ISLNK()
before checking the result of the lstat which is in "log".

> +	symref = resolve_ref(oldref, orig_sha1, 0, &flag);
> +	if (flag & REF_ISSYMREF)
> +		is_symref = 1;
>  	if (!resolve_ref(oldref, orig_sha1, 1, &flag))
>  		return error("refname %s not found", oldref);

Do we really need two calls to resolve_ref()?  Your new call calls it
without must-exist bit --- why?  Immediately after that, the existing call
will barf if it does not exist anyway.

I agree it is good to have symref aware delete_ref(), but I am not sure
supporting symref in rename_ref() is either needed or necessarily a good
idea.  You also need to worry about a symref pointing at a branch yet to
be born.

In the meantime, I think we should just check (flag & REF_ISSYMREF) after
the existing resolve_ref() we can see in the context above, and error out
saying you cannot rename a symref, and do nothing else.

^ permalink raw reply

* Re: [PATCH 4/7] textconv: don't convert for every operation
From: Junio C Hamano @ 2008-10-25 18:32 UTC (permalink / raw)
  To: Jeff King; +Cc: Johannes Sixt, Matthieu Moy, git
In-Reply-To: <20081025071912.GA24287@coredump.intra.peff.net>

Jeff King <peff@peff.net> writes:

>> I am also somewhat worried about the performance impact of running
>> get_textconv() to the same filespec many times when no textconv is
>> defined, which is the normal case we should optimize for.  It appears that
>> diff_filespec_load_driver() is optimized for a wrong case (i.e. "we
>> already know this needs a custom driver and we know which one").
>
> No, it is the same as before. We always end up with a driver at the end
> of the function, so further calls will be no-ops. So we do exactly one
> attribute lookup per filespec, caching the result.

Ah, I missed that driver named "default".  Sorry for the noise.

> I think it makes sense to figure out _what_ needs fixed first, because
> it might be somewhat minor. So far I see:
>
>   - leak from fill_mmfile; this definitely needs fixed. The quick fix is
>     minor (free if we did a textconv). A more involved fix is to pull it
>     out of fill_mmfile entirely and put the code directly into
>     builtin_diff, which would be part of a re-roll of this latest
>     series.  But see below.
>
>   - Keep fill_mmfile allocation semantics clear.  I was trying to keep
>     it simple for other fill_mmfile callers to opt-in to textconv, even
>     if they chose to do it by some user-controlled mechanism instead of
>     by default (e.g., diff.TextconvDiffstat or something). But maybe
>     that is not of value to us. Again, that is a re-roll of this series.

It would be either:

 (1) non-textconv users call fill_mmfile(&mf, ..., 0), use mf and return
     without clean-up as before, while textconv users do:

 	fill_mmfile(&mf, ..., 1);
        use mf;
        if (mf->ptr != one->data)
		clean up mf->ptr;
        return;

or

 (2) non-textconv users are unchanged from v1.6.0, while textconv users
     do:

	const char *textconv = get_textconv(...);
	fill_mmfile(&mf, ...); /* no change to fill_mmfile() */
	if (textconv)
        	munge_mmfile(&mf);
	use mf;
        if (textconv)
        	cleanup_mmfile(&mf);

The end result may not be that much different, but I find the latter
easier to follow for three reasons:

 * we expect that majority of the users of fill_mmfile() are non textconv
   users.  I'd feel safer to keep their codepath the same as v1.6.0;

 * fill_mmfile() semantics is the same as long before -- it just gives it
   a borrowed pointer;

 * the code that makes a change to mmfile that requires clean-up does so
   explicitly, and that is followed by an explicit clean-up, both
   contained in the same function;

>   - performance considerations with driver loading. I believe this is a
>     non-issue. So either you are reading the code wrong,...

Yes I was.  Thanks and sorry.

^ permalink raw reply

* git export to svn
From: Warren Harris @ 2008-10-25 18:40 UTC (permalink / raw)
  To: git

Is there a way to export a git repository along with its history to  
svn? (git svn init seems to want to go in the other direction.) I know  
this is in some sense "going backwards" but I need to commit my work  
to a client. Thanks,

Warren

^ permalink raw reply

* Re: git export to svn
From: Warren Harris @ 2008-10-25 19:11 UTC (permalink / raw)
  To: J.H.; +Cc: git
In-Reply-To: <1224960205.2874.11.camel@localhost.localdomain>

John,

Thanks for your quick reply. I tried that, but got the following error:


$ git clone ../test2/
Initialized empty Git repository in /Users/warren/projects/tmp/test2- 
git-clone/test2/.git/
# ...svn test2 dir already created with subdirs trunk, tags and  
branches...
$ git svn init https://svn/svn/SANDBOX/warren/test2 -T trunk -t tags - 
b branches
Using higher level of URL: https://svn/svn/SANDBOX/warren/test2 => https://svn/svn
$ git svn dcommit
Can't call method "full_url" on an undefined value at /opt/local/ 
libexec/git-core/git-svn line 425.

I then tried the hints from here: http://www.basementcoders.com/2008/9/30/git-svn-gotcha 
, but still no luck:

$ git merge --no-ff master
Already up-to-date.
$ git svn dcommit
Can't call method "full_url" on an undefined value at /opt/local/ 
libexec/git-core/git-svn line 425.


Warren


On Oct 25, 2008, at 11:43 AM, J.H. wrote:

> The basic way you would want to do it, it attach your git tree to SVN
> and then git svn dcommit - which will replay the uncommitted changes
> back into SVN - git svn init will do the attachment - assuming that  
> your
> git / svn repositories are at least based from the same place.
>
> - John 'Warthog9' Hawley
>
> On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
>> Is there a way to export a git repository along with its history to
>> svn? (git svn init seems to want to go in the other direction.) I  
>> know
>> this is in some sense "going backwards" but I need to commit my work
>> to a client. Thanks,
>>
>> Warren
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: [PATCH v2] Fixed git archive for bare repos
From: Junio C Hamano @ 2008-10-25 19:15 UTC (permalink / raw)
  To: Deskin Miller
  Cc: René Scharfe, Charles Bailey, git, kenneth johansson,
	gitster
In-Reply-To: <20081025153814.GA26752@euler>

Thanks all.  Will apply to 'maint' for 1.6.0.4.

^ permalink raw reply

* Re: git export to svn
From: J.H. @ 2008-10-25 18:43 UTC (permalink / raw)
  To: Warren Harris; +Cc: git
In-Reply-To: <FC51BBF1-B2CA-4A00-9312-2333FDA537C2@gmail.com>

The basic way you would want to do it, it attach your git tree to SVN
and then git svn dcommit - which will replay the uncommitted changes
back into SVN - git svn init will do the attachment - assuming that your
git / svn repositories are at least based from the same place.

- John 'Warthog9' Hawley

On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
> Is there a way to export a git repository along with its history to  
> svn? (git svn init seems to want to go in the other direction.) I know  
> this is in some sense "going backwards" but I need to commit my work  
> to a client. Thanks,
> 
> Warren
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 4/7] textconv: don't convert for every operation
From: Jeff King @ 2008-10-25 19:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Sixt, Matthieu Moy, git
In-Reply-To: <7v3aika5l7.fsf@gitster.siamese.dyndns.org>

On Sat, Oct 25, 2008 at 11:32:20AM -0700, Junio C Hamano wrote:

> The end result may not be that much different, but I find the latter
> easier to follow for three reasons:

Your reasoning here is sound. My initial thought was to make it a
one-liner change to "turn on" text conversion in other spots. But

  a) it didn't turn out that way, since you still have to keep track of
     the "did I textconv" when determining binary-ness, and whether to
     free()

  b) we don't actually want to do it anywhere else (except perhaps, as I
     mentioned, in blame, but that is a totally different interface
     anyway)

I will re-roll my latest series according to your recommendation
(unless you are set on reverting the first part; if so, please tell me
asap so I can work under that assumption).

-Peff

^ permalink raw reply

* Re: [PATCH 5/5] blame: use xdi_diff_hunks(), get rid of struct patch
From: Junio C Hamano @ 2008-10-25 19:36 UTC (permalink / raw)
  To: René Scharfe; +Cc: Brian Downing, git
In-Reply-To: <49031FB8.8060003@lsrfire.ath.cx>

René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:

> Based on a patch by Brian Downing, this replaces the struct patch based
> code for blame passing with calls to xdi_diff_hunks().  This way we
> avoid generating and then parsing patches; we only let the interesting
> infos be passed to our callbacks instead.  This makes blame a bit faster:
>
>    $ blame="./git blame -M -C -C -p --incremental v1.6.0"
>
>    # master
>    $ /usr/bin/time $blame Makefile >/dev/null
>    1.38user 0.14system 0:01.52elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
>    0inputs+0outputs (0major+12226minor)pagefaults 0swaps
>    $ /usr/bin/time $blame cache.h >/dev/null
>    1.66user 0.13system 0:01.80elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
>    0inputs+0outputs (0major+12262minor)pagefaults 0swaps
>
>    # this patch series
>    $ /usr/bin/time $blame Makefile >/dev/null
>    1.27user 0.12system 0:01.40elapsed 99%CPU (0avgtext+0avgdata 0maxresident)k
>    0inputs+0outputs (0major+11836minor)pagefaults 0swaps
>    $ /usr/bin/time $blame cache.h >/dev/null
>    1.52user 0.12system 0:01.70elapsed 97%CPU (0avgtext+0avgdata 0maxresident)k
>    0inputs+0outputs (0major+12052minor)pagefaults 0swaps
>
> Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>

The resulting series reads quite clean.  I like it.

> Brian, your numbers looked much more impressive.  Could you please clock
> this code with your repository and the file server.c?  I wonder if this
> callback mechanism is just too complicated or if your case simply benefits
> lots more than the two files from git mentioned above.
>
> The patch series ends here without adding xdiff caching, for two reasons.
> It's quite easy to add it; patch 4 from your series applies unchanged and
> patch 5 is just needs a few small changes to account for the absence of
> compare_buffer().  More importantly, speed actually went down with caching
> for the test case.  The common tail optimization (xdi_diff() vs. xdl_diff())
> seems to beat caching for cache.h and Makefile..

Perhaps revision.c in our history would be more interesting than cache.h
or Makefile, as there are more line migrations from different places to
that file.

^ permalink raw reply

* Re: git export to svn
From: J.H. @ 2008-10-25 20:12 UTC (permalink / raw)
  To: Warren Harris; +Cc: git
In-Reply-To: <77DFC428-35AE-4F66-9D9F-3D4E0005727D@gmail.com>

Even with init - your going to need to do a fetch so that you have a
copy of the svn in your tree - if the git tree you've already got has
the svn references (take a look at git-log if it seems to have an svn
line in the log then at some point someone pulled in the svn tree into
git) if not your going to effectively be pulling the entire svn tree
into your git tree.

The only other real way to get your changes / patches into svn is to
dump them out as patches and them individually apply / commit them to
your svn tree.

- John 'Warthog9' Hawley


On Sat, 2008-10-25 at 12:11 -0700, Warren Harris wrote:
> John,
> 
> Thanks for your quick reply. I tried that, but got the following error:
> 
> 
> $ git clone ../test2/
> Initialized empty Git repository in /Users/warren/projects/tmp/test2- 
> git-clone/test2/.git/
> # ...svn test2 dir already created with subdirs trunk, tags and  
> branches...
> $ git svn init https://svn/svn/SANDBOX/warren/test2 -T trunk -t tags - 
> b branches
> Using higher level of URL: https://svn/svn/SANDBOX/warren/test2 => https://svn/svn
> $ git svn dcommit
> Can't call method "full_url" on an undefined value at /opt/local/ 
> libexec/git-core/git-svn line 425.
> 
> I then tried the hints from here: http://www.basementcoders.com/2008/9/30/git-svn-gotcha 
> , but still no luck:
> 
> $ git merge --no-ff master
> Already up-to-date.
> $ git svn dcommit
> Can't call method "full_url" on an undefined value at /opt/local/ 
> libexec/git-core/git-svn line 425.
> 
> 
> Warren
> 
> 
> On Oct 25, 2008, at 11:43 AM, J.H. wrote:
> 
> > The basic way you would want to do it, it attach your git tree to SVN
> > and then git svn dcommit - which will replay the uncommitted changes
> > back into SVN - git svn init will do the attachment - assuming that  
> > your
> > git / svn repositories are at least based from the same place.
> >
> > - John 'Warthog9' Hawley
> >
> > On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
> >> Is there a way to export a git repository along with its history to
> >> svn? (git svn init seems to want to go in the other direction.) I  
> >> know
> >> this is in some sense "going backwards" but I need to commit my work
> >> to a client. Thanks,
> >>
> >> Warren
> >> --
> >> To unsubscribe from this list: send the line "unsubscribe git" in
> >> the body of a message to majordomo@vger.kernel.org
> >> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> >
> 
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: Problem with git filter-branch
From: Johannes Schindelin @ 2008-10-25 20:36 UTC (permalink / raw)
  To: Pascal Obry; +Cc: git list
In-Reply-To: <4902E7D8.6050401@obry.net>

Hi,

On Sat, 25 Oct 2008, Pascal Obry wrote:

> Anyway, I used to run the following command:
> 
> $ git filter-branch --tag-name-filter cat --parent-filter "sed -e
> 's/^$/-p c96d4da294667de1800687d25340551683153002/'" svn-release_2_6
> 
> without problem, I now get this:
> 
> Namespace refs/original/ not empty
> rm: cannot remove directory
> `/home/obry/dev/repositories/git/proj/.git-rewrite': Directory not empty

It is a (maybe ill-conceived) feature.  When branches are rewritten, their 
original versions are stored in the refs/original/ namespace.  You can 
force overwriting with "-f".

I wonder if people would like to have this feature removed; reflogs should 
be enough.

Thoughts?

Ciao,
Dscho

^ permalink raw reply

* Re: git export to svn
From: Warren Harris @ 2008-10-25 20:29 UTC (permalink / raw)
  To: J.H.; +Cc: git
In-Reply-To: <1224965564.2874.49.camel@localhost.localdomain>

I tried a fetch, but still no luck:

$ git svn fetch
W: Ignoring error from SVN, path probably does not exist: (175002): RA  
layer request failed: REPORT of '/svn/!svn/bc/100': Could not read  
chunk size: Secure connection truncated (https://svn)
W: Do not be alarmed at the above message git-svn is just searching  
aggressively for old history.
This may take a while on large repositories
r58084 = c01dadf89b552077da132273485e7569d8694518 (trunk)
	A	...
r58088 = 7916f3a02ad6c759985bd9fb886423c373a72125 (trunk)

$ git svn rebase
Unable to determine upstream SVN information from working tree history

$ git svn dcommit
Can't call method "full_url" on an undefined value at /opt/local/ 
libexec/git-core/git-svn line 425.


Looks like the only option is applying individual patches to preserve  
my history...

Warren


On Oct 25, 2008, at 1:12 PM, J.H. wrote:

> Even with init - your going to need to do a fetch so that you have a
> copy of the svn in your tree - if the git tree you've already got has
> the svn references (take a look at git-log if it seems to have an svn
> line in the log then at some point someone pulled in the svn tree into
> git) if not your going to effectively be pulling the entire svn tree
> into your git tree.
>
> The only other real way to get your changes / patches into svn is to
> dump them out as patches and them individually apply / commit them to
> your svn tree.
>
> - John 'Warthog9' Hawley
>
>
> On Sat, 2008-10-25 at 12:11 -0700, Warren Harris wrote:
>> John,
>>
>> Thanks for your quick reply. I tried that, but got the following  
>> error:
>>
>>
>> $ git clone ../test2/
>> Initialized empty Git repository in /Users/warren/projects/tmp/test2-
>> git-clone/test2/.git/
>> # ...svn test2 dir already created with subdirs trunk, tags and
>> branches...
>> $ git svn init https://svn/svn/SANDBOX/warren/test2 -T trunk -t  
>> tags -
>> b branches
>> Using higher level of URL: https://svn/svn/SANDBOX/warren/test2 => https://svn/svn
>> $ git svn dcommit
>> Can't call method "full_url" on an undefined value at /opt/local/
>> libexec/git-core/git-svn line 425.
>>
>> I then tried the hints from here: http://www.basementcoders.com/2008/9/30/git-svn-gotcha
>> , but still no luck:
>>
>> $ git merge --no-ff master
>> Already up-to-date.
>> $ git svn dcommit
>> Can't call method "full_url" on an undefined value at /opt/local/
>> libexec/git-core/git-svn line 425.
>>
>>
>> Warren
>>
>>
>> On Oct 25, 2008, at 11:43 AM, J.H. wrote:
>>
>>> The basic way you would want to do it, it attach your git tree to  
>>> SVN
>>> and then git svn dcommit - which will replay the uncommitted changes
>>> back into SVN - git svn init will do the attachment - assuming that
>>> your
>>> git / svn repositories are at least based from the same place.
>>>
>>> - John 'Warthog9' Hawley
>>>
>>> On Sat, 2008-10-25 at 11:40 -0700, Warren Harris wrote:
>>>> Is there a way to export a git repository along with its history to
>>>> svn? (git svn init seems to want to go in the other direction.) I
>>>> know
>>>> this is in some sense "going backwards" but I need to commit my  
>>>> work
>>>> to a client. Thanks,
>>>>
>>>> Warren
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe git" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe git" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ 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