aboutsummaryrefslogtreecommitdiff
path: root/setup.c
blob: 453bddbb17365c8b090757c544edcc0a61fc96fb (plain)
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
#include "cache.h"

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

	if (!prefix) {
		char **p;
		if (!entry)
			return NULL;
		p = pathspec;
		do {
			if (*entry != '.')
				continue;
			/* fixup ? */
		} while ((entry = *++p) != NULL);
		return (const char **) pathspec;
	}

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

	/* Otherwise we have to re-write the entries.. */
	prefixlen = strlen(prefix);
	p = pathspec;
	do {
		int speclen, len = prefixlen;
		char *n;

		for (;;) {
			if (!strcmp(entry, ".")) {
				entry++;
				break;
			}
			if (!strncmp(entry, "./", 2)) {
				entry += 2;
				continue;
			}
			if (!strncmp(entry, "../", 3)) {
				do {
					if (!len)
						die("'%s' is outside repository", *p);
					len--;
				} while (len && prefix[len-1] != '/');
				entry += 3;
				continue;
			}
			break;
		}
		speclen = strlen(entry);
		n = xmalloc(speclen + len + 1);
		
		memcpy(n, prefix, len);
		memcpy(n + len, entry, speclen+1);
		*p = n;
	} while ((entry = *++p) != NULL);
	return (const char **) pathspec;
}

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 (gitenv(GIT_DIR_ENVIRONMENT))
		return NULL;

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

	offset = len = strlen(cwd);
	for (;;) {
		/*
		 * We always want to see a .git/HEAD and a .git/refs/
		 * subdirectory
		 */
		if (!access(".git/HEAD", R_OK) && !access(".git/refs/", X_OK)) {
			/*
			 * Then we need either a GIT_OBJECT_DIRECTORY define
			 * or a .git/objects/ directory
			 */
			if (gitenv(DB_ENVIRONMENT) || !access(".git/objects/", X_OK))
				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;
}