Git development
 help / color / mirror / Atom feed
* Re: [PATCH 2/4] Convert resolve_ref+xstrdup to new resolve_refdup function
From: Michael Haggerty @ 2011-12-13 14:09 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Nguyễn Thái Ngọc Duy, git, Jonathan Nieder
In-Reply-To: <7vpqft4qap.fsf@alter.siamese.dyndns.org>

On 12/12/2011 07:07 PM, Junio C Hamano wrote:
> Nguyễn Thái Ngọc Duy <pclouds@gmail.com> writes:
> 
>> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
> 
> Thanks.
> 
> The patch looks correct but I have a slight maintainability concern and a
> suggestion for possible improvement.
> 
>> ...
>> diff --git a/builtin/checkout.c b/builtin/checkout.c
>> index b7c6302..a66d3eb 100644
>> --- a/builtin/checkout.c
>> +++ b/builtin/checkout.c
>> @@ -696,17 +696,14 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
>>  {
>>  	int ret = 0;
>>  	struct branch_info old;
>> +	char *path;
>>  	unsigned char rev[20];
>>  	int flag;
>>  	memset(&old, 0, sizeof(old));
>> -	old.path = resolve_ref("HEAD", rev, 0, &flag);
>> -	if (old.path)
>> -		old.path = xstrdup(old.path);
>> +	old.path = path = resolve_refdup("HEAD", rev, 0, &flag);
> 
> This uses "one 'const char *' pointer that is used for reading data from
> and an extra 'char *' pointer that is used only for freeing" approach,
> which has two advantages and one disadvantage:
> [...]
> When naming a "for-freeing" pointer variable, the kind of data the area of
> memory happens to contain is of secondary importance. Being deliberately
> vague about what the area of memory may contain is a good thing, because
> it actively discourages the program from looking at the area via the
> pointer if the variable is named "to_free" or something that does not
> specify what it contains.

The to_free variable could even be declared void* to make it even less
(ab)usable.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* [PATCH/RFC] Makefile: add 'help' target for target summary
From: Nguyễn Thái Ngọc Duy @ 2011-12-13 13:16 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

I find this "make help" very helpful (at work, on a different
project). With this I don't have to crawl through Makefile when I need
something but cannot remember what's the target name. It should also
help discover new targets.

We may also have "make vars" (or something like that) that shows list
of user-configurable variables, basically a conversion of the big
comment block near the makefile's top into a printable target.

I don't work with this Makefile much, so this is just an idea. Anyone
up to turn it to something actually useful?

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

diff --git a/Makefile b/Makefile
index ed82320..abf6cf9 100644
--- a/Makefile
+++ b/Makefile
@@ -2603,3 +2603,17 @@ profile-all: profile-clean
 	$(MAKE) CFLAGS="$(PROFILE_GEN_CFLAGS)" all
 	$(MAKE) CFLAGS="$(PROFILE_GEN_CFLAGS)" -j1 test
 	$(MAKE) CFLAGS="$(PROFILE_USE_CFLAGS)" all
+
+.PHONY: help
+
+help:
+	@echo "test		Run the test suite"
+	@echo "coverage	Build git with coverage support"
+	@echo "cover_db	Generate coverage database from *.gcov"
+	@echo "cover_db_html	Generate coverage report"
+	@echo "profile-all	Build git with profiling support"
+	@echo "clean		Clean intermediate files"
+	@echo "distclean	Clean even more for dist packaging"
+	@echo "sparse		Run git with sparse"
+	@echo "cscope		Generate cscope symbol database"
+	@echo "check-docs	Check documentation"
-- 
1.7.8.36.g69ee2

^ permalink raw reply related

* Re: Question about commit message wrapping
From: Holger Hellmuth @ 2011-12-13 13:14 UTC (permalink / raw)
  To: Michael Haggerty
  Cc: Frans Klaver, Andrew Ardill, Jakub Narebski,
	Sidney San Martín, git
In-Reply-To: <4EE6C31C.60909@alum.mit.edu>

On 13.12.2011 04:14, Michael Haggerty wrote:
> On 12/12/2011 11:16 PM, Frans Klaver wrote:
>> Wrapped code as in auto-wrapped? Or as in manually wrapped? Python
>> programmers have significant white space, but you can still hard wrap
>> stuff, as long as the next statement is properly indented.

I meant as in auto-wrapped and also not as a permanent change but 
something done to a long line on output to the screen.

> FWIW I think automatic wrapping of commit messages is a bad idea.  I
> wrap my commit messages deliberately to make them look the way I want

Which you still can do (since hard line endings would not be ignored). 
On displays wider than your line limit you will still see it exactly 
like intended. Only on narrow displays your commit message would look 
bad, admittedly even worse than cut-off lines.

> them to look.  The assumption of an 80-character display has historical
> reasons, but it is also a relatively comfortable line-width to read
> (even on wider displays).  And given that commit messages sometimes
> contain "flowable" paragraph text, sometimes code snippets, sometimes
> ASCII art, etc, no automatic wrapping will work correctly unless
> everybody agrees that commit messages must be written in some specific
> form of markup (or lightweight markup).  And I can't imagine such a
> thing ever happening.

With that assumption everyone could be happy with automatic wrapping of 
lines on screen output. You can hard wrap and it will look exactly as 
intended. In the same commit message you could also just write a 
paragraph without hitting the return-key at all and have a commit 
message that looks good in web browsers and too narrow gitk windows.

^ permalink raw reply

* Please confirm from Libyian Embassy
From: Jimmy Zakia @ 2011-12-13 21:34 UTC (permalink / raw)


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

In a brief introduction, I am an embassy attachй with the Libyan Government in the Hague, Netherlands.
Please kindly see the attachment for more details and respond immediately

[-- Attachment #2: attachment.rtf --]
[-- Type: application/octet-stream, Size: 3042 bytes --]

^ permalink raw reply

* [PATCH] Convert resolve_ref+xstrdup to new resolve_refdup function
From: Nguyễn Thái Ngọc Duy @ 2011-12-13 12:31 UTC (permalink / raw)
  To: git, Junio C Hamano
  Cc: Jonathan Nieder, Nguyễn Thái Ngọc Duy
In-Reply-To: <7vpqft4qap.fsf@alter.siamese.dyndns.org>


Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 2011/12/13 Junio C Hamano <gitster@pobox.com>:
 > A handful of places in the existing codebase use this "two pointers"
 > approach primarily for the second advantage. The way they avoid the
 > disadvantage is by naming the other pointer "$something_to_free" (and the
 > "$something_" part is optional if there is only one such variable in the
 > context) to make it clear that the variable is not meant to be looked at
 > in the code and its primary purpose is for cleaning up at the end.
 >
 > Perhaps renaming this "path" to "to_free" (or "path_to_free" if you want
 > to hint the "path-ness" to the readers, but see below) would make it less
 > likely that future tweakers mistakenly look at, modify the string thru, or
 > worse yet move the pointer itself.

 Thanks. The patch looks better with "_to_free" naming convention. I
 learn something new today.

 builtin/branch.c        |   12 +++++-------
 builtin/checkout.c      |   15 +++++++--------
 builtin/fmt-merge-msg.c |    7 ++++---
 builtin/for-each-ref.c  |    7 ++-----
 builtin/merge.c         |   12 +++++-------
 builtin/notes.c         |    7 ++++---
 builtin/receive-pack.c  |    7 +++----
 builtin/show-branch.c   |    4 +---
 cache.h                 |    1 +
 reflog-walk.c           |   15 ++++++++-------
 refs.c                  |    6 ++++++
 wt-status.c             |    4 +---
 12 files changed, 47 insertions(+), 50 deletions(-)

diff --git a/builtin/branch.c b/builtin/branch.c
index e1e486e..59efe2c 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -104,6 +104,7 @@ static int branch_merged(int kind, const char *name,
 	 */
 	struct commit *reference_rev = NULL;
 	const char *reference_name = NULL;
+	char *reference_name_to_free = NULL;
 	int merged;
 
 	if (kind == REF_LOCAL_BRANCH) {
@@ -114,11 +115,9 @@ static int branch_merged(int kind, const char *name,
 		    branch->merge &&
 		    branch->merge[0] &&
 		    branch->merge[0]->dst &&
-		    (reference_name =
-		     resolve_ref(branch->merge[0]->dst, sha1, 1, NULL)) != NULL) {
-			reference_name = xstrdup(reference_name);
+		    (reference_name = reference_name_to_free =
+		     resolve_refdup(branch->merge[0]->dst, sha1, 1, NULL)) != NULL)
 			reference_rev = lookup_commit_reference(sha1);
-		}
 	}
 	if (!reference_rev)
 		reference_rev = head_rev;
@@ -143,7 +142,7 @@ static int branch_merged(int kind, const char *name,
 				"         '%s', even though it is merged to HEAD."),
 				name, reference_name);
 	}
-	free((char *)reference_name);
+	free(reference_name_to_free);
 	return merged;
 }
 
@@ -731,10 +730,9 @@ int cmd_branch(int argc, const char **argv, const char *prefix)
 
 	track = git_branch_track;
 
-	head = resolve_ref("HEAD", head_sha1, 0, NULL);
+	head = resolve_refdup("HEAD", head_sha1, 0, NULL);
 	if (!head)
 		die(_("Failed to resolve HEAD as a valid ref."));
-	head = xstrdup(head);
 	if (!strcmp(head, "HEAD")) {
 		detached = 1;
 	} else {
diff --git a/builtin/checkout.c b/builtin/checkout.c
index b7c6302..dde44d7 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -696,17 +696,14 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 {
 	int ret = 0;
 	struct branch_info old;
+	char *path_to_free;
 	unsigned char rev[20];
 	int flag;
 	memset(&old, 0, sizeof(old));
-	old.path = resolve_ref("HEAD", rev, 0, &flag);
-	if (old.path)
-		old.path = xstrdup(old.path);
+	old.path = path_to_free = resolve_refdup("HEAD", rev, 0, &flag);
 	old.commit = lookup_commit_reference_gently(rev, 1);
-	if (!(flag & REF_ISSYMREF)) {
-		free((char *)old.path);
+	if (!(flag & REF_ISSYMREF))
 		old.path = NULL;
-	}
 
 	if (old.path && !prefixcmp(old.path, "refs/heads/"))
 		old.name = old.path + strlen("refs/heads/");
@@ -720,8 +717,10 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 	}
 
 	ret = merge_working_tree(opts, &old, new);
-	if (ret)
+	if (ret) {
+		free(path_to_free);
 		return ret;
+	}
 
 	if (!opts->quiet && !old.path && old.commit && new->commit != old.commit)
 		orphaned_commit_warning(old.commit);
@@ -729,7 +728,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 	update_refs_for_switch(opts, &old, new);
 
 	ret = post_checkout_hook(old.commit, new->commit, 1);
-	free((char *)old.path);
+	free(path_to_free);
 	return ret || opts->writeout_error;
 }
 
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index bdfa0ea..e55e994 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -372,14 +372,15 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 	int i = 0, pos = 0;
 	unsigned char head_sha1[20];
 	const char *current_branch;
+	char *current_branch_to_free;
 
 	/* get current branch */
-	current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
+	current_branch = current_branch_to_free =
+		resolve_refdup("HEAD", head_sha1, 1, NULL);
 	if (!current_branch)
 		die("No current branch");
 	if (!prefixcmp(current_branch, "refs/heads/"))
 		current_branch += 11;
-	current_branch = xstrdup(current_branch);
 
 	/* get a line */
 	while (pos < in->len) {
@@ -421,7 +422,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 	}
 
 	strbuf_complete_line(out);
-	free((char *)current_branch);
+	free(current_branch_to_free);
 	return 0;
 }
 
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index d90e5d2..b01d76a 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -628,11 +628,8 @@ static void populate_value(struct refinfo *ref)
 
 	if (need_symref && (ref->flag & REF_ISSYMREF) && !ref->symref) {
 		unsigned char unused1[20];
-		const char *symref;
-		symref = resolve_ref(ref->refname, unused1, 1, NULL);
-		if (symref)
-			ref->symref = xstrdup(symref);
-		else
+		ref->symref = resolve_refdup(ref->refname, unused1, 1, NULL);
+		if (!ref->symref)
 			ref->symref = "";
 	}
 
diff --git a/builtin/merge.c b/builtin/merge.c
index a1c8534..d4079e6 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1096,6 +1096,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	struct commit_list *common = NULL;
 	const char *best_strategy = NULL, *wt_strategy = NULL;
 	struct commit_list **remotes = &remoteheads;
+	char *branch_to_free;
 
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage_with_options(builtin_merge_usage, builtin_merge_options);
@@ -1104,12 +1105,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	 * Check if we are _not_ on a detached HEAD, i.e. if there is a
 	 * current branch.
 	 */
-	branch = resolve_ref("HEAD", head_sha1, 0, &flag);
-	if (branch) {
-		if (!prefixcmp(branch, "refs/heads/"))
-			branch += 11;
-		branch = xstrdup(branch);
-	}
+	branch = branch_to_free = resolve_refdup("HEAD", head_sha1, 0, &flag);
+	if (branch && !prefixcmp(branch, "refs/heads/"))
+		branch += 11;
 	if (!branch || is_null_sha1(head_sha1))
 		head_commit = NULL;
 	else
@@ -1520,6 +1518,6 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		ret = suggest_conflicts(option_renormalize);
 
 done:
-	free((char *)branch);
+	free(branch_to_free);
 	return ret;
 }
diff --git a/builtin/notes.c b/builtin/notes.c
index 10b8bc7..11a24d7 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -804,6 +804,7 @@ static int merge_commit(struct notes_merge_options *o)
 	struct notes_tree *t;
 	struct commit *partial;
 	struct pretty_print_context pretty_ctx;
+	char *local_ref_to_free;
 	int ret;
 
 	/*
@@ -826,10 +827,10 @@ static int merge_commit(struct notes_merge_options *o)
 	t = xcalloc(1, sizeof(struct notes_tree));
 	init_notes(t, "NOTES_MERGE_PARTIAL", combine_notes_overwrite, 0);
 
-	o->local_ref = resolve_ref("NOTES_MERGE_REF", sha1, 0, NULL);
+	o->local_ref = local_ref_to_free =
+		resolve_refdup("NOTES_MERGE_REF", sha1, 0, NULL);
 	if (!o->local_ref)
 		die("Failed to resolve NOTES_MERGE_REF");
-	o->local_ref = xstrdup(o->local_ref);
 
 	if (notes_merge_commit(o, t, partial, sha1))
 		die("Failed to finalize notes merge");
@@ -846,7 +847,7 @@ static int merge_commit(struct notes_merge_options *o)
 	free_notes(t);
 	strbuf_release(&msg);
 	ret = merge_abort(o);
-	free((char *)o->local_ref);
+	free(local_ref_to_free);
 	return ret;
 }
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index b6d957c..fa251ec 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -37,6 +37,7 @@ static int prefer_ofs_delta = 1;
 static int auto_update_server_info;
 static int auto_gc = 1;
 static const char *head_name;
+static char *head_name_to_free;
 static int sent_capabilities;
 
 static enum deny_action parse_deny_action(const char *var, const char *value)
@@ -695,10 +696,8 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
 
 	check_aliased_updates(commands);
 
-	free((char *)head_name);
-	head_name = resolve_ref("HEAD", sha1, 0, NULL);
-	if (head_name)
-		head_name = xstrdup(head_name);
+	free(head_name_to_free);
+	head_name = head_name_to_free = resolve_refdup("HEAD", sha1, 0, NULL);
 
 	for (cmd = commands; cmd; cmd = cmd->next)
 		if (!cmd->skip_update)
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 4b480d7..a1f148e 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -726,10 +726,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 
 		if (ac == 0) {
 			static const char *fake_av[2];
-			const char *refname;
 
-			refname = resolve_ref("HEAD", sha1, 1, NULL);
-			fake_av[0] = xstrdup(refname);
+			fake_av[0] = resolve_refdup("HEAD", sha1, 1, NULL);
 			fake_av[1] = NULL;
 			av = fake_av;
 			ac = 1;
diff --git a/cache.h b/cache.h
index 8c98d05..4887a3e 100644
--- a/cache.h
+++ b/cache.h
@@ -866,6 +866,7 @@ extern int read_ref(const char *filename, unsigned char *sha1);
  * errno is sometimes set on errors, but not always.
  */
 extern const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag);
+extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag);
 
 extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
 extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
diff --git a/reflog-walk.c b/reflog-walk.c
index da71a85..52eddb7 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -50,11 +50,12 @@ static struct complete_reflogs *read_complete_reflog(const char *ref)
 	for_each_reflog_ent(ref, read_one_reflog, reflogs);
 	if (reflogs->nr == 0) {
 		unsigned char sha1[20];
-		const char *name = resolve_ref(ref, sha1, 1, NULL);
+		const char *name;
+		char *name_to_free;
+		name = name_to_free = resolve_refdup(ref, sha1, 1, NULL);
 		if (name) {
-			name = xstrdup(name);
 			for_each_reflog_ent(name, read_one_reflog, reflogs);
-			free((char *)name);
+			free(name_to_free);
 		}
 	}
 	if (reflogs->nr == 0) {
@@ -171,11 +172,11 @@ int add_reflog_for_walk(struct reflog_walk_info *info,
 	else {
 		if (*branch == '\0') {
 			unsigned char sha1[20];
-			const char *head = resolve_ref("HEAD", sha1, 0, NULL);
-			if (!head)
-				die ("No current branch");
 			free(branch);
-			branch = xstrdup(head);
+			branch = resolve_refdup("HEAD", sha1, 0, NULL);
+			if (!branch)
+				die ("No current branch");
+
 		}
 		reflogs = read_complete_reflog(branch);
 		if (!reflogs || reflogs->nr == 0) {
diff --git a/refs.c b/refs.c
index f5cb297..8ffb32f 100644
--- a/refs.c
+++ b/refs.c
@@ -605,6 +605,12 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
 	return ref;
 }
 
+char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag)
+{
+	const char *ret = resolve_ref(ref, sha1, reading, flag);
+	return ret ? xstrdup(ret) : NULL;
+}
+
 /* The argument to filter_refs */
 struct ref_filter {
 	const char *pattern;
diff --git a/wt-status.c b/wt-status.c
index 70fdb76..9ffc535 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -111,7 +111,6 @@ void status_printf_more(struct wt_status *s, const char *color,
 void wt_status_prepare(struct wt_status *s)
 {
 	unsigned char sha1[20];
-	const char *head;
 
 	memset(s, 0, sizeof(*s));
 	memcpy(s->color_palette, default_wt_status_colors,
@@ -119,8 +118,7 @@ void wt_status_prepare(struct wt_status *s)
 	s->show_untracked_files = SHOW_NORMAL_UNTRACKED_FILES;
 	s->use_color = -1;
 	s->relative_paths = 1;
-	head = resolve_ref("HEAD", sha1, 0, NULL);
-	s->branch = head ? xstrdup(head) : NULL;
+	s->branch = resolve_refdup("HEAD", sha1, 0, NULL);
 	s->reference = "HEAD";
 	s->fp = stdout;
 	s->index_file = get_index_file();
-- 
1.7.8.36.g69ee2

^ permalink raw reply related

* [PATCH/RFC 2/2] change all unchecked calls to setenv to xsetenv
From: Erik Faye-Lund @ 2011-12-13 12:10 UTC (permalink / raw)
  To: git
In-Reply-To: <1323778227-1664-1-git-send-email-kusmabite@gmail.com>

This avoids us from accidentally dropping state, possibly leading
to unexpected behaviour.

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---

While reviewing some patches for Git for Windows, I realized that
we almost never check the return-value from setenv. This can lead
to quite surprising errors in unusual sitations. Mostly, an error
would probably be preferred. So here we go.

However, I'm not at all convinced myself that all of these make
sense; in particular settings like GIT_EDITOR and GIT_PAGER could
perhaps benefit from having a warning printed rather than a hard
error.

Thoughts?

 builtin/clone.c      |    2 +-
 builtin/commit.c     |    6 +++---
 builtin/help.c       |    4 ++--
 builtin/init-db.c    |    2 +-
 builtin/merge.c      |    4 ++--
 builtin/notes.c      |    2 +-
 builtin/remote-ext.c |    4 ++--
 builtin/revert.c     |    2 +-
 config.c             |    2 +-
 exec_cmd.c           |    4 ++--
 git.c                |   18 +++++++++---------
 pager.c              |    2 +-
 setup.c              |    6 +++---
 13 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index efe8b6c..8d81c29 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -566,7 +566,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 	atexit(remove_junk);
 	sigchain_push_common(remove_junk_on_signal);
 
-	setenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
+	xsetenv(CONFIG_ENVIRONMENT, mkpath("%s/config", git_dir), 1);
 
 	if (safe_create_leading_directories_const(git_dir) < 0)
 		die(_("could not create leading directories of '%s'"), git_dir);
diff --git a/builtin/commit.c b/builtin/commit.c
index e36e9ad..2b87da9 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -361,13 +361,13 @@ static char *prepare_index(int argc, const char **argv, const char *prefix,
 			die(_("unable to create temporary index"));
 
 		old_index_env = getenv(INDEX_ENVIRONMENT);
-		setenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
+		xsetenv(INDEX_ENVIRONMENT, index_lock.filename, 1);
 
 		if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
 			die(_("interactive add failed"));
 
 		if (old_index_env && *old_index_env)
-			setenv(INDEX_ENVIRONMENT, old_index_env, 1);
+			xsetenv(INDEX_ENVIRONMENT, old_index_env, 1);
 		else
 			unsetenv(INDEX_ENVIRONMENT);
 
@@ -1023,7 +1023,7 @@ static int parse_and_validate_options(int argc, const char *argv[],
 	if (edit_flag)
 		use_editor = 1;
 	if (!use_editor)
-		setenv("GIT_EDITOR", ":", 1);
+		xsetenv("GIT_EDITOR", ":", 1);
 
 	/* Sanity check options */
 	if (amend && !current_head)
diff --git a/builtin/help.c b/builtin/help.c
index 61ff798..e7dc15b 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -330,7 +330,7 @@ static void setup_man_path(void)
 	if (old_path)
 		strbuf_addstr(&new_path, old_path);
 
-	setenv("MANPATH", new_path.buf, 1);
+	xsetenv("MANPATH", new_path.buf, 1);
 
 	strbuf_release(&new_path);
 }
@@ -371,7 +371,7 @@ static void show_man_page(const char *git_cmd)
 static void show_info_page(const char *git_cmd)
 {
 	const char *page = cmd_to_page(git_cmd);
-	setenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
+	xsetenv("INFOPATH", system_path(GIT_INFO_PATH), 1);
 	execlp("info", "info", "gitman", page, (char *)NULL);
 	die("no info viewer handled the request");
 }
diff --git a/builtin/init-db.c b/builtin/init-db.c
index d07554c..21ff09e 100644
--- a/builtin/init-db.c
+++ b/builtin/init-db.c
@@ -537,7 +537,7 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	if (is_bare_repository_cfg == 1) {
 		static char git_dir[PATH_MAX+1];
 
-		setenv(GIT_DIR_ENVIRONMENT,
+		xsetenv(GIT_DIR_ENVIRONMENT,
 			getcwd(git_dir, sizeof(git_dir)), argc > 0);
 	}
 
diff --git a/builtin/merge.c b/builtin/merge.c
index a1c8534..a4ae473 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1257,7 +1257,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	strbuf_addstr(&buf, "merge");
 	for (i = 0; i < argc; i++)
 		strbuf_addf(&buf, " %s", argv[i]);
-	setenv("GIT_REFLOG_ACTION", buf.buf, 0);
+	xsetenv("GIT_REFLOG_ACTION", buf.buf, 0);
 	strbuf_reset(&buf);
 
 	for (i = 0; i < argc; i++) {
@@ -1267,7 +1267,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 		remotes = &commit_list_insert(commit, remotes)->next;
 		strbuf_addf(&buf, "GITHEAD_%s",
 			    sha1_to_hex(commit->object.sha1));
-		setenv(buf.buf, argv[i], 1);
+		xsetenv(buf.buf, argv[i], 1);
 		strbuf_reset(&buf);
 		if (merge_remote_util(commit) &&
 		    merge_remote_util(commit)->obj &&
diff --git a/builtin/notes.c b/builtin/notes.c
index 10b8bc7..7b53c69 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -1076,7 +1076,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
 		struct strbuf sb = STRBUF_INIT;
 		strbuf_addstr(&sb, override_notes_ref);
 		expand_notes_ref(&sb);
-		setenv("GIT_NOTES_REF", sb.buf, 1);
+		xsetenv("GIT_NOTES_REF", sb.buf, 1);
 		strbuf_release(&sb);
 	}
 
diff --git a/builtin/remote-ext.c b/builtin/remote-ext.c
index 692c834..0b2169a 100644
--- a/builtin/remote-ext.c
+++ b/builtin/remote-ext.c
@@ -38,8 +38,8 @@ static char *strip_escapes(const char *str, const char *service,
 		psoff = 4;
 
 	/* Pass the service to command. */
-	setenv("GIT_EXT_SERVICE", service, 1);
-	setenv("GIT_EXT_SERVICE_NOPREFIX", service + psoff, 1);
+	xsetenv("GIT_EXT_SERVICE", service, 1);
+	xsetenv("GIT_EXT_SERVICE_NOPREFIX", service + psoff, 1);
 
 	/* Scan the length of argument. */
 	while (str[rpos] && (escape || str[rpos] != ' ')) {
diff --git a/builtin/revert.c b/builtin/revert.c
index 1ea525c..955a99f 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -1007,7 +1007,7 @@ static int pick_commits(struct commit_list *todo_list, struct replay_opts *opts)
 	struct commit_list *cur;
 	int res;
 
-	setenv(GIT_REFLOG_ACTION, action_name(opts), 0);
+	xsetenv(GIT_REFLOG_ACTION, action_name(opts), 0);
 	if (opts->allow_ff)
 		assert(!(opts->signoff || opts->no_commit ||
 				opts->record_origin || opts->edit));
diff --git a/config.c b/config.c
index 5ea101f..f461a62 100644
--- a/config.c
+++ b/config.c
@@ -43,7 +43,7 @@ void git_config_push_parameter(const char *text)
 		strbuf_addch(&env, ' ');
 	}
 	sq_quote_buf(&env, text);
-	setenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
+	xsetenv(CONFIG_DATA_ENVIRONMENT, env.buf, 1);
 	strbuf_release(&env);
 }
 
diff --git a/exec_cmd.c b/exec_cmd.c
index 171e841..a5a92dd 100644
--- a/exec_cmd.c
+++ b/exec_cmd.c
@@ -63,7 +63,7 @@ void git_set_argv_exec_path(const char *exec_path)
 	/*
 	 * Propagate this setting to external programs.
 	 */
-	setenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
+	xsetenv(EXEC_PATH_ENVIRONMENT, exec_path, 1);
 }
 
 
@@ -108,7 +108,7 @@ void setup_path(void)
 	else
 		strbuf_addstr(&new_path, _PATH_DEFPATH);
 
-	setenv("PATH", new_path.buf, 1);
+	xsetenv("PATH", new_path.buf, 1);
 
 	strbuf_release(&new_path);
 }
diff --git a/git.c b/git.c
index 8e34903..cb80de2 100644
--- a/git.c
+++ b/git.c
@@ -54,7 +54,7 @@ int check_pager_config(const char *cmd)
 static void commit_pager_choice(void) {
 	switch (use_pager) {
 	case 0:
-		setenv("GIT_PAGER", "cat", 1);
+		xsetenv("GIT_PAGER", "cat", 1);
 		break;
 	case 1:
 		setup_pager();
@@ -109,7 +109,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--no-replace-objects")) {
 			read_replace_refs = 0;
-			setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
+			xsetenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
@@ -117,13 +117,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No directory given for --git-dir.\n" );
 				usage(git_usage_string);
 			}
-			setenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
+			xsetenv(GIT_DIR_ENVIRONMENT, (*argv)[1], 1);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, "--git-dir=")) {
-			setenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
+			xsetenv(GIT_DIR_ENVIRONMENT, cmd + 10, 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--namespace")) {
@@ -131,13 +131,13 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No namespace given for --namespace.\n" );
 				usage(git_usage_string);
 			}
-			setenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
+			xsetenv(GIT_NAMESPACE_ENVIRONMENT, (*argv)[1], 1);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, "--namespace=")) {
-			setenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
+			xsetenv(GIT_NAMESPACE_ENVIRONMENT, cmd + 12, 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--work-tree")) {
@@ -145,19 +145,19 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
 				fprintf(stderr, "No directory given for --work-tree.\n" );
 				usage(git_usage_string);
 			}
-			setenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
+			xsetenv(GIT_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
 			if (envchanged)
 				*envchanged = 1;
 			(*argv)++;
 			(*argc)--;
 		} else if (!prefixcmp(cmd, "--work-tree=")) {
-			setenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
+			xsetenv(GIT_WORK_TREE_ENVIRONMENT, cmd + 12, 1);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--bare")) {
 			static char git_dir[PATH_MAX+1];
 			is_bare_repository_cfg = 1;
-			setenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
+			xsetenv(GIT_DIR_ENVIRONMENT, getcwd(git_dir, sizeof(git_dir)), 0);
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "-c")) {
diff --git a/pager.c b/pager.c
index 975955b..d3a1299 100644
--- a/pager.c
+++ b/pager.c
@@ -76,7 +76,7 @@ void setup_pager(void)
 	if (!pager)
 		return;
 
-	setenv("GIT_PAGER_IN_USE", "true", 1);
+	xsetenv("GIT_PAGER_IN_USE", "true", 1);
 
 	/* spawn the pager */
 	pager_argv[0] = pager;
diff --git a/setup.c b/setup.c
index 61c22e6..06f38d0 100644
--- a/setup.c
+++ b/setup.c
@@ -309,7 +309,7 @@ void setup_work_tree(void)
 	 * if $GIT_WORK_TREE is set relative
 	 */
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
-		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
+		xsetenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
 	set_git_dir(relative_path(git_dir, work_tree));
 	initialized = 1;
@@ -683,9 +683,9 @@ const char *setup_git_directory_gently(int *nongit_ok)
 
 	prefix = setup_git_directory_gently_1(nongit_ok);
 	if (prefix)
-		setenv("GIT_PREFIX", prefix, 1);
+		xsetenv("GIT_PREFIX", prefix, 1);
 	else
-		setenv("GIT_PREFIX", "", 1);
+		xsetenv("GIT_PREFIX", "", 1);
 
 	if (startup_info) {
 		startup_info->have_repository = !nongit_ok || !*nongit_ok;
-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply related

* [PATCH/RFC 1/2] wrapper: supply xsetenv
From: Erik Faye-Lund @ 2011-12-13 12:10 UTC (permalink / raw)
  To: git

Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>
---
 git-compat-util.h |    1 +
 wrapper.c         |    6 ++++++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/git-compat-util.h b/git-compat-util.h
index 77062ed..551a0be 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -439,6 +439,7 @@ extern int xdup(int fd);
 extern FILE *xfdopen(int fd, const char *mode);
 extern int xmkstemp(char *template);
 extern int xmkstemp_mode(char *template, int mode);
+extern int xsetenv(const char *name, const char *val, int override);
 extern int odb_mkstemp(char *template, size_t limit, const char *pattern);
 extern int odb_pack_keep(char *name, size_t namesz, unsigned char *sha1);
 
diff --git a/wrapper.c b/wrapper.c
index 85f09df..442800b 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -381,3 +381,9 @@ int remove_or_warn(unsigned int mode, const char *file)
 {
 	return S_ISGITLINK(mode) ? rmdir_or_warn(file) : unlink_or_warn(file);
 }
+
+int xsetenv(const char *name, const char *val, int overwrite)
+{
+	if (setenv(name, val, overwrite))
+		die_errno("setenv failed");
+}
-- 
1.7.7.1.msysgit.0.272.g9e47e

^ permalink raw reply related

* [PATCH resend] Do not create commits whose message contains NUL
From: Nguyễn Thái Ngọc Duy @ 2011-12-13 11:56 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

We assume that the commit log messages are uninterpreted sequences of
non-NUL bytes (see Documentation/i18n.txt). However the assumption
does not really stand out and it's quite easy to set an editor to save
in a NUL-included encoding. Currently we silently cut at the first NUL
we see.

Make it more obvious that NUL is not welcome by refusing to create
such commits. Those who deliberately want to create them can still do
with hash-object.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 This is from UTF-16 in commit message discussion [1] a few months
 ago. I don't want to resurrect the discussion again. However I think
 it's a good idea to stop users from shooting themselves in this case,
 especially at porcelain level.
 
 There were no comments on this patch previously. So, any comments
 this time ? Should I drop it?

 [1] http://thread.gmane.org/gmane.comp.version-control.git/184123/focus=184335
 commit.c               |    3 +++
 t/t3900-i18n-commit.sh |    6 ++++++
 t/t3900/UTF-16.txt     |  Bin 0 -> 32 bytes
 3 files changed, 9 insertions(+), 0 deletions(-)
 create mode 100644 t/t3900/UTF-16.txt

diff --git a/commit.c b/commit.c
index d67b8c7..0775eec 100644
--- a/commit.c
+++ b/commit.c
@@ -855,6 +855,9 @@ int commit_tree(const char *msg, size_t msg_len, unsigned char *tree,
 
 	assert_sha1_type(tree, OBJ_TREE);
 
+	if (strlen(msg) < msg_len)
+		die(_("cannot commit with NUL in commit message"));
+
 	/* Not having i18n.commitencoding is the same as having utf-8 */
 	encoding_is_utf8 = is_encoding_utf8(git_commit_encoding);
 
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 1f62c15..d48a7c0 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -34,6 +34,12 @@ test_expect_success 'no encoding header for base case' '
 	test z = "z$E"
 '
 
+test_expect_failure 'UTF-16 refused because of NULs' '
+	echo UTF-16 >F &&
+	git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-16.txt
+'
+
+
 for H in ISO8859-1 eucJP ISO-2022-JP
 do
 	test_expect_success "$H setup" '
diff --git a/t/t3900/UTF-16.txt b/t/t3900/UTF-16.txt
new file mode 100644
index 0000000000000000000000000000000000000000..53296be684253f40964c0604be7fa7ff12e200cb
GIT binary patch
literal 32
mcmezOpWz6@X@-jo=NYasZ~@^#h9rjP3@HpR7}6Nh8Mpw;r3yp<

literal 0
HcmV?d00001

-- 
1.7.8.36.g69ee2

^ permalink raw reply related

* Re: Auto update submodules after merge and reset
From: Andreas T.Auer @ 2011-12-13  9:45 UTC (permalink / raw)
  To: Jens Lehmann; +Cc: Phil Hord, git
In-Reply-To: <4EE682A3.8070704@web.de>



On 12.12.2011 23:39 Jens Lehmann wrote:
>  Am 11.12.2011 22:15, schrieb Andreas T.Auer:
> >
> > In my use case the branches on the submodules follow the
> > superproject and (mostly) versions that are committed there, it
> > just adds the possibility to keep on working without checking out
> > a branch after an update and without colliding with existing
> > branchnames in the submodule.
>
>  Using superproject branch names in the submodules make no sense for a
>  lot of use cases.
The most useful workflows for some use cases make no sense for a lot of 
other use cases. That is why configuration options are useful, right? 
There is no one-size-fits-all. It surely won't make sense for 
independent submodules.

> > The other use case wants to follow the commits of that other
> > submodule without checking the corresponding gitlinks into the
> > superproject. But wouldn't it also make sense here to define
> > actually a mapping in the .gitmodule that says "if the branch
> > 'develop' is checkedout in the supermodule then with every
> > submodule update automatically pull the newest 'unstable' commit
> > from the submodule"? Or for "master" follow "stable" or for the
> > "maint" branch follow updates in the "bugfixes" branch.
> >
> > For example
> >
> > [submodule "commonlib"] update = heads develop:unstable
> > master:stable maint:bugfixes
>
>  Having that configured with "branch=unstable", "branch=stable" etc.
>  in .gitmodules on the superprojects branches would be simpler and
>  achieve the same functionality.

Yes, this has been my first thought also, but there is also a good point 
to keep the .gitmodules stable, or you always have to change the file 
when branches change their names. So when the maint branch of version 
1.3 become an archive branch and the new maint is on 1.4, which was the 
master before then you have to change the .gitmodules on these branches. 
I.e. .gitmodules of 1.4 have "stable" and must have "bugfixes" now and 
.gitmodules of 1.3 has "bugfixes" and must remove the floating 
completely. I'm not sure that this can always be solved with "easy" 
merging and therefore it is probably not really simpler, when you have 
to do this for every new release. Or what do you think?

> > So whenever a defined branch is checked out in the superproject
> > the mapped branch will be checked out in the submodule ("new"
> > commit), but if a (e.g. tagged) commit is checked out ("old"
> > commit) then the gitlink in the superproject is used to check out
> > the referenced commit in the submodule.
>
>  I think checkout should only use the submodule commit recorded in the
>  superproject and a subsequent "git submodule update" should be needed
>  to update the submodule to tip. Otherwise you record SHA-1 but still
>  won't be able to bisect ...

bisect would leave the branch and therefore uses the recorded SHA1 for 
the submodule checkout instead of the tip. "follow-the-tip" should only 
work if the superproject follows the tip.
If you configure auto-update on checkout you would not expect that a 
separate git submodule update has a different behavior.

> > In http://thread.gmane.org/gmane.comp.version-control.git/183837
> > was discussed whether the gitlink in the superproject should be
> > set to all-zero if updates follow the tip or maybe use the SHA1 of
> > the commit when the submodule was added. I think the gitlink should
> > be updated everytime when a new commit in the superproject is
> > created.
>
>  Nope, only when "git submodule update" is run. Otherwise you'll
>  spray the history with submodule updates totally unrelated to the
>  commits in the superproject, which is rather confusing.

Of course, committing a new version to the superproject should not 
trigger pulling in a new version for the submodule or an automatic jump 
to the tip of the submodule. I just meant a normal manual "commit -a" 
behavior. Putting a 0{40} hash in the gitlink or only the hash of the 
submodule, when it first was added would be a special treatment that is 
neither needed nor wanted.

^ permalink raw reply

* Re: [PATCH v4 2/2] push: teach --recurse-submodules the on-demand option
From: Jens Lehmann @ 2011-12-13  8:48 UTC (permalink / raw)
  To: Phil Hord; +Cc: Junio C Hamano, Heiko Voigt, Fredrik Gustafsson, git
In-Reply-To: <CABURp0qkKXCW-U=78OpnejdtdpphhJtOoDubz77m7Gt3o5sC=Q@mail.gmail.com>

Am 13.12.2011 00:50, schrieb Phil Hord:
> On Mon, Dec 12, 2011 at 5:29 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
>> Am 12.12.2011 22:16, schrieb Phil Hord:
>>>  I thought-experimented with this a bit last year and came to the
>>> conclusion that I should be able to 'float' to tips (developer
>>> convenience) and also to store the SHA-1 of each gitlink through
>>> history (automated maybe; as-needed).
>>
>> Which means that after "git submodule update" floated a submodule branch
>> further, you would have to commit that in the superproject.
> 
> Sadly, yes.  Currently I have my CI-server do this for me after it
> verifies each new submodule commit is able to build successfully.

Which I think is a good thing to do, as you have a good chance of
catching breakage introduced by the submodule updates. "float-only"
submodules won't always be a pleasant experience, as they can (and
sometimes will) get you into trouble when advancing them introduces
bugs (and then you can't even bisect that breakage).

>>> The problem with "float + gitlinks", of course, is that it looks like
>>> "not floating" to the developers (git-status is dirty unless
>>> overridden, etc.)
>>
>> Yeah. But what if each "git submodule update" would update the tip of
>> the submodule branch and add that to the superproject? You could follow
>> a tip but still produce reproducible trees.
> 
> Yes, and that's what I want.
> 
> Not what it sounded like was being suggested before, which (to my
> eyes) implied that the submodule gitlinks were useless noise.

It was suggested in other threads in the past. For a start, you could
write a script doing that and play around with it. And if that works
well for you, we can discuss if implementing that functionality into
"git submodule update" makes sense.

^ permalink raw reply

* Re: [PATCH v3 0/3] grep attributes and multithreading
From: Thomas Rast @ 2011-12-13  8:44 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, René Scharfe, Jeff King, Eric Herman
In-Reply-To: <7vsjkpz763.fsf@alter.siamese.dyndns.org>

Junio C Hamano wrote:
> Thanks; sign-off?

Ooops, not again!

> [PATCH v3 1/3] grep: load funcname patterns for -W

Signed-off-by: Thomas Rast <trast@student.ethz.ch>

-- 
Thomas Rast
trast@{inf,student}.ethz.ch

^ permalink raw reply

* Re: Auto update submodules after merge and reset
From: Jens Lehmann @ 2011-12-13  7:52 UTC (permalink / raw)
  To: Phil Hord; +Cc: Andreas T.Auer, git
In-Reply-To: <CABURp0r37+VHBVVKepHPC4jwa-wJ0b+qwLrhhFR8KXnMQYTT3w@mail.gmail.com>

Am 13.12.2011 00:43, schrieb Phil Hord:
> On Mon, Dec 12, 2011 at 5:39 PM, Jens Lehmann <Jens.Lehmann@web.de> wrote:
>> Am 11.12.2011 22:15, schrieb Andreas T.Auer:
>>> In http://thread.gmane.org/gmane.comp.version-control.git/183837 was discussed whether the gitlink in the superproject should be set to all-zero if updates follow the tip or maybe use the SHA1 of the commit when the submodule was added. I think the gitlink should be updated everytime when a new commit in the superproject is created.
>>
>> Nope, only when "git submodule update" is run. Otherwise you'll spray the
>> history with submodule updates totally unrelated to the commits in the
>> superproject, which is rather confusing.
> 
> And this is why my superproject is a makefile, a .gitmodules file and
> a bunch of gitlinks.  We only use it to track the advancement of
> submodule activity.

Which is fine. Did you think about having a branch where only the
submodules are updated (and built and tested) and committed to by a
buildbot when everything is fine? You could then merge that branch
whenever you want up-to-date submodules and have the reproducibility
of the exact model while being able to "float" along the updates of
that branch?

I think it always boils down to this: Either commit new gitlinks, so
the submodules get updated in a reproducible manner, or don't use
gitlinks at all so the submodules can float wherever they want.

> So yes, I want my superproject's gitlinks to update automatically.  I
> just don't know a smart way to make that happen.

Yup, that has been the endpoint of all discussions about that topic
so far. And until someone comes up with a smart way to make that
happen, I would rather not put something half-baked into git.

(But please tell us when you found a smart way to do that! ;-)

^ permalink raw reply

* Re: [PATCH v2 28/51] refs.c: rename ref_array -> ref_dir
From: Junio C Hamano @ 2011-12-13  6:37 UTC (permalink / raw)
  To: Michael Haggerty
  Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
	Johan Herland, Julian Phillips
In-Reply-To: <4EE6E61F.8080405@alum.mit.edu>

Michael Haggerty <mhagger@alum.mit.edu> writes:

> Apropos testing, it is unsettling that our test suite doesn't show any
> failures after my changes.  The dir entries in extra_refs are now always
> sorted and de-duped when do_for_each_ref() is called.  Could it be that
> duplicate ".have" references never come up in the test suite?  It sounds
> like an important code path is not being tested.  In particular, I won't
> be able to test whether my fix works :-/

I doubt anybody thought of using more than one --reference while cloning
or having more than one entry in $GIT_DIR/objects/info/alternates in a
repository that is being pushed into, even though we might have tests for
simpler single --reference and single alternate cases.

As to the order of the changes, my gut feeling is that it would make it
harder to debug your series to delay the removal of "extra_ref" hackery,
as it would be a corner case that your "hierarchical" structure never has
to worry about in the end result.

Another possibility is to keep the extra_ref interface in refs.c, without
any of your changes (i.e. keep it just as a flat list, with the original
interface to append to it without any dedup and other fancy features) and
also keep the special casing of it in for_each_ref(). AFAIK, that is the
only iterator that should care about the extra refs. Thinking about it a
bit more, removal of add_extra_ref() API may be unnecessarily complex with
no real gain. For example, extra refs added in builtin/clone.c is used by
builtin/fetch-pack.c, meaning that the codepath that discovers and
remembers these extra history anchor points and the codepath that uses
them while walking the history are not localized and we would need some
sort of "extra ref API" anyway. I am leaning towards this option.

^ permalink raw reply

* Re: [PATCH v2] Update documentation for stripspace
From: Frans Klaver @ 2011-12-13  6:28 UTC (permalink / raw)
  To: Junio C Hamano, Conrad Irwin; +Cc: git
In-Reply-To: <1323728909-7847-1-git-send-email-conrad.irwin@gmail.com>

On Mon, 12 Dec 2011 23:28:29 +0100, Conrad Irwin <conrad.irwin@gmail.com>  
wrote:

>> an incomplete line, i.e. "ensures the output does not end with an
>> incomplete line by adding '\n' at the end if needed".
>
> Hmm, I'm not sure that's the best way of describing it — I've gone with:
> "add a missing '\n' to the last line if necessary.".

In most editors/IDE's I know and that support this, this is called "ensure  
new-line at end of file". I find this wording clearer than the above two  
options.

Cheers,
Frans

^ permalink raw reply

* Re: Question about commit message wrapping
From: Frans Klaver @ 2011-12-13  6:16 UTC (permalink / raw)
  To: Michael Haggerty
  Cc: Holger Hellmuth, Andrew Ardill, Jakub Narebski,
	Sidney San Martín, git
In-Reply-To: <4EE6C31C.60909@alum.mit.edu>

On Tue, 13 Dec 2011 04:14:36 +0100, Michael Haggerty  
<mhagger@alum.mit.edu> wrote:

> On 12/12/2011 11:16 PM, Frans Klaver wrote:
>> Wrapped code as in auto-wrapped? Or as in manually wrapped? Python
>> programmers have significant white space, but you can still hard wrap
>> stuff, as long as the next statement is properly indented.
>
> This is incorrect.  Python statements can only be broken across lines
> within unbalanced parenthesis (or using '\' or within a multiline
> string).  For example,
>
>     x =
>         1
>
> is a syntax error, while
>
>     y = (
>         1
>         )
>
> or
>
>     f(1,
>           2,
>       3,
>       4)
>
> are both valid.

Hm yes, my statement was quite incomplete. What you describe here is what  
I meant, and I should have taken the time to word it down properly. Thanks  
for taking the time to do so.



>
> FWIW I think automatic wrapping of commit messages is a bad idea.  I
> wrap my commit messages deliberately to make them look the way I want
> them to look.  The assumption of an 80-character display has historical
> reasons, but it is also a relatively comfortable line-width to read
> (even on wider displays).  And given that commit messages sometimes
> contain "flowable" paragraph text, sometimes code snippets, sometimes
> ASCII art, etc, no automatic wrapping will work correctly unless
> everybody agrees that commit messages must be written in some specific
> form of markup (or lightweight markup).  And I can't imagine such a
> thing ever happening.
>
> As for "future-proofing", do you really think there will be a lot of
> programming happening on mobile phones with less than 80-character-wide
> displays?  (And even my little HTC can easily fit 80 characters if I
> rotate the phone to "landscape" mode.)

Makes sense.

^ permalink raw reply

* Re: Git blame only current branch
From: Junio C Hamano @ 2011-12-13  5:47 UTC (permalink / raw)
  To: Vijay Lakshminarayanan; +Cc: Jeff King, Stephen Bash, git discussion list
In-Reply-To: <8739cpteat.fsf@gmail.com>

Vijay Lakshminarayanan <laksvij@gmail.com> writes:

> The code reads fine when there's no numeral 1 around but now it doesn't
> read well.  I think refactoring
>
>     struct commit_list *l
>
> to 
>
>     struct commit_list *lst
>
> is justified.  Thoughts?

Not justified at all.

What is "lst" and why is it not spelled "list"?  It is a disease to drop
vowels when you do not have to.

If I were to name a new variable that points at one element of a linked
list and is used to walk the list (surprise!) "element" or perhaps "elem"
for short, but in the context of that short function I honestly do not see
much need for such a naming. The variable is extremely short-lived and
there is no room for confusion.

^ permalink raw reply

* Re: [PATCH v2 28/51] refs.c: rename ref_array -> ref_dir
From: Michael Haggerty @ 2011-12-13  5:43 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
	Johan Herland, Julian Phillips
In-Reply-To: <7v7h21xps9.fsf@alter.siamese.dyndns.org>

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

On 12/13/2011 01:45 AM, Junio C Hamano wrote:
> mhagger@alum.mit.edu writes:
> 
>> From: Michael Haggerty <mhagger@alum.mit.edu>
>>
>> This purely textual change is in preparation for storing references
>> hierarchically, when the old ref_array structure will represent one
>> "directory" of references.  Rename functions that deal with this
>> structure analogously, and also rename the structure's "refs" member
>> to "entries".
>>
>> Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
>> ---
>>  refs.c |  166 ++++++++++++++++++++++++++++++++--------------------------------
>>  1 files changed, 83 insertions(+), 83 deletions(-)
>>
>> diff --git a/refs.c b/refs.c
>> index fe6d657..b74ef80 100644
>> --- a/refs.c
>> +++ b/refs.c
>> @@ -106,9 +106,9 @@ struct ref_value {
>>  	unsigned char peeled[20];
>>  };
>>  
>> -struct ref_array {
>> +struct ref_dir {
>>  	int nr, alloc;
>> -	struct ref_entry **refs;
>> +	struct ref_entry **entries;
>>  };
> 
> The s/refs/entries/ renaming is a sane thing to do; on the other hand, I
> somehow find the s/ref_array/ref_dir/ renaming is a short-sighted change
> and undesirable, as you are essentially declaring that "if you use this
> structure, the contents you store there are expected to be named
> hierarchically", forbidding users that want to use a simple flat array.

This data structure is not exposed outside of the module, so it only
describes the de facto current storage scheme rather than making any
promises to the outside world.

> BUT. That was an observation before I continued reading the remainder of
> the series.

> I think the above observation primarily come from my worries around the
> extra ref stuff, which by nature does not fit well with the hierarchical
> naming (they do not even have any meaningful names). Sorting or requiring
> uniqueness among them do not make any sense, let alone cutting their names
> in hierarchical boundaries.
> 
> As an alternative, it _might_ make sense to get rid of "add_extra_ref()"
> API from refs.c and make it the responsibility for its users to add their
> extra anchor points where they use for_each_ref() to find out all anchor
> points in the history from the refs.c subsystem. If we go that route, I
> fully agree that "s/ref_array/ref_dir/" renaming is the right thing to do,
> as refs.c subsystem will _only_ handle the hierarchical ref namespace and
> nothing else after such a change.

I absolutely agree; the fact that extra refs are part of the refs module
has the foul smell of expedience.  And your suggestion for changing the
situation makes sense to me as far as I can follow it.  But I don't
think I have the gumption to attack another big part of the code base
before I've even finished the changes that I still have planned for the
refs API.

If somebody else wants to volunteer to make extra_refs redundant, I
would be happy to support that person on the refs side.

Otherwise, I propose to just avoid de-duping extra refs so that my patch
series doesn't make things worse.  If it is acceptable, I would prefer
to add the fix as a patch at the end of the series, because after

    struct ref_dir: store a reference to the enclosing ref_cache

ref_dir carries around information that can be used to distinguish
between the extra_refs and other ref caches.  I think it is as easy as
the attached patch (untested).

Apropos testing, it is unsettling that our test suite doesn't show any
failures after my changes.  The dir entries in extra_refs are now always
sorted and de-duped when do_for_each_ref() is called.  Could it be that
duplicate ".have" references never come up in the test suite?  It sounds
like an important code path is not being tested.  In particular, I won't
be able to test whether my fix works :-/

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

[-- Attachment #2: fix-dedup.diff --]
[-- Type: text/x-patch, Size: 1358 bytes --]

diff --git a/refs.c b/refs.c
index 2d5c827..2fd3db2 100644
--- a/refs.c
+++ b/refs.c
@@ -457,7 +457,6 @@ static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2
  */
 static void sort_ref_dir(struct ref_entry *direntry)
 {
-	int i, j;
 	struct ref_entry *last = NULL;
 	struct ref_dir *dir;
 	assert(direntry->flag & REF_DIR);
@@ -468,19 +467,24 @@ static void sort_ref_dir(struct ref_entry *direntry)
 
 	qsort(dir->entries, dir->nr, sizeof(*dir->entries), ref_entry_cmp);
 
-	/* Remove any duplicates: */
-	for (i = 0, j = 0; j < dir->nr; j++) {
-		struct ref_entry *entry = dir->entries[j];
-		if (last && is_dup_ref(last, entry)) {
-			free_ref_entry(entry);
-		} else if (entry->flag & REF_DIR) {
-			dir->entries[i++] = entry;
-			last = NULL;
-		} else {
-			last = dir->entries[i++] = entry;
+	/* Remove any duplicates, but not for extra_refs: */
+	if (dir->ref_cache != NULL) {
+		int i, j;
+		for (i = 0, j = 0; j < dir->nr; j++) {
+			struct ref_entry *entry = dir->entries[j];
+			if (last && is_dup_ref(last, entry)) {
+				free_ref_entry(entry);
+			} else if (entry->flag & REF_DIR) {
+				dir->entries[i++] = entry;
+				last = NULL;
+			} else {
+				last = dir->entries[i++] = entry;
+			}
 		}
+		dir->nr = i;
 	}
-	dir->sorted = dir->nr = i;
+
+	dir->sorted = dir->nr;
 }
 
 #define DO_FOR_EACH_INCLUDE_BROKEN 01

^ permalink raw reply related

* Re: [PATCH 2/3] test-terminal: set output terminals to raw mode
From: Jonathan Nieder @ 2011-12-13  5:09 UTC (permalink / raw)
  To: Thomas Rast; +Cc: git, Junio C Hamano, Jeff King, Michael Haggerty
In-Reply-To: <201112122001.36303.trast@student.ethz.ch>

Thomas Rast wrote:

> I tested this tweak of the script:
[...]
> That's over ssh on
>
>   $ uname -a
>   Darwin mackeller.inf.ethz.ch 11.1.0 Darwin Kernel Version 11.1.0: Tue Jul 26 16:07:11 PDT 2011; root:xnu-1699.22.81~1/RELEASE_X86_64 x86_64

Thanks.  I've passed this information on to Apple (rdar://9046540),
though I have no reason to believe anyone reads the reports there. :)

^ permalink raw reply

* Re: [PATCH v2 08/51] is_dup_ref(): extract function from sort_ref_array()
From: Michael Haggerty @ 2011-12-13  5:00 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
	Johan Herland, Julian Phillips
In-Reply-To: <4EE6D61A.2030300@alum.mit.edu>

On 12/13/2011 05:35 AM, Michael Haggerty wrote:
> Is it *really* possible to have multiple extra_refs with the same name,
> or is this more of a hypothetical problem that requires more careful
> analysis?

I see that you already answered this question downthread.  I will reply
to your analysis there.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: [PATCH v2 08/51] is_dup_ref(): extract function from sort_ref_array()
From: Michael Haggerty @ 2011-12-13  4:35 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Jeff King, Drew Northup, Jakub Narebski, Heiko Voigt,
	Johan Herland, Julian Phillips
In-Reply-To: <7vvcplxq4r.fsf@alter.siamese.dyndns.org>

On 12/12/2011 11:33 PM, Junio C Hamano wrote:
> mhagger@alum.mit.edu writes:
> 
>> +/*
>> + * Emit a warning and return true iff ref1 and ref2 have the same name
>> + * and the same sha1.  Die if they have the same name but different
>> + * sha1s.
>> + */
>> +static int is_dup_ref(const struct ref_entry *ref1, const struct ref_entry *ref2)
>> +{
>> +	if (!strcmp(ref1->name, ref2->name)) {
>> +		/* Duplicate name; make sure that the SHA1s match: */
>> +		if (hashcmp(ref1->sha1, ref2->sha1))
>> +			die("Duplicated ref, and SHA1s don't match: %s",
>> +			    ref1->name);
>> +		warning("Duplicated ref: %s", ref1->name);
>> +		return 1;
>> +	} else {
>> +		return 0;
>> +	}
>> +}
> 
> At this step, is_dup_ref() is only called from sort_ref_array() which in
> turn is only called on either a collection of loose or packed refs, so
> warning is warranted. IOW I do not see anything wrong with _this_ patch.

I agree.

> Later in the series, however, the collection of extra refs seems to be
> shoved into a phoney "direntry" and made to go through the same add_ref()
> machinery that uses find_containing_direntry() which in turn calls
> search_ref_dir() that smells like a definite no-no.

Correct.

I had remembered your explanation of the purpose of extra refs and also
that they have unusual names, but I hadn't allowed for the possibility
that multiple extra_refs can have the same name.  The old code never
sorted the extra refs and therefore never checked or eliminated
duplicates.  The new code does, as sorting is an intrinsic part of
looking up references and reference subdirectories in the hierarchical
cache.  It is introduced along with the meat of the change in

    [PATCH v2 29/51] refs: store references hierarchically

So...the new code would die if two extra refs have the same name but
different SHA1s, and emit a warning if they have the same name and the
same SHA1s.  (However, it is no problem for an extra ref to have the
same name as a packed or loose ref.)

Is it *really* possible to have multiple extra_refs with the same name,
or is this more of a hypothetical problem that requires more careful
analysis?

If the former, then I will have to do some work.  My approach would
probably be to allow sorting without de-duplication; that way extra_refs
can continue to share most of the code used for the other ref caches.
It would be relatively easy to add such a fix on top of the patch
series, where every ref_entry knows the ref_cache with which it is
associated.  It would be quite a bit more painful to massage such a fix
through the whole patch series.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: [PATCH 4/4] connect.c: drop path_match function
From: Michael Haggerty @ 2011-12-13  3:23 UTC (permalink / raw)
  To: Jeff King; +Cc: git, Kevin Sawicki
In-Reply-To: <20111213004959.GD3699@sigill.intra.peff.net>

On 12/13/2011 01:49 AM, Jeff King wrote:
> I just did the exact-string match inline in the previous patch. I could
> also have modified path_match to do it. But really, I can't think of a
> worse name for a global function in a system which is all about
> managing content in paths. Unless, you know, it actually matched paths.
> Which it doesn't.

The tacit assumption that a reference is always a file is all over the
code and is often confusing.  My

    [PATCH v2 02/51] refs: rename "refname" variables

is a step towards making the distinction more explicit, at least in the
refs code.

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: Question about commit message wrapping
From: Michael Haggerty @ 2011-12-13  3:14 UTC (permalink / raw)
  To: Frans Klaver
  Cc: Holger Hellmuth, Andrew Ardill, Jakub Narebski,
	Sidney San Martín, git
In-Reply-To: <op.v6edibfz0aolir@keputer>

On 12/12/2011 11:16 PM, Frans Klaver wrote:
> Wrapped code as in auto-wrapped? Or as in manually wrapped? Python
> programmers have significant white space, but you can still hard wrap
> stuff, as long as the next statement is properly indented.

This is incorrect.  Python statements can only be broken across lines
within unbalanced parenthesis (or using '\' or within a multiline
string).  For example,

    x =
        1

is a syntax error, while

    y = (
        1
        )

or

    f(1,
          2,
      3,
      4)

are both valid.

FWIW I think automatic wrapping of commit messages is a bad idea.  I
wrap my commit messages deliberately to make them look the way I want
them to look.  The assumption of an 80-character display has historical
reasons, but it is also a relatively comfortable line-width to read
(even on wider displays).  And given that commit messages sometimes
contain "flowable" paragraph text, sometimes code snippets, sometimes
ASCII art, etc, no automatic wrapping will work correctly unless
everybody agrees that commit messages must be written in some specific
form of markup (or lightweight markup).  And I can't imagine such a
thing ever happening.

As for "future-proofing", do you really think there will be a lot of
programming happening on mobile phones with less than 80-character-wide
displays?  (And even my little HTC can easily fit 80 characters if I
rotate the phone to "landscape" mode.)

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: Git blame only current branch
From: Jeff King @ 2011-12-13  2:14 UTC (permalink / raw)
  To: Vijay Lakshminarayanan; +Cc: Stephen Bash, git discussion list
In-Reply-To: <8739cpteat.fsf@gmail.com>

On Tue, Dec 13, 2011 at 07:37:22AM +0530, Vijay Lakshminarayanan wrote:

> > diff --git a/builtin/blame.c b/builtin/blame.c
> > index 80febbe..c19a8cd 100644
> > --- a/builtin/blame.c
> > +++ b/builtin/blame.c
> > @@ -1191,6 +1191,8 @@ static int num_scapegoats(struct rev_info *revs, struct commit *commit)
> >  {
> >  	int cnt;
> >  	struct commit_list *l = first_scapegoat(revs, commit);
> > +	if (revs->first_parent_only)
> > +		return l ? 1 : 0;
> >  	for (cnt = 0; l; l = l->next)
> >  		cnt++;
> >  	return cnt;
> 
> I just spent 30s staring at this wondering why you needed to do 
> 
>     return 1 ? 1 : 0;
> 
> which always returns 1 anyway before I realized it was a lowercase L.
> 
> The code reads fine when there's no numeral 1 around but now it doesn't
> read well.  I think refactoring
> 
>     struct commit_list *l
> 
> to 
> 
>     struct commit_list *lst
> 
> is justified.  Thoughts?

Sure, that would help. I wasn't planning to push this forward as a
"real" patch, but if somebody wants to do some testing and, more
importantly read through the code to make sure I am not violating some
assumptions, then it might be worth including upstream.

-Peff

^ permalink raw reply

* Re: Git blame only current branch
From: Vijay Lakshminarayanan @ 2011-12-13  2:07 UTC (permalink / raw)
  To: Jeff King; +Cc: Stephen Bash, git discussion list
In-Reply-To: <20111212165542.GA4802@sigill.intra.peff.net>

Jeff King <peff@peff.net> writes:

[snip]

> diff --git a/builtin/blame.c b/builtin/blame.c
> index 80febbe..c19a8cd 100644
> --- a/builtin/blame.c
> +++ b/builtin/blame.c
> @@ -1191,6 +1191,8 @@ static int num_scapegoats(struct rev_info *revs, struct commit *commit)
>  {
>  	int cnt;
>  	struct commit_list *l = first_scapegoat(revs, commit);
> +	if (revs->first_parent_only)
> +		return l ? 1 : 0;
>  	for (cnt = 0; l; l = l->next)
>  		cnt++;
>  	return cnt;

I just spent 30s staring at this wondering why you needed to do 

    return 1 ? 1 : 0;

which always returns 1 anyway before I realized it was a lowercase L.

The code reads fine when there's no numeral 1 around but now it doesn't
read well.  I think refactoring

    struct commit_list *l

to 

    struct commit_list *lst

is justified.  Thoughts?

> -Peff

-- 
Cheers
~vijay

Gnus should be more complicated.

^ permalink raw reply

* Re: [PATCH 2/2] Makefile: optionally exclude code that needs Unix sockets
From: Jeff King @ 2011-12-13  0:58 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Sixt, git
In-Reply-To: <7v1us91i5b.fsf@alter.siamese.dyndns.org>

On Mon, Dec 12, 2011 at 03:31:44PM -0800, Junio C Hamano wrote:

> > In theory we should also disable the documentation for credential-cache.
> > But that means surgery not only to Documentation/Makefile, but figuring
> > out how to pass the flags down to the actual asciidoc process (since
> > gitcredentials(7) mentions it in the text). Certainly possible, but I
> > don't know if it's worth the effort or not.
> 
> I do not think it matters that much. We've been shipping documentation for
> stuff like remote archiver and daemon without conditional compilation, no?

True. Let's not worry about it, then.

> I'll queue a single patch that is a squash between 2/2 and Peff's test
> updates between "credentials: add "cache" helper" and "strbuf: add
> strbuf_add*_urlencode" in the series.

That's perfect. Thanks.

-Peff

^ 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