Git development
 help / color / mirror / Atom feed
* Re: [PATCH 0/3] Teach Git about the patience diff algorithm
From: Linus Torvalds @ 2009-01-02 18:49 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Pierre Habouzit, davidel, Francis Galiegue, Git ML
In-Reply-To: <alpine.DEB.1.00.0901021914420.30769@pacific.mpi-cbg.de>



On Fri, 2 Jan 2009, Johannes Schindelin wrote:
> 
> BTW the "-p" is not necessary with "show", indeed, you cannot even switch 
> it off.

I was just switching back-and-forth between "git log" and "git show" so 
the -p came from just that, and is not necessary.

And you _can_ suppress the patch generation - use "-s".

			Linus

^ permalink raw reply

* Re: [CLEANUP PATCH RESEND] git wrapper: Make while loop more reader-friendly
From: Johannes Schindelin @ 2009-01-02 18:49 UTC (permalink / raw)
  To: Boyd Stephen Smith Jr.; +Cc: git, gitster
In-Reply-To: <200901021228.07599.bss@iguanasuicide.net>

Hi,

On Fri, 2 Jan 2009, Boyd Stephen Smith Jr. wrote:

> On Friday 2009 January 02 12:07:52 you wrote:
> > It is not a good practice to prefer performance over readability in
> > something as performance uncritical as finding the trailing slash
> > of argv[0].
> >
> > So avoid head-scratching by making the loop user-readable, and not
> > hyper-performance-optimized.
> 
> > -	do
> > -		--slash;
> > -	while (cmd <= slash && !is_dir_sep(*slash));
> > +	while (cmd <= slash && !is_dir_sep(*slash))
> > +		slash--;
> 
> What confused people?  The predecrement or the do/while?  Should people that 
> don't understand one of those be hacking on git?
> 
> That said, I'm not opposed to the patch.  It is easier on the eyes, though I 
> prefer the one-liner:
> for (; cmd <= slash && !is_dir_sep(*slash); --slash);

As I mentioned in the commit message: readability is something to be 
cherished and worshipped.

For your pleasure, I will not go into details about the motions my bowels 
went through when I looked at those three lines.  Or your single line, for 
that matter.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 0/3] Teach Git about the patience diff algorithm
From: Johannes Schindelin @ 2009-01-02 18:46 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Clemens Buchacher, Adeodato Simó, Pierre Habouzit, davidel,
	Francis Galiegue, Git ML
In-Reply-To: <alpine.LFD.2.00.0901020833000.5086@localhost.localdomain>

Hi,

On Fri, 2 Jan 2009, Linus Torvalds wrote:


> On Fri, 2 Jan 2009, Clemens Buchacher wrote:
> >
> > Only two choices, and I still get it wrong. The diffs should be 
> > labeled the other way around, of course.
> 
> Yes, this one is a real patience diff change, but it's also the same one 
> that I've seen in the google fanboi findings. What google did _not_ show 
> was any real-life examples, or anybody doing any critical analysis.

FWIW it's the test case in the commit introducing the --patience option.

> So I was hoping for something else than a single "in this case patience 
> diff works really well". I was hoping to see what it does in real life.

I will dig out a real-world example where I _know_ patience diff would 
have helped.  (I remember that I rewrote a pretty large diff which was 
sent on this list, only to understand what it actually does, and I am 
pretty certain this is a good real-world showcase.)

But yes, I agree, the thing does not matter _all_ that much in reality.

The case where I expect a real improvement is when you modify a function 
and insert a function just before it, and Myers' algorithm matches mainly 
empty lines and lines ending in curly brackets.

In other words: something I tried to tackle with ee95ec5d(xdl_merge(): 
introduce XDL_MERGE_ZEALOUS_ALNUM) for merges.

The typical look of such a diff is something like this:

-<... some function header ...>
+<... a completely different function header ...>
 {
-	<... variables ...>
+	<... other variables ...>
 
 	for (i = 0; i < 10; i++) {
-		<... some code ...>
+		<... some code doing something completely different ...>
	}
 
 	return 0;
 }

+<... the function header which was removed earlier ...>
+{
 	<... refactored _and also reindented_ code ...>

> And I haven't seen _any_ real critical analysis of it. Anywhere.

Neither have I.  Let alone something close to documentation.

For example, when the "patience diff algorithm" is explained, it looks 
more like a longest common sequence algorithm when the input is already 
sorted in the first item.

Further, there is no rigorous analysis of the runtime (I figured that the 
original runtime is O(nm) where "n" is the number of lines and "m" is the 
length of the maximal ordered sequence of common unique lines, and my 
implementation can only improve that to O(n log(m))).

This could be improved, I think, for the most common case where you have 
pretty long common _continuous_ sequences of unique lines, i.e. large 
ranges of lines that are identical.

The runtime is especially horrible in the light of the runtime of Myers' 
algorithm, which uses O(n d), where d is the edit distance, i.e. the 
number of lines added + number of lines removed.  (Note: in the real 
world, there are substantial speed ups for consecutive edits, i.e. line 
ranges where there are no common lines at all.)

Also, I am less than thrilled by the job the fanbois did coming up with 
"convincing" evidence: exactly as you pointed out, there are _no_ 
real-world examples where it helps.

And the worst part: one can only _guess_ what motivated patience diff.  I 
imagine it came from the observation that function headers are unique, and 
that you usually want to preserve as much context around them.

Ciao,
Dscho

^ permalink raw reply

* Re: [CLEANUP PATCH RESEND] git wrapper: Make while loop more reader-friendly
From: Boyd Stephen Smith Jr. @ 2009-01-02 18:28 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, gitster
In-Reply-To: <alpine.DEB.1.00.0901021240270.27818@racer>

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

On Friday 2009 January 02 12:07:52 you wrote:
> It is not a good practice to prefer performance over readability in
> something as performance uncritical as finding the trailing slash
> of argv[0].
>
> So avoid head-scratching by making the loop user-readable, and not
> hyper-performance-optimized.

> -	do
> -		--slash;
> -	while (cmd <= slash && !is_dir_sep(*slash));
> +	while (cmd <= slash && !is_dir_sep(*slash))
> +		slash--;

What confused people?  The predecrement or the do/while?  Should people that 
don't understand one of those be hacking on git?

That said, I'm not opposed to the patch.  It is easier on the eyes, though I 
prefer the one-liner:
for (; cmd <= slash && !is_dir_sep(*slash); --slash);
-- 
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

* Re: [PATCH 0/3] Teach Git about the patience diff algorithm
From: Johannes Schindelin @ 2009-01-02 18:17 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Pierre Habouzit, davidel, Francis Galiegue, Git ML
In-Reply-To: <alpine.LFD.2.00.0901011151440.5086@localhost.localdomain>

Hi,

On Thu, 1 Jan 2009, Linus Torvalds wrote:

> On Thu, 1 Jan 2009, Linus Torvalds wrote:
> > 
> > So could we have some actual real data on it?
> 
> .. and some testing. I tried to get some limited data for the kernel 
> myself, by doing
> 
> 	git log --patience -p v2.6.28.. > ~/patience
> 
> but I just got a core-dump instead.
> 
> Pinpointing it to a specific commit shows a smaller failure case:
> 
> 	git show -p --patience 05d564fe00c05bf8ff93948057ca1acb5bc68e10
> 
> which might help you debug this.

Thanks.  I am on it.  valgrind finds an earlier place in 
xdl_change_compact() which I think is rather more sensible, but at the 
same time a bit worrisome, too, as I did not expect any errors _that_ 
late in the game (I did not touch that code).

BTW the "-p" is not necessary with "show", indeed, you cannot even switch 
it off.

Ciao,
Dscho

^ permalink raw reply

* [CLEANUP PATCH] show <tag>: reuse pp_user_info() instead of duplicating code
From: Johannes Schindelin @ 2009-01-02 18:08 UTC (permalink / raw)
  To: git, gitster


We used to extract the tagger information "by hand" in "git show <tag>",
but the function pp_user_info() already does that.  Even better:
it respects the commit_format and date_format specified by the user.

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

	Just a little cleanup, as I tripped over that part of Git's source.

 builtin-log.c |   21 ++++++---------------
 1 files changed, 6 insertions(+), 15 deletions(-)

diff --git a/builtin-log.c b/builtin-log.c
index 99d1137..bc4e1e9 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -249,22 +249,13 @@ int cmd_whatchanged(int argc, const char **argv, const char *prefix)
 
 static void show_tagger(char *buf, int len, struct rev_info *rev)
 {
-	char *email_end, *p;
-	unsigned long date;
-	int tz;
+	struct strbuf out = STRBUF_INIT;
 
-	email_end = memchr(buf, '>', len);
-	if (!email_end)
-		return;
-	p = ++email_end;
-	while (isspace(*p))
-		p++;
-	date = strtoul(p, &p, 10);
-	while (isspace(*p))
-		p++;
-	tz = (int)strtol(p, NULL, 10);
-	printf("Tagger: %.*s\nDate:   %s\n", (int)(email_end - buf), buf,
-	       show_date(date, tz, rev->date_mode));
+	pp_user_info("Tagger", rev->commit_format, &out, buf, rev->date_mode,
+		git_log_output_encoding ?
+		git_log_output_encoding: git_commit_encoding);
+	printf("%s\n", out.buf);
+	strbuf_release(&out);
 }
 
 static int show_object(const unsigned char *sha1, int show_tag_object,
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* [PATCH] bundle: allow rev-list options to exclude annotated tags
From: Johannes Schindelin @ 2009-01-02 18:08 UTC (permalink / raw)
  To: git, gitster


With options such as "--all --since=2.weeks.ago", annotated tags used to
be included, when they should have been excluded.  The reason is that we
heavily abuse the revision walker to determine what needs to be included
or excluded.  And the revision walker does not show tags at all (and
therefore never marks tags as uninteresting).

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 bundle.c          |   32 ++++++++++++++++++++++++++++++++
 t/t5704-bundle.sh |   33 +++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 0 deletions(-)
 create mode 100755 t/t5704-bundle.sh

diff --git a/bundle.c b/bundle.c
index daecd8e..4977962 100644
--- a/bundle.c
+++ b/bundle.c
@@ -167,6 +167,32 @@ int list_bundle_refs(struct bundle_header *header, int argc, const char **argv)
 	return list_refs(&header->references, argc, argv);
 }
 
+static int is_tag_in_date_range(struct object *tag, struct rev_info *revs)
+{
+	unsigned long size;
+	enum object_type type;
+	char *buf, *line, *lineend;
+	unsigned long date;
+
+	if (revs->max_age == -1 && revs->min_age == -1)
+		return 1;
+
+	buf = read_sha1_file(tag->sha1, &type, &size);
+	if (!buf)
+		return 1;
+	line = memmem(buf, size, "\ntagger ", 8);
+	if (!line++)
+		return 1;
+	lineend = memchr(line, buf + size - line, '\n');
+	line = memchr(line, lineend ? lineend - line : buf + size - line, '>');
+	if (!line++)
+		return 1;
+	date = strtoul(line, NULL, 10);
+	free(buf);
+	return (revs->max_age == -1 || revs->max_age < date) &&
+		(revs->min_age == -1 || revs->min_age > date);
+}
+
 int create_bundle(struct bundle_header *header, const char *path,
 		int argc, const char **argv)
 {
@@ -255,6 +281,12 @@ int create_bundle(struct bundle_header *header, const char *path,
 			flag = 0;
 		display_ref = (flag & REF_ISSYMREF) ? e->name : ref;
 
+		if (e->item->type == OBJ_TAG &&
+				!is_tag_in_date_range(e->item, &revs)) {
+			e->item->flags |= UNINTERESTING;
+			continue;
+		}
+
 		/*
 		 * Make sure the refs we wrote out is correct; --max-count and
 		 * other limiting options could have prevented all the tips
diff --git a/t/t5704-bundle.sh b/t/t5704-bundle.sh
new file mode 100755
index 0000000..a8f4419
--- /dev/null
+++ b/t/t5704-bundle.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='some bundle related tests'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+	: > file &&
+	git add file &&
+	test_tick &&
+	git commit -m initial &&
+	test_tick &&
+	git tag -m tag tag &&
+	: > file2 &&
+	git add file2 &&
+	: > file3 &&
+	test_tick &&
+	git commit -m second &&
+	git add file3 &&
+	test_tick &&
+	git commit -m third
+
+'
+
+test_expect_success 'tags can be excluded by rev-list options' '
+
+	git bundle create bundle --all --since=7.Apr.2005.15:16:00.-0700 &&
+	git ls-remote bundle > output &&
+	! grep tag output
+
+'
+
+test_done
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* [RESEND PATCH] git add: do not add files from a submodule
From: Johannes Schindelin @ 2009-01-02 18:08 UTC (permalink / raw)
  To: git, gitster


It comes quite as a surprise to an unsuspecting Git user that calling
"git add submodule/file" (which is a mistake, alright) _removes_
the submodule in the index, and adds the file.  Instead, complain loudly.

While at it, be nice when the user said "git add submodule/" which is
most likely the consequence of tab-completion, and stage the submodule,
instead of trying to add the contents of that directory.

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

	Okay, so I let this slip for way too long.  AFAIR I waited for
	a few patches to go into 'next', and it was in an -rc cycle.

	Happily, the patches seem to be in, and we're out of -rc.

	Looking over the patch again, I do not find anything obviously
	wrong, but certainly somebody will.

 builtin-add.c              |   28 ++++++++++++++++++++++++++++
 t/t7400-submodule-basic.sh |   25 +++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 0 deletions(-)

diff --git a/builtin-add.c b/builtin-add.c
index 719de8b..ac98c83 100644
--- a/builtin-add.c
+++ b/builtin-add.c
@@ -68,6 +68,33 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p
         free(seen);
 }
 
+static void treat_gitlinks(const char **pathspec)
+{
+	int i;
+
+	if (!pathspec || !*pathspec)
+		return;
+
+	for (i = 0; i < active_nr; i++) {
+		struct cache_entry *ce = active_cache[i];
+		if (S_ISGITLINK(ce->ce_mode)) {
+			int len = ce_namelen(ce), j;
+			for (j = 0; pathspec[j]; j++) {
+				int len2 = strlen(pathspec[j]);
+				if (len2 <= len || pathspec[j][len] != '/' ||
+				    memcmp(ce->name, pathspec[j], len))
+					continue;
+				if (len2 == len + 1)
+					/* strip trailing slash */
+					pathspec[j] = xstrndup(ce->name, len);
+				else
+					die ("Path '%s' is in submodule '%.*s'",
+						pathspec[j], len, ce->name);
+			}
+		}
+	}
+}
+
 static void fill_directory(struct dir_struct *dir, const char **pathspec,
 		int ignored_too)
 {
@@ -261,6 +288,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
 
 	if (read_cache() < 0)
 		die("index file corrupt");
+	treat_gitlinks(pathspec);
 
 	if (add_new_files)
 		/* This picks up the paths that are not tracked */
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index be73f7b..2ec7ac6 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -209,4 +209,29 @@ test_expect_success 'update --init' '
 
 '
 
+test_expect_success 'do not add files from a submodule' '
+
+	git reset --hard &&
+	test_must_fail git add init/a
+
+'
+
+test_expect_success 'gracefully add submodule with a trailing slash' '
+
+	git reset --hard &&
+	git commit -m "commit subproject" init &&
+	(cd init &&
+	 echo b > a) &&
+	git add init/ &&
+	git diff --exit-code --cached init &&
+	commit=$(cd init &&
+	 git commit -m update a >/dev/null &&
+	 git rev-parse HEAD) &&
+	git add init/ &&
+	test_must_fail git diff --exit-code --cached init &&
+	test $commit = $(git ls-files --stage |
+		sed -n "s/^160000 \([^ ]*\).*/\1/p")
+
+'
+
 test_done
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* [PATCH] bisect view: call gitk if Cygwin's SESSIONNAME variable is set
From: Johannes Schindelin @ 2009-01-02 18:08 UTC (permalink / raw)
  To: git, gitster


It seems that Cygwin sets the variable SESSIONNAME when an interactive
desktop session is running, and does not set it when you log in via ssh.

So we can use this variable to determine whether to run gitk or git log
in git bisect view.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 git-bisect.sh |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/git-bisect.sh b/git-bisect.sh
index 17a35f6..85db4ba 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -508,7 +508,7 @@ bisect_visualize() {
 
 	if test $# = 0
 	then
-		case "${DISPLAY+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
+		case "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" in
 		'')	set git log ;;
 		set*)	set gitk ;;
 		esac
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* [TOY PATCH] diffcore-rename: replace basename_same() heuristics by levenshtein
From: Johannes Schindelin @ 2009-01-02 18:07 UTC (permalink / raw)
  To: git


When the environment variable GIT_USE_LEVENSHTEIN is set, the rename
score is reduced by the Damerau-Levenshtein distance.  This should
lead to a little more intuitive rename scores.

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

	I have this in my personal tree, but I did not really use it.
	Maybe others want to play with it.

 diffcore-rename.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/diffcore-rename.c b/diffcore-rename.c
index 168a95b..1f4b371 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -5,6 +5,7 @@
 #include "diff.h"
 #include "diffcore.h"
 #include "hash.h"
+#include "levenshtein.h"
 
 /* Table of rename/copy destinations */
 
@@ -187,7 +188,9 @@ static int estimate_similarity(struct diff_filespec *src,
 	if (!dst->size)
 		score = 0; /* should not happen */
 	else
-		score = (int)(src_copied * MAX_SCORE / max_size);
+		score = (int)(src_copied * MAX_SCORE / max_size)
+			- (getenv("GIT_USE_LEVENSHTEIN") ?
+			   levenshtein(src->path, dst->path, 1, 1, 1, 1) : 0);
 	return score;
 }
 
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* [CLEANUP PATCH RESEND] git wrapper: Make while loop more reader-friendly
From: Johannes Schindelin @ 2009-01-02 18:07 UTC (permalink / raw)
  To: git, gitster


It is not a good practice to prefer performance over readability in
something as performance uncritical as finding the trailing slash
of argv[0].

So avoid head-scratching by making the loop user-readable, and not
hyper-performance-optimized.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
 git.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/git.c b/git.c
index 940a498..e0d9071 100644
--- a/git.c
+++ b/git.c
@@ -428,9 +428,8 @@ int main(int argc, const char **argv)
 	 * name, and the dirname as the default exec_path
 	 * if we don't have anything better.
 	 */
-	do
-		--slash;
-	while (cmd <= slash && !is_dir_sep(*slash));
+	while (cmd <= slash && !is_dir_sep(*slash))
+		slash--;
 	if (cmd <= slash) {
 		*slash++ = 0;
 		git_set_argv0_path(cmd);
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* [PATCH RESEND] Introduce core.keepHardLinks
From: Johannes Schindelin @ 2009-01-02 18:07 UTC (permalink / raw)
  To: git, gitster


When a tracked file was hard linked, we used to break the hard link
whenever Git writes to that file.

In some situations, this behavior is less-than-desirable, especially
given the fact that some popular editors do not do that, such as
(in alphabetical order) emacs and vi.

So teach Git not to break hard links when the config variable
core.keepHardLinks is set to true.  For backwards compatibility, this
variable defaults to false.

>From a safety viewpoint, nothing really changes, as to keep hard links,
Git will now open the files it updates with O_TRUNC instead of deleting
them first and then opening them with O_EXCL.

To keep the implementation simple, mode changes will still break the
hard links.

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

	Only the commit message was modified since last time, to
	provide a better justification for the patch.

 Documentation/config.txt |    4 +++
 cache.h                  |    1 +
 config.c                 |    4 +++
 entry.c                  |    7 ++++-
 environment.c            |    1 +
 t/t0056-hardlinked.sh    |   58 ++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 73 insertions(+), 2 deletions(-)
 create mode 100644 t/t0056-hardlinked.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 7408bb2..086d8a4 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -209,6 +209,10 @@ core.symlinks::
 	file. Useful on filesystems like FAT that do not support
 	symbolic links. True by default.
 
+core.keepHardLinks::
+	If true, do not break hard links by deleting and recreating the
+	files.  Off by default.
+
 core.gitProxy::
 	A "proxy command" to execute (as 'command host port') instead
 	of establishing direct connection to the remote server when
diff --git a/cache.h b/cache.h
index 231c06d..a9c5812 100644
--- a/cache.h
+++ b/cache.h
@@ -538,6 +538,7 @@ enum rebase_setup_type {
 
 extern enum branch_track git_branch_track;
 extern enum rebase_setup_type autorebase;
+extern int keep_hard_links;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
diff --git a/config.c b/config.c
index 790405a..8ff2b4b 100644
--- a/config.c
+++ b/config.c
@@ -492,6 +492,10 @@ static int git_default_core_config(const char *var, const char *value)
 
 	if (!strcmp(var, "core.preloadindex")) {
 		core_preload_index = git_config_bool(var, value);
+	}
+
+	if (!strcmp(var, "core.keephardlinks")) {
+		keep_hard_links = git_config_bool(var, value);
 		return 0;
 	}
 
diff --git a/entry.c b/entry.c
index aa2ee46..dfddf83 100644
--- a/entry.c
+++ b/entry.c
@@ -82,7 +82,8 @@ static void remove_subtree(const char *path)
 static int create_file(const char *path, unsigned int mode)
 {
 	mode = (mode & 0100) ? 0777 : 0666;
-	return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
+	return open(path, O_WRONLY | O_CREAT |
+			(keep_hard_links ? O_TRUNC : O_EXCL), mode);
 }
 
 static void *read_blob_entry(struct cache_entry *ce, const char *path, unsigned long *size)
@@ -225,7 +226,9 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t
 			if (!state->force)
 				return error("%s is a directory", path);
 			remove_subtree(path);
-		} else if (unlink(path))
+		} else if ((!keep_hard_links || !S_ISREG(st.st_mode) ||
+					st.st_mode != ce->ce_mode) &&
+				unlink(path))
 			return error("unable to unlink old '%s' (%s)", path, strerror(errno));
 	} else if (state->not_new)
 		return 0;
diff --git a/environment.c b/environment.c
index e278bce..fc91809 100644
--- a/environment.c
+++ b/environment.c
@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
 enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;
 enum rebase_setup_type autorebase = AUTOREBASE_NEVER;
+int keep_hard_links = 0;
 
 /* Parallel index stat data preload? */
 int core_preload_index = 0;
diff --git a/t/t0056-hardlinked.sh b/t/t0056-hardlinked.sh
new file mode 100644
index 0000000..934c2bc
--- /dev/null
+++ b/t/t0056-hardlinked.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+
+test_description='read-tree and checkout respect hardlinked files'
+
+. ./test-lib.sh
+
+cat > file << EOF
+1. Nf3 Nf6 2. c4 g6 3. Nc3 Bg7 4. d4 O-O 5. Bf4 d5 6. Qb3 dxc4 7. Qxc4 c6
+8. e4 Nbd7 9. Rd1 Nb6 10. Qc5 Bg4 11. Bg5 Na4 12. Qa3 Nxc3 13. bxc3 Nxe4
+14. Bxe7 Qb6 15. Bc4 Nxc3 16. Bc5 Rfe8+ 17. Kf1 Be6 18. Bxb6 Bxc4+ 19. Kg1 Ne2+
+20. Kf1 Nxd4+ 21. Kg1 Ne2+ 22. Kf1 Nc3+ 23. Kg1 axb6 24. Qb4 Ra4 25. Qxb6 Nxd1
+26. h3 Rxa2 27. Kh2 Nxf2 28. Re1 Rxe1 29. Qd8+ Bf8 30. Nxe1 Bd5 31. Nf3 Ne4
+32. Qb8 b5 33. h4 h5 34. Ne5 Kg7 35. Kg1 Bc5+ 36. Kf1 Ng3+ 37. Ke1 Bb4+
+38. Kd1 Bb3+ 39. Kc1 Ne2+ 40. Kb1 Nc3+
+EOF
+
+ln file link || {
+	say "Could not hard link; skipping test"
+	test_done
+	exit
+}
+
+test_expect_success setup '
+
+	git config core.keepHardLinks true &&
+	test_cmp file link &&
+	cp file old &&
+	git add file &&
+	test_tick &&
+	git commit -m initial &&
+	echo "41. Kc1 Rc2#" >> file &&
+	git add file &&
+	test_tick &&
+	git commit -m 2nd &&
+	test_cmp file link &&
+	! test_cmp file old
+
+'
+
+test_expect_success 'checking a file out does not break the hard link' '
+
+	git checkout HEAD^ -- file &&
+	test_cmp file link &&
+	test_cmp file old
+
+'
+
+test_expect_success 'read-tree -u -m does not break the hard link' '
+
+	git reset --hard &&
+	test_cmp file link &&
+	git read-tree -u -m HEAD^ &&
+	test_cmp file link &&
+	test_cmp file old
+
+'
+
+test_done
-- 
1.6.1.rc3.224.g95ac9

^ permalink raw reply related

* Re: git-difftool
From: David Aguilar @ 2009-01-02 17:39 UTC (permalink / raw)
  To: Matthieu Moy; +Cc: markus.heidelberg, git
In-Reply-To: <vpq63kxofi3.fsf@bauges.imag.fr>

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

On Fri, Jan 2, 2009 at 8:10 AM, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:
>
> As done with "vimdiff" in another message, simply write a
> one-liner wrapper script that calls xxdiff $2 $3, and call this
> wrapper script.
>
> ...
>
> Right, but a script "git-difftool" calling the later is a one-liner,
> so 2 one-liners give you the same result as the ~500 lines script
> proposed. And GIT_EXTERNAL_DIFF has the great advantage
> of being maintained together with git, and will most likely handle
> all cases (diff between index, working tree, arbitrary commit, ...)
> correctly.
>
> --
> Matthieu
>

Thanks for the feedback.  I've done exactly what you suggested.

I now have a git-difftool wrapper script that basically just sets up
the environment for git-difftool-helper.  git-difftool-helper does all
of the merge tool configuration stuff ala
http://www.kernel.org/pub/software/scm/git/docs/git-mergetool.html (it
uses the same git config variables and thus works with existing custom
commands).  If you drop them both into the same directory it should
work as-is (it munges $PATH).

It's not a two-liner (they do all that git config stuff and handle
more than just vimdiff) but it does use GIT_EXTERNAL_DIFF now, which
makes the script infinitely more useful.  This is much nicer now since
you can pass any 'git diff' options to git-difftool and it'll handle
it correctly.

The usage is simpler now too:

usage: git difftool [--no-prompt] [--tool=tool] ["git diff" options]


Thanks for your help,

-- 
    David

[-- Attachment #2: git-difftool --]
[-- Type: application/octet-stream, Size: 1876 bytes --]

#!/usr/bin/env perl
# This is a wrapper around the GIT_EXTERNAL_DIFF compatible
# git-difftool-helper script.
#
# Copyright (c) 2009 David Aguilar

use strict;
use warnings;

use File::Basename qw(dirname);

# Prints usage and exits
sub usage
{
	print << 'USAGE';

usage: git difftool [--no-prompt] [--tool=tool] ["git diff" options]
USAGE
	exit 1;
}

# Sets PATH, GIT_PAGER, and GIT_EXTERNAL_DIFF so that
# git-difftool-helper is invoked by 'git diff'.
sub setup_environment
{
	my @paths = ( dirname($0), split(':', $ENV{PATH}) );
	$ENV{PATH} = join(':', @paths);
	$ENV{GIT_PAGER} = '';
	$ENV{GIT_EXTERNAL_DIFF} = 'git-difftool-helper';
}

# Sets an environment variable recognized by git-difftool-helper
# to signal that we shouldn't prompt before viewing each file.
sub no_prompt
{
	$ENV{GIT_DIFFTOOL_NO_PROMPT} = 'true';
}

# Sets a default value for the merge tool used by git-difftool-helper.
sub setup_mergetool
{
	$ENV{GIT_MERGE_TOOL} = shift;
}

# Processes command-line flags and generates a corresponding
# 'git diff' command.  Any arguments that are unknown to this
# script are assumed to be arguments intended for 'git diff'.
sub generate_command
{
	my @command = ('git', 'diff');
	my $skip_next = 0;

	my $idx = -1;
	for my $arg (@ARGV) {
		$idx++;

		if ($skip_next) {
			$skip_next = 0;
			next;
		}

		if ($arg eq '-h' or $arg eq '--help') {
			usage()
		}

		if ($arg eq '--no-prompt') {
			no_prompt();
			next;
		}

		if ($arg eq '-t' or $arg eq '--tool') {
			$skip_next = 1;
			if ( scalar(@ARGV) <= $idx + 1 ) {
				usage();
			}
			setup_mergetool($ARGV[$idx + 1]);
			next;
		}

		if ($arg =~ /^--tool=/) {
			$arg = substr($arg, 7);
			setup_mergetool($arg);
			next;
		}
		push @command, $arg;
	}
	return @command
}

# Sets up the git-difftool environment and execs 'git diff'.
sub main
{
	setup_environment();
	exec(generate_command());
}

main()

[-- Attachment #3: git-difftool-helper --]
[-- Type: application/octet-stream, Size: 5979 bytes --]

#!/bin/sh
#
# git-difftool-helper:
#    invoked via 'git difftool' to view diffs using external diff viewers.
#
# Copyright (c) 2009 David Aguilar.
#
# You can use this script directly with the following settings:
#   export GIT_PAGER=''
#   export GIT_EXTERNAL_DIFF=git-difftool-helper
#   git diff ...

# Should we prompt before viewing each file?
should_prompt () {
	! test -n "$GIT_DIFFTOOL_NO_PROMPT"
}

# Should we keep the backup .orig file?
keep_backup_mode="$(git config --bool merge.keepBackup || echo true)"
keep_backup () {
	test "$keep_backup_mode" = "true"
}

# This function manages the backup .orig file.
# A backup $MERGED.orig file is created if changes are detected.
cleanup_temp_files () {
	if test -n "$MERGED"; then
		if keep_backup && test "$MERGED" -nt "$BACKUP"; then
			test -f "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig"
		else
			rm -f -- "$BACKUP"
		fi
	fi
}

# This is called when users Ctrl-C out of git-difftool-helper.
sigint_handler () {
	echo
	cleanup_temp_files
	exit 1
}

# This function prepares temporary files and launches the appropriate
# merge tool.
launch_merge_tool () {
	# Merged is the filename as it appears in the work tree
	# Local is the contents of a/filename
	# Remote is the contents of b/filename
	# Custom merge tool commands might use $BASE so we provide it
	MERGED="$1"
	LOCAL="$2"
	REMOTE="$3"
	BASE="$1"
	ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')"
	BACKUP="$MERGED.BACKUP.$ext"

	# Create and ensure that we clean up $BACKUP
	test -f "$MERGED" && cp -- "$MERGED" "$BACKUP"
	trap sigint_handler SIGINT

	# $LOCAL and $REMOTE are temporary files so prompt
	# the user with the real $MERGED name before launching $merge_tool.
	if should_prompt; then
		printf "\nViewing: '$MERGED'\n"
		printf "Hit return to launch '%s': " "$merge_tool"
		read ans
	fi

	# Run the appropriate merge tool command
	case "$merge_tool" in
	kdiff3)
		basename=$(basename "$MERGED")
		"$merge_tool_path" --auto \
			--L1 "$basename (A)" \
			--L2 "$basename (B)" \
			-o "$MERGED" "$LOCAL" "$REMOTE" \
			> /dev/null 2>&1
		;;

	tkdiff)
		"$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE"
		;;

	meld|vimdiff)
		"$merge_tool_path" "$LOCAL" "$REMOTE"
		;;

	gvimdiff)
		"$merge_tool_path" -f "$LOCAL" "$REMOTE"
		;;

	xxdiff)
		"$merge_tool_path" \
			-X \
			-R 'Accel.SaveAsMerged: "Ctrl-S"' \
			-R 'Accel.Search: "Ctrl+F"' \
			-R 'Accel.SearchForward: "Ctrl-G"' \
			--merged-file "$MERGED" \
			"$LOCAL" "$REMOTE"
		;;

	opendiff)
		"$merge_tool_path" "$LOCAL" "$REMOTE" \
			-merge "$MERGED" | cat
		;;

	ecmerge)
		"$merge_tool_path" "$LOCAL" "$REMOTE" \
			--default --mode=merge2 --to="$MERGED"
		;;

	emerge)
		"$merge_tool_path" -f emerge-files-command \
			"$LOCAL" "$REMOTE" "$(basename "$MERGED")"
		;;

	*)
		if test -n "$merge_tool_cmd"; then
			( eval $merge_tool_cmd )
		fi
		;;
	esac

	cleanup_temp_files
}

# Verifies that mergetool.<tool>.cmd exists
valid_custom_tool() {
	merge_tool_cmd="$(git config mergetool.$1.cmd)"
	test -n "$merge_tool_cmd"
}

# Verifies that the chosen merge tool is properly setup.
# Built-in merge tools are always valid.
valid_tool() {
	case "$1" in
	kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge)
		;; # happy
	*)
		if ! valid_custom_tool "$1"
		then
			return 1
		fi
		;;
	esac
}

# Sets up the merge_tool_path variable.
# This handles the mergetool.<tool>.path configuration.
init_merge_tool_path() {
	merge_tool_path=$(git config mergetool."$1".path)
	if test -z "$merge_tool_path"; then
		case "$1" in
		emerge)
			merge_tool_path=emacs
			;;
		*)
			merge_tool_path="$1"
			;;
		esac
	fi
}

# Allow the GIT_MERGE_TOOL variable to provide a default value
test -n "$GIT_MERGE_TOOL" && merge_tool="$GIT_MERGE_TOOL"

# If not merge tool was specified then use the merge.tool
# configuration variable.  If that's invalid then reset merge_tool.
if test -z "$merge_tool"; then
	merge_tool=$(git config merge.tool)
	if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then
		echo >&2 "git config option merge.tool set to unknown tool: $merge_tool"
		echo >&2 "Resetting to default..."
		unset merge_tool
	fi
fi

# Try to guess an appropriate merge tool if no tool has been set.
if test -z "$merge_tool"; then

	# We have a $DISPLAY so try some common UNIX merge tools
	if test -n "$DISPLAY"; then
		merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff"
		# If gnome then prefer meld
		if test -n "$GNOME_DESKTOP_SESSION_ID"; then
			merge_tool_candidates="meld $merge_tool_candidates"
		fi
		# If KDE then prefer kdiff3
		if test "$KDE_FULL_SESSION" = "true"; then
			merge_tool_candidates="kdiff3 $merge_tool_candidates"
		fi
	fi

	# $EDITOR is emacs so add emerge as a candidate
	if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then
		merge_tool_candidates="$merge_tool_candidates emerge"
	fi

	# $EDITOR is vim so add vimdiff as a candidate
	if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then
		merge_tool_candidates="$merge_tool_candidates vimdiff"
	fi

	merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff"
	echo "merge tool candidates: $merge_tool_candidates"

	# Loop over each candidate and stop when a valid merge tool is found.
	for i in $merge_tool_candidates
	do
		init_merge_tool_path $i
		if type "$merge_tool_path" > /dev/null 2>&1; then
			merge_tool=$i
			break
		fi
	done

	if test -z "$merge_tool" ; then
		echo "No known merge resolution program available."
		exit 1
	fi

else
	# A merge tool has been set, so verify that it's valid.
	if ! valid_tool "$merge_tool"; then
		echo >&2 "Unknown merge tool $merge_tool"
		exit 1
	fi

	init_merge_tool_path "$merge_tool"

	if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then
		echo "The merge tool $merge_tool is not available as '$merge_tool_path'"
		exit 1
	fi
fi


# Launch the merge tool helper on each path passed to us by 'git diff'
while test $# -gt 6
do
	launch_merge_tool "$1" "$2" "$5"
	shift 7
done

^ permalink raw reply

* Re: Extracting a single commit or object
From: Johannes Schindelin @ 2009-01-02 17:37 UTC (permalink / raw)
  To: Miklos Vajna; +Cc: yitzhakbg, git
In-Reply-To: <20090101180834.GJ21154@genesis.frugalware.org>

Hi,

On Thu, 1 Jan 2009, Miklos Vajna wrote:

> On Thu, Jan 01, 2009 at 05:52:49PM +0100, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > 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
> 
> Wow, that's really a monster. After removing the first leading v1.5.3:, 
> it works. (If this is a bash completion bug, I can't reproduce.)

Heh, it's just another proof that copy-n-paste ist just error-prone.

Thanks,
Dscho

^ permalink raw reply

* Re: [RFC PATCH] builtin-apply: prevent non-explicit permission changes
From: Jeff King @ 2009-01-02 17:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Alexander Potashev, Git Mailing List
In-Reply-To: <7vwsdec6za.fsf@gitster.siamese.dyndns.org>

On Fri, Jan 02, 2009 at 02:55:37AM -0800, Junio C Hamano wrote:

> A git patch that does not change the executable bit still records the mode
> on its "index" line.  "git apply" used to interpret this mode exactly the
> same way as it interprets the mode recorded on "new mode" line.  As the
> wish by the patch submitter to set the mode to the one recorded on the
> line.

Nit: I had to read that third sentence several times to make sense of
it, since it is not a complete sentence (I think s/line\. As/line: as/
might help).

> This changes the semantics of the mode recorded on the "index" line;
> instead of interpreting it as the submitter's wish to set the mode to the
> recorded value, it merely informs what the mode submitter happened to
> have, and the presense of the "index" line is taken as submitter's wish to
> keep whatever the mode is on the receiving end.

I have been following this thread but didn't have a chance to look
closely until now. I think this change is definitely the right thing, as
it follows the normal semantics for a patch (which are basically a
merge: "change the parts we changed, but leave everything else, even if
the other side changed it").

>  builtin-apply.c           |    4 ++-

The implementation looks good to me.

>  t/t4129-apply-samemode.sh |   62 ++++++++++++++++++++++++++++++++++++++++

And the tests make me feel warm and fuzzy. It is always nice to see
tests that aren't just "X was broken, and now it works" or "new feature
Y works" but "here is every case spelled out with its desired behavior."
I think those are the tests that really help keep us regression-proof.

-Peff

^ permalink raw reply

* Re: [PATCH 0/3] Teach Git about the patience diff algorithm
From: Linus Torvalds @ 2009-01-02 16:42 UTC (permalink / raw)
  To: Clemens Buchacher
  Cc: Adeodato Simó, Johannes Schindelin, Pierre Habouzit, davidel,
	Francis Galiegue, Git ML
In-Reply-To: <20090102105856.GB14691@localhost>



On Fri, 2 Jan 2009, Clemens Buchacher wrote:
>
> Only two choices, and I still get it wrong. The diffs should be labeled the
> other way around, of course.

Yes, this one is a real patience diff change, but it's also the same one 
that I've seen in the google fanboi findings. What google did _not_ show 
was any real-life examples, or anybody doing any critical analysis.

So I was hoping for something else than a single "in this case patience 
diff works really well". I was hoping to see what it does in real life. 
But when I tried it on the kernel archive, I get a core dump.

For example, in real life, files are bigger, and unique lines are not 
necessarily always common (generated files, whatever). Depending on unique 
line ordering may work fine in 95% of all cases, but do you know that it 
works fine in general? Does it work when 50% of lines are unique? I 
believe it does. Does ti work when just 1% of lines are unique? I just 
don't know.

And I haven't seen _any_ real critical analysis of it. Anywhere.

			Linus

^ permalink raw reply

* Re: git-difftool
From: Matthieu Moy @ 2009-01-02 16:10 UTC (permalink / raw)
  To: markus.heidelberg; +Cc: David Aguilar, git
In-Reply-To: <200901020113.32082.markus.heidelberg@web.de>

Markus Heidelberg <markus.heidelberg@web.de> writes:

> Matthieu Moy, 01.01.2009:
>> "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.
>
> This works with GUI tools, but not with console tools.

Actually, it does if you call git --no-pager.

> GVim works, Vim
> doesn't.
> And invoking
>     git difftool
> is by far more convenient than
>     GIT_EXTERNAL_DIFF=vimdiff git diff

Right, but a script "git-difftool" calling the later is a one-liner,
so 2 one-liners give you the same result as the ~500 lines script
proposed. And GIT_EXTERNAL_DIFF has the great advantage of being
maintained together with git, and will most likely handle all cases
(diff between index, working tree, arbitrary commit, ...) correctly.

-- 
Matthieu

^ permalink raw reply

* [PATCH] cvsserver: add option to configure commit message
From: Fabian Emmes @ 2009-01-02 15:40 UTC (permalink / raw)
  To: git; +Cc: gitster, Fabian Emmes, Lars Noschinski

cvsserver annotates each commit message by "via git-CVS emulator". This is
made configurable via gitcvs.commitmsgannotation.

Signed-off-by: Fabian Emmes <fabian.emmes@rwth-aachen.de>
Signed-off-by: Lars Noschinski <lars@public.noschinski.de>
---
 Documentation/config.txt |    4 ++++
 git-cvsserver.perl       |    8 +++++++-
 2 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 7408bb2..8b14d8a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -723,6 +723,10 @@ gc.rerereunresolved::
 	kept for this many days when 'git-rerere gc' is run.
 	The default is 15 days.  See linkgit:git-rerere[1].
 
+gitcvs.commitmsgannotation::
+	Append this string to each commit message. Set to empty string
+	to disable this feature. Defaults to "via git-CVS emulator".
+
 gitcvs.enabled::
 	Whether the CVS server interface is enabled for this repository.
 	See linkgit:git-cvsserver[1].
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index b0a805c..cbcaeb4 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -1358,7 +1358,13 @@ sub req_ci
     # write our commit message out if we have one ...
     my ( $msg_fh, $msg_filename ) = tempfile( DIR => $TEMP_DIR );
     print $msg_fh $state->{opt}{m};# if ( exists ( $state->{opt}{m} ) );
-    print $msg_fh "\n\nvia git-CVS emulator\n";
+    if ( defined ( $cfg->{gitcvs}{commitmsgannotation} ) ) {
+        if ($cfg->{gitcvs}{commitmsgannotation} !~ /^\s*$/ ) {
+            print $msg_fh "\n\n".$cfg->{gitcvs}{commitmsgannotation}."\n"
+        }
+    } else {
+        print $msg_fh "\n\nvia git-CVS emulator\n";
+    }
     close $msg_fh;
 
     my $commithash = `git-commit-tree $treehash -p $parenthash < $msg_filename`;
-- 
1.5.6.3

^ permalink raw reply related

* [PATCH] cvsserver: change generation of CVS author names
From: Fabian Emmes @ 2009-01-02 15:40 UTC (permalink / raw)
  To: git; +Cc: gitster, Fabian Emmes, Lars Noschinski
In-Reply-To: <1230910814-32307-1-git-send-email-fabian.emmes@rwth-aachen.de>

CVS username is generated from local part email address.
We take the whole local part but restrict the character set to the
Portable Filename Character Set, which is used for Unix login names
according to Single Unix Specification v3.

Signed-off-by: Fabian Emmes <fabian.emmes@rwth-aachen.de>
Signed-off-by: Lars Noschinski <lars@public.noschinski.de>
---
 git-cvsserver.perl |   12 +++++++++---
 1 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index cbcaeb4..fef7faf 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -2533,12 +2533,18 @@ sub open_blob_or_die
     return $fh;
 }
 
-# Generate a CVS author name from Git author information, by taking
-# the first eight characters of the user part of the email address.
+# Generate a CVS author name from Git author information, by taking the local
+# part of the email address and replacing characters not in the Portable
+# Filename Character Set (see IEEE Std 1003.1-2001, 3.276) by underscores. CVS
+# Login names are Unix login names, which should be restricted to this
+# character set.
 sub cvs_author
 {
     my $author_line = shift;
-    (my $author) = $author_line =~ /<([^>@]{1,8})/;
+    (my $author) = $author_line =~ /<([^@>]*)/;
+
+    $author =~ s/[^-a-zA-Z0-9_.]/_/g;
+    $author =~ s/^-/_/;
 
     $author;
 }
-- 
1.5.6.3

^ permalink raw reply related

* Re: git checkout does not warn about tags without corresponding commits
From: Miklos Vajna @ 2009-01-02 15:04 UTC (permalink / raw)
  To: Henrik Austad; +Cc: git
In-Reply-To: <200901021325.58049.henrik@austad.us>

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

On Fri, Jan 02, 2009 at 01:25:57PM +0100, Henrik Austad <henrik@austad.us> wrote:
> I can see that there's no commit for this, but, when there's a tag. I thought 
> that a tag was just a commit-sha1 with a name attached, along with some tag 
> info and a signature. Can you really create a tag without a commit?

Sure, you can tag any object type (blob, tree, commit or tag), but
usually only commits are tagged.

See for example the 'junio-gpg-pub' tag in git.git which tags a blob.

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

^ permalink raw reply

* Re: [RFC PATCH] builtin-apply: prevent non-explicit permission changes
From: Alexander Potashev @ 2009-01-02 13:37 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List
In-Reply-To: <7v3ag2frv8.fsf@gitster.siamese.dyndns.org>

On 16:56 Thu 01 Jan     , Junio C Hamano wrote:
> Alexander Potashev <aspotashev@gmail.com> writes:
> 
> > On 05:00 Thu 01 Jan     , Junio C Hamano wrote:
> >> Alexander Potashev <aspotashev@gmail.com> writes:
> > ...
> >> > @@ -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?
> >
> > Do you mean overwriting of 'patch->new_mode' right after patch parsing?
> 
> My question was if we should assign st_mode to new_mode _unconditionally_
> here, even when patch->new_mode has already been read from the explicit
> mode change line (i.e. "new mode ", line not "index "line) of the patch
> input.
> 
> The call-chain of the program looks like this:
> 
> -> apply_patch()
>    -> parse_chunk()
>       -> find_header()
>          * initialize new_mode and old_mode to 0
>          -> parse_git_header()
>             * set new_mode and old_mode from the patch metainfo, i.e.
>               "new mode", "old mode" and "index" lines.
>       -> parse_single_patch()
>    -> check_patch_list()
>       -> check_patch()
>          -> check_preimage()
>             * make sure there is no local mods
>             * warn if old_mode read from the patch (i.e. the preimage file
>               the patch submitter used to prepare the patch against) does not
>               match what we have
>          * warn about mode inconsistency (e.g. the patch submitter thinks
>            the mode should be 0644 but our tree has 0755).
>          -> apply_data()
>    -> write_out_results()
>       -> write_out_one_result(0)
>          * delete old
>       -> write_out_one_result(1)
>          * create new
> 
> Currently the mode 100644 on the "index" line in a patch is handled
> exactly in the same way as having "old mode 100644" and "new mode 100644"
> lines in the metainfo.  The patch submitter claims to have started from
> 100644 and he claims that he wants to have 100644 as the result.  That is
> why there is a warning in check_patch().
> 
> If we stop reading the new mode from the "index" line (but we still read
> "old_mode" there) without any other change you made in your patch, what
> breaks (i.e. without the patch->new_mode assignment hunk)?  I haven't
> followed the codepath too closely, and I suspect you found some cases
> where new_mode stays 0 as initialized, and that may be the reason you have
> this assignment.
> 
> But the assignment being unconditional bothered me a lot.
> 
> I tend to agree that the current "The final mode bits I want to have on
> this path is this" semantics we give to the "index" line is much less
> useful and less sane and it is a good idea to redefine it as "FYI, the
> copy I made this patch against had this mode bits.  I do not intend to
> change the mode bits of the path with this patch."
> 
>  builtin-apply.c |    4 +++-
>  1 files changed, 3 insertions(+), 1 deletions(-)
> 
> diff --git c/builtin-apply.c w/builtin-apply.c
> index 07244b0..a8f75ed 100644
> --- c/builtin-apply.c
> +++ w/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,8 @@ 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);
> +	if (!patch->new_mode)
> +		patch->new_mode = st_mode;

This is a _major_ fix, with my patch it would never change any
permissions at all.

I couldn't fully understand that problem last night, sorry for the
noise.

>  	return 0;
>  
>   is_new:

^ permalink raw reply

* [PATCH] gitweb: suggest name for OPML view
From: Giuseppe Bilotta @ 2009-01-02 12:49 UTC (permalink / raw)
  To: git; +Cc: Jakub Narebski, Petr Baudis, Junio C Hamano, Giuseppe Bilotta

Suggest opml.xml as name for OPML view by providing the appropriate
header, consistently with similar usage in project_index view.

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
 gitweb/gitweb.perl |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index b164001..995bc1a 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -6122,7 +6122,11 @@ sub git_atom {
 sub git_opml {
 	my @list = git_get_projects_list();
 
-	print $cgi->header(-type => 'text/xml', -charset => 'utf-8');
+	print $cgi->header(
+		-type => 'text/xml',
+		-charset => 'utf-8',
+		-content_disposition => 'inline; filename="opml.xml"');
+
 	print <<XML;
 <?xml version="1.0" encoding="utf-8"?>
 <opml version="1.0">
-- 
1.5.6.5

^ permalink raw reply related

* Re: [PATCH] gitweb: use href() when generating URLs in OPML
From: Jakub Narebski @ 2009-01-02 13:09 UTC (permalink / raw)
  To: Giuseppe Bilotta; +Cc: git, Petr Baudis, Junio C Hamano
In-Reply-To: <1230898528-24187-1-git-send-email-giuseppe.bilotta@gmail.com>

Giuseppe Bilotta wrote:
> Since the OPML project list view was hand-coding the RSS and HTML URLs,
> it didn't respect global options such as use_pathinfo. Make it use
> href() to ensure consistency with the rest of the gitweb setup.

Good catch. I guess it was before href(..., -full=>1)...

> 
> Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>

Acked-by: Jakub Narebski <jnareb@gmail.com>

> ---
>  gitweb/gitweb.perl |    4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
> index fa7d8ad..b164001 100755
> --- a/gitweb/gitweb.perl
> +++ b/gitweb/gitweb.perl
> @@ -6146,8 +6146,8 @@ XML
>  		}
>  
>  		my $path = esc_html(chop_str($proj{'path'}, 25, 5));
> -		my $rss  = "$my_url?p=$proj{'path'};a=rss";
> -		my $html = "$my_url?p=$proj{'path'};a=summary";
> +		my $rss  = href('project' => $proj{'path'}, 'action' => 'rss', -full => 1);
> +		my $html = href('project' => $proj{'path'}, 'action' => 'summary', -full => 1);
>  		print "<outline type=\"rss\" text=\"$path\" title=\"$path\" xmlUrl=\"$rss\" htmlUrl=\"$html\"/>\n";
>  	}
>  	print <<XML;
> -- 
> 1.5.6.5
> 
> 

-- 
Jakub Narebski
Poland

^ permalink raw reply

* [PATCH] gitweb: use href() when generating URLs in OPML
From: Giuseppe Bilotta @ 2009-01-02 12:15 UTC (permalink / raw)
  To: git; +Cc: Jakub Narebski, Petr Baudis, Junio C Hamano, Giuseppe Bilotta

Since the OPML project list view was hand-coding the RSS and HTML URLs,
it didn't respect global options such as use_pathinfo. Make it use
href() to ensure consistency with the rest of the gitweb setup.

Signed-off-by: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
---
 gitweb/gitweb.perl |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index fa7d8ad..b164001 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -6146,8 +6146,8 @@ XML
 		}
 
 		my $path = esc_html(chop_str($proj{'path'}, 25, 5));
-		my $rss  = "$my_url?p=$proj{'path'};a=rss";
-		my $html = "$my_url?p=$proj{'path'};a=summary";
+		my $rss  = href('project' => $proj{'path'}, 'action' => 'rss', -full => 1);
+		my $html = href('project' => $proj{'path'}, 'action' => 'summary', -full => 1);
 		print "<outline type=\"rss\" text=\"$path\" title=\"$path\" xmlUrl=\"$rss\" htmlUrl=\"$html\"/>\n";
 	}
 	print <<XML;
-- 
1.5.6.5

^ permalink raw reply related

* Re: [PATCH v3] Add a commit.signoff configuration option to always use --signoff in commit
From: Adeodato Simó @ 2009-01-02 12:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <20090101221817.GA29267@chistera.yi.org>

* Adeodato Simó [Thu, 01 Jan 2009 23:18:17 +0100]:

> * Junio C Hamano [Tue, 30 Dec 2008 13:04:13 -0800]:

> > They actually started making me think
> > that commmit.signoff might be more trouble than it is worth.

> I am beginning to think the same myself, and I'm okay with letting go.
> If somebody has a sensible plan, I can invest some time on implementing
> it, but I'll reckon it all tastes too messy at the moment.

> Thanks for your time.

Oh, I see you merged the last version into pu. I don't know if that
means it'd be bad for me to abandon now, but as said, if somebody helps
me figure out things, I'm open to continue working on it.

I just don't want to be pushing for inclusion of something of
sub-standard (UI) quality.

Cheers,

-- 
Adeodato Simó                                     dato at net.com.org.es
Debian Developer                                  adeodato at debian.org
 
Will you just stand still?
                -- Luke Danes

^ 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