Git development
 help / color / mirror / Atom feed
* Re: git-difftool
From: Matthieu Moy @ 2009-01-01 17:58 UTC (permalink / raw)
  To: David Aguilar; +Cc: git
In-Reply-To: <402731c90812311211p548c49d3p100f79ddee7163b0@mail.gmail.com>

"David Aguilar" <davvid@gmail.com> writes:

> Hmm... in theory, yes, but in practice, no.
> xxdiff is too gimp to handle what 'git diff' hands it =)

As done with "vimdiff" in another message, simply write a one-liner
wrapper script that calls xxdiff $2 $3, and call this wrapper script.

-- 
Matthieu

^ permalink raw reply

* Re: [PATCH] Documentation/git-bundle.txt: Dumping contents of any bundle
From: Johannes Schindelin @ 2009-01-01 17:03 UTC (permalink / raw)
  To: jidanni; +Cc: git
In-Reply-To: <87prj7mz50.fsf_-_@jidanni.org>

Hi,

On Thu, 1 Jan 2009, jidanni@jidanni.org wrote:

> >>>>> "JK" == Jeff King <peff@peff.net> writes:
> 
> JK> AFAIK, there is no tool to try salvaging strings from an incomplete pack
> JK> (and you can't just run "strings" because the deltas are zlib
> JK> compressed). So if I were in the police forensics department, I think I
> JK> would read Documentation/technical/pack-format.txt and start hacking a
> JK> solution as quickly as possible.
> 
> Hogwash. Patch follows. Maybe even better methods are available.
> 
> Signed-off-by: jidanni <jidanni@jidanni.org>
> ---

Just for the record: this is in so many ways not a commit message I want 
to have in git.git.  I hope it is not applied.

Ciao,
Dscho

^ permalink raw reply

* Re: is there an easier way to do this ?
From: Johannes Schindelin @ 2009-01-01 16:55 UTC (permalink / raw)
  To: Zorba; +Cc: git
In-Reply-To: <gjeacg$3r5$4@ger.gmane.org>

Hi,

A: Because it messes up the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

On Tue, 30 Dec 2008, Zorba wrote:

> > "Zorba" <cr@altmore.co.uk> writes:
> >
> >> ok, now I'm in this for real, archiving versions of our website project 
> >> (5k
> >> files approx)
> >>
> >> so here is the workflow:
> >>
> >> - copy version 1 files into GIT dir
> >>
> >> - open git bash
> >>
> >> $ git init
> >>
> >> $ git add .
> >>
> >> $ git commit -m "version1"
> >>
> >> all vanilla ? cool
> >> next job = store version 2 [...]
> >
> > Check out contrib/fast-import/import-tars.perl
>
> thanks Jakub, but I don't mind copying the versions in by hand and 
> running the git commits on them sequentially.

It's not only about how much work you are doing.  It's also about 
preserving as much metadata as possible.

Ciao,
Dscho

^ permalink raw reply

* Re: Extracting a single commit or object
From: Johannes Schindelin @ 2009-01-01 16:52 UTC (permalink / raw)
  To: yitzhakbg; +Cc: git
In-Reply-To: <21223948.post@talk.nabble.com>

Hi,

On Tue, 30 Dec 2008, yitzhakbg wrote:

> How would I extract a single commit from a repository by it's SHA1 (or 
> any other treeish)?

Your question is not precise enough to answer.  Are you looking for

- the commit message?
- the patch?
- all the files referenced by that commit?
- all the files _and revisions_ referenced by that commit?

The answer depends quite a lot on the question...

> For that matter, how is any one single object extracted? Examples please.

The user-friendly way to look at a tree is

	git show HEAD:Documentation/

or some such.  Likewise, you can inspect single blobs like this:

	git show HEAD:README

If you activated bash completion, you can even complete monsters like 
this:

	git show \
v1.5.3:v1.5.3:t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master

Hth,
Dscho

^ permalink raw reply

* [PATCH 3/3] bash completions: Add the --patience option
From: Johannes Schindelin @ 2009-01-01 16:39 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: davidel, Francis Galiegue, Git ML
In-Reply-To: <alpine.DEB.1.00.0901011730190.30769@pacific.mpi-cbg.de>


Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 contrib/completion/git-completion.bash |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index a046441..b3e1e22 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -777,6 +777,7 @@ _git_diff ()
 			--no-prefix --src-prefix= --dst-prefix=
 			--base --ours --theirs
 			--inter-hunk-context=
+			--patience
 			"
 		return
 		;;
@@ -969,6 +970,7 @@ _git_log ()
 			--parents --children --full-history
 			--merge
 			--inter-hunk-context=
+			--patience
 			"
 		return
 		;;
-- 
1.6.1.rc3.412.ga72b

^ permalink raw reply related

* [PATCH 2/3] Introduce the diff option '--patience'
From: Johannes Schindelin @ 2009-01-01 16:39 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: davidel, Francis Galiegue, Git ML
In-Reply-To: <alpine.DEB.1.00.0901011730190.30769@pacific.mpi-cbg.de>


This commit teaches Git to produce diff output using the patience diff
algorithm with the diff option '--patience'.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	git log --check complains about this patch, for obvious reasons.

 Documentation/diff-options.txt |    3 +
 Makefile                       |    2 +-
 diff.c                         |    2 +
 t/t4033-diff-patience.sh       |  168 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 174 insertions(+), 1 deletions(-)
 create mode 100755 t/t4033-diff-patience.sh

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 671f533..15ef35a 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -36,6 +36,9 @@ endif::git-format-patch[]
 --patch-with-raw::
 	Synonym for "-p --raw".
 
+--patience:
+	Generate a diff using the "patience diff" algorithm.
+
 --stat[=width[,name-width]]::
 	Generate a diffstat.  You can override the default
 	output width for 80-column terminal by "--stat=width".
diff --git a/Makefile b/Makefile
index 154cf34..2217873 100644
--- a/Makefile
+++ b/Makefile
@@ -1287,7 +1287,7 @@ $(LIB_FILE): $(LIB_OBJS)
 	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
 
 XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \
-	xdiff/xmerge.o
+	xdiff/xmerge.o xdiff/xpatience.o
 $(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \
 	xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h
 
diff --git a/diff.c b/diff.c
index 56b80f9..67718b7 100644
--- a/diff.c
+++ b/diff.c
@@ -2472,6 +2472,8 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		options->xdl_opts |= XDF_IGNORE_WHITESPACE_CHANGE;
 	else if (!strcmp(arg, "--ignore-space-at-eol"))
 		options->xdl_opts |= XDF_IGNORE_WHITESPACE_AT_EOL;
+	else if (!strcmp(arg, "--patience"))
+		options->xdl_opts |= XDF_PATIENCE_DIFF;
 
 	/* flags options */
 	else if (!strcmp(arg, "--binary")) {
diff --git a/t/t4033-diff-patience.sh b/t/t4033-diff-patience.sh
new file mode 100755
index 0000000..63c1b00
--- /dev/null
+++ b/t/t4033-diff-patience.sh
@@ -0,0 +1,168 @@
+#!/bin/sh
+
+test_description='patience diff algorithm'
+
+. ./test-lib.sh
+
+cat > file1 << EOF
+#include <stdio.h>
+
+// Frobs foo heartily
+int frobnitz(int foo)
+{
+    int i;
+    for(i = 0; i < 10; i++)
+    {
+        printf("Your answer is: ");
+        printf("%d\n", foo);
+    }
+}
+
+int fact(int n)
+{
+    if(n > 1)
+    {
+        return fact(n-1) * n;
+    }
+    return 1;
+}
+
+int main(int argc, char **argv)
+{
+    frobnitz(fact(10));
+}
+EOF
+
+cat > file2 << EOF
+#include <stdio.h>
+
+int fib(int n)
+{
+    if(n > 2)
+    {
+        return fib(n-1) + fib(n-2);
+    }
+    return 1;
+}
+
+// Frobs foo heartily
+int frobnitz(int foo)
+{
+    int i;
+    for(i = 0; i < 10; i++)
+    {
+        printf("%d\n", foo);
+    }
+}
+
+int main(int argc, char **argv)
+{
+    frobnitz(fib(10));
+}
+EOF
+
+cat > expect << EOF
+diff --git a/file1 b/file2
+index 6faa5a3..e3af329 100644
+--- a/file1
++++ b/file2
+@@ -1,26 +1,25 @@
+ #include <stdio.h>
+ 
++int fib(int n)
++{
++    if(n > 2)
++    {
++        return fib(n-1) + fib(n-2);
++    }
++    return 1;
++}
++
+ // Frobs foo heartily
+ int frobnitz(int foo)
+ {
+     int i;
+     for(i = 0; i < 10; i++)
+     {
+-        printf("Your answer is: ");
+         printf("%d\n", foo);
+     }
+ }
+ 
+-int fact(int n)
+-{
+-    if(n > 1)
+-    {
+-        return fact(n-1) * n;
+-    }
+-    return 1;
+-}
+-
+ int main(int argc, char **argv)
+ {
+-    frobnitz(fact(10));
++    frobnitz(fib(10));
+ }
+EOF
+
+test_expect_success 'patience diff' '
+
+	test_must_fail git diff --no-index --patience file1 file2 > output &&
+	test_cmp expect output
+
+'
+
+test_expect_success 'patience diff output is valid' '
+
+	mv file2 expect &&
+	git apply < output &&
+	test_cmp expect file2
+
+'
+
+cat > uniq1 << EOF
+1
+2
+3
+4
+5
+6
+EOF
+
+cat > uniq2 << EOF
+a
+b
+c
+d
+e
+f
+EOF
+
+cat > expect << EOF
+diff --git a/uniq1 b/uniq2
+index b414108..0fdf397 100644
+--- a/uniq1
++++ b/uniq2
+@@ -1,6 +1,6 @@
+-1
+-2
+-3
+-4
+-5
+-6
++a
++b
++c
++d
++e
++f
+EOF
+
+test_expect_success 'completely different files' '
+
+	test_must_fail git diff --no-index --patience uniq1 uniq2 > output &&
+	test_cmp expect output
+
+'
+
+test_done
-- 
1.6.1.rc3.412.ga72b

^ permalink raw reply related

* [PATCH 1/3] Implement the patience diff algorithm
From: Johannes Schindelin @ 2009-01-01 16:38 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: davidel, Francis Galiegue, Git ML
In-Reply-To: <alpine.DEB.1.00.0901011730190.30769@pacific.mpi-cbg.de>


The patience diff algorithm produces slightly more intuitive output
than the classic Myers algorithm, as it does not try to minimize the
number of +/- lines first, but tries to preserve the lines that are
unique.

To this end, it first determines lines that are unique in both files,
then the maximal sequence which preserves the order (relative to both
files) is extracted.

Starting from this initial set of common lines, the rest of the lines
is handled recursively, with Myers' algorithm as a fallback when
the patience algorithm fails (due to no common unique lines).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 xdiff/xdiff.h     |    1 +
 xdiff/xdiffi.c    |    3 +
 xdiff/xdiffi.h    |    2 +
 xdiff/xpatience.c |  374 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 380 insertions(+), 0 deletions(-)
 create mode 100644 xdiff/xpatience.c

diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 361f802..4da052a 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -32,6 +32,7 @@ extern "C" {
 #define XDF_IGNORE_WHITESPACE (1 << 2)
 #define XDF_IGNORE_WHITESPACE_CHANGE (1 << 3)
 #define XDF_IGNORE_WHITESPACE_AT_EOL (1 << 4)
+#define XDF_PATIENCE_DIFF (1 << 5)
 #define XDF_WHITESPACE_FLAGS (XDF_IGNORE_WHITESPACE | XDF_IGNORE_WHITESPACE_CHANGE | XDF_IGNORE_WHITESPACE_AT_EOL)
 
 #define XDL_PATCH_NORMAL '-'
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index 9d0324a..3e97462 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -329,6 +329,9 @@ int xdl_do_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	xdalgoenv_t xenv;
 	diffdata_t dd1, dd2;
 
+	if (xpp->flags & XDF_PATIENCE_DIFF)
+		return xdl_do_patience_diff(mf1, mf2, xpp, xe);
+
 	if (xdl_prepare_env(mf1, mf2, xpp, xe) < 0) {
 
 		return -1;
diff --git a/xdiff/xdiffi.h b/xdiff/xdiffi.h
index 3e099dc..ad033a8 100644
--- a/xdiff/xdiffi.h
+++ b/xdiff/xdiffi.h
@@ -55,5 +55,7 @@ int xdl_build_script(xdfenv_t *xe, xdchange_t **xscr);
 void xdl_free_script(xdchange_t *xscr);
 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
 		  xdemitconf_t const *xecfg);
+int xdl_do_patience_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
+		xdfenv_t *env);
 
 #endif /* #if !defined(XDIFFI_H) */
diff --git a/xdiff/xpatience.c b/xdiff/xpatience.c
new file mode 100644
index 0000000..6687940
--- /dev/null
+++ b/xdiff/xpatience.c
@@ -0,0 +1,374 @@
+/*
+ *  LibXDiff by Davide Libenzi ( File Differential Library )
+ *  Copyright (C) 2003-2009 Davide Libenzi, Johannes E. Schindelin
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2.1 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  Davide Libenzi <davidel@xmailserver.org>
+ *
+ */
+#include "xinclude.h"
+#include "xtypes.h"
+#include "xdiff.h"
+
+/*
+ * The basic idea of patience diff is to find lines that are unique in
+ * both files.  These are intuitively the ones that we want to see as
+ * common lines.
+ *
+ * The maximal ordered sequence of such line pairs (where ordered means
+ * that the order in the sequence agrees with the order of the lines in
+ * both files) naturally defines an initial set of common lines.
+ *
+ * Now, the algorithm tries to extend the set of common lines by growing
+ * the line ranges where the files have identical lines.
+ *
+ * Between those common lines, the patience diff algorithm is applied
+ * recursively, until no unique line pairs can be found; these line ranges
+ * are handled by the well-known Myers algorithm.
+ */
+
+#define NON_UNIQUE ULONG_MAX
+
+/*
+ * This is a hash mapping from line hash to line numbers in the first and
+ * second file.
+ */
+struct hashmap {
+	int nr, alloc;
+	struct entry {
+		unsigned long hash;
+		/*
+		 * 0 = unused entry, 1 = first line, 2 = second, etc.
+		 * line2 is NON_UNIQUE if the line is not unique
+		 * in either the first or the second file.
+		 */
+		unsigned long line1, line2;
+		/*
+		 * "next" & "previous" are used for the longest common
+		 * sequence;
+		 * initially, "next" reflects only the order in file1.
+		 */
+		struct entry *next, *previous;
+	} *entries, *first, *last;
+	/* were common records found? */
+	unsigned long has_matches;
+	mmfile_t *file1, *file2;
+	xdfenv_t *env;
+	xpparam_t const *xpp;
+};
+
+/* The argument "pass" is 1 for the first file, 2 for the second. */
+static void insert_record(int line, struct hashmap *map, int pass)
+{
+	xrecord_t **records = pass == 1 ?
+		map->env->xdf1.recs : map->env->xdf2.recs;
+	xrecord_t *record = records[line - 1], *other;
+	/*
+	 * After xdl_prepare_env() (or more precisely, due to
+	 * xdl_classify_record()), the "ha" member of the records (AKA lines)
+	 * is _not_ the hash anymore, but a linearized version of it.  In
+	 * other words, the "ha" member is guaranteed to start with 0 and
+	 * the second record's ha can only be 0 or 1, etc.
+	 *
+	 * So we multiply ha by 2 in the hope that the hashing was
+	 * "unique enough".
+	 */
+	int index = (int)((record->ha << 1) % map->alloc);
+
+	while (map->entries[index].line1) {
+		other = map->env->xdf1.recs[map->entries[index].line1 - 1];
+		if (map->entries[index].hash != record->ha ||
+				!xdl_recmatch(record->ptr, record->size,
+					other->ptr, other->size,
+					map->xpp->flags)) {
+			if (++index >= map->alloc)
+				index = 0;
+			continue;
+		}
+		if (pass == 2)
+			map->has_matches = 1;
+		if (pass == 1 || map->entries[index].line2)
+			map->entries[index].line2 = NON_UNIQUE;
+		else
+			map->entries[index].line2 = line;
+		return;
+	}
+	if (pass == 2)
+		return;
+	map->entries[index].line1 = line;
+	map->entries[index].hash = record->ha;
+	if (!map->first)
+		map->first = map->entries + index;
+	if (map->last) {
+		map->last->next = map->entries + index;
+		map->entries[index].previous = map->last;
+	}
+	map->last = map->entries + index;
+	map->nr++;
+}
+
+/*
+ * This function has to be called for each recursion into the inter-hunk
+ * parts, as previously non-unique lines can become unique when being
+ * restricted to a smaller part of the files.
+ *
+ * It is assumed that env has been prepared using xdl_prepare().
+ */
+static int fill_hashmap(mmfile_t *file1, mmfile_t *file2,
+		xpparam_t const *xpp, xdfenv_t *env,
+		struct hashmap *result,
+		int line1, int count1, int line2, int count2)
+{
+	result->file1 = file1;
+	result->file2 = file2;
+	result->xpp = xpp;
+	result->env = env;
+
+	/* We know exactly how large we want the hash map */
+	result->alloc = count1 * 2;
+	result->entries = (struct entry *)
+		xdl_malloc(result->alloc * sizeof(struct entry));
+	if (!result->entries)
+		return -1;
+	memset(result->entries, 0, result->alloc * sizeof(struct entry));
+
+	/* First, fill with entries from the first file */
+	while (count1--)
+		insert_record(line1++, result, 1);
+
+	/* Then search for matches in the second file */
+	while (count2--)
+		insert_record(line2++, result, 2);
+
+	return 0;
+}
+
+/*
+ * Find the longest sequence with a smaller last element (meaning a smaller
+ * line2, as we construct the sequence with entries ordered by line1).
+ */
+static int binary_search(struct entry **sequence, int longest,
+		struct entry *entry)
+{
+	int left = -1, right = longest;
+
+	while (left + 1 < right) {
+		int middle = (left + right) / 2;
+		/* by construction, no two entries can be equal */
+		if (sequence[middle]->line2 > entry->line2)
+			right = middle;
+		else
+			left = middle;
+	}
+	/* return the index in "sequence", _not_ the sequence length */
+	return left;
+}
+
+/*
+ * The idea is to start with the list of common unique lines sorted by
+ * the order in file1.  For each of these pairs, the longest (partial)
+ * sequence whose last element's line2 is smaller is determined.
+ *
+ * For efficiency, the sequences are kept in a list containing exactly one
+ * item per sequence length: the sequence with the smallest last
+ * element (in terms of line2).
+ */
+static struct entry *find_longest_common_sequence(struct hashmap *map)
+{
+	struct entry **sequence = xdl_malloc(map->nr * sizeof(struct entry *));
+	int longest = 0, i;
+	struct entry *entry;
+
+	for (entry = map->first; entry; entry = entry->next) {
+		if (!entry->line2 || entry->line2 == NON_UNIQUE)
+			continue;
+		i = binary_search(sequence, longest, entry);
+		entry->previous = i < 0 ? NULL : sequence[i];
+		sequence[++i] = entry;
+		if (i == longest)
+			longest++;
+	}
+
+	/* No common unique lines were found */
+	if (!longest)
+		return NULL;
+
+	/* Iterate starting at the last element, adjusting the "next" members */
+	entry = sequence[longest - 1];
+	entry->next = NULL;
+	while (entry->previous) {
+		entry->previous->next = entry;
+		entry = entry->previous;
+	}
+	return entry;
+}
+
+static int match(struct hashmap *map, int line1, int line2)
+{
+	xrecord_t *record1 = map->env->xdf1.recs[line1 - 1];
+	xrecord_t *record2 = map->env->xdf2.recs[line2 - 1];
+	return xdl_recmatch(record1->ptr, record1->size,
+		record2->ptr, record2->size, map->xpp->flags);
+}
+
+static int patience_diff(mmfile_t *file1, mmfile_t *file2,
+		xpparam_t const *xpp, xdfenv_t *env,
+		int line1, int count1, int line2, int count2);
+
+static int walk_common_sequence(struct hashmap *map, struct entry *first,
+		int line1, int count1, int line2, int count2)
+{
+	int end1 = line1 + count1, end2 = line2 + count2;
+	int next1, next2;
+
+	for (;;) {
+		/* Try to grow the line ranges of common lines */
+		if (first) {
+			next1 = first->line1;
+			next2 = first->line2;
+			while (next1 > line1 && next2 > line2 &&
+					match(map, next1 - 1, next2 - 1)) {
+				next1--;
+				next2--;
+			}
+		} else {
+			next1 = end1;
+			next2 = end2;
+		}
+		while (line1 < next1 && line2 < next2 &&
+				match(map, line1, line2)) {
+			line1++;
+			line2++;
+		}
+
+		/* Recurse */
+		if (next1 > line1 || next2 > line2) {
+			struct hashmap submap;
+
+			memset(&submap, 0, sizeof(submap));
+			if (patience_diff(map->file1, map->file2,
+					map->xpp, map->env,
+					line1, next1 - line1,
+					line2, next2 - line2))
+				return -1;
+		}
+
+		if (!first)
+			return 0;
+
+		while (first->next &&
+				first->next->line1 == first->line1 + 1 &&
+				first->next->line2 == first->line2 + 1)
+			first = first->next;
+
+		line1 = first->line1 + 1;
+		line2 = first->line2 + 1;
+
+		first = first->next;
+	}
+}
+
+static int fall_back_to_classic_diff(struct hashmap *map,
+		int line1, int count1, int line2, int count2)
+{
+	/*
+	 * This probably does not work outside Git, since
+	 * we have a very simple mmfile structure.
+	 *
+	 * Note: ideally, we would reuse the prepared environment, but
+	 * the libxdiff interface does not (yet) allow for diffing only
+	 * ranges of lines instead of the whole files.
+	 */
+	mmfile_t subfile1, subfile2;
+	xpparam_t xpp;
+	xdfenv_t env;
+
+	subfile1.ptr = (char *)map->env->xdf1.recs[line1 - 1]->ptr;
+	subfile1.size = map->env->xdf1.recs[line1 + count1 - 2]->ptr +
+		map->env->xdf1.recs[line1 + count1 - 2]->size - subfile1.ptr;
+	subfile2.ptr = (char *)map->env->xdf2.recs[line2 - 1]->ptr;
+	subfile2.size = map->env->xdf2.recs[line2 + count2 - 2]->ptr +
+		map->env->xdf2.recs[line2 + count2 - 2]->size - subfile2.ptr;
+	xpp.flags = map->xpp->flags & ~XDF_PATIENCE_DIFF;
+	if (xdl_do_diff(&subfile1, &subfile2, &xpp, &env) < 0)
+		return -1;
+
+	memcpy(map->env->xdf1.rchg + line1 - 1, env.xdf1.rchg, count1);
+	memcpy(map->env->xdf2.rchg + line2 - 1, env.xdf2.rchg, count2);
+
+	return 0;
+}
+
+/*
+ * Recursively find the longest common sequence of unique lines,
+ * and if none was found, ask xdl_do_diff() to do the job.
+ *
+ * This function assumes that env was prepared with xdl_prepare_env().
+ */
+static int patience_diff(mmfile_t *file1, mmfile_t *file2,
+		xpparam_t const *xpp, xdfenv_t *env,
+		int line1, int count1, int line2, int count2)
+{
+	struct hashmap map;
+	struct entry *first;
+	int result = 0;
+
+	/* trivial case: one side is empty */
+	if (!count1) {
+		while(count2--)
+			env->xdf2.rchg[line2++ - 1] = 1;
+		return 0;
+	} else if (!count2) {
+		while(count1--)
+			env->xdf1.rchg[line1++ - 1] = 1;
+		return 0;
+	}
+
+	memset(&map, 0, sizeof(map));
+	if (fill_hashmap(file1, file2, xpp, env, &map,
+			line1, count1, line2, count2))
+		return -1;
+
+	/* are there any matching lines at all? */
+	if (!map.has_matches) {
+		while(count1--)
+			env->xdf1.rchg[line1++ - 1] = 1;
+		while(count2--)
+			env->xdf2.rchg[line2++ - 1] = 1;
+		return 0;
+	}
+
+	first = find_longest_common_sequence(&map);
+	if (first)
+		result = walk_common_sequence(&map, first,
+			line1, count1, line2, count2);
+	else
+		result = fall_back_to_classic_diff(&map,
+			line1, count1, line2, count2);
+
+	return result;
+}
+
+int xdl_do_patience_diff(mmfile_t *file1, mmfile_t *file2,
+		xpparam_t const *xpp, xdfenv_t *env)
+{
+	if (xdl_prepare_env(file1, file2, xpp, env) < 0)
+		return -1;
+
+	/* environment is cleaned up in xdl_diff() */
+	return patience_diff(file1, file2, xpp, env,
+			1, env->xdf1.nrec, 1, env->xdf2.nrec);
+}
-- 
1.6.1.rc3.412.ga72b

^ permalink raw reply related

* [PATCH 0/3] Teach Git about the patience diff algorithm
From: Johannes Schindelin @ 2009-01-01 16:38 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: davidel, Francis Galiegue, Git ML
In-Reply-To: <20081104152351.GA21842@artemis.corp>


Nothing fancy, really, just a straight-forward implementation of the
heavily under-documented and under-analyzed paience diff algorithm.

One thing is a bit ugly: the libxdiff interface does not allow to
calculate diffs of ranges of lines.  So instead of reusing an initialized
environment (with line hashes and all), the simple structure of mmfile_t
is exploited to fake an mmfile_t of a file _part_, reusing the file's
buffer.

And this mmfile_t pair gets a new environment, recalculating hashes and 
all.

Davide, I think it would be easier to refactor xdl_do_diff() to take line
ranges, and use that interface both in xpatience.c and in xmerge.c.  
(Although I do not know if you took xmerge.c at all; you seemed a bit 
reluctant about it back when I sent it to you.)

For those interested in studying the code, I suggest starting with the 
short comment at the beginning of xpatience.c and then working yourself up 
from the end (i.e. xdl_do_patience_diff()).

It might be a good idea to think about using this code in our merging code
once it is well reviewed and tested, as it might help a substantial number
of otherwise non-trivial merge conflicts.

Oh, and the bash completions are so trivial I did not even bother to test
them.

Happy new year.

Johannes Schindelin (3):
  Implement the patience diff algorithm
  Introduce the diff option '--patience'
  bash completions: Add the --patience option

 Documentation/diff-options.txt         |    3 +
 Makefile                               |    2 +-
 contrib/completion/git-completion.bash |    2 +
 diff.c                                 |    2 +
 t/t4033-diff-patience.sh               |  168 ++++++++++++++
 xdiff/xdiff.h                          |    1 +
 xdiff/xdiffi.c                         |    3 +
 xdiff/xdiffi.h                         |    2 +
 xdiff/xpatience.c                      |  374 ++++++++++++++++++++++++++++++++
 9 files changed, 556 insertions(+), 1 deletions(-)
 create mode 100755 t/t4033-diff-patience.sh
 create mode 100644 xdiff/xpatience.c

^ permalink raw reply

* Re: [PATCH] Documentation/gitcli.txt: dashed forms not allowed anymore
From: Miklos Vajna @ 2009-01-01 14:40 UTC (permalink / raw)
  To: jidanni; +Cc: git, gitster
In-Reply-To: <87ljtvmygk.fsf@jidanni.org>

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

On Thu, Jan 01, 2009 at 12:39:39PM +0800, jidanni@jidanni.org wrote:
> - * it's preferred to use the non dashed form of git commands, which means that
> -   you should prefer `"git foo"` to `"git-foo"`.
> + * it's required to use the non dashed form of git commands, which means that
> +   you must use `"git foo"` and not `"git-foo"`. The latter no longer works.

I would append: "unless you add the output of `git --exec-path` to your
PATH."

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [RFC PATCH] builtin-apply: prevent non-explicit permission changes
From: Junio C Hamano @ 2009-01-01 13:00 UTC (permalink / raw)
  To: Alexander Potashev; +Cc: Git Mailing List
In-Reply-To: <20081230235357.GA12747@myhost>

Alexander Potashev <aspotashev@gmail.com> writes:

>  builtin-apply.c |    3 ++-
>  1 files changed, 2 insertions(+), 1 deletions(-)
>
> diff --git a/builtin-apply.c b/builtin-apply.c
> index 07244b0..071f6d8 100644
> --- a/builtin-apply.c
> +++ b/builtin-apply.c
> @@ -630,7 +630,7 @@ static int gitdiff_index(const char *line, struct patch *patch)
>  	memcpy(patch->new_sha1_prefix, line, len);
>  	patch->new_sha1_prefix[len] = 0;
>  	if (*ptr == ' ')
> -		patch->new_mode = patch->old_mode = strtoul(ptr+1, NULL, 8);
> +		patch->old_mode = strtoul(ptr+1, NULL, 8);
>  	return 0;
>  }
>  
> @@ -2447,6 +2447,7 @@ static int check_preimage(struct patch *patch, struct cache_entry **ce, struct s
>  	if (st_mode != patch->old_mode)
>  		fprintf(stderr, "warning: %s has type %o, expected %o\n",
>  			old_name, st_mode, patch->old_mode);
> +	patch->new_mode = st_mode;

Can you do this unconditionally, overwriting whatever we read from the
patch header metainfo lines?

^ permalink raw reply

* Re: shallow clone, shallow fetch?
From: Sitaram Chamarty @ 2009-01-01  9:25 UTC (permalink / raw)
  To: git
In-Reply-To: <877i5fohwr.fsf@jidanni.org>

On 2009-01-01, jidanni@jidanni.org <jidanni@jidanni.org> wrote:
> Last week I did git-clone --depth 1 This week I wanted to freshen my
> repository, with the same goal: "I don't care about history, just
> fast forward me with the least bytes transfered." But all I can find
> is just plain git pull. Did I achieve my goal?
> $ git pull
> remote: Counting objects: 7007, done.
> remote: Compressing objects: 100% (3057/3057), done.
> remote: Total 7007 (delta 4280), reused 6076 (delta 3625)
> Receiving objects: 100% (7007/7007), 2.96 MiB | 26 KiB/s, done.
> Resolving deltas: 100% (4280/4280), done.
> From git://git.kernel.org/pub/scm/git/git
>    2fa431b..bbbb865  html       -> origin/html
>    a9012e3..936b705  maint      -> origin/maint
>    dfd79c7..794d84e  man        -> origin/man
>    159c88e..c32f76f  master     -> origin/master
>    3b9b952..6f67462  next       -> origin/next
>  + b14a7fb...89bdc19 pu         -> origin/pu  (forced update)

The hashes certainly agree with what I have (just did a pull
this minute), except I also have a new branch called
"origin/todo" at SHA1=6670008 which you seem to be missing.

I'm not familiar enough with shallow clones to draw any
conclusions though :-(

^ permalink raw reply

* Re: git has modified files after clean checkout
From: Caleb Cushing @ 2009-01-01  8:48 UTC (permalink / raw)
  To: David Aguilar; +Cc: git
In-Reply-To: <402731c90812311541v28ac9617ge52e0e5c0f1298d2@mail.gmail.com>

>  The files you mention contain CRLF.  Do you have core.autocrlf set
>  globally somewhere, perhaps in your ~/.gitconfig?

yes I have it set to input

>  Anyways.. like I said -- I couldn't reproduce your problem so this is
>  pure speculation on my part =)

it's inconsistent although I see something more often than not, and
only with this particular repository. Sometimes it's one set of files
other times it's others. this time it was 2 sometimes it's more like
40 (just throwing numbers around) and that can be the same unchanged
clone. seem to happen on checkout. heck even noticed a git reset
--hard HEAD didn't clear it all the first time today, in one case.

after sleep I'll see if 1.6.1 fixes my issue.

-- 
Caleb Cushing

http://xenoterracide.blogspot.com

^ permalink raw reply

* Re: git-difftool
From: Ping Yin @ 2009-01-01  7:38 UTC (permalink / raw)
  To: Matthieu Moy; +Cc: David Aguilar, git
In-Reply-To: <vpqhc4kz5zh.fsf@bauges.imag.fr>

On Thu, Jan 1, 2009 at 12:04 AM, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:
> David Aguilar <davvid@gmail.com> writes:
>
>> The usual use case for this script is when you have either
>> staged or unstaged changes and you'd like to see the changes
>> in a side-by-side diff viewer (e.g. xxdiff, tkdiff, etc).
>>
>>       git difftool [<filename>*]
>
> Is it not a complex way of saying
>
>        GIT_EXTERNAL_DIFF=xxdiff git diff

$ cat mydiff
#!/bin/bash
exec vimdiff $2 $5

then i run

$ GIT_EXTERNAL_DIFF=mydiff  git diff

but it gives me the error
Vim: Warning: Output is not to a terminal

$ ps -ef | grep vimdiff
ping     20284 20283  1 15:37 pts/13   00:00:00 vimdiff
/tmp/.diff_XXXQK6 index.php

^ permalink raw reply

* Re: git-difftool
From: Boyd Stephen Smith Jr. @ 2008-12-31 21:20 UTC (permalink / raw)
  To: David Aguilar; +Cc: git, Matthieu Moy
In-Reply-To: <402731c90812311211p548c49d3p100f79ddee7163b0@mail.gmail.com>

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

On Wednesday 2008 December 31 14:11:07 you wrote:
> On Wed, Dec 31, 2008 at 8:04 AM, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:
> > David Aguilar <davvid@gmail.com> writes:
> >> The usual use case for this script is when you have either
> >> staged or unstaged changes and you'd like to see the changes
> >> in a side-by-side diff viewer (e.g. xxdiff, tkdiff, etc).
> >>
> >>       git difftool [<filename>*]
> >
> > Is it not a complex way of saying
> >
> >        GIT_EXTERNAL_DIFF=xxdiff git diff
> >
> > ?
>
> Hmm... in theory, yes, but in practice, no.
> xxdiff is too gimp to handle what 'git diff' hands it =)

What about something like:
git diff | xxdiff -

I normally use:
git diff | kompare -

and it works fine.
-- 
Boyd Stephen Smith Jr.                     ,= ,-_-. =. 
bss@iguanasuicide.net                     ((_/)o o(\_))
ICQ: 514984 YM/AIM: DaTwinkDaddy           `-'(. .)`-' 
http://iguanasuicide.net/                      \_/     

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* [PATCH] Documentation/gitcli.txt: dashed forms not allowed anymore
From: jidanni @ 2009-01-01  4:39 UTC (permalink / raw)
  To: git; +Cc: gitster

Non dashed command forms now mandatory.

Signed-off-by: jidanni <jidanni@jidanni.org>
---
 Documentation/gitcli.txt |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/gitcli.txt b/Documentation/gitcli.txt
index 29e5929..9f582f6 100644
--- a/Documentation/gitcli.txt
+++ b/Documentation/gitcli.txt
@@ -45,8 +45,8 @@ disambiguating `\--` at appropriate places.
 Here are the rules regarding the "flags" that you should follow when you are
 scripting git:
 
- * it's preferred to use the non dashed form of git commands, which means that
-   you should prefer `"git foo"` to `"git-foo"`.
+ * it's required to use the non dashed form of git commands, which means that
+   you must use `"git foo"` and not `"git-foo"`. The latter no longer works.
 
  * splitting short options to separate words (prefer `"git foo -a -b"`
    to `"git foo -ab"`, the latter may not even work).
-- 
1.6.0.6

^ permalink raw reply related

* [PATCH] Documentation/git-bundle.txt: Dumping contents of any bundle
From: jidanni @ 2009-01-01  4:24 UTC (permalink / raw)
  To: peff, gitster; +Cc: mdl123, spearce, git
In-Reply-To: <20081219205100.GA26671@coredump.intra.peff.net>

>>>>> "JK" == Jeff King <peff@peff.net> writes:

JK> AFAIK, there is no tool to try salvaging strings from an incomplete pack
JK> (and you can't just run "strings" because the deltas are zlib
JK> compressed). So if I were in the police forensics department, I think I
JK> would read Documentation/technical/pack-format.txt and start hacking a
JK> solution as quickly as possible.

Hogwash. Patch follows. Maybe even better methods are available.

Signed-off-by: jidanni <jidanni@jidanni.org>
---
 Documentation/git-bundle.txt |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 1b66ab7..80248f5 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -164,6 +164,28 @@ $ git pull bundle
 would treat it as if it is talking with a remote side over the
 network.
 
+DUMPING CONTENTS OF ANY BUNDLE
+-----------------------
+
+Even if we cannot unbundle a bundle,
+
+------------
+$ git init
+$ git bundle unbundle mybundle.bun
+error: Repository lacks these prerequisite commits...
+------------
+
+We can still examine all the data contained within,
+
+------------
+$ sed '/^PACK/,$!d' mybundle.bun > mybundle.pack
+$ git unpack-objects < mybundle.pack
+$ cd .git/objects
+$ ls ??/*|tr -d /|git cat-file --batch-check
+$ ls ??/*|tr -d /|git cat-file --batch
+------------
+
+
 Author
 ------
 Written by Mark Levedahl <mdl123@verizon.net>
-- 
1.6.0.6

^ permalink raw reply related

* Re: shallow clone, shallow fetch?
From: jidanni @ 2009-01-01  2:54 UTC (permalink / raw)
  To: git
In-Reply-To: <87vdt24zz4.fsf@jidanni.org>

Last week I did git-clone --depth 1 This week I wanted to freshen my
repository, with the same goal: "I don't care about history, just
fast forward me with the least bytes transfered." But all I can find
is just plain git pull. Did I achieve my goal?
$ git pull
remote: Counting objects: 7007, done.
remote: Compressing objects: 100% (3057/3057), done.
remote: Total 7007 (delta 4280), reused 6076 (delta 3625)
Receiving objects: 100% (7007/7007), 2.96 MiB | 26 KiB/s, done.
Resolving deltas: 100% (4280/4280), done.
From git://git.kernel.org/pub/scm/git/git
   2fa431b..bbbb865  html       -> origin/html
   a9012e3..936b705  maint      -> origin/maint
   dfd79c7..794d84e  man        -> origin/man
   159c88e..c32f76f  master     -> origin/master
   3b9b952..6f67462  next       -> origin/next
 + b14a7fb...89bdc19 pu         -> origin/pu  (forced update)
Merge made by recursive.
 Documentation/Makefile             |    9 +++++----
 Documentation/RelNotes-1.6.1.1.txt |   23 +++++++++++++++++++++++
 Documentation/cat-texi.perl        |    8 ++++++--
 Documentation/git-reset.txt        |   29 ++++++++++++++++++++++++++++-
 builtin-pack-objects.c             |    9 ++++++++-
 builtin-reset.c                    |   26 ++++++++++++++++++--------
 gitweb/gitweb.perl                 |    5 +++--
 t/t5302-pack-index.sh              |    1 +
 8 files changed, 92 insertions(+), 18 deletions(-)
 create mode 100644 Documentation/RelNotes-1.6.1.1.txt

^ permalink raw reply

* Re: why still no empty directory support in git
From: Anatol Pomozov @ 2009-01-01  2:50 UTC (permalink / raw)
  To: Liu Yubao; +Cc: Ping Yin, Git Mailing List
In-Reply-To: <4959BB07.6000106@gmail.com>

Hi

On Mon, Dec 29, 2008 at 10:09 PM, Liu Yubao <yubao.liu@gmail.com> wrote:
>
> Ping Yin wrote:
> > Yes, i know this topic has been discussed for many times. However, i
> > am still not clear about the real reason.
> >
> > So which is the reason?
> >
> > 1. it's by design, intentional
> It's saied somewhere git is a "stupid content tracker", it cares file content
> not file name, and empty directories will complicate the merge algorithm
> unnecessarily.

Could you please explain how will it complicate merging. What is the
difference between merging 2 directories with 0 and 5 files and
merging 2 directories with 5 and 10 files?

+1 that git should respect empty directories. Git should handle file
content and not decide for user does he want to keep empty directory
in the source tree or not.

--
anatol

^ permalink raw reply

* Re: git has modified files after clean checkout
From: David Aguilar @ 2008-12-31 23:41 UTC (permalink / raw)
  To: Caleb Cushing; +Cc: git
In-Reply-To: <81bfc67a0812311223g2b6e8476y84b23c19977dfd10@mail.gmail.com>

On Wed, Dec 31, 2008 at 12:23 PM, Caleb Cushing <xenoterracide@gmail.com> wrote:
> here's what I did
>
> rm -r portage
> git clone git@github.com:xenoterracide/portage.git


Here's the anonymous clone URL (the one you provided is private)
    $ git clone git://github.com/xenoterracide/portage.git

Read on below...

> cd portage
> git checkout origin/regen2 -b regen2
> git status
>
> # On branch regen2
> # Changed but not updated:
> #   (use "git add <file>..." to update what will be committed)
> #
> #       modified:
> x11-themes/metacity-themes/files/metacity-themes-1.0-gentoo.diff
> #       modified:
> x11-themes/metacity-themes/files/metacity-themes-1.2-gentoo.diff
> #
> no changes added to commit (use "git add" and/or "git commit -a")
>
> why are there files claiming to be modified? this is a clean clone.
> I've had this before I usually end up doing a git reset --hard HEAD,
> but I'm thinking it's a bug, since I've seen it vary on the same clone
> and sometimes even disappear.
>
> git version 1.6.0.6
> --
> Caleb Cushing
>
> http://xenoterracide.blogspot.com

I followed the steps above and did not run into any such issues.

$ git status
# On branch regen2
nothing to commit (working directory clean)

$ git version
git version 1.6.1.28.gc32f76
(Junio's latest master at the moment)

Here's my quick guess based on what I'm seeing --

The files you mention contain CRLF.  Do you have core.autocrlf set
globally somewhere, perhaps in your ~/.gitconfig?

It's possible that the autocrlf stuff is messing with those files.
They seem to be a mix of both unix LF and CRLF (the CRLF stuff doesn't
start until line 104 of
x11-themes/metacity-themes/files/metacity-themes-1.0-gentoo.diff, for
example, which is kinda odd but maybe be intentional?)

Check your autocrlf settings.
The following commands print out nothing for me:

    $ git config core.autocrlf
    $ git config --global core.autocrlf

Anyways.. like I said -- I couldn't reproduce your problem so this is
pure speculation on my part =)

Good luck,

-- 
    David

^ permalink raw reply

* git has modified files after clean checkout
From: Caleb Cushing @ 2008-12-31 20:23 UTC (permalink / raw)
  To: git

here's what I did

rm -r portage
git clone git@github.com:xenoterracide/portage.git
cd portage
git checkout origin/regen2 -b regen2
git status

# On branch regen2
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#       modified:
x11-themes/metacity-themes/files/metacity-themes-1.0-gentoo.diff
#       modified:
x11-themes/metacity-themes/files/metacity-themes-1.2-gentoo.diff
#
no changes added to commit (use "git add" and/or "git commit -a")

why are there files claiming to be modified? this is a clean clone.
I've had this before I usually end up doing a git reset --hard HEAD,
but I'm thinking it's a bug, since I've seen it vary on the same clone
and sometimes even disappear.

git version 1.6.0.6
-- 
Caleb Cushing

http://xenoterracide.blogspot.com

^ permalink raw reply

* Re: git-difftool
From: David Aguilar @ 2008-12-31 20:11 UTC (permalink / raw)
  To: Matthieu Moy; +Cc: git
In-Reply-To: <vpqhc4kz5zh.fsf@bauges.imag.fr>

On Wed, Dec 31, 2008 at 8:04 AM, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:
> David Aguilar <davvid@gmail.com> writes:
>
>> The usual use case for this script is when you have either
>> staged or unstaged changes and you'd like to see the changes
>> in a side-by-side diff viewer (e.g. xxdiff, tkdiff, etc).
>>
>>       git difftool [<filename>*]
>
> Is it not a complex way of saying
>
>        GIT_EXTERNAL_DIFF=xxdiff git diff
>
> ?
>
> (My 2 cents, and happy new year ;-)
>
> --
> Matthieu
>

Hmm... in theory, yes, but in practice, no.
xxdiff is too gimp to handle what 'git diff' hands it =)


For example:

$ GIT_EXTERNAL_DIFF=echo git diff test
test /tmp/.diff_1dh4TW 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 100644 test 0000

$ GIT_EXTERNAL_DIFF=xxdiff git diff test
xxdiff (cmdline.cpp:762):
You can specify at most 3 filenames.
Extra arguments: " 100644 test 0000000000000000000000000000000000000000 100644"
Use 'xxdiff --help' for more information.
external diff died, stopping at test.


I checked the git-diff documentation and could not find a way to
inhibit the sha1, mode, etc. args that are sent to GIT_EXTERNAL_DIFF
(nor should there be, I presume).

I'm all for finding the simplest way and GIT_EXTERNAL_DIFF seems like
the right entry point.  What I should do is change the script so that
it handles all of the choosing-a-merge-tool-logic and just have git
call it via GIT_EXTERNAL_DIFF.  That would definitely simplify the
script since 'git diff' would be handling all of the tmp file and
option processing logic.  wow, I really like that idea.  Thanks for
the tip!


Happy new year,

-- 
    David

^ permalink raw reply

* [JGIT PATCH] Improve the sideband progress scaper to be more accurate
From: Shawn O. Pearce @ 2008-12-31 19:04 UTC (permalink / raw)
  To: Robin Rosenberg; +Cc: git
In-Reply-To: <20081231073505.GA22551@spearce.org>

By matching only whole lines we should be able to improve the
progress scaper so we avoid ugly output like we had been seeing:

  EGIT.contrib/jgit clone git://repo.or.cz/libgit2.git LIBGIT2
  Initialized empty Git repository in /home/me/SW/LIBGIT2/.git
  Counting objects:       547
  Compressing objects:    100% (192/192)
  ts:                     100% (192/192)
  Compressing objects:    100% (192/192)
  ng objects:             100% (192/192)

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
 > Would it be hard to get the progress look better?

 Maybe this does the trick.  Its hard to reproduce so its hard to
 come up with the condition that was giving us the problem before.
 I suspect its because we were getting line fragments on the sideband
 channel, but I'm not sure that was really the case.

 .../jgit/transport/SideBandInputStream.java        |   37 +++++++++++++++++--
 1 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/SideBandInputStream.java b/org.spearce.jgit/src/org/spearce/jgit/transport/SideBandInputStream.java
index 3ec9bff..f0ba3d3 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/transport/SideBandInputStream.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/SideBandInputStream.java
@@ -73,10 +73,10 @@
 	private static final int CH_ERROR = 3;
 
 	private static Pattern P_UNBOUNDED = Pattern.compile(
-			".*?([\\w ]+): (\\d+)(, done)?.*", Pattern.DOTALL);
+			"^([\\w ]+): (\\d+)( |, done)?.*", Pattern.DOTALL);
 
 	private static Pattern P_BOUNDED = Pattern.compile(
-			".*?([\\w ]+):.*\\((\\d+)/(\\d+)\\).*", Pattern.DOTALL);
+			"^([\\w ]+):.*\\((\\d+)/(\\d+)\\).*", Pattern.DOTALL);
 
 	private final PacketLineIn pckIn;
 
@@ -84,6 +84,8 @@
 
 	private final ProgressMonitor monitor;
 
+	private String progressBuffer = "";
+
 	private String currentTask;
 
 	private int lastCnt;
@@ -160,7 +162,31 @@ private void needDataPacket() throws IOException {
 		}
 	}
 
-	private void progress(final String msg) {
+	private void progress(String pkt) {
+		pkt = progressBuffer + pkt;
+		for (;;) {
+			final int lf = pkt.indexOf('\n');
+			final int cr = pkt.indexOf('\r');
+			final int s;
+			if (0 <= lf && 0 <= cr)
+				s = Math.min(lf, cr);
+			else if (0 <= lf)
+				s = lf;
+			else if (0 <= cr)
+				s = cr;
+			else
+				break;
+
+			final String msg = pkt.substring(0, s);
+			if (doProgressLine(msg))
+				pkt = pkt.substring(s + 1);
+			else
+				break;
+		}
+		progressBuffer = pkt;
+	}
+
+	private boolean doProgressLine(final String msg) {
 		Matcher matcher;
 
 		matcher = P_BOUNDED.matcher(msg);
@@ -175,7 +201,7 @@ private void progress(final String msg) {
 			final int cnt = Integer.parseInt(matcher.group(2));
 			monitor.update(cnt - lastCnt);
 			lastCnt = cnt;
-			return;
+			return true;
 		}
 
 		matcher = P_UNBOUNDED.matcher(msg);
@@ -189,7 +215,10 @@ private void progress(final String msg) {
 			final int cnt = Integer.parseInt(matcher.group(2));
 			monitor.update(cnt - lastCnt);
 			lastCnt = cnt;
+			return true;
 		}
+
+		return false;
 	}
 
 	private String readString(final int len) throws IOException {
-- 
1.6.1.59.g6f6746


-- 
Shawn.

^ permalink raw reply related

* Re: gitweb $export_ok question
From: Thomas Amsler @ 2008-12-31 18:56 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: git@vger.kernel.org
In-Reply-To: <6db6bed70812311013l3cf575c1y874e71e70d1dde57@mail.gmail.com>

One more question. Now, on the gitweb home page, the project name
hyper link shows up as:

authz.git/.git

where it used to be just:

authz.git/

is there a way to configure this so that it doesn't show the trailing .git?

Best,
-- Thomas




On Wed, Dec 31, 2008 at 10:13 AM, Thomas Amsler <tpamsler@ucdavis.edu> wrote:
> That did the trick. It wasn't quite clear from the documentation that the
> file defined by $export_ok has to be located in repository/.git/
>
> Thank you for your help.
>
> Best,
> -- Thomas
>
>
>
> On Wed, Dec 31, 2008 at 1:00 AM, Jakub Narebski <jnareb@gmail.com> wrote:
>>
>> Thomas Amsler wrote:
>>
>> > Thank you for your information.
>> >
>> > I have just tried that but the repository doesn't show up in gitweb
>> >
>> > - added to /etc/gitweb.conf
>> > -- $export_ok = "gitweb-export-ok"
>> > - touched the "gitweb-export-ok" file in the repository
>> > -- touch /path-to-repo/repository/authz.git/gitweb-export-ok
>> >
>> > Then gitweb reports:
>> >
>> > 404 - No projects found
>> >
>> > Does the gitweb-export-ok file need to be part of  the repo so that it
>> > is
>> > tracked?
>>
>> No, gitweb-export-ok file has to be in $GIT_DIR (like description file),
>> not part of repo.
>>
>> As to "No projects found" error: what is your $projectroot? Is it
>> either "/path-to-repo/repository" or "/path-to-repo"? Is repository
>> readable and searchable for the web server user (does it have correct
>> permissions)?
>> --
>> Jakub Narebski
>> Poland
>> --
>> 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: for newbs = little exercise / tutorial / warmup for windows and other non-sophisticated new Git users :-) [Scanned]
From: Sitaram Chamarty @ 2008-12-31 16:33 UTC (permalink / raw)
  To: git
In-Reply-To: <alpine.LNX.1.00.0812311103000.19665@iabervon.org>

On 2008-12-31, Daniel Barkalow <barkalow@iabervon.org> wrote:
>> $ git checkout .                    // tidy up current commit
>> $ git checkout <version>     // roll back

> Either that, or:
>
> $ git checkout <version>
> $ git checkout .
>
> (it doesn't matter whether you get rid of the local modifications and 
> deletions before switching, or switch first, and then get rid of any 
> remaining local modifications and deletions)
>
> You may also want:
>
> $ git clean

I think "git checkout -f <version>" will do *all* of that.

^ permalink raw reply

* Re: for newbs = little exercise / tutorial / warmup for windows and other non-sophisticated new Git users :-) [Scanned]
From: Daniel Barkalow @ 2008-12-31 16:24 UTC (permalink / raw)
  To: Zorba; +Cc: git
In-Reply-To: <gjfnsb$5ph$4@ger.gmane.org>

On Wed, 31 Dec 2008, Zorba wrote:

> Ok, now I'm following you, cos I just "broke" checkout again by deleting 
> files from working dirs before running it.
> 
> git-checkout takes into account the state of the working tree in the commit 
> it is run FROM, as well as the commit it is checking out.
> 
> It relies on the working tree being in synch with the commit it is run from.
> If I delete files, I screw around with this initial state.
> Files that git-checkout is relying on to be there are not copied in by it, 
> so if I've deleted (or modified) those files, hard luck.

It's not relying on these files to be there; it's actually aware that 
they're not there. It thinks that any modifications you've made might be 
important work, and carefully preserves it.

Actually, it should be telling you the changes that it's carrying over 
with lines like:

D	ABC.txt

(which indicated that you've deleted ABC.txt, and it's keeping that 
modification)

> I remember s/o saying git minimizes file I/O, and this whats happening here.
> 
> It puts a big demand on the user, to keep their index & working dir in synch 
> with whats in the commit.

The user is hopefully not going to make a lot of random undesired changes 
in general. It's hard to get much done that way. If you have made changes, 
you can use "git checkout ." to get the versions back from the index, or 
"git checkout HEAD ." to get them back from the commit. 

> Ah,
> 
> $ git checkout .
> 
> will restore the state of the working dir to be in synch with the CURRENT 
> commit, so it will be safe to checkout other branches
> 
> BINGO !!
> what I need to do is run the sequence
> 
> $ git checkout .                    // tidy up current commit
> $ git checkout <version>     // roll back
> 
> n'est pas ?

Either that, or:

$ git checkout <version>
$ git checkout .

(it doesn't matter whether you get rid of the local modifications and 
deletions before switching, or switch first, and then get rid of any 
remaining local modifications and deletions)

You may also want:

$ git clean

To get rid of untracked files you may have around (use "git clean -x" if 
you also want to get rid of files you've told git to ignore).

Incidentally, if your goal is to give someone a copy of the state as of a 
particular version, you can use:

$ git archive --format=zip <commit> > version.zip

This doesn't involve your working directory at all, and just generates a 
zip file out of the history. I find that this means I rarely actually care 
about having a working directory that's free of random junk.

	-Daniel
*This .sig left intentionally blank*

^ 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