summaryrefslogtreecommitdiff
path: root/refs.c
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-09-30 14:19:25 -0700
committerJunio C Hamano <junkio@cox.net>2006-09-30 15:07:58 -0700
commit22a3844ebada55c207e2b85fb68509a7c9e2b5f0 (patch)
tree8db48be91749565d184b16b4e36ab5d1828e73f1 /refs.c
parent5cc3cef997503e7543d927dbe23daca891131168 (diff)
downloadgit-22a3844ebada55c207e2b85fb68509a7c9e2b5f0.tar.gz
lock_ref_sha1(): check D/F conflict with packed ref when creating.
This makes the ref locking codepath to notice if an existing ref overlaps with the ref we are creating. Signed-off-by: Junio C Hamano <junkio@cox.net>
Diffstat (limited to 'refs.c')
-rw-r--r--refs.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/refs.c b/refs.c
index 157de432ce..2bfa92a8a3 100644
--- a/refs.c
+++ b/refs.c
@@ -588,6 +588,30 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
orig_ref, strerror(errno));
goto error_return;
}
+ if (is_null_sha1(lock->old_sha1)) {
+ /* The ref did not exist and we are creating it.
+ * Make sure there is no existing ref that is packed
+ * whose name begins with our refname, nor a ref whose
+ * name is a proper prefix of our refname.
+ */
+ int namlen = strlen(ref); /* e.g. 'foo/bar' */
+ struct ref_list *list = get_packed_refs();
+ while (list) {
+ /* list->name could be 'foo' or 'foo/bar/baz' */
+ int len = strlen(list->name);
+ int cmplen = (namlen < len) ? namlen : len;
+ const char *lead = (namlen < len) ? list->name : ref;
+
+ if (!strncmp(ref, list->name, cmplen) &&
+ lead[cmplen] == '/') {
+ error("'%s' exists; cannot create '%s'",
+ list->name, ref);
+ goto error_return;
+ }
+ list = list->next;
+ }
+ }
+
lock->lk = xcalloc(1, sizeof(struct lock_file));
lock->ref_name = xstrdup(ref);