Add branch --set-upstream
[gitweb.git] / strbuf.c
index 720737d856b694bc5239f0c18af372959c99e744..a6153dca278abe957254fa091fdcd8eb13b90b25 100644 (file)
--- a/strbuf.c
+++ b/strbuf.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "refs.h"
 
 int prefixcmp(const char *str, const char *prefix)
 {
@@ -139,14 +140,11 @@ void strbuf_list_free(struct strbuf **sbs)
 
 int strbuf_cmp(const struct strbuf *a, const struct strbuf *b)
 {
-       int cmp;
-       if (a->len < b->len) {
-               cmp = memcmp(a->buf, b->buf, a->len);
-               return cmp ? cmp : -1;
-       } else {
-               cmp = memcmp(a->buf, b->buf, b->len);
-               return cmp ? cmp : a->len != b->len;
-       }
+       int len = a->len < b->len ? a->len: b->len;
+       int cmp = memcmp(a->buf, b->buf, len);
+       if (cmp)
+               return cmp;
+       return a->len < b->len ? -1: a->len != b->len;
 }
 
 void strbuf_splice(struct strbuf *sb, size_t pos, size_t len,
@@ -237,21 +235,40 @@ void strbuf_expand(struct strbuf *sb, const char *format, expand_fn_t fn,
        }
 }
 
+size_t strbuf_expand_dict_cb(struct strbuf *sb, const char *placeholder,
+               void *context)
+{
+       struct strbuf_expand_dict_entry *e = context;
+       size_t len;
+
+       for (; e->placeholder && (len = strlen(e->placeholder)); e++) {
+               if (!strncmp(placeholder, e->placeholder, len)) {
+                       if (e->value)
+                               strbuf_addstr(sb, e->value);
+                       return len;
+               }
+       }
+       return 0;
+}
+
 size_t strbuf_fread(struct strbuf *sb, size_t size, FILE *f)
 {
        size_t res;
+       size_t oldalloc = sb->alloc;
 
        strbuf_grow(sb, size);
        res = fread(sb->buf + sb->len, 1, size, f);
-       if (res > 0) {
+       if (res > 0)
                strbuf_setlen(sb, sb->len + res);
-       }
+       else if (oldalloc == 0)
+               strbuf_release(sb);
        return res;
 }
 
 ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
 {
        size_t oldlen = sb->len;
+       size_t oldalloc = sb->alloc;
 
        strbuf_grow(sb, hint ? hint : 8192);
        for (;;) {
@@ -259,7 +276,10 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
 
                cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1);
                if (cnt < 0) {
-                       strbuf_setlen(sb, oldlen);
+                       if (oldalloc == 0)
+                               strbuf_release(sb);
+                       else
+                               strbuf_setlen(sb, oldlen);
                        return -1;
                }
                if (!cnt)
@@ -272,7 +292,37 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)
        return sb->len - oldlen;
 }
 
-int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
+#define STRBUF_MAXLINK (2*PATH_MAX)
+
+int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint)
+{
+       size_t oldalloc = sb->alloc;
+
+       if (hint < 32)
+               hint = 32;
+
+       while (hint < STRBUF_MAXLINK) {
+               int len;
+
+               strbuf_grow(sb, hint);
+               len = readlink(path, sb->buf, hint);
+               if (len < 0) {
+                       if (errno != ERANGE)
+                               break;
+               } else if (len < hint) {
+                       strbuf_setlen(sb, len);
+                       return 0;
+               }
+
+               /* .. the buffer was too small - try again */
+               hint *= 2;
+       }
+       if (oldalloc == 0)
+               strbuf_release(sb);
+       return -1;
+}
+
+int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term)
 {
        int ch;
 
@@ -282,10 +332,10 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
 
        strbuf_reset(sb);
        while ((ch = fgetc(fp)) != EOF) {
-               if (ch == term)
-                       break;
                strbuf_grow(sb, 1);
                sb->buf[sb->len++] = ch;
+               if (ch == term)
+                       break;
        }
        if (ch == EOF && sb->len == 0)
                return EOF;
@@ -294,6 +344,15 @@ int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
        return 0;
 }
 
+int strbuf_getline(struct strbuf *sb, FILE *fp, int term)
+{
+       if (strbuf_getwholeline(sb, fp, term))
+               return EOF;
+       if (sb->buf[sb->len-1] == term)
+               strbuf_setlen(sb, sb->len-1);
+       return 0;
+}
+
 int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
 {
        int fd, len;
@@ -308,3 +367,19 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
 
        return len;
 }
+
+int strbuf_branchname(struct strbuf *sb, const char *name)
+{
+       int len = strlen(name);
+       if (interpret_branch_name(name, sb) == len)
+               return 0;
+       strbuf_add(sb, name, len);
+       return len;
+}
+
+int strbuf_check_branch_ref(struct strbuf *sb, const char *name)
+{
+       strbuf_branchname(sb, name);
+       strbuf_splice(sb, 0, 0, "refs/heads/", 11);
+       return check_ref_format(sb->buf);
+}