Merge branch 'tb/t0027-crlf'
[gitweb.git] / refs.c
diff --git a/refs.c b/refs.c
index 91c88bad4a764e20c810276fc5b9c1689ba328c3..132eff52ca4092eae4c2e1c0f86a8c380f88778a 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -1602,16 +1602,15 @@ static int resolve_missing_loose_ref(const char *refname,
 }
 
 /* This function needs to return a meaningful errno on failure */
-static const char *resolve_ref_unsafe_1(const char *refname,
-                                       int resolve_flags,
-                                       unsigned char *sha1,
-                                       int *flags,
-                                       struct strbuf *sb_path)
+static const char *resolve_ref_1(const char *refname,
+                                int resolve_flags,
+                                unsigned char *sha1,
+                                int *flags,
+                                struct strbuf *sb_refname,
+                                struct strbuf *sb_path,
+                                struct strbuf *sb_contents)
 {
        int depth = MAXDEPTH;
-       ssize_t len;
-       char buffer[256];
-       static char refname_buffer[256];
        int bad_name = 0;
 
        if (flags)
@@ -1677,19 +1676,18 @@ static const char *resolve_ref_unsafe_1(const char *refname,
 
                /* Follow "normalized" - ie "refs/.." symlinks by hand */
                if (S_ISLNK(st.st_mode)) {
-                       len = readlink(path, buffer, sizeof(buffer)-1);
-                       if (len < 0) {
+                       strbuf_reset(sb_contents);
+                       if (strbuf_readlink(sb_contents, path, 0) < 0) {
                                if (errno == ENOENT || errno == EINVAL)
                                        /* inconsistent with lstat; retry */
                                        goto stat_ref;
                                else
                                        return NULL;
                        }
-                       buffer[len] = 0;
-                       if (starts_with(buffer, "refs/") &&
-                                       !check_refname_format(buffer, 0)) {
-                               strcpy(refname_buffer, buffer);
-                               refname = refname_buffer;
+                       if (starts_with(sb_contents->buf, "refs/") &&
+                           !check_refname_format(sb_contents->buf, 0)) {
+                               strbuf_swap(sb_refname, sb_contents);
+                               refname = sb_refname->buf;
                                if (flags)
                                        *flags |= REF_ISSYMREF;
                                if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
@@ -1718,28 +1716,26 @@ static const char *resolve_ref_unsafe_1(const char *refname,
                        else
                                return NULL;
                }
-               len = read_in_full(fd, buffer, sizeof(buffer)-1);
-               if (len < 0) {
+               strbuf_reset(sb_contents);
+               if (strbuf_read(sb_contents, fd, 256) < 0) {
                        int save_errno = errno;
                        close(fd);
                        errno = save_errno;
                        return NULL;
                }
                close(fd);
-               while (len && isspace(buffer[len-1]))
-                       len--;
-               buffer[len] = '\0';
+               strbuf_rtrim(sb_contents);
 
                /*
                 * Is it a symbolic ref?
                 */
-               if (!starts_with(buffer, "ref:")) {
+               if (!starts_with(sb_contents->buf, "ref:")) {
                        /*
                         * Please note that FETCH_HEAD has a second
                         * line containing other data.
                         */
-                       if (get_sha1_hex(buffer, sha1) ||
-                           (buffer[40] != '\0' && !isspace(buffer[40]))) {
+                       if (get_sha1_hex(sb_contents->buf, sha1) ||
+                           (sb_contents->buf[40] != '\0' && !isspace(sb_contents->buf[40]))) {
                                if (flags)
                                        *flags |= REF_ISBROKEN;
                                errno = EINVAL;
@@ -1754,10 +1750,12 @@ static const char *resolve_ref_unsafe_1(const char *refname,
                }
                if (flags)
                        *flags |= REF_ISSYMREF;
-               buf = buffer + 4;
+               buf = sb_contents->buf + 4;
                while (isspace(*buf))
                        buf++;
-               refname = strcpy(refname_buffer, buf);
+               strbuf_reset(sb_refname);
+               strbuf_addstr(sb_refname, buf);
+               refname = sb_refname->buf;
                if (resolve_flags & RESOLVE_REF_NO_RECURSE) {
                        hashclr(sha1);
                        return refname;
@@ -1779,10 +1777,15 @@ static const char *resolve_ref_unsafe_1(const char *refname,
 const char *resolve_ref_unsafe(const char *refname, int resolve_flags,
                               unsigned char *sha1, int *flags)
 {
+       static struct strbuf sb_refname = STRBUF_INIT;
+       struct strbuf sb_contents = STRBUF_INIT;
        struct strbuf sb_path = STRBUF_INIT;
-       const char *ret = resolve_ref_unsafe_1(refname, resolve_flags,
-                                              sha1, flags, &sb_path);
+       const char *ret;
+
+       ret = resolve_ref_1(refname, resolve_flags, sha1, flags,
+                           &sb_refname, &sb_path, &sb_contents);
        strbuf_release(&sb_path);
+       strbuf_release(&sb_contents);
        return ret;
 }
 
@@ -2222,8 +2225,7 @@ int for_each_glob_ref_in(each_ref_fn fn, const char *pattern,
 
        if (!has_glob_specials(pattern)) {
                /* Append implied '/' '*' if not present. */
-               if (real_pattern.buf[real_pattern.len - 1] != '/')
-                       strbuf_addch(&real_pattern, '/');
+               strbuf_complete(&real_pattern, '/');
                /* No need to check for '*', there is none. */
                strbuf_addch(&real_pattern, '*');
        }
@@ -2730,7 +2732,7 @@ static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)
                int namelen = strlen(entry->name) + 1;
                struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
                hashcpy(n->sha1, entry->u.value.oid.hash);
-               strcpy(n->name, entry->name);
+               memcpy(n->name, entry->name, namelen); /* includes NUL */
                n->next = cb->ref_to_prune;
                cb->ref_to_prune = n;
        }
@@ -3365,10 +3367,10 @@ static int log_ref_write_fd(int fd, const unsigned char *old_sha1,
        msglen = msg ? strlen(msg) : 0;
        maxlen = strlen(committer) + msglen + 100;
        logrec = xmalloc(maxlen);
-       len = sprintf(logrec, "%s %s %s\n",
-                     sha1_to_hex(old_sha1),
-                     sha1_to_hex(new_sha1),
-                     committer);
+       len = xsnprintf(logrec, maxlen, "%s %s %s\n",
+                       sha1_to_hex(old_sha1),
+                       sha1_to_hex(new_sha1),
+                       committer);
        if (msglen)
                len += copy_msg(logrec + len - 1, msg) - 1;
 
@@ -4020,10 +4022,10 @@ void ref_transaction_free(struct ref_transaction *transaction)
 static struct ref_update *add_update(struct ref_transaction *transaction,
                                     const char *refname)
 {
-       size_t len = strlen(refname);
-       struct ref_update *update = xcalloc(1, sizeof(*update) + len + 1);
+       size_t len = strlen(refname) + 1;
+       struct ref_update *update = xcalloc(1, sizeof(*update) + len);
 
-       strcpy((char *)update->refname, refname);
+       memcpy((char *)update->refname, refname, len); /* includes NUL */
        ALLOC_GROW(transaction->updates, transaction->nr + 1, transaction->alloc);
        transaction->updates[transaction->nr++] = update;
        return update;