mergetool: Add a test for running mergetool in a sub-directory
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 156714e54ee6c980a48f01610d78d10301e849b7..33ced65a7801f8653d608a9580e237ce8df39ae2 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -390,6 +390,18 @@ int resolve_gitlink_ref(const char *path, const char *refname, unsigned char *re
        return retval;
 }
 
+/*
+ * If the "reading" argument is set, this function finds out what _object_
+ * the ref points at by "reading" the ref.  The ref, if it is not symbolic,
+ * has to exist, and if it is symbolic, it has to point at an existing ref,
+ * because the "read" goes through the symref to the ref it points at.
+ *
+ * The access that is not "reading" may often be "writing", but does not
+ * have to; it can be merely checking _where it leads to_. If it is a
+ * prelude to "writing" to the ref, a write to a symref that points at
+ * yet-to-be-born ref will create the real ref pointed by the symref.
+ * reading=0 allows the caller to check where such a symref leads to.
+ */
 const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
 {
        int depth = MAXDEPTH;
@@ -401,7 +413,7 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
                *flag = 0;
 
        for (;;) {
-               const char *path = git_path("%s", ref);
+               char path[PATH_MAX];
                struct stat st;
                char *buf;
                int fd;
@@ -409,13 +421,8 @@ const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *
                if (--depth < 0)
                        return NULL;
 
-               /* Special case: non-existing file.
-                * Not having the refs/heads/new-branch is OK
-                * if we are writing into it, so is .git/HEAD
-                * that points at refs/heads/master still to be
-                * born.  It is NOT OK if we are resolving for
-                * reading.
-                */
+               git_snpath(path, sizeof(path), "%s", ref);
+               /* Special case: non-existing file. */
                if (lstat(path, &st) < 0) {
                        struct ref_list *list = get_packed_refs();
                        while (list) {
@@ -788,10 +795,10 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
        char *ref_file;
        const char *orig_ref = ref;
        struct ref_lock *lock;
-       struct stat st;
        int last_errno = 0;
        int type, lflags;
        int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
+       int missing = 0;
 
        lock = xcalloc(1, sizeof(struct ref_lock));
        lock->lock_fd = -1;
@@ -819,12 +826,13 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
                        orig_ref, strerror(errno));
                goto error_return;
        }
+       missing = is_null_sha1(lock->old_sha1);
        /* When 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.
         */
-       if (is_null_sha1(lock->old_sha1) &&
+       if (missing &&
             !is_refname_available(ref, NULL, get_packed_refs(), 0))
                goto error_return;
 
@@ -838,7 +846,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char
        lock->ref_name = xstrdup(ref);
        lock->orig_ref_name = xstrdup(orig_ref);
        ref_file = git_path("%s", ref);
-       if (lstat(ref_file, &st) && errno == ENOENT)
+       if (missing)
                lock->force_write = 1;
        if ((flags & REF_NODEREF) && (type & REF_ISSYMREF))
                lock->force_write = 1;
@@ -932,7 +940,7 @@ int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
                        lock->lk->filename[i] = 0;
                        path = lock->lk->filename;
                } else {
-                       path = git_path(refname);
+                       path = git_path("%s", refname);
                }
                err = unlink(path);
                if (err && errno != ENOENT) {
@@ -1136,13 +1144,14 @@ static int log_ref_write(const char *ref_name, const unsigned char *old_sha1,
        int logfd, written, oflags = O_APPEND | O_WRONLY;
        unsigned maxlen, len;
        int msglen;
-       char *log_file, *logrec;
+       char log_file[PATH_MAX];
+       char *logrec;
        const char *committer;
 
        if (log_all_ref_updates < 0)
                log_all_ref_updates = !is_bare_repository();
 
-       log_file = git_path("logs/%s", ref_name);
+       git_snpath(log_file, sizeof(log_file), "logs/%s", ref_name);
 
        if (log_all_ref_updates &&
            (!prefixcmp(ref_name, "refs/heads/") ||
@@ -1271,7 +1280,7 @@ int create_symref(const char *ref_target, const char *refs_heads_master,
        const char *lockpath;
        char ref[1000];
        int fd, len, written;
-       char *git_HEAD = xstrdup(git_path("%s", ref_target));
+       char *git_HEAD = git_pathdup("%s", ref_target);
        unsigned char old_sha1[20], new_sha1[20];
 
        if (logmsg && read_ref(ref_target, old_sha1))