Document git-merge-cache -o
[git.git] / sha1_file.c
index ee62eee..942b673 100644 (file)
@@ -7,6 +7,7 @@
  * creation etc.
  */
 #include <stdarg.h>
+#include <limits.h>
 #include "cache.h"
 
 #ifndef O_NOATIME
@@ -58,6 +59,38 @@ int get_sha1_file(const char *path, unsigned char *result)
        return get_sha1_hex(buffer, result);
 }
 
+static char *git_dir, *git_object_dir, *git_index_file;
+static void setup_git_env(void)
+{
+       git_dir = gitenv(GIT_DIR_ENVIRONMENT);
+       if (!git_dir)
+               git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
+       git_object_dir = gitenv(DB_ENVIRONMENT);
+       if (!git_object_dir) {
+               git_object_dir = xmalloc(strlen(git_dir) + 9);
+               sprintf(git_object_dir, "%s/objects", git_dir);
+       }
+       git_index_file = gitenv(INDEX_ENVIRONMENT);
+       if (!git_index_file) {
+               git_index_file = xmalloc(strlen(git_dir) + 7);
+               sprintf(git_index_file, "%s/index", git_dir);
+       }
+}
+
+char *get_object_directory(void)
+{
+       if (!git_object_dir)
+               setup_git_env();
+       return git_object_dir;
+}
+
+char *get_index_file(void)
+{
+       if (!git_index_file)
+               setup_git_env();
+       return git_index_file;
+}
+
 int get_sha1(const char *str, unsigned char *sha1)
 {
        static char pathname[PATH_MAX];
@@ -69,15 +102,16 @@ int get_sha1(const char *str, unsigned char *sha1)
                "refs/snap",
                NULL
        };
-       const char *gitdir;
        const char **p;
 
        if (!get_sha1_hex(str, sha1))
                return 0;
 
-       gitdir = ".git";
+       if (!git_dir)
+               setup_git_env();
        for (p = prefix; *p; p++) {
-               snprintf(pathname, sizeof(pathname), "%s/%s/%s", gitdir, *p, str);
+               snprintf(pathname, sizeof(pathname), "%s/%s/%s",
+                        git_dir, *p, str);
                if (!get_sha1_file(pathname, sha1))
                        return 0;
        }
@@ -119,7 +153,7 @@ static void fill_sha1_path(char *pathbuf, const unsigned char *sha1)
  *
  * Also note that this returns the location for creating.  Reading
  * SHA1 file can happen from any alternate directory listed in the
- * SHA1_FILE_DIRECTORIES environment variable if it is not found in
+ * DB_ENVIRONMENT environment variable if it is not found in
  * the primary object database.
  */
 char *sha1_file_name(const unsigned char *sha1)
@@ -127,7 +161,7 @@ char *sha1_file_name(const unsigned char *sha1)
        static char *name, *base;
 
        if (!base) {
-               char *sha1_file_directory = get_object_directory();
+               const char *sha1_file_directory = get_object_directory();
                int len = strlen(sha1_file_directory);
                base = xmalloc(len + 60);
                memcpy(base, sha1_file_directory, len);
@@ -140,20 +174,40 @@ char *sha1_file_name(const unsigned char *sha1)
        return base;
 }
 
-static struct alternate_object_database
-{
+static struct alternate_object_database {
        char *base;
        char *name;
 } *alt_odb;
 
+/*
+ * Prepare alternate object database registry.
+ * alt_odb points at an array of struct alternate_object_database.
+ * This array is terminated with an element that has both its base
+ * and name set to NULL.  alt_odb[n] comes from n'th non-empty
+ * element from colon separated ALTERNATE_DB_ENVIRONMENT environment
+ * variable, and its base points at a statically allocated buffer
+ * that contains "/the/directory/corresponding/to/.git/objects/...",
+ * while its name points just after the slash at the end of
+ * ".git/objects/" in the example above, and has enough space to hold
+ * 40-byte hex SHA1, an extra slash for the first level indirection,
+ * and the terminating NUL.
+ * This function allocates the alt_odb array and all the strings
+ * pointed by base fields of the array elements with one xmalloc();
+ * the string pool immediately follows the array.
+ */
 static void prepare_alt_odb(void)
 {
        int pass, totlen, i;
-       void *buf;
        const char *cp, *last;
        char *op = 0;
-       const char *alt = getenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
-
+       const char *alt = gitenv(ALTERNATE_DB_ENVIRONMENT) ? : "";
+
+       /* The first pass counts how large an area to allocate to
+        * hold the entire alt_odb structure, including array of
+        * structs and path buffers for them.  The second pass fills
+        * the structure and prepares the path buffers for use by
+        * fill_sha1_path().
+        */
        for (totlen = pass = 0; pass < 2; pass++) {
                last = alt;
                i = 0;
@@ -181,7 +235,7 @@ static void prepare_alt_odb(void)
                } while (*cp);
                if (pass)
                        break;
-               alt_odb = buf = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen);
+               alt_odb = xmalloc(sizeof(*alt_odb) * (i + 1) + totlen);
                alt_odb[i].base = alt_odb[i].name = 0;
                op = (char*)(&alt_odb[i+1]);
        }
@@ -411,7 +465,7 @@ int write_sha1_file(char *buf, unsigned long len, const char *type, unsigned cha
        stream.next_in = hdr;
        stream.avail_in = hdrlen;
        while (deflate(&stream, 0) == Z_OK)
-               /* nothing */
+               /* nothing */;
 
        /* Then the data itself.. */
        stream.next_in = buf;