Merge branch 'jc/maint-rerere-in-workdir'
authorJunio C Hamano <gitster@pobox.com>
Sun, 27 Mar 2011 03:13:16 +0000 (20:13 -0700)
committerJunio C Hamano <gitster@pobox.com>
Sun, 27 Mar 2011 03:13:16 +0000 (20:13 -0700)
* jc/maint-rerere-in-workdir:
  rerere: make sure it works even in a workdir attached to a young repository

1  2 
cache.h
rerere.c
sha1_file.c

diff --cc cache.h
Simple merge
diff --cc rerere.c
Simple merge
diff --cc sha1_file.c
@@@ -31,43 -35,42 +31,72 @@@ static inline uintmax_t sz_fmt(size_t s
  
  const unsigned char null_sha1[20];
  
 -static inline int offset_1st_component(const char *path)
 +static int git_open_noatime(const char *name, struct packed_git *p);
 +
 +/*
 + * This is meant to hold a *small* number of objects that you would
 + * want read_sha1_file() to be able to return, but yet you do not want
 + * to write them into the object store (e.g. a browse-only
 + * application).
 + */
 +static struct cached_object {
 +      unsigned char sha1[20];
 +      enum object_type type;
 +      void *buf;
 +      unsigned long size;
 +} *cached_objects;
 +static int cached_object_nr, cached_object_alloc;
 +
 +static struct cached_object empty_tree = {
 +      EMPTY_TREE_SHA1_BIN_LITERAL,
 +      OBJ_TREE,
 +      "",
 +      0
 +};
 +
 +static struct cached_object *find_cached_object(const unsigned char *sha1)
  {
 -      if (has_dos_drive_prefix(path))
 -              return 2 + (path[2] == '/');
 -      return *path == '/';
 +      int i;
 +      struct cached_object *co = cached_objects;
 +
 +      for (i = 0; i < cached_object_nr; i++, co++) {
 +              if (!hashcmp(co->sha1, sha1))
 +                      return co;
 +      }
 +      if (!hashcmp(sha1, empty_tree.sha1))
 +              return &empty_tree;
 +      return NULL;
  }
  
+ int mkdir_in_gitdir(const char *path)
+ {
+       if (mkdir(path, 0777)) {
+               int saved_errno = errno;
+               struct stat st;
+               struct strbuf sb = STRBUF_INIT;
+               if (errno != EEXIST)
+                       return -1;
+               /*
+                * Are we looking at a path in a symlinked worktree
+                * whose original repository does not yet have it?
+                * e.g. .git/rr-cache pointing at its original
+                * repository in which the user hasn't performed any
+                * conflict resolution yet?
+                */
+               if (lstat(path, &st) || !S_ISLNK(st.st_mode) ||
+                   strbuf_readlink(&sb, path, st.st_size) ||
+                   !is_absolute_path(sb.buf) ||
+                   mkdir(sb.buf, 0777)) {
+                       strbuf_release(&sb);
+                       errno = saved_errno;
+                       return -1;
+               }
+               strbuf_release(&sb);
+       }
+       return adjust_shared_perm(path);
+ }
  int safe_create_leading_directories(char *path)
  {
        char *pos = path + offset_1st_component(path);