453bddbb17365c8b090757c544edcc0a61fc96fb
   1#include "cache.h"
   2
   3const char **get_pathspec(const char *prefix, char **pathspec)
   4{
   5        char *entry = *pathspec;
   6        char **p;
   7        int prefixlen;
   8
   9        if (!prefix) {
  10                char **p;
  11                if (!entry)
  12                        return NULL;
  13                p = pathspec;
  14                do {
  15                        if (*entry != '.')
  16                                continue;
  17                        /* fixup ? */
  18                } while ((entry = *++p) != NULL);
  19                return (const char **) pathspec;
  20        }
  21
  22        if (!entry) {
  23                static const char *spec[2];
  24                spec[0] = prefix;
  25                spec[1] = NULL;
  26                return spec;
  27        }
  28
  29        /* Otherwise we have to re-write the entries.. */
  30        prefixlen = strlen(prefix);
  31        p = pathspec;
  32        do {
  33                int speclen, len = prefixlen;
  34                char *n;
  35
  36                for (;;) {
  37                        if (!strcmp(entry, ".")) {
  38                                entry++;
  39                                break;
  40                        }
  41                        if (!strncmp(entry, "./", 2)) {
  42                                entry += 2;
  43                                continue;
  44                        }
  45                        if (!strncmp(entry, "../", 3)) {
  46                                do {
  47                                        if (!len)
  48                                                die("'%s' is outside repository", *p);
  49                                        len--;
  50                                } while (len && prefix[len-1] != '/');
  51                                entry += 3;
  52                                continue;
  53                        }
  54                        break;
  55                }
  56                speclen = strlen(entry);
  57                n = xmalloc(speclen + len + 1);
  58                
  59                memcpy(n, prefix, len);
  60                memcpy(n + len, entry, speclen+1);
  61                *p = n;
  62        } while ((entry = *++p) != NULL);
  63        return (const char **) pathspec;
  64}
  65
  66const char *setup_git_directory(void)
  67{
  68        static char cwd[PATH_MAX+1];
  69        int len, offset;
  70
  71        /*
  72         * If GIT_DIR is set explicitly, we're not going
  73         * to do any discovery
  74         */
  75        if (gitenv(GIT_DIR_ENVIRONMENT))
  76                return NULL;
  77
  78        if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
  79                die("Unable to read current working directory");
  80
  81        offset = len = strlen(cwd);
  82        for (;;) {
  83                /*
  84                 * We always want to see a .git/HEAD and a .git/refs/
  85                 * subdirectory
  86                 */
  87                if (!access(".git/HEAD", R_OK) && !access(".git/refs/", X_OK)) {
  88                        /*
  89                         * Then we need either a GIT_OBJECT_DIRECTORY define
  90                         * or a .git/objects/ directory
  91                         */
  92                        if (gitenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK))
  93                                break;
  94                }
  95                chdir("..");
  96                do {
  97                        if (!offset)
  98                                die("Not a git repository");
  99                } while (cwd[--offset] != '/');
 100        }
 101
 102        if (offset == len)
 103                return NULL;
 104
 105        /* Make "offset" point to past the '/', and add a '/' at the end */
 106        offset++;
 107        cwd[len++] = '/';
 108        cwd[len] = 0;
 109        return cwd + offset;
 110}