Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

file 127 lines (113 sloc) 2.423 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
#include "cache.h"

char *prefix_path(const char *prefix, int len, char *path)
{
char *orig = path;
for (;;) {
char c;
if (*path != '.')
break;
c = path[1];
/* "." */
if (!c) {
path++;
break;
}
/* "./" */
if (c == '/') {
path += 2;
continue;
}
if (c != '.')
break;
c = path[2];
if (!c)
path += 2;
else if (c == '/')
path += 3;
else
break;
/* ".." and "../" */
/* Remove last component of the prefix */
do {
if (!len)
die("'%s' is outside repository", orig);
len--;
} while (len && prefix[len-1] != '/');
continue;
}
if (len) {
int speclen = strlen(path);
char *n = xmalloc(speclen + len + 1);

memcpy(n, prefix, len);
memcpy(n + len, path, speclen+1);
path = n;
}
return path;
}

const char **get_pathspec(const char *prefix, char **pathspec)
{
char *entry = *pathspec;
char **p;
int prefixlen;

if (!prefix && !entry)
return NULL;

if (!entry) {
static const char *spec[2];
spec[0] = prefix;
spec[1] = NULL;
return spec;
}

/* Otherwise we have to re-write the entries.. */
p = pathspec;
prefixlen = prefix ? strlen(prefix) : 0;
do {
*p = prefix_path(prefix, prefixlen, entry);
} while ((entry = *++p) != NULL);
return (const char **) pathspec;
}

/*
* Test it it looks like we're at the top
* level git directory. We want to see a
*
* - a HEAD symlink and a refs/ directory under ".git"
* - either a .git/objects/ directory _or_ the proper
* GIT_OBJECT_DIRECTORY environment variable
*/
static int is_toplevel_directory(void)
{
struct stat st;

return !lstat(".git/HEAD", &st) &&
S_ISLNK(st.st_mode) &&
!access(".git/refs/", X_OK) &&
(getenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK));
}

const char *setup_git_directory(void)
{
static char cwd[PATH_MAX+1];
int len, offset;

/*
* If GIT_DIR is set explicitly, we're not going
* to do any discovery
*/
if (getenv(GIT_DIR_ENVIRONMENT))
return NULL;

if (!getcwd(cwd, sizeof(cwd)) || cwd[0] != '/')
die("Unable to read current working directory");

offset = len = strlen(cwd);
for (;;) {
if (is_toplevel_directory())
break;
chdir("..");
do {
if (!offset)
die("Not a git repository");
} while (cwd[--offset] != '/');
}

if (offset == len)
return NULL;

/* Make "offset" point to past the '/', and add a '/' at the end */
offset++;
cwd[len++] = '/';
cwd[len] = 0;
return cwd + offset;
}
Something went wrong with that request. Please try again.