git_snpath(): retire and replace with strbuf_git_path()
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>
Sun, 30 Nov 2014 08:24:28 +0000 (15:24 +0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 1 Dec 2014 19:00:11 +0000 (11:00 -0800)
In the previous patch, git_snpath() is modified to allocate a new
strbuf buffer because vsnpath() needs that. But that makes it
awkward because git_snpath() receives a pre-allocated buffer from
outside and has to copy data back. Rename it to strbuf_git_path()
and make it receive strbuf directly.

Using git_path() in update_refs_for_switch() which used to call
git_snpath() is safe because that function and all of its callers do
not keep any pointer to the round-robin buffer pool allocated by
get_pathname().

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
builtin/checkout.c
cache.h
path.c
refs.c
refs.h
index c600ec14c71dc100669f57fbc989480e9a799e73..195aca7257fe2a6b52fbee5f21f5ad785be57991 100644 (file)
@@ -588,18 +588,21 @@ static void update_refs_for_switch(const struct checkout_opts *opts,
                if (opts->new_orphan_branch) {
                        if (opts->new_branch_log && !log_all_ref_updates) {
                                int temp;
-                               char log_file[PATH_MAX];
-                               const char *ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch);
+                               struct strbuf log_file = STRBUF_INIT;
+                               int ret;
+                               const char *ref_name;
 
+                               ref_name = mkpath("refs/heads/%s", opts->new_orphan_branch);
                                temp = log_all_ref_updates;
                                log_all_ref_updates = 1;
-                               if (log_ref_setup(ref_name, log_file, sizeof(log_file))) {
+                               ret = log_ref_setup(ref_name, &log_file);
+                               log_all_ref_updates = temp;
+                               strbuf_release(&log_file);
+                               if (ret) {
                                        fprintf(stderr, _("Can not do reflog for '%s'\n"),
                                            opts->new_orphan_branch);
-                                       log_all_ref_updates = temp;
                                        return;
                                }
-                               log_all_ref_updates = temp;
                        }
                }
                else
diff --git a/cache.h b/cache.h
index dbee0a30b9379ebc4e3f9a3578fc9d330de983bf..56643cfac3f80bb1b20f29531f4bf4a774b54e4e 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -679,8 +679,8 @@ extern int check_repository_format(void);
 
 extern char *mksnpath(char *buf, size_t n, const char *fmt, ...)
        __attribute__((format (printf, 3, 4)));
-extern char *git_snpath(char *buf, size_t n, const char *fmt, ...)
-       __attribute__((format (printf, 3, 4)));
+extern void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
+       __attribute__((format (printf, 2, 3)));
 extern char *git_pathdup(const char *fmt, ...)
        __attribute__((format (printf, 1, 2)));
 extern char *mkpathdup(const char *fmt, ...)
diff --git a/path.c b/path.c
index a7ceea26fbdee5b8f94c5023d1a8de5f1f4a9fa8..47753aaffcb7393233b3b311fc0773ee7938da73 100644 (file)
--- a/path.c
+++ b/path.c
@@ -70,19 +70,12 @@ static void vsnpath(struct strbuf *buf, const char *fmt, va_list args)
        strbuf_cleanup_path(buf);
 }
 
-char *git_snpath(char *buf, size_t n, const char *fmt, ...)
+void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
 {
-       struct strbuf sb = STRBUF_INIT;
        va_list args;
        va_start(args, fmt);
-       vsnpath(&sb, fmt, args);
+       vsnpath(sb, fmt, args);
        va_end(args);
-       if (sb.len >= n)
-               strlcpy(buf, bad_path, n);
-       else
-               memcpy(buf, sb.buf, sb.len + 1);
-       strbuf_release(&sb);
-       return buf;
 }
 
 char *git_pathdup(const char *fmt, ...)
diff --git a/refs.c b/refs.c
index 23617e0c568aab244d17b1744c180ea9eb7c50e6..5ed991bd92856bc8b2c5978923a118b8122a6eb5 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1444,7 +1444,11 @@ static int resolve_missing_loose_ref(const char *refname,
 }
 
 /* This function needs to return a meaningful errno on failure */
-const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned char *sha1, int *flags)
+static const char *resolve_ref_unsafe_1(const char *refname,
+                                       int resolve_flags,
+                                       unsigned char *sha1,
+                                       int *flags,
+                                       struct strbuf *sb_path)
 {
        int depth = MAXDEPTH;
        ssize_t len;
@@ -1475,7 +1479,7 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
                bad_name = 1;
        }
        for (;;) {
-               char path[PATH_MAX];
+               const char *path;
                struct stat st;
                char *buf;
                int fd;
@@ -1485,7 +1489,9 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
                        return NULL;
                }
 
-               git_snpath(path, sizeof(path), "%s", refname);
+               strbuf_reset(sb_path);
+               strbuf_git_path(sb_path, "%s", refname);
+               path = sb_path->buf;
 
                /*
                 * We might have to loop back here to avoid a race
@@ -1612,6 +1618,16 @@ const char *resolve_ref_unsafe(const char *refname, int resolve_flags, unsigned
        }
 }
 
+const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
+                              unsigned char *sha1, int *flags)
+{
+       struct strbuf sb_path = STRBUF_INIT;
+       const char *ret = resolve_ref_unsafe_1(refname, resolve_flags,
+                                              sha1, flags, &sb_path);
+       strbuf_release(&sb_path);
+       return ret;
+}
+
 char *resolve_refdup(const char *ref, int resolve_flags, unsigned char *sha1, int *flags)
 {
        const char *ret = resolve_ref_unsafe(ref, resolve_flags, sha1, flags);
@@ -2941,11 +2957,15 @@ static int copy_msg(char *buf, const char *msg)
 }
 
 /* This function must set a meaningful errno on failure */
-int log_ref_setup(const char *refname, char *logfile, int bufsize)
+int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
 {
        int logfd, oflags = O_APPEND | O_WRONLY;
+       char *logfile;
 
-       git_snpath(logfile, bufsize, "logs/%s", refname);
+       strbuf_git_path(sb_logfile, "logs/%s", refname);
+       logfile = sb_logfile->buf;
+       /* make sure the rest of the function can't change "logfile" */
+       sb_logfile = NULL;
        if (log_all_ref_updates &&
            (starts_with(refname, "refs/heads/") ||
             starts_with(refname, "refs/remotes/") ||
@@ -2990,22 +3010,26 @@ int log_ref_setup(const char *refname, char *logfile, int bufsize)
        return 0;
 }
 
-static int log_ref_write(const char *refname, const unsigned char *old_sha1,
-                        const unsigned char *new_sha1, const char *msg)
+static int log_ref_write_1(const char *refname, const unsigned char *old_sha1,
+                          const unsigned char *new_sha1, const char *msg,
+                          struct strbuf *sb_log_file)
 {
        int logfd, result, written, oflags = O_APPEND | O_WRONLY;
        unsigned maxlen, len;
        int msglen;
-       char log_file[PATH_MAX];
+       const char *log_file;
        char *logrec;
        const char *committer;
 
        if (log_all_ref_updates < 0)
                log_all_ref_updates = !is_bare_repository();
 
-       result = log_ref_setup(refname, log_file, sizeof(log_file));
+       result = log_ref_setup(refname, sb_log_file);
        if (result)
                return result;
+       log_file = sb_log_file->buf;
+       /* make sure the rest of the function can't change "log_file" */
+       sb_log_file = NULL;
 
        logfd = open(log_file, oflags);
        if (logfd < 0)
@@ -3038,6 +3062,15 @@ static int log_ref_write(const char *refname, const unsigned char *old_sha1,
        return 0;
 }
 
+static int log_ref_write(const char *refname, const unsigned char *old_sha1,
+                        const unsigned char *new_sha1, const char *msg)
+{
+       struct strbuf sb = STRBUF_INIT;
+       int ret = log_ref_write_1(refname, old_sha1, new_sha1, msg, &sb);
+       strbuf_release(&sb);
+       return ret;
+}
+
 int is_branch(const char *refname)
 {
        return !strcmp(refname, "HEAD") || starts_with(refname, "refs/heads/");
diff --git a/refs.h b/refs.h
index 2bc3556874a7b1cbccb4cebf4e3dc2fa13cc780f..1f882209595485cb7ba164a5750511bf46fb0c17 100644 (file)
--- a/refs.h
+++ b/refs.h
@@ -210,7 +210,7 @@ extern void unlock_ref(struct ref_lock *lock);
 /*
  * Setup reflog before using. Set errno to something meaningful on failure.
  */
-int log_ref_setup(const char *refname, char *logfile, int bufsize);
+int log_ref_setup(const char *refname, struct strbuf *logfile);
 
 /** Reads log for the value of ref during at_time. **/
 extern int read_ref_at(const char *refname, unsigned int flags,