From 9d33f7c22fda81f7be8a7aa1576e6d399d3b45ec Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 16 Jul 2009 16:25:18 -0500 Subject: [PATCH 1/3] refs.c: release file descriptor on error return Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- refs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/refs.c b/refs.c index 90163bdc5..bb0762ee2 100644 --- a/refs.c +++ b/refs.c @@ -1525,8 +1525,10 @@ int for_each_recent_reflog_ent(const char *ref, each_reflog_ent_fn fn, long ofs, if (fstat(fileno(logfp), &statbuf) || statbuf.st_size < ofs || fseek(logfp, -ofs, SEEK_END) || - fgets(buf, sizeof(buf), logfp)) + fgets(buf, sizeof(buf), logfp)) { + fclose(logfp); return -1; + } } while (fgets(buf, sizeof(buf), logfp)) { From b45a09c4b4a80ccc6eeb0f390ab8f4eb6f31c922 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 16 Jul 2009 16:25:19 -0500 Subject: [PATCH 2/3] sha1_name.c: avoid unnecessary strbuf_release When we fall back to a standard for_each_reflog_ent() after failing to find the nth branch switch (or if we had a short reflog) with the call to for_each_recent_reflog_ent(), we do not need to free the memory allocated for our strbuf's since a strbuf_reset() will be performed in grab_nth_branch_switch() before assigning to the entry. Plus, the strbuf_release() negates the non-zero hint we initially gave to strbuf_init() just above these lines. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- sha1_name.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sha1_name.c b/sha1_name.c index 904bcd96a..44bb62d27 100644 --- a/sha1_name.c +++ b/sha1_name.c @@ -777,8 +777,6 @@ int interpret_branch_name(const char *name, struct strbuf *buf) for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb); if (cb.cnt < nth) { cb.cnt = 0; - for (i = 0; i < nth; i++) - strbuf_release(&cb.buf[i]); for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb); } if (cb.cnt < nth) From 78d3b06e0f5e6aaea001ee8e3e7c8e401dc4b244 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 18 Jul 2009 12:26:38 -0700 Subject: [PATCH 3/3] checkout -f: deal with a D/F conflict entry correctly When we switch branches with "checkout -f", unpack_trees() feeds two cache_entries to oneway_merge() function in its src[] array argument. The zeroth entry comes from the current index, and the first entry represents what the merge result should be, taken from the tree recorded in the commit we are switching to. When we have a blob (either regular file or a symlink) in the index and in the work tree at path "foo", and the switched-to tree has "foo/bar", i.e. "foo" becomes a directory, src[0] is obviously that blob currently registered at "foo". Even though we do not have anything at "foo" in the switched-to tree, src[1] is _not_ NULL in this case. The unpack_trees() machinery places a special marker df_conflict_entry to signal that no blob exists at "foo", but it will become a directory that may have somthing underneath it (namely "foo/bar"), so a usual 3-way merge can notice the situation. But oneway_merge() codepath failed to notice this and passed the special marker directly to merged_entry(). This happens to remove the "foo" in the end because the df_conflict_entry does not have any name (hence the "error" message) and its addition in add_index_entry() is rejected, but it is wrong. Signed-off-by: Junio C Hamano Acked-by: Linus Torvalds --- unpack-trees.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpack-trees.c b/unpack-trees.c index aaacaf101..a0697d241 100644 --- a/unpack-trees.c +++ b/unpack-trees.c @@ -982,7 +982,7 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o) return error("Cannot do a oneway merge of %d trees", o->merge_size); - if (!a) + if (!a || a == o->df_conflict_entry) return deleted_entry(old, old, o); if (old && same(old, a)) {