Subject: [PATCH 01/10] Allow resolve_ref() caller to decide whether to receive static buffer

From: Nguyễn Thái Ngọc Duy <[email-masked]>
Date: Tue, 15 Nov 2011 13:07:47 +0700

resolve_ref() is taught to return a xstrdup'd buffer if alloc is true.
All callers are updated to receive static buffer as before though.

Signed-off-by: Nguyễn Thái Ngọc Duy <[email-masked]>
---
 branch.c                |    2 +-
 builtin/branch.c        |    6 +++---
 builtin/checkout.c      |    2 +-
 builtin/commit.c        |    2 +-
 builtin/fmt-merge-msg.c |    2 +-
 builtin/for-each-ref.c  |    2 +-
 builtin/fsck.c          |    2 +-
 builtin/merge.c         |    2 +-
 builtin/notes.c         |    2 +-
 builtin/receive-pack.c  |    4 ++--
 builtin/remote.c        |    2 +-
 builtin/show-branch.c   |    4 ++--
 builtin/symbolic-ref.c  |    2 +-
 cache.h                 |    2 +-
 reflog-walk.c           |    4 ++--
 refs.c                  |   31 ++++++++++++++++++-------------
 remote.c                |    6 +++---
 transport.c             |    2 +-
 wt-status.c             |    2 +-
 19 files changed, 43 insertions(+), 38 deletions(-)

diff --git a/branch.c b/branch.c
index d809876..a5ee614 100644
--- a/branch.c
+++ b/branch.c
@@ -151,7 +151,7 @@ int validate_new_branchname(const char *name, struct strbuf *ref,
 		const char *head;
 		unsigned char sha1[20];
 
-		head = resolve_ref("HEAD", sha1, 0, NULL);
+		head = resolve_ref("HEAD", sha1, 0, NULL, 0);
 		if (!is_bare_repository() && head && !strcmp(head, ref->buf))
 			die("Cannot force update the current branch.");
 	}
diff --git a/builtin/branch.c b/builtin/branch.c
index 0fe9c4d..43b494c 100644
--- a/builtin/branch.c
+++ b/builtin/branch.c
@@ -115,7 +115,7 @@ static int branch_merged(int kind, const char *name,
 		    branch->merge[0] &&
 		    branch->merge[0]->dst &&
 		    (reference_name =
-		     resolve_ref(branch->merge[0]->dst, sha1, 1, NULL)) != NULL)
+		     resolve_ref(branch->merge[0]->dst, sha1, 1, NULL, 0)) != NULL)
 			reference_rev = lookup_commit_reference(sha1);
 	}
 	if (!reference_rev)
@@ -250,7 +250,7 @@ static char *resolve_symref(const char *src, const char *prefix)
 	int flag;
 	const char *dst, *cp;
 
-	dst = resolve_ref(src, sha1, 0, &flag);
+	dst = resolve_ref(src, sha1, 0, &flag, 0);
 	if (!(dst && (flag & REF_ISSYMREF)))
 		return NULL;
 	if (prefix && (cp = skip_prefix(dst, prefix)))
@@ -688,7 +688,7 @@ 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_ref("HEAD", head_sha1, 0, NULL, 0);
 	if (!head)
 		die(_("Failed to resolve HEAD as a valid ref."));
 	head = xstrdup(head);
diff --git a/builtin/checkout.c b/builtin/checkout.c
index beeaee4..f92c737 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -699,7 +699,7 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
 	unsigned char rev[20];
 	int flag;
 	memset(&old, 0, sizeof(old));
-	old.path = xstrdup(resolve_ref("HEAD", rev, 0, &flag));
+	old.path = xstrdup(resolve_ref("HEAD", rev, 0, &flag, 0));
 	old.commit = lookup_commit_reference_gently(rev, 1);
 	if (!(flag & REF_ISSYMREF)) {
 		free((char *)old.path);
diff --git a/builtin/commit.c b/builtin/commit.c
index c46f2d1..11ae005 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1259,7 +1259,7 @@ static void print_summary(const char *prefix, const unsigned char *sha1,
 	struct commit *commit;
 	struct strbuf format = STRBUF_INIT;
 	unsigned char junk_sha1[20];
-	const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL);
+	const char *head = resolve_ref("HEAD", junk_sha1, 0, NULL, 0);
 	struct pretty_print_context pctx = {0};
 	struct strbuf author_ident = STRBUF_INIT;
 	struct strbuf committer_ident = STRBUF_INIT;
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 7e2f225..c80f4b7 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -263,7 +263,7 @@ static int do_fmt_merge_msg(int merge_title, struct strbuf *in,
 	const char *current_branch;
 
 	/* get current branch */
-	current_branch = resolve_ref("HEAD", head_sha1, 1, NULL);
+	current_branch = resolve_ref("HEAD", head_sha1, 1, NULL, 0);
 	if (!current_branch)
 		die("No current branch");
 	if (!prefixcmp(current_branch, "refs/heads/"))
diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index d90e5d2..09d7d6b 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -629,7 +629,7 @@ 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);
+		symref = resolve_ref(ref->refname, unused1, 1, NULL, 0);
 		if (symref)
 			ref->symref = xstrdup(symref);
 		else
diff --git a/builtin/fsck.c b/builtin/fsck.c
index df1a88b..4d3d87e 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -532,7 +532,7 @@ static int fsck_head_link(void)
 	if (verbose)
 		fprintf(stderr, "Checking HEAD link\n");
 
-	head_points_at = resolve_ref("HEAD", head_sha1, 0, &flag);
+	head_points_at = resolve_ref("HEAD", head_sha1, 0, &flag, 0);
 	if (!head_points_at)
 		return error("Invalid HEAD");
 	if (!strcmp(head_points_at, "HEAD"))
diff --git a/builtin/merge.c b/builtin/merge.c
index 42b4f9e..d9c7a80 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -1095,7 +1095,7 @@ 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);
+	branch = resolve_ref("HEAD", head_sha1, 0, &flag, 0);
 	if (branch && !prefixcmp(branch, "refs/heads/"))
 		branch += 11;
 	if (!branch || is_null_sha1(head_sha1))
diff --git a/builtin/notes.c b/builtin/notes.c
index f8e437d..9c70d8f 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -825,7 +825,7 @@ 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 = resolve_ref("NOTES_MERGE_REF", sha1, 0, NULL, 0);
 	if (!o->local_ref)
 		die("Failed to resolve NOTES_MERGE_REF");
 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index 7ec68a1..903f2c5 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -571,7 +571,7 @@ static void check_aliased_update(struct command *cmd, struct string_list *list)
 	int flag;
 
 	strbuf_addf(&buf, "%s%s", get_git_namespace(), cmd->ref_name);
-	dst_name = resolve_ref(buf.buf, sha1, 0, &flag);
+	dst_name = resolve_ref(buf.buf, sha1, 0, &flag, 0);
 	strbuf_release(&buf);
 
 	if (!(flag & REF_ISSYMREF))
@@ -695,7 +695,7 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
 
 	check_aliased_updates(commands);
 
-	head_name = resolve_ref("HEAD", sha1, 0, NULL);
+	head_name = resolve_ref("HEAD", sha1, 0, NULL, 0);
 
 	for (cmd = commands; cmd; cmd = cmd->next)
 		if (!cmd->skip_update)
diff --git a/builtin/remote.c b/builtin/remote.c
index 407abfb..4a3b529 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -573,7 +573,7 @@ static int read_remote_branches(const char *refname,
 	strbuf_addf(&buf, "refs/remotes/%s/", rename->old);
 	if (!prefixcmp(refname, buf.buf)) {
 		item = string_list_append(rename->remote_branches, xstrdup(refname));
-		symref = resolve_ref(refname, orig_sha1, 1, &flag);
+		symref = resolve_ref(refname, orig_sha1, 1, &flag, 0);
 		if (flag & REF_ISSYMREF)
 			item->util = xstrdup(symref);
 		else
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 4b480d7..d8282ad 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -728,7 +728,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 			static const char *fake_av[2];
 			const char *refname;
 
-			refname = resolve_ref("HEAD", sha1, 1, NULL);
+			refname = resolve_ref("HEAD", sha1, 1, NULL, 0);
 			fake_av[0] = xstrdup(refname);
 			fake_av[1] = NULL;
 			av = fake_av;
@@ -791,7 +791,7 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
 		}
 	}
 
-	head_p = resolve_ref("HEAD", head_sha1, 1, NULL);
+	head_p = resolve_ref("HEAD", head_sha1, 1, NULL, 0);
 	if (head_p) {
 		head_len = strlen(head_p);
 		memcpy(head, head_p, head_len + 1);
diff --git a/builtin/symbolic-ref.c b/builtin/symbolic-ref.c
index dea849c..50cbdd1 100644
--- a/builtin/symbolic-ref.c
+++ b/builtin/symbolic-ref.c
@@ -12,7 +12,7 @@ static void check_symref(const char *HEAD, int quiet)
 {
 	unsigned char sha1[20];
 	int flag;
-	const char *refs_heads_master = resolve_ref(HEAD, sha1, 0, &flag);
+	const char *refs_heads_master = resolve_ref(HEAD, sha1, 0, &flag, 0);
 
 	if (!refs_heads_master)
 		die("No such ref: %s", HEAD);
diff --git a/cache.h b/cache.h
index 5badece..b2f0d56 100644
--- a/cache.h
+++ b/cache.h
@@ -866,7 +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_ref(const char *ref, unsigned char *sha1, int reading, int *flag, int alloc);
 
 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 5d81d39..f71cca6 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -50,7 +50,7 @@ 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 = resolve_ref(ref, sha1, 1, NULL, 0);
 		if (name)
 			for_each_reflog_ent(name, read_one_reflog, reflogs);
 	}
@@ -168,7 +168,7 @@ 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);
+			const char *head = resolve_ref("HEAD", sha1, 0, NULL, 0);
 			if (!head)
 				die ("No current branch");
 			free(branch);
diff --git a/refs.c b/refs.c
index 44c1c86..0387490 100644
--- a/refs.c
+++ b/refs.c
@@ -361,7 +361,7 @@ static int warn_if_dangling_symref(const char *refname, const unsigned char *sha
 	if (!(flags & REF_ISSYMREF))
 		return 0;
 
-	resolves_to = resolve_ref(refname, junk, 0, NULL);
+	resolves_to = resolve_ref(refname, junk, 0, NULL, 0);
 	if (!resolves_to || strcmp(resolves_to, d->refname))
 		return 0;
 
@@ -497,16 +497,19 @@ static int get_packed_ref(const char *ref, unsigned char *sha1)
 	return -1;
 }
 
-const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
+char *resolve_ref(const char *ref_ro, unsigned char *sha1, int reading, int *flag, int alloc)
 {
 	int depth = MAXDEPTH;
 	ssize_t len;
+	char *ref;
 	char buffer[256];
 	static char ref_buffer[256];
 
 	if (flag)
 		*flag = 0;
 
+	ref = strcpy(ref_buffer, ref_ro);
+
 	if (check_refname_format(ref, REFNAME_ALLOW_ONELEVEL))
 		return NULL;
 
@@ -531,14 +534,14 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
 			if (!get_packed_ref(ref, sha1)) {
 				if (flag)
 					*flag |= REF_ISPACKED;
-				return ref;
+				goto done;
 			}
 			/* The reference is not a packed reference, either. */
 			if (reading) {
 				return NULL;
 			} else {
 				hashclr(sha1);
-				return ref;
+				goto done;
 			}
 		}
 
@@ -602,7 +605,9 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
 			*flag |= REF_ISBROKEN;
 		return NULL;
 	}
-	return ref;
+
+done:
+	return alloc ? xstrdup(ref) : ref;
 }
 
 /* The argument to filter_refs */
@@ -614,7 +619,7 @@ struct ref_filter {
 
 int read_ref_full(const char *ref, unsigned char *sha1, int reading, int *flags)
 {
-	if (resolve_ref(ref, sha1, reading, flags))
+	if (resolve_ref(ref, sha1, reading, flags, 0))
 		return 0;
 	return -1;
 }
@@ -1118,7 +1123,7 @@ int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
 
 		this_result = refs_found ? sha1_from_ref : sha1;
 		mksnpath(fullref, sizeof(fullref), *p, len, str);
-		r = resolve_ref(fullref, this_result, 1, &flag);
+		r = resolve_ref(fullref, this_result, 1, &flag, 0);
 		if (r) {
 			if (!refs_found++)
 				*ref = xstrdup(r);
@@ -1148,7 +1153,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
 		const char *ref, *it;
 
 		mksnpath(path, sizeof(path), *p, len, str);
-		ref = resolve_ref(path, hash, 1, NULL);
+		ref = resolve_ref(path, hash, 1, NULL, 0);
 		if (!ref)
 			continue;
 		if (!stat(git_path("logs/%s", path), &st) &&
@@ -1184,7 +1189,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
 	lock = xcalloc(1, sizeof(struct ref_lock));
 	lock->lock_fd = -1;
 
-	ref = resolve_ref(ref, lock->old_sha1, mustexist, &type);
+	ref = resolve_ref(ref, lock->old_sha1, mustexist, &type, 0);
 	if (!ref && errno == EISDIR) {
 		/* we are trying to lock foo but we used to
 		 * have foo/bar which now does not exist;
@@ -1197,7 +1202,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
 			error("there are still refs under '%s'", orig_ref);
 			goto error_return;
 		}
-		ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, &type);
+		ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, &type, 0);
 	}
 	if (type_p)
 	    *type_p = type;
@@ -1360,7 +1365,7 @@ int rename_ref(const char *oldref, const char *newref, const char *logmsg)
 	if (log && S_ISLNK(loginfo.st_mode))
 		return error("reflog for %s is a symlink", oldref);
 
-	symref = resolve_ref(oldref, orig_sha1, 1, &flag);
+	symref = resolve_ref(oldref, orig_sha1, 1, &flag, 0);
 	if (flag & REF_ISSYMREF)
 		return error("refname %s is a symbolic ref, renaming it is not supported",
 			oldref);
@@ -1649,7 +1654,7 @@ int write_ref_sha1(struct ref_lock *lock,
 		unsigned char head_sha1[20];
 		int head_flag;
 		const char *head_ref;
-		head_ref = resolve_ref("HEAD", head_sha1, 1, &head_flag);
+		head_ref = resolve_ref("HEAD", head_sha1, 1, &head_flag, 0);
 		if (head_ref && (head_flag & REF_ISSYMREF) &&
 		    !strcmp(head_ref, lock->ref_name))
 			log_ref_write("HEAD", lock->old_sha1, sha1, logmsg);
@@ -1986,7 +1991,7 @@ int update_ref(const char *action, const char *refname,
 int ref_exists(const char *refname)
 {
 	unsigned char sha1[20];
-	return !!resolve_ref(refname, sha1, 1, NULL);
+	return !!resolve_ref(refname, sha1, 1, NULL, 0);
 }
 
 struct ref *find_ref_by_name(const struct ref *list, const char *name)
diff --git a/remote.c b/remote.c
index 6655bb0..e776ba3 100644
--- a/remote.c
+++ b/remote.c
@@ -482,7 +482,7 @@ static void read_config(void)
 		return;
 	default_remote_name = xstrdup("origin");
 	current_branch = NULL;
-	head_ref = resolve_ref("HEAD", sha1, 0, &flag);
+	head_ref = resolve_ref("HEAD", sha1, 0, &flag, 0);
 	if (head_ref && (flag & REF_ISSYMREF) &&
 	    !prefixcmp(head_ref, "refs/heads/")) {
 		current_branch =
@@ -1007,7 +1007,7 @@ static char *guess_ref(const char *name, struct ref *peer)
 	struct strbuf buf = STRBUF_INIT;
 	unsigned char sha1[20];
 
-	const char *r = resolve_ref(peer->name, sha1, 1, NULL);
+	const char *r = resolve_ref(peer->name, sha1, 1, NULL, 0);
 	if (!r)
 		return NULL;
 
@@ -1058,7 +1058,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
 		unsigned char sha1[20];
 		int flag;
 
-		dst_value = resolve_ref(matched_src->name, sha1, 1, &flag);
+		dst_value = resolve_ref(matched_src->name, sha1, 1, &flag, 0);
 		if (!dst_value ||
 		    ((flag & REF_ISSYMREF) &&
 		     prefixcmp(dst_value, "refs/heads/")))
diff --git a/transport.c b/transport.c
index 51814b5..063c285 100644
--- a/transport.c
+++ b/transport.c
@@ -163,7 +163,7 @@ static void set_upstreams(struct transport *transport, struct ref *refs,
 		/* Follow symbolic refs (mainly for HEAD). */
 		localname = ref->peer_ref->name;
 		remotename = ref->name;
-		tmp = resolve_ref(localname, sha, 1, &flag);
+		tmp = resolve_ref(localname, sha, 1, &flag, 0);
 		if (tmp && flag & REF_ISSYMREF &&
 			!prefixcmp(tmp, "refs/heads/"))
 			localname = tmp;
diff --git a/wt-status.c b/wt-status.c
index 70fdb76..96dc603 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -119,7 +119,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);
+	head = resolve_ref("HEAD", sha1, 0, NULL, 0);
 	s->branch = head ? xstrdup(head) : NULL;
 	s->reference = "HEAD";
 	s->fp = stdout;
-- 
1.7.4.74.g639db