Git development
 help / color / mirror / Atom feed
* Re: [PATCH] cache-tree: do not cache empty trees
From: Jonathan Nieder @ 2011-02-05 10:14 UTC (permalink / raw)
  To: Nguyễn Thái Ngọc Duy
  Cc: git, Ilari Liusvaara, Jakub Narebski, Dmitry S. Kravtsov,
	Shawn Pearce
In-Reply-To: <1296899427-1394-1-git-send-email-pclouds@gmail.com>

Hi,

Some quick nits to save myself time.  The basic idea of the patch
seems sound.

Nguyễn Thái Ngọc Duy wrote:

> --- /dev/null
> +++ b/t/t1013-read-tree-empty.sh
> @@ -0,0 +1,38 @@
> +#!/bin/sh
> +
> +test_description='read-tree with empty trees'
> +
> +. ./test-lib.sh
> +
> +T1=f4ec99e8174c01eab488469b4c2680500bbb18da
> +T2=4b825dc642cb6eb9a060e54bf8d69288fbee4904

What are these trees?  Do they need to be hardcoded?

> +
> +test_expect_success 'setup' '
> +	printf "40000 empty\0\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04" >newtree &&

printf '\xab' is unfortunately unportable.  I suppose
this should rather say something like

 test_unequal () {
	printf '%s\n' "$1" >bad &&
	printf '%s\n' "$2" >actual &&
	! test_cmp bad actual
 }

	empty_tree=$(git mktree </dev/null) &&
	tree_with_empty_subtree=$(
		echo "040000 tree $empty_tree	empty" |
		git mktree
	) &&
	test_unequal "$empty_tree" "$tree_with_empty_subtree"

> +test_expect_success 'ls-tree T1 (with empty tree)' '
> +	git ls-tree $T1 >actual &&
> +	cat <<EOF >expected &&
> +040000 tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904	empty
> +EOF
> +	test_cmp expected actual
> +'

	echo "040000 tree $empty_tree	empty" >expect &&
	git ls-tree "$tree_with_empty_subtree" >actual &&
	test_cmp expect actual

> +
> +test_expect_success 'write-tree removes empty tree' '
> +	git read-tree "$T1" &&
> +	git write-tree >actual
> +	echo $T2 >expected
> +	test_cmp expected actual
> +'

	git read-tree "$tree_with_empty_subtree" &&
	...

Sane?
Jonathan

^ permalink raw reply

* Re: [PATCH] cache-tree: do not cache empty trees
From: Nguyen Thai Ngoc Duy @ 2011-02-05 10:32 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: git, Ilari Liusvaara, Jakub Narebski, Dmitry S. Kravtsov,
	Shawn Pearce
In-Reply-To: <20110205101412.GB1685@elie>

2011/2/5 Jonathan Nieder <jrnieder@gmail.com>:
> Nguyễn Thái Ngọc Duy wrote:
>> +
>> +T1=f4ec99e8174c01eab488469b4c2680500bbb18da
>> +T2=4b825dc642cb6eb9a060e54bf8d69288fbee4904
>
> What are these trees?  Do they need to be hardcoded?

I have uneasy feeling constructing a tree manually. Hardcoding it (or
less automatic check) makes me feel better. I'm cooking a patch to
make hash-object reject malformed trees/commits/tags. Then I'll remove
these SHA-1.

>> +
>> +test_expect_success 'setup' '
>> +     printf "40000 empty\0\x4b\x82\x5d\xc6\x42\xcb\x6e\xb9\xa0\x60\xe5\x4b\xf8\xd6\x92\x88\xfb\xee\x49\x04" >newtree &&
>
> printf '\xab' is unfortunately unportable.  I suppose
> this should rather say something like
>
>  test_unequal () {
>        printf '%s\n' "$1" >bad &&
>        printf '%s\n' "$2" >actual &&
>        ! test_cmp bad actual
>  }
>
>        empty_tree=$(git mktree </dev/null) &&
>        tree_with_empty_subtree=$(
>                echo "040000 tree $empty_tree   empty" |
>                git mktree
>        ) &&
>        test_unequal "$empty_tree" "$tree_with_empty_subtree"

Hah! Was wondering how the heck they could create trees manually. So
it's mktree. Thanks!

>        ...
>
> Sane?

Don't know. But it's definitely saner than my version.
-- 
Duy

^ permalink raw reply

* [PATCH 1/2] Add const to parse_{commit,tag}_buffer()
From: Nguyễn Thái Ngọc Duy @ 2011-02-05 10:52 UTC (permalink / raw)
  To: git, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 commit.c |    6 +++---
 commit.h |    2 +-
 tag.c    |    2 +-
 tag.h    |    2 +-
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/commit.c b/commit.c
index 74d6601..ac337c7 100644
--- a/commit.c
+++ b/commit.c
@@ -245,10 +245,10 @@ int unregister_shallow(const unsigned char *sha1)
 	return 0;
 }
 
-int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
 {
-	char *tail = buffer;
-	char *bufptr = buffer;
+	const char *tail = buffer;
+	const char *bufptr = buffer;
 	unsigned char parent[20];
 	struct commit_list **pptr;
 	struct commit_graft *graft;
diff --git a/commit.h b/commit.h
index eb6c5af..659c87c 100644
--- a/commit.h
+++ b/commit.h
@@ -38,7 +38,7 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
 					      int quiet);
 struct commit *lookup_commit_reference_by_name(const char *name);
 
-int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
 int parse_commit(struct commit *item);
 
 /* Find beginning and length of commit subject. */
diff --git a/tag.c b/tag.c
index f789744..ecf7c1e 100644
--- a/tag.c
+++ b/tag.c
@@ -56,7 +56,7 @@ static unsigned long parse_tag_date(const char *buf, const char *tail)
 	return strtoul(dateptr, NULL, 10);
 }
 
-int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
+int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
 {
 	unsigned char sha1[20];
 	char type[20];
diff --git a/tag.h b/tag.h
index 8522370..5ee88e6 100644
--- a/tag.h
+++ b/tag.h
@@ -13,7 +13,7 @@ struct tag {
 };
 
 extern struct tag *lookup_tag(const unsigned char *sha1);
-extern int parse_tag_buffer(struct tag *item, void *data, unsigned long size);
+extern int parse_tag_buffer(struct tag *item, const void *data, unsigned long size);
 extern int parse_tag(struct tag *item);
 extern struct object *deref_tag(struct object *, const char *, int);
 extern size_t parse_signature(const char *buf, unsigned long size);
-- 
1.7.3.4.878.g439c7

^ permalink raw reply related

* [PATCH 2/2] Make hash-object more robust against malformed objects
From: Nguyễn Thái Ngọc Duy @ 2011-02-05 10:52 UTC (permalink / raw)
  To: git, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1296903141-27075-1-git-send-email-pclouds@gmail.com>

Commits, trees and tags have structure. Don't let users feed git
with malformed ones. Sooner or later git will die() when
encountering them.

Note that this patch does not check semantics. A tree that points
to non-existent objects is perfectly OK (and should be so, users
may choose to add commit first, then its associated tree for example)

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/hash-object.c  |    2 +-
 cache.h                |    2 +-
 read-cache.c           |    2 +-
 sha1_file.c            |   54 +++++++++++++++++++++++++++++++++++++++++------
 t/t1007-hash-object.sh |   13 +++++++++++
 5 files changed, 63 insertions(+), 10 deletions(-)

diff --git a/builtin/hash-object.c b/builtin/hash-object.c
index 080af1a..c90acdd 100644
--- a/builtin/hash-object.c
+++ b/builtin/hash-object.c
@@ -15,7 +15,7 @@ static void hash_fd(int fd, const char *type, int write_object, const char *path
 	struct stat st;
 	unsigned char sha1[20];
 	if (fstat(fd, &st) < 0 ||
-	    index_fd(sha1, fd, &st, write_object, type_from_string(type), path))
+	    index_fd(sha1, fd, &st, write_object, type_from_string(type), path, 1))
 		die(write_object
 		    ? "Unable to add %s to database"
 		    : "Unable to hash %s", path);
diff --git a/cache.h b/cache.h
index d83d68c..9186a56 100644
--- a/cache.h
+++ b/cache.h
@@ -501,7 +501,7 @@ extern int ie_match_stat(const struct index_state *, struct cache_entry *, struc
 extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
 
 extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
-extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path);
+extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, enum object_type type, const char *path, int format_check);
 extern int index_path(unsigned char *sha1, const char *path, struct stat *st, int write_object);
 extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 
diff --git a/read-cache.c b/read-cache.c
index 4f2e890..fbc12f3 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -92,7 +92,7 @@ static int ce_compare_data(struct cache_entry *ce, struct stat *st)
 
 	if (fd >= 0) {
 		unsigned char sha1[20];
-		if (!index_fd(sha1, fd, st, 0, OBJ_BLOB, ce->name))
+		if (!index_fd(sha1, fd, st, 0, OBJ_BLOB, ce->name, 0))
 			match = hashcmp(sha1, ce->sha1);
 		/* index_fd() closed the file descriptor already */
 	}
diff --git a/sha1_file.c b/sha1_file.c
index d86a8db..58ca858 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -13,6 +13,7 @@
 #include "commit.h"
 #include "tag.h"
 #include "tree.h"
+#include "tree-walk.h"
 #include "refs.h"
 #include "pack-revindex.h"
 #include "sha1-lookup.h"
@@ -2471,8 +2472,37 @@ int has_sha1_file(const unsigned char *sha1)
 	return has_loose_object(sha1);
 }
 
+static void check_tree(const void *buf, size_t size)
+{
+	struct tree_desc desc;
+	struct name_entry entry;
+
+	init_tree_desc(&desc, buf, size);
+	while (tree_entry(&desc, &entry))
+		/* do nothing
+		 * tree_entry() will die() on malformed entries */
+		;
+}
+
+static void check_commit(const void *buf, size_t size)
+{
+	struct commit c;
+	memset(&c, 0, sizeof(c));
+	if (parse_commit_buffer(&c, buf, size))
+		die("corrupt commit");
+}
+
+static void check_tag(const void *buf, size_t size)
+{
+	struct tag t;
+	memset(&t, 0, sizeof(t));
+	if (parse_tag_buffer(&t, buf, size))
+		die("corrupt tag");
+}
+
 static int index_mem(unsigned char *sha1, void *buf, size_t size,
-		     int write_object, enum object_type type, const char *path)
+		     int write_object, enum object_type type,
+		     const char *path, int format_check)
 {
 	int ret, re_allocated = 0;
 
@@ -2490,6 +2520,14 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
 			re_allocated = 1;
 		}
 	}
+	if (format_check) {
+		if (type == OBJ_TREE)
+			check_tree(buf, size);
+		if (type == OBJ_COMMIT)
+			check_commit(buf, size);
+		if (type == OBJ_TAG)
+			check_tag(buf, size);
+	}
 
 	if (write_object)
 		ret = write_sha1_file(buf, size, typename(type), sha1);
@@ -2503,7 +2541,7 @@ static int index_mem(unsigned char *sha1, void *buf, size_t size,
 #define SMALL_FILE_SIZE (32*1024)
 
 int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
-	     enum object_type type, const char *path)
+	     enum object_type type, const char *path, int format_check)
 {
 	int ret;
 	size_t size = xsize_t(st->st_size);
@@ -2512,23 +2550,25 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object,
 		struct strbuf sbuf = STRBUF_INIT;
 		if (strbuf_read(&sbuf, fd, 4096) >= 0)
 			ret = index_mem(sha1, sbuf.buf, sbuf.len, write_object,
-					type, path);
+					type, path, format_check);
 		else
 			ret = -1;
 		strbuf_release(&sbuf);
 	} else if (!size) {
-		ret = index_mem(sha1, NULL, size, write_object, type, path);
+		ret = index_mem(sha1, NULL, size, write_object, type, path,
+				format_check);
 	} else if (size <= SMALL_FILE_SIZE) {
 		char *buf = xmalloc(size);
 		if (size == read_in_full(fd, buf, size))
 			ret = index_mem(sha1, buf, size, write_object, type,
-					path);
+					path, format_check);
 		else
 			ret = error("short read %s", strerror(errno));
 		free(buf);
 	} else {
 		void *buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
-		ret = index_mem(sha1, buf, size, write_object, type, path);
+		ret = index_mem(sha1, buf, size, write_object, type, path,
+				format_check);
 		munmap(buf, size);
 	}
 	close(fd);
@@ -2546,7 +2586,7 @@ int index_path(unsigned char *sha1, const char *path, struct stat *st, int write
 		if (fd < 0)
 			return error("open(\"%s\"): %s", path,
 				     strerror(errno));
-		if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path) < 0)
+		if (index_fd(sha1, fd, st, write_object, OBJ_BLOB, path, 0) < 0)
 			return error("%s: failed to insert into database",
 				     path);
 		break;
diff --git a/t/t1007-hash-object.sh b/t/t1007-hash-object.sh
index dd32432..6d52b82 100755
--- a/t/t1007-hash-object.sh
+++ b/t/t1007-hash-object.sh
@@ -188,4 +188,17 @@ for args in "-w --stdin-paths" "--stdin-paths -w"; do
 	pop_repo
 done
 
+test_expect_success 'corrupt tree' '
+	echo abc >malformed-tree
+	test_must_fail git hash-object -t tree malformed-tree
+'
+
+test_expect_success 'corrupt commit' '
+	test_must_fail git hash-object -t commit --stdin </dev/null
+'
+
+test_expect_success 'corrupt tag' '
+	test_must_fail git hash-object -t tag --stdin </dev/null
+'
+
 test_done
-- 
1.7.3.4.878.g439c7

^ permalink raw reply related

* Re: [PATCH] git pull: Remove option handling done by fetch
From: Jens Lehmann @ 2011-02-05 11:26 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Junio C Hamano, Git Mailing List
In-Reply-To: <201102042326.08607.j6t@kdbg.org>

Am 04.02.2011 23:26, schrieb Johannes Sixt:
> On Freitag, 4. Februar 2011, Jens Lehmann wrote:
>> In commits be254a0ea9 and 7dce19d374 the handling of the new fetch options
>> "--[no-]recurse-submodules" had been added to git-pull.sh. This was not
>> necessary because all options to "git fetch" are passed to it and handled
>> there, so lets remove them.
>>
>> Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
>> ---
>>
>> I noticed this while implementing the on-demand recursive fetch.
>>
>>  git-pull.sh |   10 ++--------
>>  1 files changed, 2 insertions(+), 8 deletions(-)
>>
>> diff --git a/git-pull.sh b/git-pull.sh
>> index eb87f49..20a3bbe 100755
>> --- a/git-pull.sh
>> +++ b/git-pull.sh
>> @@ -38,7 +38,7 @@ test -z "$(git ls-files -u)" || die_conflict
>>  test -f "$GIT_DIR/MERGE_HEAD" && die_merge
>>
>>  strategy_args= diffstat= no_commit= squash= no_ff= ff_only=
>> -log_arg= verbosity= progress= recurse_submodules=
>> +log_arg= verbosity= progress=
>>  merge_args=
>>  curr_branch=$(git symbolic-ref -q HEAD)
>>  curr_branch_short="${curr_branch#refs/heads/}"
>> @@ -105,12 +105,6 @@ do
>>  	--no-r|--no-re|--no-reb|--no-reba|--no-rebas|--no-rebase)
>>  		rebase=false
>>  		;;
>> -	--recurse-submodules)
>> -		recurse_submodules=--recurse-submodules
>> -		;;
>> -	--no-recurse-submodules)
>> -		recurse_submodules=--no-recurse-submodules
>> -		;;
>>  	--d|--dr|--dry|--dry-|--dry-r|--dry-ru|--dry-run)
>>  		dry_run=--dry-run
>>  		;;
>> @@ -223,7 +217,7 @@ test true = "$rebase" && {
>>  	done
>>  }
>>  orig_head=$(git rev-parse -q --verify HEAD)
>>  -git fetch $verbosity $progress $dry_run $recurse_submodules 
>> --update-head-ok "$@" || exit 1
>>> +git fetch $verbosity $progress $dry_run 
>> --update-head-ok "$@" || exit 1 test -z "$dry_run" || exit 0
>>
>>  curr_head=$(git rev-parse -q --verify HEAD)
> 
> Huh? What will, for example,
> 
>    git pull --recurse-submodules --no-ff origin
> 
> do before and after your patch? Doesn't your patch force users to 
> write --[no-]recurse-submodules last?

Yes, but isn't that exactly what the pull man-page says? Quote:
"Options meant for git pull itself and the underlying git merge
must be given before the options meant for git fetch."
(The reason I added this option handling in the first place was
that I hadn't been aware of this at that time either ... ;-)

Thanks for your review!

^ permalink raw reply

* Re: [idea] separate .git dir and the working tree
From: Jonathan Nieder @ 2011-02-05 13:27 UTC (permalink / raw)
  To: git; +Cc: redstun, Mike Gant
In-Reply-To: <20110205032339.GA15303@mg1>

(restoring cc list; please do not cull cc's)

Mike Gant wrote:
> On Sat, Feb 05, 2011 at 10:53:58AM +0800, redstun wrote:

>> I think separating the .git directory from its working tree could
>> increase the safety of the data to one more level higher.
[...]
> GIT_DIR and GIT_WORK_TREE might be what you are looking for. Explanation
> of usage in 'man git'

The .git directory is allowed to be a symlink.  Or a file like so

	gitdir: /path/to/git/repo

for symlink-challenged operating systems.  See gitrepository-layout(7)
for details.

Cheers,
Jonathan

^ permalink raw reply

* [PATCH] Add support for merging from upstream by default.
From: Jared Hance @ 2011-02-05 13:31 UTC (permalink / raw)
  To: git; +Cc: Jared Hance
In-Reply-To: <m2k4he23z6.fsf@whitebox.home>

Adds the option merge.defaultupstream to add support for merging from the
upstream branch by default. The upstream branch is found using
branch.[name].upstream.
---

I checked it this time, it really is the right usage.

 builtin/merge.c |   42 +++++++++++++++++++++++++++++++++++-------
 1 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index 42fff38..596febe 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -37,7 +37,7 @@ struct strategy {
 };
 
 static const char * const builtin_merge_usage[] = {
-	"git merge [options] <remote>...",
+	"git merge [options] [<remote>...]",
 	"git merge [options] <msg> HEAD <remote>",
 	NULL
 };
@@ -58,6 +58,8 @@ static int option_renormalize;
 static int verbosity;
 static int allow_rerere_auto;
 static int abort_current_merge;
+static int default_upstream;
+static const char *upstream_branch;
 
 static struct strategy all_strategy[] = {
 	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -519,8 +521,15 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 			      builtin_merge_usage, 0);
 		free(buf);
 	}
-
-	if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
+        else if(branch && !prefixcmp(k, "branch.") &&
+                !prefixcmp(k + 7, branch) &&
+                !strcmp(k + 7 + strlen(branch), ".upstream")) {
+                return git_config_string(&upstream_branch, k, v);
+        }
+
+        if (!strcmp(k, "merge.defaultupstream"))
+                default_upstream = git_config_bool(k, v);
+        else if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
 		show_diffstat = git_config_bool(k, v);
 	else if (!strcmp(k, "pull.twohead"))
 		return git_config_string(&pull_twohead, k, v);
@@ -983,9 +992,28 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	if (!allow_fast_forward && fast_forward_only)
 		die("You cannot combine --no-ff with --ff-only.");
 
-	if (!argc)
-		usage_with_options(builtin_merge_usage,
-			builtin_merge_options);
+	if (!argc) {
+                if(default_upstream && upstream_branch) {
+		        struct object *o;
+                        struct commit *commit;
+
+                        o = peel_to_type(upstream_branch, 0, NULL, OBJ_COMMIT);
+                        if (!o)
+                            die("%s - not something we can merge", argv[i]);
+                        commit = lookup_commit(o->sha1);
+                        commit->util = (void *)upstream_branch;
+                        remotes = &commit_list_insert(commit, remotes)->next;
+
+                        strbuf_addf(&buf, "GITHEAD_%s", sha1_to_hex(o->sha1));
+                        setenv(buf.buf, upstream_branch, 1);
+                        strbuf_reset(&buf);
+                }
+                else {
+		        usage_with_options(builtin_merge_usage,
+			        builtin_merge_options);
+
+                }
+        }
 
 	/*
 	 * This could be traditional "merge <msg> HEAD <commit>..."  and
@@ -1048,7 +1076,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	if (head_invalid || !argc)
+	if (head_invalid || (!argc && !(default_upstream && upstream_branch)))
 		usage_with_options(builtin_merge_usage,
 			builtin_merge_options);
 
-- 
1.7.4

^ permalink raw reply related

* [PATCH 1/2] sha1_file.c: move find_cached_object up so sha1_object_info can use it
From: Nguyễn Thái Ngọc Duy @ 2011-02-05 14:03 UTC (permalink / raw)
  To: git, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 sha1_file.c |   70 +++++++++++++++++++++++++++++-----------------------------
 1 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index d86a8db..9fd7e16 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -37,6 +37,41 @@ const unsigned char null_sha1[20];
 
 static int git_open_noatime(const char *name, struct packed_git *p);
 
+/*
+ * This is meant to hold a *small* number of objects that you would
+ * want read_sha1_file() to be able to return, but yet you do not want
+ * to write them into the object store (e.g. a browse-only
+ * application).
+ */
+static struct cached_object {
+	unsigned char sha1[20];
+	enum object_type type;
+	void *buf;
+	unsigned long size;
+} *cached_objects;
+static int cached_object_nr, cached_object_alloc;
+
+static struct cached_object empty_tree = {
+	EMPTY_TREE_SHA1_BIN,
+	OBJ_TREE,
+	"",
+	0
+};
+
+static struct cached_object *find_cached_object(const unsigned char *sha1)
+{
+	int i;
+	struct cached_object *co = cached_objects;
+
+	for (i = 0; i < cached_object_nr; i++, co++) {
+		if (!hashcmp(co->sha1, sha1))
+			return co;
+	}
+	if (!hashcmp(sha1, empty_tree.sha1))
+		return &empty_tree;
+	return NULL;
+}
+
 int safe_create_leading_directories(char *path)
 {
 	char *pos = path + offset_1st_component(path);
@@ -2033,41 +2068,6 @@ static void *read_packed_sha1(const unsigned char *sha1,
 	return data;
 }
 
-/*
- * This is meant to hold a *small* number of objects that you would
- * want read_sha1_file() to be able to return, but yet you do not want
- * to write them into the object store (e.g. a browse-only
- * application).
- */
-static struct cached_object {
-	unsigned char sha1[20];
-	enum object_type type;
-	void *buf;
-	unsigned long size;
-} *cached_objects;
-static int cached_object_nr, cached_object_alloc;
-
-static struct cached_object empty_tree = {
-	EMPTY_TREE_SHA1_BIN,
-	OBJ_TREE,
-	"",
-	0
-};
-
-static struct cached_object *find_cached_object(const unsigned char *sha1)
-{
-	int i;
-	struct cached_object *co = cached_objects;
-
-	for (i = 0; i < cached_object_nr; i++, co++) {
-		if (!hashcmp(co->sha1, sha1))
-			return co;
-	}
-	if (!hashcmp(sha1, empty_tree.sha1))
-		return &empty_tree;
-	return NULL;
-}
-
 int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
 		      unsigned char *sha1)
 {
-- 
1.7.3.4.878.g439c7

^ permalink raw reply related

* [PATCH 2/2] sha1_object_info: examine cached_object store too
From: Nguyễn Thái Ngọc Duy @ 2011-02-05 14:03 UTC (permalink / raw)
  To: git, Junio C Hamano; +Cc: Nguyễn Thái Ngọc Duy
In-Reply-To: <1296914582-619-1-git-send-email-pclouds@gmail.com>

Cached object store was added in d66b37b (Add pretend_sha1_file()
interface. - 2007-02-04) as a way to temporarily inject some objects
to object store.

But only read_sha1_file() knows about this store. While it will return
an object from this store, sha1_object_info() will happily say
"object not found".

Teach sha1_object_info() about the cached store for consistency.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 "git mktree" does not accept empty tree as it should do because of this.

 sha1_file.c |    8 ++++++++
 1 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/sha1_file.c b/sha1_file.c
index 9fd7e16..0b830c8 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2020,9 +2020,17 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
 
 int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 {
+	struct cached_object *co;
 	struct pack_entry e;
 	int status;
 
+	co = find_cached_object(sha1);
+	if (co) {
+		if (sizep)
+			*sizep = co->size;
+		return co->type;
+	}
+
 	if (!find_pack_entry(sha1, &e)) {
 		/* Most likely it's a loose object. */
 		status = sha1_loose_object_info(sha1, sizep);
-- 
1.7.3.4.878.g439c7

^ permalink raw reply related

* [PATCH] cache-tree: do not cache empty trees
From: Nguyễn Thái Ngọc Duy @ 2011-02-05 14:07 UTC (permalink / raw)
  To: git, Ilari Liusvaara
  Cc: Jakub Narebski, Jonathan Nieder, Dmitry S. Kravtsov, Shawn Pearce,
	Nguyễn Thái Ngọc Duy
In-Reply-To: <1296899427-1394-1-git-send-email-pclouds@gmail.com>

Current index does not support empty trees. But users can construct
empty trees directly using plumbing. When empty trees are checked out,
things become inconsistent:

 - If cache-tree somehow is invalidated, when a tree is read to index,
   empty trees disappear. When we write trees back, empty trees will
   be gone.

 - If cache-tree is generated by read-tree and remains valid by the
   time trees are written back, empty trees remain.

Let's do it in a consistent way, always disregard empty trees in
index. If users choose to create empty trees their own way, they
should not use index at all.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Third version. Cleaned up t1013. Also needs [1] for mktree to work
 with empty trees.

 [1] http://mid.gmane.org/1296914582-619-1-git-send-email-pclouds@gmail.com

 cache-tree.c               |    9 +++++++++
 t/t1013-read-tree-empty.sh |   20 ++++++++++++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)
 create mode 100755 t/t1013-read-tree-empty.sh

diff --git a/cache-tree.c b/cache-tree.c
index f755590..03732ad 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -621,9 +621,18 @@ static void prime_cache_tree_rec(struct cache_tree *it, struct tree *tree)
 			struct tree *subtree = lookup_tree(entry.sha1);
 			if (!subtree->object.parsed)
 				parse_tree(subtree);
+			if (!hashcmp(entry.sha1, (unsigned char *)EMPTY_TREE_SHA1_BIN)) {
+				warning("empty tree detected! Will be removed in new commits");
+				cnt = -1;
+				break;
+			}
 			sub = cache_tree_sub(it, entry.path);
 			sub->cache_tree = cache_tree();
 			prime_cache_tree_rec(sub->cache_tree, subtree);
+			if (sub->cache_tree->entry_count == -1) {
+				cnt = -1;
+				break;
+			}
 			cnt += sub->cache_tree->entry_count;
 		}
 	}
diff --git a/t/t1013-read-tree-empty.sh b/t/t1013-read-tree-empty.sh
new file mode 100755
index 0000000..8d2ab97
--- /dev/null
+++ b/t/t1013-read-tree-empty.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+test_description='read-tree with empty trees'
+
+. ./test-lib.sh
+
+EMPTY_TREE=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+
+test_expect_success 'setup' '
+	echo "040000 tree $EMPTY_TREE	empty" | git mktree >tree
+'
+
+test_expect_success 'write-tree removes empty tree' '
+	git read-tree `cat tree` &&
+	git write-tree >actual
+	echo $EMPTY_TREE >expected
+	test_cmp expected actual
+'
+
+test_done
-- 
1.7.3.4.878.g439c7

^ permalink raw reply related

* Re: [idea] separate .git dir and the working tree
From: redstun @ 2011-02-05 14:24 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: git, Mike Gant
In-Reply-To: <20110205132708.GA18391@elie>

Making .git a symbol link is nice.

Regarding the GIT_DIR variable, looks like it needs to be paired with
the GIT_WORK_TREE variable, does this mean that I can only have one
local git repository?

what I wanted is, I may have multiple git working tree in my $HOME, like:
$HOME/proj1
$HOME/proj2,

I then wanted their .git directories respectively located at
/safe/disk/.git_proj1
/safe/disk/.git_proj2

How can I get this? I tried to read the doc but didn't have much luck.

Thanks

On Sat, Feb 5, 2011 at 9:27 PM, Jonathan Nieder <jrnieder@gmail.com> wrote:
> (restoring cc list; please do not cull cc's)
>
> Mike Gant wrote:
>> On Sat, Feb 05, 2011 at 10:53:58AM +0800, redstun wrote:
>
>>> I think separating the .git directory from its working tree could
>>> increase the safety of the data to one more level higher.
> [...]
>> GIT_DIR and GIT_WORK_TREE might be what you are looking for. Explanation
>> of usage in 'man git'
>
> The .git directory is allowed to be a symlink.  Or a file like so
>
>        gitdir: /path/to/git/repo
>
> for symlink-challenged operating systems.  See gitrepository-layout(7)
> for details.
>
> Cheers,
> Jonathan
>

^ permalink raw reply

* Re: Performance issue exposed by git-filter-branch
From: Elijah Newren @ 2011-02-05 14:21 UTC (permalink / raw)
  To: Ken Brownfield; +Cc: git
In-Reply-To: <010EA68F-6122-47C7-B761-7D786F37B0C6@irridia.com>

Hi,

On Fri, Feb 4, 2011 at 2:17 PM, Ken Brownfield <krb@irridia.com> wrote:
> Thanks for the feedback on git_fast_filter.  It takes 11.5 hours on our repository instead of 6.5 days, so that's a significant improvement. :-)  I have a couple of observations:
>
> 1) You said that your repo would have taken 2-3 months to filter with git-filter-branch, and the time was reduced to ~1hr.  I'm surprised our reduction was not quite as dramatic, although I presume the variability of repo contents are the explanation.

Variability of the repo certainly would account for some differences,
though I suspect more of the differences come from what kind of
filtering we were doing.  For example, the advantage of
git_fast_filter over filter-branch's --index-filter will be much less
than its advantage over filter-branch's --tree-filter.  Further, in my
case, I was parsing and potentially editing the contents of all files,
which becomes much more painful with filter-branch as you'll need to
re-edit the exact same contents in as many revisions of history as the
file remains unchanged in (in other words, duplicating the same work
hundreds or thousands of times).  With git_fast_filter, I only needed
to parse/edit a given version of some file exactly once.  That's what
really helped in my case.

> 2) The resulting repository pack files are actually much larger.  A garbage collection reduces the size below the original, but only slightly.  I'm concerned that the recreated repository has redundant or inefficiently stored information, but I'm not sure how to verify what objects are taking up what space.

You may want to use packinfo.pl from under contrib/stats/ in the git
repository to find out what objects take up how much space.  From my
notes on using it for this purpose:

  git verify-pack -v .git/objects/pack/pack-<sha1sum>.idx |
packinfo.pl -tree -filenames > tree-info.txt
  sort -k 4 -n tree-info.txt | grep -v ^$ | less

> 3) git_fast_filter doesn't currently support remote submodules.  When it tries to parse a submodule line, the regex fails and the code aborts:
>
> Expected:
>        M 100644 :433236 foo/bar/bletch
> Received, something like:
>        M 100644 cd821b4c0ea8e9493069ff43712a0b09 foo/bar/bletch
>
> To correct the issue, I modified git_fast_filter to simply skip these.  While we no longer utilize remote submodules, I would prefer not to have them removed.
>
> Any feedback on what the proper behavior would be in the submodule case?  Perhaps this is covered in your internal version?

git_fast_filter would need to be modified to handle this kind of
input, create an appropriate object type, and that object type would
need to be able to appropriately output itself later.  Since
submodules haven't really been relevant for me, I've never bothered
implementing this[*].  The assumption that git-fast-export will
produce numeric ids (i.e. that submodules are not present) is somewhat
hardwired in, so it'd take a little bit of refactoring, though
probably not to bad.


Elijah

[*] Well, actually we did hit it once somewhat recently when someone
created a commit containing a submodule...and then also immediately
reverted it.  Since we don't want to use submodules, I simply put in a
hack that would recognize them and unconditionally strip them out on
the input parsing end, which sounds like the same thing you did.
That's obviously not what you're asking for.

^ permalink raw reply

* [1.8.0] Re: reorganize the mess that the source tree has become
From: Nicolas Sebrecht @ 2011-02-05 15:11 UTC (permalink / raw)
  To: Drew Northup
  Cc: Nicolas Sebrecht, Miles Bader, Hilco Wijbenga, git, Nicolas Pitre,
	George Spelvin, Eugene Sajine
In-Reply-To: <1296859660.1255.49.camel@drew-northup.unet.maine.edu>

The 04/02/11, Drew Northup wrote:

> Having once upon a time (in CVS days) taken over a project that was
> neatly organized into tons of folders I can say that more folders is not
> always better.
> If you are organizing things into modules by folders, and those things
> are mutually exclusive pre-compilation then doing so may make sense. If
> the folders ADD value to the project by adding organization--as opposed
> to hiding disorganization--then they may have value.

This _is_ what we are talking about. Not tons of folders or whathever
you might think.

> destructive things
>                                                       killed that first
> project
>                            project       exploded with a fury resembling
> a religious confrontation.                  see that happen to Git
>                see that project die                  you exasperate
> enough of the core developers

Read again. I'm pretty sure this was not your goal but this almostly
looks like FUD to me. So, I don't think I'll involve to more discussion
in this subthread.

-- 
Nicolas Sebrecht

^ permalink raw reply

* ignoring file modes completely
From: Rafael Kitover @ 2011-02-05 15:24 UTC (permalink / raw)
  To: git

Hello,

I found the core.filemode option, which ignores executable bits, but I 
need an option to ignore all mode differences, and such an option does 
not seem to exist.

The reason for this is that I'm trying to use msysGit with Cygwin git, 
sometimes to work with an msysGit clone in cygwin or to work with a 
Cygwin git clone in msysGit. For example, I would like to use "git 
cpan-init" under Cygwin, then use msysGit to work with the repository, 
this is currently impossible.

Here is "git status" on a repo made with Cygwin git under msysGit:

$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working 
directory)
#
#       modified:   Makefile.PL
#       modified:   t/02ads.t
#       modified:   t/02cxn.t
#       modified:   t/04os.t
...
...

Every file is modified because the modes do not match :(

Would it be possible to add some sort of option to ignore all file mode 
changes?

^ permalink raw reply

* Re: ignoring file modes completely
From: Jared Hance @ 2011-02-05 16:03 UTC (permalink / raw)
  To: rkitover; +Cc: git
In-Reply-To: <4D4D6BC2.90101@io.com>

On Sat, 2011-02-05 at 10:24 -0500, Rafael Kitover wrote: 
> Hello,
> 
> I found the core.filemode option, which ignores executable bits, but I 
> need an option to ignore all mode differences, and such an option does 
> not seem to exist.

The only mode tracked by Git is the executable bit, so this shouldn't
even be an issue. Are you sure the executable bit isn't the problem?

^ permalink raw reply

* Re: ignoring file modes completely
From: Rafael Kitover @ 2011-02-05 16:09 UTC (permalink / raw)
  To: git
In-Reply-To: <1296921829.5467.1.camel@localhost.localdomain>

On 2/5/2011 11:03 AM, Jared Hance wrote:
> On Sat, 2011-02-05 at 10:24 -0500, Rafael Kitover wrote:
>> Hello,
>>
>> I found the core.filemode option, which ignores executable bits, but I
>> need an option to ignore all mode differences, and such an option does
>> not seem to exist.
>
> The only mode tracked by Git is the executable bit, so this shouldn't
> even be an issue. Are you sure the executable bit isn't the problem?
>
$ git config --global core.filemode
false

Output of "git diff HEAD" :

diff --git a/Makefile.PL b/Makefile.PL
old mode 100755
new mode 100644
diff --git a/t/02ads.t b/t/02ads.t
old mode 100755
new mode 100644
diff --git a/t/02cxn.t b/t/02cxn.t
old mode 100755
new mode 100644
diff --git a/t/04os.t b/t/04os.t
old mode 100755
new mode 100644
...
...

^ permalink raw reply

* [PATCH] more portable absolute dir check in Git.pm
From: Rafael Kitover @ 2011-02-05 16:19 UTC (permalink / raw)
  To: git

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

I was trying to get msysGit to work with activeperl. I'm not sure how 
far I got, I will revisit this problem in the future, but here is a patch.

It removes a problematic make fragment that doesn't work on nmake (and 
probably dmake as well.) As well as a better absolute dir check in Git.pm .

[-- Attachment #2: 0001-more-portable-absolute-dir-check-in-Git.pm.patch --]
[-- Type: text/plain, Size: 1553 bytes --]

>From 49f6d63f760d8b0b6988ce8cf4ed175965c3bf4b Mon Sep 17 00:00:00 2001
From: Rafael Kitover <rkitover@cpan.org>
Date: Sat, 5 Feb 2011 11:13:31 -0500
Subject: [PATCH] more portable absolute dir check in Git.pm

---
 perl/Git.pm      |    4 +++-
 perl/Makefile.PL |    7 ++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index 6cb0dd1..dee06e1 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -101,6 +101,7 @@ use Error qw(:try);
 use Cwd qw(abs_path);
 use IPC::Open2 qw(open2);
 use Fcntl qw(SEEK_SET SEEK_CUR);
+use File::Spec ();
 }
 
 
@@ -184,7 +185,8 @@ sub repository {
 		};
 
 		if ($dir) {
-			$dir =~ m#^/# or $dir = $opts{Directory} . '/' . $dir;
+                        File::Spec->file_name_is_absolute($dir)
+				or $dir = $opts{Directory} . '/' . $dir;
 			$opts{Repository} = abs_path($dir);
 
 			# If --git-dir went ok, this shouldn't die either.
diff --git a/perl/Makefile.PL b/perl/Makefile.PL
index 0b9deca..7ceec50 100644
--- a/perl/Makefile.PL
+++ b/perl/Makefile.PL
@@ -1,10 +1,13 @@
 use ExtUtils::MakeMaker;
 
 sub MY::postamble {
-	return <<'MAKE_FRAG';
+	my $make_frag = <<'MAKE_FRAG';
 instlibdir:
 	@echo '$(INSTALLSITELIB)'
 
+MAKE_FRAG
+
+	$make_frag .= <<'MAKE_FRAG' if $^O ne 'MSWin32';
 ifneq (,$(DESTDIR))
 ifeq (0,$(shell expr '$(MM_VERSION)' '>' 6.10))
 $(error ExtUtils::MakeMaker version "$(MM_VERSION)" is older than 6.11 and so \
@@ -14,6 +17,8 @@ endif
 endif
 
 MAKE_FRAG
+
+	return $make_frag;
 }
 
 my %pm = ('Git.pm' => '$(INST_LIBDIR)/Git.pm');
-- 
1.7.3.1


^ permalink raw reply related

* Re: ignoring file modes completely
From: Andreas Ericsson @ 2011-02-05 16:58 UTC (permalink / raw)
  To: rkitover; +Cc: git
In-Reply-To: <4D4D7636.7090608@io.com>

On 02/05/2011 05:09 PM, Rafael Kitover wrote:
> On 2/5/2011 11:03 AM, Jared Hance wrote:
>> On Sat, 2011-02-05 at 10:24 -0500, Rafael Kitover wrote:
>>> Hello,
>>>
>>> I found the core.filemode option, which ignores executable bits, but I
>>> need an option to ignore all mode differences, and such an option does
>>> not seem to exist.
>>
>> The only mode tracked by Git is the executable bit, so this shouldn't
>> even be an issue. Are you sure the executable bit isn't the problem?
>>
> $ git config --global core.filemode
> false
> 
> Output of "git diff HEAD" :
> 
> diff --git a/Makefile.PL b/Makefile.PL
> old mode 100755
> new mode 100644
> diff --git a/t/02ads.t b/t/02ads.t
> old mode 100755
> new mode 100644
> diff --git a/t/02cxn.t b/t/02cxn.t
> old mode 100755
> new mode 100644
> diff --git a/t/04os.t b/t/04os.t
> old mode 100755
> new mode 100644

Those are all executable bit diffs.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

Considering the successes of the wars on alcohol, poverty, drugs and
terror, I think we should give some serious thought to declaring war
on peace.

^ permalink raw reply

* Re: [1.8.0] Provide proper remote ref namespaces
From: Kevin P. Fleming @ 2011-02-05 18:00 UTC (permalink / raw)
  To: Johan Herland
  Cc: Junio C Hamano, git, Sverre Rabbelier, Jeff King,
	Nguyen Thai Ngoc Duy, Nicolas Pitre
In-Reply-To: <201102050218.44325.johan@herland.net>

On 02/05/2011 02:18 AM, Johan Herland wrote:

> Today, when you fetch from a remote, the config typically says
>
> [remote "origin"]
>          fetch = +refs/heads/*:refs/remotes/origin/*
>          url = ...
>
> But this fetch refspec does not tell the full story. In addition to mapping
> origin's refs/heads/* into refs/remotes/origin/*, it also fetches origin's
> HEAD into refs/remotes/origin/HEAD, and anything in origin's refs/tags/*
> that happen to point to a fetched object is fetched into refs/tags/* (aka.
> auto-following tags). These other fetches are not explicitly specified in
> the config, but "magically" happen anyway. Instead of having such implicit
> refspecs, I'd rather have all fetch refspecs listed explicitly in the
> config, like this (for replicating current layout):
>
> [remote "origin"]
>          fetch = +HEAD:refs/remotes/origin/HEAD
>          fetch = +refs/heads/*:refs/remotes/origin/*
>          fetch = ~refs/tags/*:refs/tags/*
>          url = ...
>
> or this (in the proposed new layout):
>
> [remote "origin"]
>          fetch = +HEAD:refs/remotes/origin/HEAD
>          fetch = +refs/heads/*:refs/remotes/origin/heads*
>          fetch = +refs/tags/*:refs/remotes/origin/tags/*
>          url = ...

I would appreciate this as well; the less implicit behavior in areas 
like this, the better :-)

-- 
Kevin P. Fleming
Digium, Inc. | Director of Software Technologies
445 Jan Davis Drive NW - Huntsville, AL 35806 - USA
skype: kpfleming | jabber: kfleming@digium.com
Check us out at www.digium.com & www.asterisk.org

^ permalink raw reply

* Re: [idea] separate .git dir and the working tree
From: Jonathan Nieder @ 2011-02-05 18:04 UTC (permalink / raw)
  To: redstun; +Cc: git, Mike Gant
In-Reply-To: <AANLkTinYMuXSvKjgtpSCbJPuo=PHDGR_OgOkwtV4Azmz@mail.gmail.com>

redstun wrote:

> what I wanted is, I may have multiple git working tree in my $HOME, like:
> $HOME/proj1
> $HOME/proj2,
> 
> I then wanted their .git directories respectively located at
> /safe/disk/.git_proj1
> /safe/disk/.git_proj2
> 
> How can I get this? I tried to read the doc but didn't have much luck.

By making .git in $HOME/proj1 a symlink to /safe/disk/.git_proj1 and
making $HOME/proj2/.git a symlink to /safe/disk/.git_proj2.
GIT_DIR should be left unset for this to work.

The GIT_DIR variable is for more complicated use cases in which you
do not want a .git directory, file, or symlink in the worktree at all.

One uses it as follows:

	GIT_DIR=/somewhere/else/.git git <command> ...

The top level of the work tree is inferred to be the current working
directory and git metadata is taken from somewhere else.

Sometimes a person does not only want to work in the top level of the
working tree.  To tell git where the top level is, use the
GIT_WORK_TREE variable:

	(
		GIT_DIR=/somewhere/else/.git; export GIT_DIR
		GIT_WORK_TREE=$(pwd); export GIT_WORK_TREE

		cd sub/directory
		git <command>...

		cd ../other/directory
		git <other command>...
	)

These are not variables for your .profile, since as you mentioned, a
person typically will work with one git repo and worktree sometimes,
another git repo and work tree another time.

Hope that helps,
Jonathan

Side note: I don't think you mentioned wanting it, but for reference,
there is a nice tool for sharing objects between multiple worktrees in
contrib/worktree.  It comes with some sharp edges, as described in [1].

[1] http://thread.gmane.org/gmane.comp.version-control.git/150559

^ permalink raw reply

* [PATCH] Demonstrate breakage: checkout overwrites untracked symlink with directory
From: Johannes Sixt @ 2011-02-05 18:18 UTC (permalink / raw)
  To: Junio C Hamano, Clemens Buchacher; +Cc: git
In-Reply-To: <201102022324.22123.j6t@kdbg.org>

This adds tests where an untracked file and an untracked symlink are in the
way where a directory should be created by 'git checkout'. Commit b1735b1a
(do not overwrite files in leading path, 2010-12-14) fixed the case where
a file is in the way, but the untracked symlink is still removed silently.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
---
On Mittwoch, 2. Februar 2011, Johannes Sixt wrote:
> It seems to interact with the lstat_cache. When lstat
> reports a symlink, this result is cached; but if it is a regular file, it
> is not cached.

The case where a file is in the way was fixed only in v1.7.3.4, but symlinks
are still affected. Clemens, can you help?

-- Hannes

PS: When a date is given for commit reference in a commit message as above,
do you prefer the author date or the committer date? Above, I took the
committer date, which is 2 months behind the author date.

 t/t2019-checkout-overwrite.sh |   50 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 50 insertions(+), 0 deletions(-)
 create mode 100755 t/t2019-checkout-overwrite.sh

diff --git a/t/t2019-checkout-overwrite.sh b/t/t2019-checkout-overwrite.sh
new file mode 100755
index 0000000..e4e529d
--- /dev/null
+++ b/t/t2019-checkout-overwrite.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='checkout must not overwrite an untracked objects'
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+	mkdir -p a/b/c &&
+	>a/b/c/d &&
+	git add -A &&
+	git commit -m base &&
+	git tag start
+'
+
+test_expect_success 'create a commit where dir a/b changed to file' '
+
+	git checkout -b file &&
+	rm -rf a/b &&
+	>a/b &&
+	git add -A &&
+	git commit -m "dir to file"
+'
+
+test_expect_success 'checkout commit with dir must not remove untracked a/b' '
+
+	git rm --cached a/b &&
+	git commit -m "un-track the file" &&
+	test_must_fail git checkout start &&
+	test -f a/b
+'
+
+test_expect_success 'create a commit where dir a/b changed to symlink' '
+
+	rm -rf a/b &&	# cleanup if previous test failed
+	git checkout -f -b symlink start &&
+	rm -rf a/b &&
+	ln -s foo a/b &&
+	git add -A &&
+	git commit -m "dir to symlink"
+'
+
+test_expect_failure 'checkout commit with dir must not remove untracked a/b' '
+
+	git rm --cached a/b &&
+	git commit -m "un-track the symlink" &&
+	test_must_fail git checkout start &&
+	test -h a/b
+'
+
+test_done
-- 
1.7.4.80.g89060

^ permalink raw reply related

* Re: git-svn bug: Could not unmemoize function `lookup_svn_merge' ...
From: George V. Reilly @ 2011-02-05 18:32 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <AANLkTi=QrGK_-iJAnuKONs5WkjtKorg3wPBKdw+qWjTU@mail.gmail.com>

On Mon, Dec 27, 2010 at 9:37 PM, George V. Reilly <george@reilly.org> wrote:
> Using git version 1.7.3.2 on OS X 10.6.5 against the Subversion
> repository at work, I got
>
>    georger@George-Reillys-MacBook-Pro-17:~/src/wc-git$ git svn rebase
>        M       CoBranding/Resources/USA7/Resources.resx
>        M       CoBranding/Resources/Resources.csproj
>    Byte order is not compatible at ../../lib/Storable.pm (autosplit
> into ../../lib/auto/Storable/_retrieve.al) line 380, at
> /System/Library/Perl/5.10.0/Memoize/Storable.pm line 21
>
>    Could not unmemoize function `lookup_svn_merge', because it was
> not memoized to begin with at /usr/local/git/libexec/git-core/git-svn
> line 3194
>    END failed--call queue aborted at
> /usr/local/git/libexec/git-core/git-svn line 39.
>
> The error was repeatable.
>
> I managed to get past it by using the git-svn Perl script from Git 1.6.5.7,
> per http://kerneltrap.org/mailarchive/git/2010/1/13/20137, and invoking it thus:
>
>    $ perl -I /usr/local/git/lib/perl5/site_perl/ ~/temp/git-svn.pl rebase

After being absent for a month, the problem recurred. I upgraded to Git 1.7.4,
but it still occurs, albeit at line 3197 of git-svn.

Once again, the git-svn 1.6.5.7 works past it.
--
/George V. Reilly  george@reilly.org  Twitter: @georgevreilly
http://www.georgevreilly.com/blog  http://blogs.cozi.com/tech

^ permalink raw reply

* Re: [PATCH] Demonstrate breakage: checkout overwrites untracked symlink with directory
From: Clemens Buchacher @ 2011-02-05 18:33 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Junio C Hamano, git
In-Reply-To: <201102051918.44848.j6t@kdbg.org>

Hi Hannes,

On Sat, Feb 05, 2011 at 07:18:44PM +0100, Johannes Sixt wrote:
>
> This adds tests where an untracked file and an untracked symlink are in the
> way where a directory should be created by 'git checkout'. Commit b1735b1a
> (do not overwrite files in leading path, 2010-12-14) fixed the case where
> a file is in the way, but the untracked symlink is still removed silently.

Indeed. It was my impression from reading the code that this
behavior is intentional. To protect symlinks from being overwritten
as well, I believe we simply have to remove FL_SYMLINK from the
following line in check_leading_path().

diff --git a/symlinks.c b/symlinks.c
index 3cacebd..034943b 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -223,7 +223,7 @@ int check_leading_path(const char *name, int len)
        int flags;
        int match_len = lstat_cache_matchlen(cache, name, len, &flags,
                           FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT);
-       if (flags & (FL_SYMLINK|FL_NOENT))
+       if (flags & FL_NOENT)
                return 0;
        else if (flags & FL_DIR)
                return -1;

It does fix your testcase, but it may break others and I will have
to review the code to be sure.

Clemens

^ permalink raw reply related

* Re: [1.8.0] Provide proper remote ref namespaces
From: Nicolas Pitre @ 2011-02-05 18:39 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Johan Herland, git, Sverre Rabbelier, Jeff King,
	Nguyen Thai Ngoc Duy
In-Reply-To: <7vpqr7xw4z.fsf@alter.siamese.dyndns.org>

On Fri, 4 Feb 2011, Junio C Hamano wrote:

> For some reason, many people seem to be enthused about splitting the tag
> namespace, but I am not sure if that is a good thing in general.  Branches
> are moving pointers for people to flip around in their local repositories,
> and it makes sense to say "My master is a bit ahead of the public one",
> but what would we gain by making it _easier_ to add and exchange many tags
> with the same name (e.g. refs/remotes/*/tags/v1.7.4 vs refs/tags/v1.7.4),
> other than the extra confusion?

The extraordinary misfeature of the tag namespace at the moment comes 
from the fact that whenever you add a remote repo to fetch, and do fetch 
it, then your flat tag namespace gets polluted with all the tags the 
remote might have.  If you decide to delete some of those remote 
branches, the tags that came with it are still there and 
indistinguishable from other tags making it a real pain to sort out.

So that's what has to be fixed.  If you get duplicated tag names then 
just warn the user and give priority to the local one, or error out with 
a "ambiguous tag specification" if no local but multiple remote tags 
with the same name are found (the user would have to be more precise in 
the tag scope in that case).


Nicolas

^ permalink raw reply

* Fwd: GIT - cloning torvalds/linux-2.6.git repository trouble.
From: Valentin QUEQUET @ 2011-02-05 18:45 UTC (permalink / raw)
  To: git
In-Reply-To: <AANLkTikiKagzJMh_xuOSzfA4c-qxOHhVeU2jhmbaDHji@mail.gmail.com>

---------- Forwarded message ----------
From: Valentin QUEQUET <valentin.quequet@gmail.com>
Date: Sat, 5 Feb 2011 18:17:57 +0000
Subject: GIT - cloning torvalds/linux-2.6.git repository trouble.
To: linux-kernel@vger.kernel.org

Hi Dear Linux enthusiasts,

I recently (yesterday) began to fetch (clone, fetch, ...) the current
  Linux GIT repository:
    http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git

I first failed to fetch it through any protocol ( git:// , http:// , https:// )
  because of my UNRELIABLE WiFi connexion.

I eventually managed to download the following file :

http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/refs/heads/master
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/info/packs

http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-0b38509807589c455b1c769368348bd845441959.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-c53d2db50f885f3803a3afd46484b54c06b1433e.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-910f14bdd726702c46cfd622ee40fcaf4881a5ec.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-81315ef1065b534c70a409978aa11daf2e27fdb5.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-83898168fc5bce601472bd3260cd6b08f5f4f7b2.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-7ff1ea46fec7532e88a900a9a1340794fb3ffa3f.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-221cb4abe6bb3165bf062219200020148b83948b.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-6576226aba312e2a3b610665e35cfc466f980c55.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-0ab67efdf76cff54cd9fa5166d1df19c8edf685a.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-0b7fc86700a243d2ea341c04926c4425fe85fd26.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-fb3e46067bf5b97b6b49dbda9cda51cf3ef3b660.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-04fb51824d013a5fbac892f95369d92daf60f195.idx
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-76001124ed6335482ee1cea785f93426ab278417.idx

http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-0b38509807589c455b1c769368348bd845441959.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-c53d2db50f885f3803a3afd46484b54c06b1433e.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-910f14bdd726702c46cfd622ee40fcaf4881a5ec.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-81315ef1065b534c70a409978aa11daf2e27fdb5.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-83898168fc5bce601472bd3260cd6b08f5f4f7b2.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-7ff1ea46fec7532e88a900a9a1340794fb3ffa3f.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-221cb4abe6bb3165bf062219200020148b83948b.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-6576226aba312e2a3b610665e35cfc466f980c55.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-0ab67efdf76cff54cd9fa5166d1df19c8edf685a.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-0b7fc86700a243d2ea341c04926c4425fe85fd26.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-fb3e46067bf5b97b6b49dbda9cda51cf3ef3b660.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-04fb51824d013a5fbac892f95369d92daf60f195.pack
http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/pack/pack-76001124ed6335482ee1cea785f93426ab278417.pack

And all these .pack and .idx files appear to be valid ones, with
respect to the "git verify-pack" command.

This set of files seems to be consistent with the current state (by that time)
  of the Linux git repository (torvalds/linux-2.6.git)

Now, I would like YOU to tell ME how I can checkout from the PACKs
I've just downloaded.

How may I populate the working directory , objects/xy/... , refs/... ,
... hierarchies to
  make my (local) repository usable.

I suspect I shall find this information in documentation related to
the "git fetch" command,
  but I haven't managed to get it right.

Your HELP is very welcome.


If you prefer not to pollute LKML, you may choose to aswer me at:

  valentin.quequet@gmail.com


Thanks in advance,

Valentin

^ 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