Merge branch 'jm/maint-misc-fix' into maint
authorJunio C Hamano <gitster@pobox.com>
Mon, 30 May 2011 07:09:41 +0000 (00:09 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 30 May 2011 07:09:41 +0000 (00:09 -0700)
* jm/maint-misc-fix:
  read_gitfile_gently: use ssize_t to hold read result
  remove tests of always-false condition
  rerere.c: diagnose a corrupt MERGE_RR when hitting EOF between TAB and '\0'

1  2 
fsck.c
rerere.c
setup.c
transport.c

diff --combined fsck.c
--- 1/fsck.c
--- 2/fsck.c
+++ b/fsck.c
@@@ -347,14 -347,26 +347,14 @@@ int fsck_object(struct object *obj, in
  int fsck_error_function(struct object *obj, int type, const char *fmt, ...)
  {
        va_list ap;
 -      int len;
        struct strbuf sb = STRBUF_INIT;
  
-       strbuf_addf(&sb, "object %s:", obj->sha1?sha1_to_hex(obj->sha1):"(null)");
+       strbuf_addf(&sb, "object %s:", sha1_to_hex(obj->sha1));
  
        va_start(ap, fmt);
 -      len = vsnprintf(sb.buf + sb.len, strbuf_avail(&sb), fmt, ap);
 +      strbuf_vaddf(&sb, fmt, ap);
        va_end(ap);
  
 -      if (len < 0)
 -              len = 0;
 -      if (len >= strbuf_avail(&sb)) {
 -              strbuf_grow(&sb, len + 2);
 -              va_start(ap, fmt);
 -              len = vsnprintf(sb.buf + sb.len, strbuf_avail(&sb), fmt, ap);
 -              va_end(ap);
 -              if (len >= strbuf_avail(&sb))
 -                      die("this should not happen, your snprintf is broken");
 -      }
 -
        error("%s", sb.buf);
        strbuf_release(&sb);
        return 1;
diff --combined rerere.c
+++ b/rerere.c
@@@ -7,11 -7,6 +7,11 @@@
  #include "ll-merge.h"
  #include "attr.h"
  
 +#define RESOLVED 0
 +#define PUNTED 1
 +#define THREE_STAGED 2
 +void *RERERE_RESOLVED = &RERERE_RESOLVED;
 +
  /* if rerere_enabled == -1, fall back to detection of .git/rr-cache */
  static int rerere_enabled = -1;
  
@@@ -47,8 -42,14 +47,14 @@@ static void read_rr(struct string_list 
                name = xstrdup(buf);
                if (fgetc(in) != '\t')
                        die("corrupt MERGE_RR");
-               for (i = 0; i < sizeof(buf) && (buf[i] = fgetc(in)); i++)
-                       ; /* do nothing */
+               for (i = 0; i < sizeof(buf); i++) {
+                       int c = fgetc(in);
+                       if (c < 0)
+                               die("corrupt MERGE_RR");
+                       buf[i] = c;
+                       if (c == 0)
+                                break;
+               }
                if (i == sizeof(buf))
                        die("filename too long");
                string_list_insert(rr, buf)->util = name;
@@@ -350,74 -351,21 +356,74 @@@ static int handle_cache(const char *pat
        return hunk_no;
  }
  
 -static int find_conflict(struct string_list *conflict)
 +static int check_one_conflict(int i, int *type)
  {
 -      int i;
 -      if (read_cache() < 0)
 -              return error("Could not read index");
 -      for (i = 0; i+1 < active_nr; i++) {
 +      struct cache_entry *e = active_cache[i];
 +
 +      if (!ce_stage(e)) {
 +              *type = RESOLVED;
 +              return i + 1;
 +      }
 +
 +      *type = PUNTED;
 +      if (ce_stage(e) == 1) {
 +              if (active_nr <= ++i)
 +                      return i + 1;
 +      }
 +
 +      /* Only handle regular files with both stages #2 and #3 */
 +      if (i + 1 < active_nr) {
                struct cache_entry *e2 = active_cache[i];
 -              struct cache_entry *e3 = active_cache[i+1];
 +              struct cache_entry *e3 = active_cache[i + 1];
                if (ce_stage(e2) == 2 &&
                    ce_stage(e3) == 3 &&
 -                  ce_same_name(e2, e3) &&
 +                  ce_same_name(e, e3) &&
                    S_ISREG(e2->ce_mode) &&
 -                  S_ISREG(e3->ce_mode)) {
 -                      string_list_insert(conflict, (const char *)e2->name);
 -                      i++; /* skip over both #2 and #3 */
 +                  S_ISREG(e3->ce_mode))
 +                      *type = THREE_STAGED;
 +      }
 +
 +      /* Skip the entries with the same name */
 +      while (i < active_nr && ce_same_name(e, active_cache[i]))
 +              i++;
 +      return i;
 +}
 +
 +static int find_conflict(struct string_list *conflict)
 +{
 +      int i;
 +      if (read_cache() < 0)
 +              return error("Could not read index");
 +
 +      for (i = 0; i < active_nr;) {
 +              int conflict_type;
 +              struct cache_entry *e = active_cache[i];
 +              i = check_one_conflict(i, &conflict_type);
 +              if (conflict_type == THREE_STAGED)
 +                      string_list_insert(conflict, (const char *)e->name);
 +      }
 +      return 0;
 +}
 +
 +int rerere_remaining(struct string_list *merge_rr)
 +{
 +      int i;
 +      if (read_cache() < 0)
 +              return error("Could not read index");
 +
 +      for (i = 0; i < active_nr;) {
 +              int conflict_type;
 +              struct cache_entry *e = active_cache[i];
 +              i = check_one_conflict(i, &conflict_type);
 +              if (conflict_type == PUNTED)
 +                      string_list_insert(merge_rr, (const char *)e->name);
 +              else if (conflict_type == RESOLVED) {
 +                      struct string_list_item *it;
 +                      it = string_list_lookup(merge_rr, (const char *)e->name);
 +                      if (it != NULL) {
 +                              free(it->util);
 +                              it->util = RERERE_RESOLVED;
 +                      }
                }
        }
        return 0;
@@@ -438,7 -386,7 +444,7 @@@ static int merge(const char *name, cons
                ret = 1;
                goto out;
        }
 -      ret = ll_merge(&result, path, &base, NULL, &cur, "", &other, "", 0);
 +      ret = ll_merge(&result, path, &base, NULL, &cur, "", &other, "", NULL);
        if (!ret) {
                FILE *f;
  
@@@ -590,7 -538,8 +596,7 @@@ static int is_rerere_enabled(void
        if (rerere_enabled < 0)
                return rr_cache_exists;
  
 -      if (!rr_cache_exists &&
 -          (mkdir(rr_cache, 0777) || adjust_shared_perm(rr_cache)))
 +      if (!rr_cache_exists && mkdir_in_gitdir(rr_cache))
                die("Could not create directory %s", rr_cache);
        return 1;
  }
diff --combined setup.c
+++ b/setup.c
@@@ -7,13 -7,10 +7,13 @@@ static int inside_work_tree = -1
  char *prefix_path(const char *prefix, int len, const char *path)
  {
        const char *orig = path;
 -      char *sanitized = xmalloc(len + strlen(path) + 1);
 -      if (is_absolute_path(orig))
 -              strcpy(sanitized, path);
 -      else {
 +      char *sanitized;
 +      if (is_absolute_path(orig)) {
 +              const char *temp = real_path(path);
 +              sanitized = xmalloc(len + strlen(temp) + 1);
 +              strcpy(sanitized, temp);
 +      } else {
 +              sanitized = xmalloc(len + strlen(path) + 1);
                if (len)
                        memcpy(sanitized, prefix, len);
                strcpy(sanitized + len, path);
@@@ -221,7 -218,7 +221,7 @@@ void setup_work_tree(void
        work_tree = get_git_work_tree();
        git_dir = get_git_dir();
        if (!is_absolute_path(git_dir))
 -              git_dir = make_absolute_path(git_dir);
 +              git_dir = real_path(get_git_dir());
        if (!work_tree || chdir(work_tree))
                die("This operation must be run in a work tree");
  
        if (getenv(GIT_WORK_TREE_ENVIRONMENT))
                setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
  
 -      set_git_dir(make_relative_path(git_dir, work_tree));
 +      set_git_dir(relative_path(git_dir, work_tree));
        initialized = 1;
  }
  
@@@ -275,7 -272,7 +275,7 @@@ const char *read_gitfile_gently(const c
        const char *slash;
        struct stat st;
        int fd;
-       size_t len;
+       ssize_t len;
  
        if (stat(path, &st))
                return NULL;
  
        if (!is_git_directory(dir))
                die("Not a git repository: %s", dir);
 -      path = make_absolute_path(dir);
 +      path = real_path(dir);
  
        free(buf);
        return path;
@@@ -392,7 -389,7 +392,7 @@@ static const char *setup_explicit_git_d
  
        if (!prefixcmp(cwd, worktree) &&
            cwd[strlen(worktree)] == '/') { /* cwd inside worktree */
 -              set_git_dir(make_absolute_path(gitdirenv));
 +              set_git_dir(real_path(gitdirenv));
                if (chdir(worktree))
                        die_errno("Could not chdir to '%s'", worktree);
                cwd[len++] = '/';
@@@ -417,7 -414,7 +417,7 @@@ static const char *setup_discovered_git
        /* --work-tree is set without --git-dir; use discovered one */
        if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
                if (offset != len && !is_absolute_path(gitdir))
 -                      gitdir = xstrdup(make_absolute_path(gitdir));
 +                      gitdir = xstrdup(real_path(gitdir));
                if (chdir(cwd))
                        die_errno("Could not come back to cwd");
                return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
  
        /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
        if (is_bare_repository_cfg > 0) {
 -              set_git_dir(offset == len ? gitdir : make_absolute_path(gitdir));
 +              set_git_dir(offset == len ? gitdir : real_path(gitdir));
                if (chdir(cwd))
                        die_errno("Could not come back to cwd");
                return NULL;
diff --combined transport.c
@@@ -156,7 -156,7 +156,7 @@@ static void set_upstreams(struct transp
                        continue;
                if (!ref->peer_ref)
                        continue;
-               if (!ref->new_sha1 || is_null_sha1(ref->new_sha1))
+               if (is_null_sha1(ref->new_sha1))
                        continue;
  
                /* Follow symbolic refs (mainly for HEAD). */
@@@ -192,7 -192,7 +192,7 @@@ static const char *rsync_url(const cha
  static struct ref *get_refs_via_rsync(struct transport *transport, int for_push)
  {
        struct strbuf buf = STRBUF_INIT, temp_dir = STRBUF_INIT;
 -      struct ref dummy = {0}, *tail = &dummy;
 +      struct ref dummy = {NULL}, *tail = &dummy;
        struct child_process rsync;
        const char *args[5];
        int temp_dir_len;
@@@ -1189,37 -1189,3 +1189,37 @@@ char *transport_anonymize_url(const cha
  literal_copy:
        return xstrdup(url);
  }
 +
 +int refs_from_alternate_cb(struct alternate_object_database *e, void *cb)
 +{
 +      char *other;
 +      size_t len;
 +      struct remote *remote;
 +      struct transport *transport;
 +      const struct ref *extra;
 +      alternate_ref_fn *ref_fn = cb;
 +
 +      e->name[-1] = '\0';
 +      other = xstrdup(real_path(e->base));
 +      e->name[-1] = '/';
 +      len = strlen(other);
 +
 +      while (other[len-1] == '/')
 +              other[--len] = '\0';
 +      if (len < 8 || memcmp(other + len - 8, "/objects", 8))
 +              return 0;
 +      /* Is this a git repository with refs? */
 +      memcpy(other + len - 8, "/refs", 6);
 +      if (!is_directory(other))
 +              return 0;
 +      other[len - 8] = '\0';
 +      remote = remote_get(other);
 +      transport = transport_get(remote, other);
 +      for (extra = transport_get_remote_refs(transport);
 +           extra;
 +           extra = extra->next)
 +              ref_fn(extra, NULL);
 +      transport_disconnect(transport);
 +      free(other);
 +      return 0;
 +}