Git development
 help / color / mirror / Atom feed
* Re: git-svn with non-standard repository layout
From: Piotr Krukowiecki @ 2012-12-05 22:19 UTC (permalink / raw)
  To: Stephen Bash; +Cc: Git Mailing List, Carsten Fuchs
In-Reply-To: <1056577717.281976.1354725880396.JavaMail.root@genarts.com>

On Wed, Dec 5, 2012 at 5:44 PM, Stephen Bash <bash@genarts.com> wrote:
> ----- Original Message -----
>> From: "Piotr Krukowiecki" <piotr.krukowiecki@gmail.com>
>> Sent: Wednesday, December 5, 2012 11:26:54 AM
>> Subject: Re: git-svn with non-standard repository layout
>>
>> On Tue, Dec 4, 2012 at 10:19 PM, Carsten Fuchs
>> <carsten.fuchs@cafu.de> wrote:
>> > Hi Piotr,
>> >
>> > Am 2012-12-04 18:29, schrieb Piotr Krukowiecki:
>> >
>> >> Is there a way to handle svn repository with following layout?
>> >>
>> >> repo/trunk
>> >> repo/branches/branch1
>> >> repo/branches/branch2
>> >> repo/branches/work/developer1/branch3
>> >> repo/branches/work/developer1/branch4
>> >> repo/branches/work/developer2/branch5
>> >
>> > see my post at
>> >     http://www.cafu.de/forum/viewtopic.php?f=14&t=1092
>> > heading "Branches outside branches/".
>> >
>> > You may need something like
>> >     git config --add svn-remote.svn.fetch
>> > "path.../branchX:refs/remotes/branchX"
>> > for each of your branches.
>>
>> that works :)
>>
>> Although not an ideal solution - I have to manually configure all
>> branches + update them as they are created
>
> It's not a 100% solution, but you can use a limited glob-like syntax in the branches and tags lines of the svn-remote config block.  You still need to do some manual work (one entry for each developer), but the wildcards eliminate a lot of the grunt work as individual branches are created.  See the very end of the git-svn manpage for examples (section titled CONFIGURATION).  I use that technique to track a subdirectory of the Slimdevices SVN repo [1], which has a similarly complex layout:
>
> repo/7.1/trunk
> repo/7.1/branches/branchA
> repo/7.1/branches/branchB
> repo/7.1/tags/tag1
> repo/7.2/trunk
> repo/7.2/branches/branchC

Do you mean something like

   branches = branches/work/*/*:refs/remotes/work/*
   branches = branches/{branch1,branch2}:refs/remotes/branches/*

instead of (currently used)

   branches = branches/work/*/*:refs/remotes/work/*
   fetch = branches/branch1:refs/remotes/branches/branch1
   fetch = branches/branch2:refs/remotes/branches/branch2

I will try that tomorrow.

BTW what's the difference between "fetch" and "branches" keys? I could
only find one: "fetch" does not support glob arguments and "branches"
do.

--
Piotr Krukowiecki

^ permalink raw reply

* [PATCH] Add directory pattern matching to attributes
From: Jean-Noël AVILA @ 2012-12-05 22:15 UTC (permalink / raw)
  To: git

The manpage of gitattributes says: "The rules how the pattern
matches paths are the same as in .gitignore files" and the gitignore
pattern rules has a pattern ending with / for directory matching.

This rule is specifically relevant for the 'export-ignore' rule used
for git archive.

Signed-off-by: Jean-Noel Avila <jn.avila@free.fr>
---
 archive.c                       |    2 +-
 attr.c                          |   47 ++++++++++++++++++++++++-------------
 attr.h                          |    4 ++--
 builtin/check-attr.c            |    7 ++++--
 builtin/pack-objects.c          |    2 +-
 convert.c                       |    2 +-
 ll-merge.c                      |    4 ++--
 t/t5002-archive-attr-pattern.sh |   49 +++++++++++++++++++++++++++++++++++++++
 userdiff.c                      |    2 +-
 ws.c                            |    2 +-
 10 files changed, 94 insertions(+), 27 deletions(-)
 create mode 100644 t/t5002-archive-attr-pattern.sh

diff --git a/archive.c b/archive.c
index 4666404..b8ff14f 100644
--- a/archive.c
+++ b/archive.c
@@ -123,7 +123,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
 	path_without_prefix = path.buf + args->baselen;
 
 	setup_archive_check(check);
-	if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
+	if (!git_check_attr(path_without_prefix, mode, ARRAY_SIZE(check), check)) {
 		if (ATTR_TRUE(check[0].value))
 			return 0;
 		args->convert = ATTR_TRUE(check[1].value);
diff --git a/attr.c b/attr.c
index 887a9ae..da386f2 100644
--- a/attr.c
+++ b/attr.c
@@ -548,7 +548,7 @@ static void bootstrap_attr_stack(void)
 	attr_stack = elem;
 }
 
-static void prepare_attr_stack(const char *path)
+static void prepare_attr_stack(const char *path, unsigned mode)
 {
 	struct attr_stack *elem, *info;
 	int dirlen, len;
@@ -645,28 +645,43 @@ static void prepare_attr_stack(const char *path)
 }
 
 static int path_matches(const char *pathname, int pathlen,
-			const char *pattern,
+			const unsigned mode, char *pattern,
 			const char *base, int baselen)
 {
-	if (!strchr(pattern, '/')) {
+	size_t len;
+	char buf[PATH_MAX];
+	char * lpattern = buf;
+	len = strlen(pattern);
+	if (PATH_MAX <= len)
+		return 0;
+	strncpy(buf,pattern,len);
+	buf[len] ='\0';
+	if (len && lpattern[len - 1] == '/') {
+		if (S_ISDIR(mode))
+			lpattern[len - 1] = '\0';
+		else
+			return 0;
+	}
+
+	if (!strchr(lpattern, '/')) {
 		/* match basename */
 		const char *basename = strrchr(pathname, '/');
 		basename = basename ? basename + 1 : pathname;
-		return (fnmatch_icase(pattern, basename, 0) == 0);
+		return (fnmatch_icase(lpattern, basename, 0) == 0);
 	}
 	/*
 	 * match with FNM_PATHNAME; the pattern has base implicitly
 	 * in front of it.
 	 */
-	if (*pattern == '/')
-		pattern++;
+	if (*lpattern == '/')
+		lpattern++;
 	if (pathlen < baselen ||
 	    (baselen && pathname[baselen] != '/') ||
 	    strncmp(pathname, base, baselen))
 		return 0;
 	if (baselen != 0)
 		baselen++;
-	return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;
+	return fnmatch_icase(lpattern, pathname + baselen, FNM_PATHNAME) == 0;
 }
 
 static int macroexpand_one(int attr_nr, int rem);
@@ -693,7 +708,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
 	return rem;
 }
 
-static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
+static int fill(const char *path, int pathlen, unsigned mode, struct attr_stack *stk, int rem)
 {
 	int i;
 	const char *base = stk->origin ? stk->origin : "";
@@ -702,7 +717,7 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
 		struct match_attr *a = stk->attrs[i];
 		if (a->is_macro)
 			continue;
-		if (path_matches(path, pathlen,
+		if (path_matches(path, pathlen, mode,
 				 a->u.pattern, base, strlen(base)))
 			rem = fill_one("fill", a, rem);
 	}
@@ -737,26 +752,26 @@ static int macroexpand_one(int attr_nr, int rem)
  * Collect all attributes for path into the array pointed to by
  * check_all_attr.
  */
-static void collect_all_attrs(const char *path)
+static void collect_all_attrs(const char *path, unsigned mode)
 {
 	struct attr_stack *stk;
 	int i, pathlen, rem;
 
-	prepare_attr_stack(path);
+	prepare_attr_stack(path, mode);
 	for (i = 0; i < attr_nr; i++)
 		check_all_attr[i].value = ATTR__UNKNOWN;
 
 	pathlen = strlen(path);
 	rem = attr_nr;
 	for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
-		rem = fill(path, pathlen, stk, rem);
+		rem = fill(path, pathlen, mode, stk, rem);
 }
 
-int git_check_attr(const char *path, int num, struct git_attr_check *check)
+int git_check_attr(const char *path, unsigned mode, int num, struct git_attr_check *check)
 {
 	int i;
 
-	collect_all_attrs(path);
+	collect_all_attrs(path, mode);
 
 	for (i = 0; i < num; i++) {
 		const char *value = check_all_attr[check[i].attr->attr_nr].value;
@@ -768,11 +783,11 @@ int git_check_attr(const char *path, int num, struct git_attr_check *check)
 	return 0;
 }
 
-int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
+int git_all_attrs(const char *path, unsigned mode, int *num, struct git_attr_check **check)
 {
 	int i, count, j;
 
-	collect_all_attrs(path);
+	collect_all_attrs(path, mode);
 
 	/* Count the number of attributes that are set. */
 	count = 0;
diff --git a/attr.h b/attr.h
index 8b08d33..125d9c2 100644
--- a/attr.h
+++ b/attr.h
@@ -36,7 +36,7 @@ struct git_attr_check {
  */
 char *git_attr_name(struct git_attr *);
 
-int git_check_attr(const char *path, int, struct git_attr_check *);
+int git_check_attr(const char *path, unsigned mode, int, struct git_attr_check *);
 
 /*
  * Retrieve all attributes that apply to the specified path.  *num
@@ -45,7 +45,7 @@ int git_check_attr(const char *path, int, struct git_attr_check *);
  * objects describing the attributes and their values.  *check must be
  * free()ed by the caller.
  */
-int git_all_attrs(const char *path, int *num, struct git_attr_check **check);
+int git_all_attrs(const char *path, unsigned mode, int *num, struct git_attr_check **check);
 
 enum git_attr_direction {
 	GIT_ATTR_CHECKIN,
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 075d01d..2928480 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -46,14 +46,17 @@ static void output_attr(int cnt, struct git_attr_check *check,
 static void check_attr(const char *prefix, int cnt,
 	struct git_attr_check *check, const char *file)
 {
+	struct stat st;
 	char *full_path =
 		prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
+	stat(full_path,&st);
 	if (check != NULL) {
-		if (git_check_attr(full_path, cnt, check))
+		stat(full_path,&st);
+		if (git_check_attr(full_path, st.st_mode, cnt, check))
 			die("git_check_attr died");
 		output_attr(cnt, check, file);
 	} else {
-		if (git_all_attrs(full_path, &cnt, &check))
+		if (git_all_attrs(full_path, st.st_mode, &cnt, &check))
 			die("git_all_attrs died");
 		output_attr(cnt, check, file);
 		free(check);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 5e14064..acf75d4 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -894,7 +894,7 @@ static int no_try_delta(const char *path)
 	struct git_attr_check check[1];
 
 	setup_delta_attr_check(check);
-	if (git_check_attr(path, ARRAY_SIZE(check), check))
+	if (git_check_attr(path, 0, ARRAY_SIZE(check), check))
 		return 0;
 	if (ATTR_FALSE(check->value))
 		return 1;
diff --git a/convert.c b/convert.c
index 6602155..e01c290 100644
--- a/convert.c
+++ b/convert.c
@@ -759,7 +759,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
 		git_config(read_convert_config, NULL);
 	}
 
-	if (!git_check_attr(path, NUM_CONV_ATTRS, ccheck)) {
+	if (!git_check_attr(path, 0, NUM_CONV_ATTRS, ccheck)) {
 		ca->crlf_action = git_path_check_crlf(path, ccheck + 4);
 		if (ca->crlf_action == CRLF_GUESS)
 			ca->crlf_action = git_path_check_crlf(path, ccheck + 0);
diff --git a/ll-merge.c b/ll-merge.c
index acea33b..a8d3b2a 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -346,7 +346,7 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2]
 		check[0].attr = git_attr("merge");
 		check[1].attr = git_attr("conflict-marker-size");
 	}
-	return git_check_attr(path, 2, check);
+	return git_check_attr(path, 0, 2, check);
 }
 
 static void normalize_file(mmfile_t *mm, const char *path)
@@ -403,7 +403,7 @@ int ll_merge_marker_size(const char *path)
 
 	if (!check.attr)
 		check.attr = git_attr("conflict-marker-size");
-	if (!git_check_attr(path, 1, &check) && check.value) {
+	if (!git_check_attr(path, 0, 1, &check) && check.value) {
 		marker_size = atoi(check.value);
 		if (marker_size <= 0)
 			marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh
new file mode 100644
index 0000000..3274057
--- /dev/null
+++ b/t/t5002-archive-attr-pattern.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='git archive attribute pattern tests'
+
+. ./test-lib.sh
+
+test_expect_exists() {
+	test_expect_success " $1 exists" "test -e $1"
+}
+
+test_expect_missing() {
+	test_expect_success " $1 does not exist" "test ! -e $1"
+}
+
+test_expect_success 'setup' '
+	echo ignored >ignored &&
+	echo ignored export-ignore >>.git/info/attributes &&
+	git add ignored &&
+
+	mkdir not-ignored-dir &&
+	echo ignored-in-tree >not-ignored-dir/ignored &&
+	echo not-ignored-in-tree >not-ignored-dir/not-ignored &&
+	git add not-ignored-dir &&
+
+	mkdir ignored-dir &&
+	echo ignored by ignored dir >ignored-dir/ignored-by-ignored-dir &&
+	echo ignored-dir/ export-ignore >>.git/info/attributes &&
+	git add ignored-dir &&
+
+	git commit -m. &&
+
+	git clone --bare . bare &&
+	cp .git/info/attributes bare/info/attributes
+'
+
+test_expect_success 'git archive' '
+	git archive HEAD >archive.tar &&
+	(mkdir archive && cd archive && "$TAR" xf -) <archive.tar
+'
+
+test_expect_missing	archive/ignored
+test_expect_missing	archive/not-ignored-dir/ignored
+test_expect_exists	archive/not-ignored-dir/not-ignored
+test_expect_exists	archive/not-ignored-dir/
+test_expect_missing	archive/ignored-dir/
+test_expect_missing	archive/ignored-dir/ignored-by-ignored-dir
+
+
+test_done
diff --git a/userdiff.c b/userdiff.c
index ed958ef..2faec37 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -275,7 +275,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path)
 
 	if (!path)
 		return NULL;
-	if (git_check_attr(path, 1, &check))
+	if (git_check_attr(path, 0, 1, &check))
 		return NULL;
 
 	if (ATTR_TRUE(check.value))
diff --git a/ws.c b/ws.c
index b498d75..f122451 100644
--- a/ws.c
+++ b/ws.c
@@ -88,7 +88,7 @@ unsigned whitespace_rule(const char *pathname)
 	struct git_attr_check attr_whitespace_rule;
 
 	setup_whitespace_attr_check(&attr_whitespace_rule);
-	if (!git_check_attr(pathname, 1, &attr_whitespace_rule)) {
+	if (!git_check_attr(pathname, 0, 1, &attr_whitespace_rule)) {
 		const char *value;
 
 		value = attr_whitespace_rule.value;
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH] Add directory pattern matching to attributes
From: Jean-Noël AVILA @ 2012-12-05 22:10 UTC (permalink / raw)
  To: git

The manpage of gitattributes says: "The rules how the pattern
matches paths are the same as in .gitignore files" and the gitignore
pattern rules has a pattern ending with / for directory matching.

This rule is specifically relevant for the 'export-ignore' rule used
for git archive.

Signed-off-by: Jean-Noel Avila <jn.avila@free.fr>
---
 archive.c                       |    2 +-
 attr.c                          |   47 ++++++++++++++++++++++++-------------
 attr.h                          |    4 ++--
 builtin/check-attr.c            |    7 ++++--
 builtin/pack-objects.c          |    2 +-
 convert.c                       |    2 +-
 ll-merge.c                      |    4 ++--
 t/t5002-archive-attr-pattern.sh |   49 +++++++++++++++++++++++++++++++++++++++
 userdiff.c                      |    2 +-
 ws.c                            |    2 +-
 10 files changed, 94 insertions(+), 27 deletions(-)
 create mode 100644 t/t5002-archive-attr-pattern.sh

diff --git a/archive.c b/archive.c
index 4666404..b8ff14f 100644
--- a/archive.c
+++ b/archive.c
@@ -123,7 +123,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
 	path_without_prefix = path.buf + args->baselen;
 
 	setup_archive_check(check);
-	if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
+	if (!git_check_attr(path_without_prefix, mode, ARRAY_SIZE(check), check)) {
 		if (ATTR_TRUE(check[0].value))
 			return 0;
 		args->convert = ATTR_TRUE(check[1].value);
diff --git a/attr.c b/attr.c
index 887a9ae..da386f2 100644
--- a/attr.c
+++ b/attr.c
@@ -548,7 +548,7 @@ static void bootstrap_attr_stack(void)
 	attr_stack = elem;
 }
 
-static void prepare_attr_stack(const char *path)
+static void prepare_attr_stack(const char *path, unsigned mode)
 {
 	struct attr_stack *elem, *info;
 	int dirlen, len;
@@ -645,28 +645,43 @@ static void prepare_attr_stack(const char *path)
 }
 
 static int path_matches(const char *pathname, int pathlen,
-			const char *pattern,
+			const unsigned mode, char *pattern,
 			const char *base, int baselen)
 {
-	if (!strchr(pattern, '/')) {
+	size_t len;
+	char buf[PATH_MAX];
+	char * lpattern = buf;
+	len = strlen(pattern);
+	if (PATH_MAX <= len)
+		return 0;
+	strncpy(buf,pattern,len);
+	buf[len] ='\0';
+	if (len && lpattern[len - 1] == '/') {
+		if (S_ISDIR(mode))
+			lpattern[len - 1] = '\0';
+		else
+			return 0;
+	}
+
+	if (!strchr(lpattern, '/')) {
 		/* match basename */
 		const char *basename = strrchr(pathname, '/');
 		basename = basename ? basename + 1 : pathname;
-		return (fnmatch_icase(pattern, basename, 0) == 0);
+		return (fnmatch_icase(lpattern, basename, 0) == 0);
 	}
 	/*
 	 * match with FNM_PATHNAME; the pattern has base implicitly
 	 * in front of it.
 	 */
-	if (*pattern == '/')
-		pattern++;
+	if (*lpattern == '/')
+		lpattern++;
 	if (pathlen < baselen ||
 	    (baselen && pathname[baselen] != '/') ||
 	    strncmp(pathname, base, baselen))
 		return 0;
 	if (baselen != 0)
 		baselen++;
-	return fnmatch_icase(pattern, pathname + baselen, FNM_PATHNAME) == 0;
+	return fnmatch_icase(lpattern, pathname + baselen, FNM_PATHNAME) == 0;
 }
 
 static int macroexpand_one(int attr_nr, int rem);
@@ -693,7 +708,7 @@ static int fill_one(const char *what, struct match_attr *a, int rem)
 	return rem;
 }
 
-static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
+static int fill(const char *path, int pathlen, unsigned mode, struct attr_stack *stk, int rem)
 {
 	int i;
 	const char *base = stk->origin ? stk->origin : "";
@@ -702,7 +717,7 @@ static int fill(const char *path, int pathlen, struct attr_stack *stk, int rem)
 		struct match_attr *a = stk->attrs[i];
 		if (a->is_macro)
 			continue;
-		if (path_matches(path, pathlen,
+		if (path_matches(path, pathlen, mode,
 				 a->u.pattern, base, strlen(base)))
 			rem = fill_one("fill", a, rem);
 	}
@@ -737,26 +752,26 @@ static int macroexpand_one(int attr_nr, int rem)
  * Collect all attributes for path into the array pointed to by
  * check_all_attr.
  */
-static void collect_all_attrs(const char *path)
+static void collect_all_attrs(const char *path, unsigned mode)
 {
 	struct attr_stack *stk;
 	int i, pathlen, rem;
 
-	prepare_attr_stack(path);
+	prepare_attr_stack(path, mode);
 	for (i = 0; i < attr_nr; i++)
 		check_all_attr[i].value = ATTR__UNKNOWN;
 
 	pathlen = strlen(path);
 	rem = attr_nr;
 	for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
-		rem = fill(path, pathlen, stk, rem);
+		rem = fill(path, pathlen, mode, stk, rem);
 }
 
-int git_check_attr(const char *path, int num, struct git_attr_check *check)
+int git_check_attr(const char *path, unsigned mode, int num, struct git_attr_check *check)
 {
 	int i;
 
-	collect_all_attrs(path);
+	collect_all_attrs(path, mode);
 
 	for (i = 0; i < num; i++) {
 		const char *value = check_all_attr[check[i].attr->attr_nr].value;
@@ -768,11 +783,11 @@ int git_check_attr(const char *path, int num, struct git_attr_check *check)
 	return 0;
 }
 
-int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
+int git_all_attrs(const char *path, unsigned mode, int *num, struct git_attr_check **check)
 {
 	int i, count, j;
 
-	collect_all_attrs(path);
+	collect_all_attrs(path, mode);
 
 	/* Count the number of attributes that are set. */
 	count = 0;
diff --git a/attr.h b/attr.h
index 8b08d33..125d9c2 100644
--- a/attr.h
+++ b/attr.h
@@ -36,7 +36,7 @@ struct git_attr_check {
  */
 char *git_attr_name(struct git_attr *);
 
-int git_check_attr(const char *path, int, struct git_attr_check *);
+int git_check_attr(const char *path, unsigned mode, int, struct git_attr_check *);
 
 /*
  * Retrieve all attributes that apply to the specified path.  *num
@@ -45,7 +45,7 @@ int git_check_attr(const char *path, int, struct git_attr_check *);
  * objects describing the attributes and their values.  *check must be
  * free()ed by the caller.
  */
-int git_all_attrs(const char *path, int *num, struct git_attr_check **check);
+int git_all_attrs(const char *path, unsigned mode, int *num, struct git_attr_check **check);
 
 enum git_attr_direction {
 	GIT_ATTR_CHECKIN,
diff --git a/builtin/check-attr.c b/builtin/check-attr.c
index 075d01d..2928480 100644
--- a/builtin/check-attr.c
+++ b/builtin/check-attr.c
@@ -46,14 +46,17 @@ static void output_attr(int cnt, struct git_attr_check *check,
 static void check_attr(const char *prefix, int cnt,
 	struct git_attr_check *check, const char *file)
 {
+	struct stat st;
 	char *full_path =
 		prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
+	stat(full_path,&st);
 	if (check != NULL) {
-		if (git_check_attr(full_path, cnt, check))
+		stat(full_path,&st);
+		if (git_check_attr(full_path, st.st_mode, cnt, check))
 			die("git_check_attr died");
 		output_attr(cnt, check, file);
 	} else {
-		if (git_all_attrs(full_path, &cnt, &check))
+		if (git_all_attrs(full_path, st.st_mode, &cnt, &check))
 			die("git_all_attrs died");
 		output_attr(cnt, check, file);
 		free(check);
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 5e14064..acf75d4 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -894,7 +894,7 @@ static int no_try_delta(const char *path)
 	struct git_attr_check check[1];
 
 	setup_delta_attr_check(check);
-	if (git_check_attr(path, ARRAY_SIZE(check), check))
+	if (git_check_attr(path, 0, ARRAY_SIZE(check), check))
 		return 0;
 	if (ATTR_FALSE(check->value))
 		return 1;
diff --git a/convert.c b/convert.c
index 6602155..e01c290 100644
--- a/convert.c
+++ b/convert.c
@@ -759,7 +759,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
 		git_config(read_convert_config, NULL);
 	}
 
-	if (!git_check_attr(path, NUM_CONV_ATTRS, ccheck)) {
+	if (!git_check_attr(path, 0, NUM_CONV_ATTRS, ccheck)) {
 		ca->crlf_action = git_path_check_crlf(path, ccheck + 4);
 		if (ca->crlf_action == CRLF_GUESS)
 			ca->crlf_action = git_path_check_crlf(path, ccheck + 0);
diff --git a/ll-merge.c b/ll-merge.c
index acea33b..a8d3b2a 100644
--- a/ll-merge.c
+++ b/ll-merge.c
@@ -346,7 +346,7 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2]
 		check[0].attr = git_attr("merge");
 		check[1].attr = git_attr("conflict-marker-size");
 	}
-	return git_check_attr(path, 2, check);
+	return git_check_attr(path, 0, 2, check);
 }
 
 static void normalize_file(mmfile_t *mm, const char *path)
@@ -403,7 +403,7 @@ int ll_merge_marker_size(const char *path)
 
 	if (!check.attr)
 		check.attr = git_attr("conflict-marker-size");
-	if (!git_check_attr(path, 1, &check) && check.value) {
+	if (!git_check_attr(path, 0, 1, &check) && check.value) {
 		marker_size = atoi(check.value);
 		if (marker_size <= 0)
 			marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh
new file mode 100644
index 0000000..3274057
--- /dev/null
+++ b/t/t5002-archive-attr-pattern.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+test_description='git archive attribute pattern tests'
+
+. ./test-lib.sh
+
+test_expect_exists() {
+	test_expect_success " $1 exists" "test -e $1"
+}
+
+test_expect_missing() {
+	test_expect_success " $1 does not exist" "test ! -e $1"
+}
+
+test_expect_success 'setup' '
+	echo ignored >ignored &&
+	echo ignored export-ignore >>.git/info/attributes &&
+	git add ignored &&
+
+	mkdir not-ignored-dir &&
+	echo ignored-in-tree >not-ignored-dir/ignored &&
+	echo not-ignored-in-tree >not-ignored-dir/not-ignored &&
+	git add not-ignored-dir &&
+
+	mkdir ignored-dir &&
+	echo ignored by ignored dir >ignored-dir/ignored-by-ignored-dir &&
+	echo ignored-dir/ export-ignore >>.git/info/attributes &&
+	git add ignored-dir &&
+
+	git commit -m. &&
+
+	git clone --bare . bare &&
+	cp .git/info/attributes bare/info/attributes
+'
+
+test_expect_success 'git archive' '
+	git archive HEAD >archive.tar &&
+	(mkdir archive && cd archive && "$TAR" xf -) <archive.tar
+'
+
+test_expect_missing	archive/ignored
+test_expect_missing	archive/not-ignored-dir/ignored
+test_expect_exists	archive/not-ignored-dir/not-ignored
+test_expect_exists	archive/not-ignored-dir/
+test_expect_missing	archive/ignored-dir/
+test_expect_missing	archive/ignored-dir/ignored-by-ignored-dir
+
+
+test_done
diff --git a/userdiff.c b/userdiff.c
index ed958ef..2faec37 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -275,7 +275,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path)
 
 	if (!path)
 		return NULL;
-	if (git_check_attr(path, 1, &check))
+	if (git_check_attr(path, 0, 1, &check))
 		return NULL;
 
 	if (ATTR_TRUE(check.value))
diff --git a/ws.c b/ws.c
index b498d75..f122451 100644
--- a/ws.c
+++ b/ws.c
@@ -88,7 +88,7 @@ unsigned whitespace_rule(const char *pathname)
 	struct git_attr_check attr_whitespace_rule;
 
 	setup_whitespace_attr_check(&attr_whitespace_rule);
-	if (!git_check_attr(pathname, 1, &attr_whitespace_rule)) {
+	if (!git_check_attr(pathname, 0, 1, &attr_whitespace_rule)) {
 		const char *value;
 
 		value = attr_whitespace_rule.value;
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH v3 1/4] git-svn: Document branches with at-sign(@).
From: Eric Wong @ 2012-12-05 21:27 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Sebastian Leske, git
In-Reply-To: <7vsj7kjo48.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> wrote:
> Sebastian Leske <Sebastian.Leske@sleske.name> writes:
> > ---
> >  Documentation/git-svn.txt |   47 +++++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 47 insertions(+)
> 
> Thanks.  Your hunk header says that there should be 53 lines in the
> postimage, but there actually are only 52.  I'll hand-tweak the
> message and apply.

Thanks all, this series
Acked-by: Eric Wong <normalperson@yhbt.net>

^ permalink raw reply

* [PATCH] Perform minimal stat comparison when some stat fields are not set
From: Robin Rosenberg @ 2012-12-05 21:20 UTC (permalink / raw)
  To: git; +Cc: gitster, spearce, Robin Rosenberg

At least JGit does sets uid, gid, ctime, ino and dev fields to zero
on update. To Git this looks like the stat data does not match and
a full file compare will be forced even it size and mtime match. This
is in practice unnecessary. Sense JGit's presence by checking if ino
and dev is zero.

Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 read-cache.c | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/read-cache.c b/read-cache.c
index fda78bc..6f13a22 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -197,21 +197,26 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 	}
 	if (ce->ce_mtime.sec != (unsigned int)st->st_mtime)
 		changed |= MTIME_CHANGED;
-	if (trust_ctime && ce->ce_ctime.sec != (unsigned int)st->st_ctime)
+
+	int minimal_stat = (ce->ce_ino == 0 && ce->ce_dev == 0);
+
+	if (trust_ctime && !minimal_stat && ce->ce_ctime.sec != (unsigned int)st->st_ctime)
 		changed |= CTIME_CHANGED;
 
 #ifdef USE_NSEC
 	if (ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
 		changed |= MTIME_CHANGED;
-	if (trust_ctime && ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
+	if (trust_ctime && !minimal_stat && ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
 		changed |= CTIME_CHANGED;
 #endif
 
-	if (ce->ce_uid != (unsigned int) st->st_uid ||
-	    ce->ce_gid != (unsigned int) st->st_gid)
-		changed |= OWNER_CHANGED;
-	if (ce->ce_ino != (unsigned int) st->st_ino)
-		changed |= INODE_CHANGED;
+	if (!minimal_stat) {
+		if (ce->ce_uid != (unsigned int) st->st_uid ||
+			ce->ce_gid != (unsigned int) st->st_gid)
+			changed |= OWNER_CHANGED;
+		if (ce->ce_ino != 0 && ce->ce_ino != (unsigned int) st->st_ino)
+			changed |= INODE_CHANGED;
+	}
 
 #ifdef USE_STDEV
 	/*
@@ -219,7 +224,7 @@ static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 	 * clients will have different views of what "device"
 	 * the filesystem is on
 	 */
-	if (ce->ce_dev != (unsigned int) st->st_dev)
+	if (!minimal_stat && ce->ce_dev != (unsigned int) st->st_dev)
 		changed |= INODE_CHANGED;
 #endif
 
-- 
1.8.0.msysgit.0.dirty

^ permalink raw reply related

* Re: [PATCH v3 1/4] git-svn: Document branches with at-sign(@).
From: Junio C Hamano @ 2012-12-05 19:27 UTC (permalink / raw)
  To: Sebastian Leske; +Cc: git, Eric Wong
In-Reply-To: <ae56cb0c64972d2caa35743485f251f9d1652a61.1354693001.git.Sebastian.Leske@sleske.name>

Sebastian Leske <Sebastian.Leske@sleske.name> writes:

> git svn sometimes creates branches with an at-sign in the name
> (branchname@revision). These branches confuse many users and it is a FAQ
> why they are created. Document when git svn creates them.
>
> Signed-off-by: Sebastian Leske <sebastian.leske@sleske.name>
> ---
>  Documentation/git-svn.txt |   47 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 47 insertions(+)

Thanks.  Your hunk header says that there should be 53 lines in the
postimage, but there actually are only 52.  I'll hand-tweak the
message and apply.

> diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
> index 8b0d3ad..55bed53 100644
> --- a/Documentation/git-svn.txt
> +++ b/Documentation/git-svn.txt
> @@ -830,6 +830,53 @@ inside git back upstream to SVN users.  Therefore it is advised that
>  users keep history as linear as possible inside git to ease
>  compatibility with SVN (see the CAVEATS section below).
>  
> +HANDLING OF SVN BRANCHES
> +------------------------
> +If 'git svn' is configured to fetch branches (and --follow-branches
> +is in effect), it will sometimes create multiple git branches for one
> +SVN branch, where the addtional branches have names of the form
> +'branchname@nnn' (with nnn an SVN revision number).  These additional
> +branches are created if 'git svn' cannot find a parent commit for the
> +first commit in an SVN branch, to connect the branch to the history of
> +the other branches.
> +
> +Normally, the first commit in an SVN branch consists
> +of a copy operation. 'git svn' will read this commit to get the SVN
> +revision the branch was created (copied) from. It will then try to find the
> +git commit that corresponds to this SVN revision, and use that as the
> +parent of the branch. However, it is possible that there is no suitable
> +git commit to serve as parent.  This will happen, among other reasons,
> +if the SVN branch is a copy of a revision that was not fetched by 'git
> +svn' (e.g. because it is an old revision that was skipped with
> +'--revision'), or if in SVN a directory was copied that is not tracked
> +by 'git svn' (such as a branch that is not tracked at all, or a
> +subdirectory of a tracked branch). In these cases, 'git svn' will still
> +create a git branch, but instead of using an existing git commit as the
> +parent of the branch, it will read the SVN history of the directory the
> +branch was copied from and create appropriate git commits (this is
> +indicated by the message "Initializing parent: <branchname>").
> +
> +Additionally, it will create a special branch named
> +'<branchname>@<SVN-Revision>', where <SVN-Revision> is the SVN revision
> +number the branch was copied from.  This branch will point to the newly
> +created parent commit of the branch.  If in SVN the branch was deleted
> +and later recreated from a different version, there will be multiple
> +such branches with an '@'.
> +
> +Note that this may mean that multiple git commits are created for a
> +single SVN revision.
> +
> +An example: In an SVN repository with a standard
> +trunk/tags/branches layout, a directory trunk/sub is created in r.100.
> +In r.200, trunk/sub is branched by copying it to branches/. 'git svn
> +clone -s' will then create a branch 'sub'. It will also create new git
> +commits for r.100 through r.199 and use these as the history of branch
> +'sub'. Thus there will be two git commits for each revision from r.100
> +to r.199 (one containing trunk/, one containing trunk/sub/). Finally,
> +it will create a branch 'sub@200' pointing to the new parent commit of
> +branch 'sub' (i.e. the commit for r.200 and trunk/sub/).
> +
>  CAVEATS
>  -------

^ permalink raw reply

* Re: [ANNOUNCE] Git v1.8.1-rc0
From: Junio C Hamano @ 2012-12-05 18:47 UTC (permalink / raw)
  To: Ramsay Jones; +Cc: git, Linux Kernel
In-Reply-To: <50BF9544.7060401@ramsay1.demon.co.uk>

Ramsay Jones <ramsay@ramsay1.demon.co.uk> writes:

> I fetch git from 'git://git.kernel.org/pub/scm/git/git.git' which has
> commit ee26a6e2 ("Git 1.8.1-rc0", 03-12-2012), but is missing the v1.8.1-rc0
> tag. Is this just an oversight ...

Thanks for letting me know; forgot to push out the tag.

^ permalink raw reply

* Re: [ANNOUNCE] Git v1.8.1-rc0
From: Ramsay Jones @ 2012-12-05 18:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Linux Kernel
In-Reply-To: <7vip8iq1vs.fsf@alter.siamese.dyndns.org>

Junio C Hamano wrote:
> A release candidate preview, Git v1.8.1-rc0, is now available for
> testing at the usual places.
> 
> This cycle has been a bit slow (perhaps because it had a major US
> holiday to slow people down) but we seem to have managed to apply
> reasonably large number of usability improvement changes, with a
> handful of new features.  There are several new and large-ish topics
> that are cooking in 'next', but I think we would better keep them
> cooking there without merging them to 'master' before the upcoming
> release to happen before the year end.  So as far as features goes,
> this preview release is pretty much *it*.
> 
> The release tarballs are found at:
> 
>     http://code.google.com/p/git-core/downloads/list
> 
> and their SHA-1 checksums are:
> 
> 39faaa15bc71f8eb52048e77ea564cecf78c7adf  git-1.8.1.rc0.tar.gz
> 2eeba24488337de02b58dc442258d58b79e2b8f4  git-htmldocs-1.8.1.rc0.tar.gz
> b28d1f8e8b9268b712b33fbdfb67dd6f14afb499  git-manpages-1.8.1.rc0.tar.gz
> 
> Also the following public repositories all have a copy of the v1.8.1-rc0
> tag and the master branch that the tag points at:
> 
>   url = git://repo.or.cz/alt-git.git
>   url = https://code.google.com/p/git-core/
>   url = git://git.sourceforge.jp/gitroot/git-core/git.git
>   url = git://git-core.git.sourceforge.net/gitroot/git-core/git-core
>   url = https://github.com/gitster/git
> 

I fetch git from 'git://git.kernel.org/pub/scm/git/git.git' which has
commit ee26a6e2 ("Git 1.8.1-rc0", 03-12-2012), but is missing the v1.8.1-rc0
tag. Is this just an oversight (the above list suggests not), or should I not
be using kernel.org?

ATB,
Ramsay Jones

^ permalink raw reply

* Re: Exploiting SHA1's  "XOR weakness" allows for faster hash calculation
From: Theodore Ts'o @ 2012-12-05 17:20 UTC (permalink / raw)
  To: Sebastian Schuberth; +Cc: git
In-Reply-To: <k9n3jd$akg$1@ger.gmane.org>

On Wed, Dec 05, 2012 at 10:19:43AM +0100, Sebastian Schuberth wrote:
> 
> to say it in advance: I do not want to trigger any bogus security
> discussion here. Instead, I believe the findings from [1] allow for
> an up to 20% faster SHA1 calculation, if my brief reading of the
> presentation is correct. Any opinions on integration this
> optimization into Git?
> 
> [1] https://hashcat.net/p12/js-sha1exp_169.pdf

It's only useful if you are trying to do brute-force password
cracking, where the password is being hashed in a very specific way.
(If for example the password was replicated N times in the input
buffer for SHA-1, instead of keeping the padding constant in the rest
of theinput buffer, this particular optimization would't apply.)

In any case, it's not at all applicable for general purpose checksum
calculations, and hence wouldn't apply to git.

Regards,

						- Ted

^ permalink raw reply

* Re: [PATCH] mingw_rmdir: do not prompt for retry when non-empty
From: Junio C Hamano @ 2012-12-05 17:00 UTC (permalink / raw)
  To: kusmabite; +Cc: Johannes Schindelin, git, msysgit
In-Reply-To: <CABPQNSbsp_V7o8jQrwjSE_x3z3cAf7T3evK+Xq9kVZF0HrGwpg@mail.gmail.com>

Erik Faye-Lund <kusmabite@gmail.com> writes:

> On Wed, Dec 5, 2012 at 5:02 PM, Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> ...
> Since we're justifying the approaches, I'd like to explain why I
> preferred the return approach: it performs less tests. While this
> might sound like premature optimizations, performance is not why I
> think it's a good idea. It makes the fix easier to verify; you don't
> need to validate that the conditions of the second loop won't happen,
> because the code exits quickly.
>
> If we added something that required cleanup, we could change the
> return to a goto with a cleanup-label, and it would still be
> relatively easy to see what's going on.
>
>> However, I have no strong opinion on this, so please apply the version you
>> like better.
>
> Since the issue is present in mainline Git as well, I'd prefer if
> Junio merged whatever he prefers. I can produce a proper patch out of
> your suggesting, if needed.

Thanks; what you and Dscho agreed in this discussion sounds good to
me, too.

-- 
*** Please reply-to-all at all times ***
*** (do not pretend to know who is subscribed and who is not) ***
*** Please avoid top-posting. ***
The msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.

You received this message because you are subscribed to the Google
Groups "msysGit" group.
To post to this group, send email to msysgit@googlegroups.com
To unsubscribe from this group, send email to
msysgit+unsubscribe@googlegroups.com
For more options, and view previous threads, visit this group at
http://groups.google.com/group/msysgit?hl=en_US?hl=en

^ permalink raw reply

* Re: git-svn with non-standard repository layout
From: Stephen Bash @ 2012-12-05 16:44 UTC (permalink / raw)
  To: Piotr Krukowiecki; +Cc: Git Mailing List
In-Reply-To: <CAA01Csoam7pXqPKnjvJB46T_sdjcW2S1oXdQT3HbUdfN4TK0kw@mail.gmail.com>

----- Original Message -----
> From: "Piotr Krukowiecki" <piotr.krukowiecki@gmail.com>
> Sent: Wednesday, December 5, 2012 11:26:54 AM
> Subject: Re: git-svn with non-standard repository layout
> 
> On Tue, Dec 4, 2012 at 10:19 PM, Carsten Fuchs
> <carsten.fuchs@cafu.de> wrote:
> > Hi Piotr,
> >
> > Am 2012-12-04 18:29, schrieb Piotr Krukowiecki:
> >
> >> Is there a way to handle svn repository with following layout?
> >>
> >> repo/trunk
> >> repo/branches/branch1
> >> repo/branches/branch2
> >> repo/branches/work/developer1/branch3
> >> repo/branches/work/developer1/branch4
> >> repo/branches/work/developer2/branch5
> >
> > see my post at
> >     http://www.cafu.de/forum/viewtopic.php?f=14&t=1092
> > heading "Branches outside branches/".
> >
> > You may need something like
> >     git config --add svn-remote.svn.fetch
> > "path.../branchX:refs/remotes/branchX"
> > for each of your branches.
> 
> that works :)
> 
> Although not an ideal solution - I have to manually configure all
> branches + update them as they are created

It's not a 100% solution, but you can use a limited glob-like syntax in the branches and tags lines of the svn-remote config block.  You still need to do some manual work (one entry for each developer), but the wildcards eliminate a lot of the grunt work as individual branches are created.  See the very end of the git-svn manpage for examples (section titled CONFIGURATION).  I use that technique to track a subdirectory of the Slimdevices SVN repo [1], which has a similarly complex layout:

repo/7.1/trunk
repo/7.1/branches/branchA
repo/7.1/branches/branchB
repo/7.1/tags/tag1
repo/7.2/trunk
repo/7.2/branches/branchC
...

HTH,
Stephen

^ permalink raw reply

* Re: git-svn with non-standard repository layout
From: Piotr Krukowiecki @ 2012-12-05 16:26 UTC (permalink / raw)
  To: Carsten Fuchs, Git Mailing List
In-Reply-To: <50BE68C9.7070100@cafu.de>

On Tue, Dec 4, 2012 at 10:19 PM, Carsten Fuchs <carsten.fuchs@cafu.de> wrote:
> Hi Piotr,
>
> Am 2012-12-04 18:29, schrieb Piotr Krukowiecki:
>
>> Is there a way to handle svn repository with following layout?
>>
>> repo/trunk
>> repo/branches/branch1
>> repo/branches/branch2
>> repo/branches/work/developer1/branch3
>> repo/branches/work/developer1/branch4
>> repo/branches/work/developer2/branch5
>
> see my post at
>     http://www.cafu.de/forum/viewtopic.php?f=14&t=1092
> heading "Branches outside branches/".
>
> You may need something like
>     git config --add svn-remote.svn.fetch
> "path.../branchX:refs/remotes/branchX"
> for each of your branches.

Thanks,

that works :)

Although not an ideal solution - I have to manually configure all
branches + update them as they are created


--
Piotr Krukowiecki

^ permalink raw reply

* Re: [PATCH] mingw_rmdir: do not prompt for retry when non-empty
From: Erik Faye-Lund @ 2012-12-05 16:23 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, msysgit, Junio C Hamano
In-Reply-To: <alpine.DEB.1.00.1212051657131.31987@s15462909.onlinehome-server.info>

On Wed, Dec 5, 2012 at 5:02 PM, Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
> Hi kusma,
>
> On Wed, 5 Dec 2012, Erik Faye-Lund wrote:
>
>> Sorry for a late reply.
>
> Yeah, sorry, my replies tend to be delayed a lot. For the record: your
> reply was not at all late.
>
>> On Tue, Dec 4, 2012 at 5:35 PM, Johannes Schindelin
>> <Johannes.Schindelin@gmx.de> wrote:
>> >
>> > On Tue, 4 Dec 2012, Erik Faye-Lund wrote:
>> >
>> >> in ab1a11be ("mingw_rmdir: set errno=ENOTEMPTY when appropriate"), a
>> >> check was added to prevent us from retrying to delete a directory
>> >> that is both in use and non-empty.
>> >>
>> >> However, this logic was slightly flawed; since we didn't return
>> >> immediately, we end up falling out of the retry-loop, but right into
>> >> the prompting loop.
>> >>
>> >> Fix this by simply returning from the function instead of breaking
>> >> the loop.
>> >>
>> >> While we're at it, change the second break to a return as well; we
>> >> already know that we won't enter the prompting-loop, beacuse
>> >> is_file_in_use_error(GetLastError()) already evaluated to false.
>> >
>> > I usually prefer to break from the loop, to be able to add whatever
>> > cleanup code we might need in the future after the loop.
>> >
>> > So does this fix the problem for you?
>> >
>> > -- snipsnap --
>> > diff --git a/compat/mingw.c b/compat/mingw.c
>> > index 04af3dc..504495a 100644
>> > --- a/compat/mingw.c
>> > +++ b/compat/mingw.c
>> > @@ -259,7 +259,8 @@ int mingw_rmdir(const char *pathname)
>> >                 return -1;
>> >
>> >         while ((ret = _wrmdir(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
>> > -               if (!is_file_in_use_error(GetLastError()))
>> > +               errno = err_win_to_posix(GetLastError());
>> > +               if (errno != EACCESS)
>> >                         break;
>> >                 if (!is_dir_empty(wpathname)) {
>> >                         errno = ENOTEMPTY;
>> > @@ -275,7 +276,7 @@ int mingw_rmdir(const char *pathname)
>> >                 Sleep(delay[tries]);
>> >                 tries++;
>> >         }
>> > -       while (ret == -1 && is_file_in_use_error(GetLastError()) &&
>> > +       while (ret == -1 && errno == EACCESS &&
>> >                ask_yes_no_if_possible("Deletion of directory '%s' failed. "
>> >                         "Should I try again?", pathname))
>> >                ret = _wrmdir(wpathname);
>>
>> Yes, as long as you do s/EACCESS/EACCES/ first. I don't mind such a
>> version instead.
>
> As you probably suspected, I did not have a way to test-compile it before
> sending.
>
> The reason I was suggesting my version of the patch was to unify the error
> handling: rather than relying on both errno and GetLastError() (but for
> different error conditions), I would like to rely on only one: errno. That
> way, they cannot contradict each other (as they did in your case).
>

Since we're justifying the approaches, I'd like to explain why I
preferred the return approach: it performs less tests. While this
might sound like premature optimizations, performance is not why I
think it's a good idea. It makes the fix easier to verify; you don't
need to validate that the conditions of the second loop won't happen,
because the code exits quickly.

If we added something that required cleanup, we could change the
return to a goto with a cleanup-label, and it would still be
relatively easy to see what's going on.

> However, I have no strong opinion on this, so please apply the version you
> like better.

Since the issue is present in mainline Git as well, I'd prefer if
Junio merged whatever he prefers. I can produce a proper patch out of
your suggesting, if needed.

-- 
*** Please reply-to-all at all times ***
*** (do not pretend to know who is subscribed and who is not) ***
*** Please avoid top-posting. ***
The msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.

You received this message because you are subscribed to the Google
Groups "msysGit" group.
To post to this group, send email to msysgit@googlegroups.com
To unsubscribe from this group, send email to
msysgit+unsubscribe@googlegroups.com
For more options, and view previous threads, visit this group at
http://groups.google.com/group/msysgit?hl=en_US?hl=en

^ permalink raw reply

* Re: [RFC] Add basic syntax check on shell scripts
From: Junio C Hamano @ 2012-12-05 16:12 UTC (permalink / raw)
  To: Jeff King; +Cc: Nguyen Thai Ngoc Duy, Torsten Bögershausen, git
In-Reply-To: <20121205075401.GB5776@sigill.intra.peff.net>

Jeff King <peff@peff.net> writes:

> You would want a "check shell script portability" script, and you would
> probably want to run it:
>
>   - on the regular built scripts; possibly during build time (I have done
>     this before with "perl -c" for perl scripts and it is reasonably
>     successful). Or in a test script, as added in his patch (though I
>     note it does not seem to pass as posted, getting confused by trying
>     to grep "git-gui").
>
>   - on the test scripts themselves via test-lint
>
> I think as long as such a script erred on the side of false negatives,
> it would be OK (because false positives are a giant headache, and
> ultimately the real test is people exercising the code itself on their
> shells; this is just an early check to help contributors who do not have
> such shells).

Yeah, you have a good point that we should cover the scripts outside tests
and test-lint is not a good match for them.

^ permalink raw reply

* Re: [PATCH] mingw_rmdir: do not prompt for retry when non-empty
From: Johannes Schindelin @ 2012-12-05 16:02 UTC (permalink / raw)
  To: Erik Faye-Lund; +Cc: git, msysgit
In-Reply-To: <CABPQNSbcSEKApDBWWt7z67DvV6=JwTGebdk6hjgR1OppPyOQwg@mail.gmail.com>

Hi kusma,

On Wed, 5 Dec 2012, Erik Faye-Lund wrote:

> Sorry for a late reply.

Yeah, sorry, my replies tend to be delayed a lot. For the record: your
reply was not at all late.

> On Tue, Dec 4, 2012 at 5:35 PM, Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> >
> > On Tue, 4 Dec 2012, Erik Faye-Lund wrote:
> >
> >> in ab1a11be ("mingw_rmdir: set errno=ENOTEMPTY when appropriate"), a
> >> check was added to prevent us from retrying to delete a directory
> >> that is both in use and non-empty.
> >>
> >> However, this logic was slightly flawed; since we didn't return
> >> immediately, we end up falling out of the retry-loop, but right into
> >> the prompting loop.
> >>
> >> Fix this by simply returning from the function instead of breaking
> >> the loop.
> >>
> >> While we're at it, change the second break to a return as well; we
> >> already know that we won't enter the prompting-loop, beacuse
> >> is_file_in_use_error(GetLastError()) already evaluated to false.
> >
> > I usually prefer to break from the loop, to be able to add whatever
> > cleanup code we might need in the future after the loop.
> >
> > So does this fix the problem for you?
> >
> > -- snipsnap --
> > diff --git a/compat/mingw.c b/compat/mingw.c
> > index 04af3dc..504495a 100644
> > --- a/compat/mingw.c
> > +++ b/compat/mingw.c
> > @@ -259,7 +259,8 @@ int mingw_rmdir(const char *pathname)
> >                 return -1;
> >
> >         while ((ret = _wrmdir(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
> > -               if (!is_file_in_use_error(GetLastError()))
> > +               errno = err_win_to_posix(GetLastError());
> > +               if (errno != EACCESS)
> >                         break;
> >                 if (!is_dir_empty(wpathname)) {
> >                         errno = ENOTEMPTY;
> > @@ -275,7 +276,7 @@ int mingw_rmdir(const char *pathname)
> >                 Sleep(delay[tries]);
> >                 tries++;
> >         }
> > -       while (ret == -1 && is_file_in_use_error(GetLastError()) &&
> > +       while (ret == -1 && errno == EACCESS &&
> >                ask_yes_no_if_possible("Deletion of directory '%s' failed. "
> >                         "Should I try again?", pathname))
> >                ret = _wrmdir(wpathname);
> 
> Yes, as long as you do s/EACCESS/EACCES/ first. I don't mind such a
> version instead.

As you probably suspected, I did not have a way to test-compile it before
sending.

The reason I was suggesting my version of the patch was to unify the error
handling: rather than relying on both errno and GetLastError() (but for
different error conditions), I would like to rely on only one: errno. That
way, they cannot contradict each other (as they did in your case).

However, I have no strong opinion on this, so please apply the version you
like better.

Ciao,
Dscho

-- 
*** Please reply-to-all at all times ***
*** (do not pretend to know who is subscribed and who is not) ***
*** Please avoid top-posting. ***
The msysGit Wiki is here: https://github.com/msysgit/msysgit/wiki - Github accounts are free.

You received this message because you are subscribed to the Google
Groups "msysGit" group.
To post to this group, send email to msysgit@googlegroups.com
To unsubscribe from this group, send email to
msysgit+unsubscribe@googlegroups.com
For more options, and view previous threads, visit this group at
http://groups.google.com/group/msysgit?hl=en_US?hl=en

^ permalink raw reply

* Re: [PATCH v2] gitk: read and write a repository specific configuration file
From: Marc Branchaud @ 2012-12-05 15:20 UTC (permalink / raw)
  To: Łukasz Stelmach; +Cc: git, paulus, gitster
In-Reply-To: <1354668583-4893-1-git-send-email-stlman@poczta.fm>

On 12-12-04 07:49 PM, Łukasz Stelmach wrote:
> Enable gitk read and write repository specific configuration
> file: ".git/k" if the file exists. To make gitk use the local
> file simply create one, e.g. with the touch(1) command.
> 
> This is very useful if one uses different views for different
> repositories. Now there is no need to store all of them in
> ~/.gitk and make the views list needlesly long.

s/needlesly/needlessly/

		M.

^ permalink raw reply

* Re: [PATCH] mingw_rmdir: do not prompt for retry when non-empty
From: Erik Faye-Lund @ 2012-12-05 15:18 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git, msysgit
In-Reply-To: <alpine.DEB.1.00.1212041728210.31987@s15462909.onlinehome-server.info>

Sorry for a late reply.

On Tue, Dec 4, 2012 at 5:35 PM, Johannes Schindelin
<Johannes.Schindelin@gmx.de> wrote:
> Hi kusma,
>
> On Tue, 4 Dec 2012, Erik Faye-Lund wrote:
>
>> in ab1a11be ("mingw_rmdir: set errno=ENOTEMPTY when appropriate"),
>> a check was added to prevent us from retrying to delete a directory
>> that is both in use and non-empty.
>>
>> However, this logic was slightly flawed; since we didn't return
>> immediately, we end up falling out of the retry-loop, but right into
>> the prompting loop.
>>
>> Fix this by simply returning from the function instead of breaking
>> the loop.
>>
>> While we're at it, change the second break to a return as well; we
>> already know that we won't enter the prompting-loop, beacuse
>> is_file_in_use_error(GetLastError()) already evaluated to false.
>
> I usually prefer to break from the loop, to be able to add whatever
> cleanup code we might need in the future after the loop.
>
> So does this fix the problem for you?
>
> -- snipsnap --
> diff --git a/compat/mingw.c b/compat/mingw.c
> index 04af3dc..504495a 100644
> --- a/compat/mingw.c
> +++ b/compat/mingw.c
> @@ -259,7 +259,8 @@ int mingw_rmdir(const char *pathname)
>                 return -1;
>
>         while ((ret = _wrmdir(wpathname)) == -1 && tries < ARRAY_SIZE(delay)) {
> -               if (!is_file_in_use_error(GetLastError()))
> +               errno = err_win_to_posix(GetLastError());
> +               if (errno != EACCESS)
>                         break;
>                 if (!is_dir_empty(wpathname)) {
>                         errno = ENOTEMPTY;
> @@ -275,7 +276,7 @@ int mingw_rmdir(const char *pathname)
>                 Sleep(delay[tries]);
>                 tries++;
>         }
> -       while (ret == -1 && is_file_in_use_error(GetLastError()) &&
> +       while (ret == -1 && errno == EACCESS &&
>                ask_yes_no_if_possible("Deletion of directory '%s' failed. "
>                         "Should I try again?", pathname))
>                ret = _wrmdir(wpathname);

Yes, as long as you do s/EACCESS/EACCES/ first. I don't mind such a
version instead.

^ permalink raw reply

* Re: remote-testsvn: Hangs at revision
From: Ramkumar Ramachandra @ 2012-12-05 13:57 UTC (permalink / raw)
  To: David Michael Barr; +Cc: Git List, Florian Achleitner
In-Reply-To: <D435D46EAB6F419CA0608075751C351C@rr-dav.id.au>

David Michael Barr wrote:
> On Wednesday, 5 December 2012 at 5:20 PM, Ramkumar Ramachandra wrote:
>> $ git clone testsvn::http://python-lastfm.googlecode.com/svn/trunk/
> I attempted to clone the same repository and was able to fetch 152 revisions.
> So the issue Ram saw might have been temporal.

Nope, I'm able to reproduce it everytime.  I wonder what's going on.

Ram

^ permalink raw reply

* Re: remote-testsvn: Hangs at revision
From: David Michael Barr @ 2012-12-05 13:28 UTC (permalink / raw)
  To: Ramkumar Ramachandra; +Cc: Git List, Florian Achleitner
In-Reply-To: <CALkWK0meveeKQe81hHyojPX0GH_WRrv7ob9-NA1Q7-TuKso+1w@mail.gmail.com>

On Wednesday, 5 December 2012 at 5:20 PM, Ramkumar Ramachandra wrote:
> Hi,
> 
> I tried out the testsvn remote helper on a simple Subversion
> repository, but it seems to hang at Revision 8 indefinitely without
> any indication of progress. I'm currently digging in to see what went
> wrong. The repository I'm cloning is:
> 
> $ git clone testsvn::http://python-lastfm.googlecode.com/svn/trunk/
I attempted to clone the same repository and was able to fetch 152 revisions.
So the issue Ram saw might have been temporal.


I did however receive a warning at the end of the clone:

    warning: remote HEAD refers to nonexistent ref, unable to checkout. 

--
David Michael Barr

^ permalink raw reply

* Re: [RFC/PATCH 1/2] reset: learn to reset to tree
From: Martin von Zweigbergk @ 2012-12-05 12:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vtxs1kq4z.fsf@alter.siamese.dyndns.org>

On Tue, Dec 4, 2012 at 9:46 PM, Junio C Hamano <gitster@pobox.com> wrote:
> Martin von Zweigbergk <martinvonz@gmail.com> writes:
>
>> More importantly, when is it desirable not to delete deleted entries?
>
> When I am trying to check out contents of Documentation/ directory
> as of an older edition because we made mistakes updating the files
> in recent versions, with "git checkout v1.9.0 Documentation/", for
> example.  Perhaps somebody had this bright idea of reformatting our
> docs with "= Newer Style =" section headers, replacing the underline
> style, and we found our toolchain depend on the underline style, or
> something.  The new files in the same directory added since v1.9.0
> may share the same mistake as the files whose recent such changes I
> am nuking with this operation, but that does not mean I want to
> retype the contents of them from scratch; I'd rather keep them
> around so that I can fix them up by hand.

I think I follow, but why, then, would you not have the save problem
with hunks *within* files that have been added in the new version? Or
is the only change to Documentation/ since the "broken" commit that a
new file has been added? That seems like a rather narrow use case in
that case? "git checkout -p" seems more generally useful (whether that
command deleted deleted files or not). It feels like I'm missing
something...

> I would have to say that it is more common; I do not recall a time I
> wanted to replace everything in a directory (and only there without
> touching other parts of the tree) with an old version, removing new
> ones.

It has happened a few times for me. I think this usually happens when
I realize that I had a better solution for some subsystem (under some
path) in some other branch (perhaps from a previous attempt at the
same problem) or an in older commit. Knowing that "git checkout $rev
$path" doesn't do what I expect and that "git reset --hard $rev $path"
is not allowed, I think I would usually do "git reset $rev $path &&
git checkout $path".

^ permalink raw reply

* [PATCH v3 4/4] git-svn: Note about tags.
From: Sebastian Leske @ 2012-11-23  7:29 UTC (permalink / raw)
  To: git; +Cc: Eric Wong, Junio C Hamano
In-Reply-To: <cover.1354693001.git.Sebastian.Leske@sleske.name>

Document that 'git svn' will import SVN tags as branches.

Signed-off-by: Sebastian Leske <sebastian.leske@sleske.name>
---
 Documentation/git-svn.txt |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 021fb0e..445b033 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -968,6 +968,12 @@ the possible corner cases (git doesn't do it, either).  Committing
 renamed and copied files is fully supported if they're similar enough
 for git to detect them.
 
+In SVN, it is possible (though discouraged) to commit changes to a tag
+(because a tag is just a directory copy, thus technically the same as a
+branch). When cloning an SVN repository, 'git svn' cannot know if such a
+commit to a tag will happen in the future. Thus it acts conservatively
+and imports all SVN tags as branches, prefixing the tag name with 'tags/'.
+
 CONFIGURATION
 -------------
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v3 3/4] git-svn: Expand documentation for --follow-parent
From: Sebastian Leske @ 2012-11-30  7:16 UTC (permalink / raw)
  To: git; +Cc: Eric Wong, Junio C Hamano
In-Reply-To: <cover.1354693001.git.Sebastian.Leske@sleske.name>

Describe what the option --follow-parent does, and what happens if it is
set or unset.

Signed-off-by: Sebastian Leske <sebastian.leske@sleske.name>
---
 Documentation/git-svn.txt |   15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index d8e5082..021fb0e 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -628,10 +628,19 @@ ADVANCED OPTIONS
 	Default: "svn"
 
 --follow-parent::
+	This option is only relevant if we are tracking branches (using
+	one of the repository layout options --trunk, --tags,
+	--branches, --stdlayout). For each tracked branch, try to find
+	out where its revision was copied from, and set
+	a suitable parent in the first git commit for the branch.
 	This is especially helpful when we're tracking a directory
-	that has been moved around within the repository, or if we
-	started tracking a branch and never tracked the trunk it was
-	descended from. This feature is enabled by default, use
+	that has been moved around within the repository.  If this
+	feature is disabled, the branches created by 'git svn' will all
+	be linear and not share any history, meaning that there will be
+	no information on where branches were branched off or merged.
+	However, following long/convoluted histories can take a long
+	time, so disabling this feature may speed up the cloning
+	process. This feature is enabled by default, use
 	--no-follow-parent to disable it.
 +
 [verse]
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v3 2/4] git-svn: Recommend use of structure options.
From: Sebastian Leske @ 2012-11-30  7:16 UTC (permalink / raw)
  To: git; +Cc: Eric Wong, Junio C Hamano
In-Reply-To: <cover.1354693001.git.Sebastian.Leske@sleske.name>

Document that when using git svn, one should usually either use the
directory structure options to import branches as branches, or only
import one subdirectory. The default behaviour of cloning all branches
and tags as subdirectories in the working copy is usually not what the
user wants.

Signed-off-by: Sebastian Leske <sebastian.leske@sleske.name>
---
 Documentation/git-svn.txt |   24 +++++++++++++++++++++---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 55bed53..d8e5082 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -739,7 +739,8 @@ for rewriteRoot and rewriteUUID which can be used together.
 BASIC EXAMPLES
 --------------
 
-Tracking and contributing to the trunk of a Subversion-managed project:
+Tracking and contributing to the trunk of a Subversion-managed project
+(ignoring tags and branches):
 
 ------------------------------------------------------------------------
 # Clone a repo (like git clone):
@@ -764,8 +765,10 @@ Tracking and contributing to an entire Subversion-managed project
 (complete with a trunk, tags and branches):
 
 ------------------------------------------------------------------------
-# Clone a repo (like git clone):
-	git svn clone http://svn.example.com/project -T trunk -b branches -t tags
+# Clone a repo with standard SVN directory layout (like git clone):
+	git svn clone http://svn.example.com/project --stdlayout
+# Or, if the repo uses a non-standard directory layout:
+	git svn clone http://svn.example.com/project -T tr -b branch -t tag
 # View all branches and tags you have cloned:
 	git branch -r
 # Create a new branch in SVN
@@ -918,6 +921,21 @@ already dcommitted.  It is considered bad practice to --amend commits
 you've already pushed to a remote repository for other users, and
 dcommit with SVN is analogous to that.
 
+When cloning an SVN repository, if none of the options for describing
+the repository layout is used (--trunk, --tags, --branches,
+--stdlayout), 'git svn clone' will create a git repository with
+completely linear history, where branches and tags appear as separate
+directories in the working copy.  While this is the easiest way to get a
+copy of a complete repository, for projects with many branches it will
+lead to a working copy many times larger than just the trunk. Thus for
+projects using the standard directory structure (trunk/branches/tags),
+it is recommended to clone with option '--stdlayout'. If the project
+uses a non-standard structure, and/or if branches and tags are not
+required, it is easiest to only clone one directory (typically trunk),
+without giving any repository layout options.  If the full history with
+branches and tags is required, the options '--trunk' / '--branches' /
+'--tags' must be used.
+
 When using multiple --branches or --tags, 'git svn' does not automatically
 handle name collisions (for example, if two branches from different paths have
 the same name, or if a branch and a tag have the same name).  In these cases,
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH v3 0/4] git-svn: More docs for branch handling
From: Sebastian Leske @ 2012-12-05  7:36 UTC (permalink / raw)
  To: git; +Cc: Eric Wong, Junio C Hamano

Updated version of my documentation patch for git-svn. Thanks to Junio C
Hamano for pointing out improvements.

Sebastian Leske (4):
  git-svn: Document branches with at-sign(@).
  git-svn: Recommend use of structure options.
  git-svn: Expand documentation for --follow-parent
  git-svn: Note about tags.

 Documentation/git-svn.txt |   92 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 86 insertions(+), 6 deletions(-)

-- 
1.7.10.4

^ permalink raw reply

* [PATCH v3 1/4] git-svn: Document branches with at-sign(@).
From: Sebastian Leske @ 2012-11-30  7:16 UTC (permalink / raw)
  To: git; +Cc: Eric Wong, Junio C Hamano
In-Reply-To: <cover.1354693001.git.Sebastian.Leske@sleske.name>

git svn sometimes creates branches with an at-sign in the name
(branchname@revision). These branches confuse many users and it is a FAQ
why they are created. Document when git svn creates them.

Signed-off-by: Sebastian Leske <sebastian.leske@sleske.name>
---
 Documentation/git-svn.txt |   47 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 8b0d3ad..55bed53 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -830,6 +830,53 @@ inside git back upstream to SVN users.  Therefore it is advised that
 users keep history as linear as possible inside git to ease
 compatibility with SVN (see the CAVEATS section below).
 
+HANDLING OF SVN BRANCHES
+------------------------
+If 'git svn' is configured to fetch branches (and --follow-branches
+is in effect), it will sometimes create multiple git branches for one
+SVN branch, where the addtional branches have names of the form
+'branchname@nnn' (with nnn an SVN revision number).  These additional
+branches are created if 'git svn' cannot find a parent commit for the
+first commit in an SVN branch, to connect the branch to the history of
+the other branches.
+
+Normally, the first commit in an SVN branch consists
+of a copy operation. 'git svn' will read this commit to get the SVN
+revision the branch was created (copied) from. It will then try to find the
+git commit that corresponds to this SVN revision, and use that as the
+parent of the branch. However, it is possible that there is no suitable
+git commit to serve as parent.  This will happen, among other reasons,
+if the SVN branch is a copy of a revision that was not fetched by 'git
+svn' (e.g. because it is an old revision that was skipped with
+'--revision'), or if in SVN a directory was copied that is not tracked
+by 'git svn' (such as a branch that is not tracked at all, or a
+subdirectory of a tracked branch). In these cases, 'git svn' will still
+create a git branch, but instead of using an existing git commit as the
+parent of the branch, it will read the SVN history of the directory the
+branch was copied from and create appropriate git commits (this is
+indicated by the message "Initializing parent: <branchname>").
+
+Additionally, it will create a special branch named
+'<branchname>@<SVN-Revision>', where <SVN-Revision> is the SVN revision
+number the branch was copied from.  This branch will point to the newly
+created parent commit of the branch.  If in SVN the branch was deleted
+and later recreated from a different version, there will be multiple
+such branches with an '@'.
+
+Note that this may mean that multiple git commits are created for a
+single SVN revision.
+
+An example: In an SVN repository with a standard
+trunk/tags/branches layout, a directory trunk/sub is created in r.100.
+In r.200, trunk/sub is branched by copying it to branches/. 'git svn
+clone -s' will then create a branch 'sub'. It will also create new git
+commits for r.100 through r.199 and use these as the history of branch
+'sub'. Thus there will be two git commits for each revision from r.100
+to r.199 (one containing trunk/, one containing trunk/sub/). Finally,
+it will create a branch 'sub@200' pointing to the new parent commit of
+branch 'sub' (i.e. the commit for r.200 and trunk/sub/).
+
 CAVEATS
 -------
 
-- 
1.7.10.4

^ permalink raw reply related


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