]> git.ipfire.org Git - thirdparty/git.git/blame - path.c
environment.h: move declarations for environment.c functions from cache.h
[thirdparty/git.git] / path.c
CommitLineData
26c8a533 1/*
3a429d3b 2 * Utilities for paths and pathnames
26c8a533
LT
3 */
4#include "cache.h"
0b027f6c 5#include "abspath.h"
32a8f510 6#include "environment.h"
f394e093 7#include "gettext.h"
41771fa4 8#include "hex.h"
c14c234f 9#include "repository.h"
395de250 10#include "strbuf.h"
a5ccdbe4 11#include "string-list.h"
77a6d840 12#include "dir.h"
2e641d58 13#include "worktree.h"
99b43a61 14#include "submodule-config.h"
e7d72d07 15#include "path.h"
0abe14f6 16#include "packfile.h"
90c62155 17#include "object-store.h"
76a53d64 18#include "lockfile.h"
e394a160 19#include "exec-cmd.h"
26c8a533 20
f66450ae 21static int get_st_mode_bits(const char *path, int *mode)
0117c2f0
TB
22{
23 struct stat st;
24 if (lstat(path, &st) < 0)
25 return -1;
26 *mode = st.st_mode;
27 return 0;
28}
0117c2f0 29
26c8a533
LT
30static char bad_path[] = "/bad-path/";
31
4ef9caf5 32static struct strbuf *get_pathname(void)
e7676d2f 33{
4ef9caf5
NTND
34 static struct strbuf pathname_array[4] = {
35 STRBUF_INIT, STRBUF_INIT, STRBUF_INIT, STRBUF_INIT
36 };
e7676d2f 37 static int index;
bb84735c
RS
38 struct strbuf *sb = &pathname_array[index];
39 index = (index + 1) % ARRAY_SIZE(pathname_array);
4ef9caf5
NTND
40 strbuf_reset(sb);
41 return sb;
e7676d2f
LT
42}
43
8262715b 44static const char *cleanup_path(const char *path)
26c8a533
LT
45{
46 /* Clean it up */
8262715b 47 if (skip_prefix(path, "./", &path)) {
26c8a533
LT
48 while (*path == '/')
49 path++;
50 }
51 return path;
52}
53
4ef9caf5
NTND
54static void strbuf_cleanup_path(struct strbuf *sb)
55{
8262715b 56 const char *path = cleanup_path(sb->buf);
4ef9caf5
NTND
57 if (path > sb->buf)
58 strbuf_remove(sb, 0, path - sb->buf);
59}
60
108bebea
AR
61char *mksnpath(char *buf, size_t n, const char *fmt, ...)
62{
63 va_list args;
64 unsigned len;
65
66 va_start(args, fmt);
67 len = vsnprintf(buf, n, fmt, args);
68 va_end(args);
69 if (len >= n) {
9db56f71 70 strlcpy(buf, bad_path, n);
108bebea
AR
71 return buf;
72 }
8262715b 73 return (char *)cleanup_path(buf);
108bebea
AR
74}
75
557bd833 76static int dir_prefix(const char *buf, const char *dir)
fe2d7776 77{
557bd833
NTND
78 int len = strlen(dir);
79 return !strncmp(buf, dir, len) &&
80 (is_dir_sep(buf[len]) || buf[len] == '\0');
81}
fe2d7776 82
557bd833
NTND
83/* $buf =~ m|$dir/+$file| but without regex */
84static int is_dir_file(const char *buf, const char *dir, const char *file)
85{
86 int len = strlen(dir);
87 if (strncmp(buf, dir, len) || !is_dir_sep(buf[len]))
88 return 0;
89 while (is_dir_sep(buf[len]))
90 len++;
91 return !strcmp(buf + len, file);
92}
93
94static void replace_dir(struct strbuf *buf, int len, const char *newdir)
95{
96 int newlen = strlen(newdir);
97 int need_sep = (buf->buf[len] && !is_dir_sep(buf->buf[len])) &&
98 !is_dir_sep(newdir[newlen - 1]);
99 if (need_sep)
100 len--; /* keep one char, to be replaced with '/' */
101 strbuf_splice(buf, 0, len, newdir, newlen);
102 if (need_sep)
103 buf->buf[newlen] = '/';
104}
105
0701530c
DT
106struct common_dir {
107 /* Not considered garbage for report_linked_checkout_garbage */
108 unsigned ignore_garbage:1;
109 unsigned is_dir:1;
c72fc40d
SG
110 /* Belongs to the common dir, though it may contain paths that don't */
111 unsigned is_common:1;
112 const char *path;
0701530c
DT
113};
114
115static struct common_dir common_list[] = {
c72fc40d
SG
116 { 0, 1, 1, "branches" },
117 { 0, 1, 1, "common" },
118 { 0, 1, 1, "hooks" },
119 { 0, 1, 1, "info" },
120 { 0, 0, 0, "info/sparse-checkout" },
121 { 1, 1, 1, "logs" },
122 { 1, 0, 0, "logs/HEAD" },
123 { 0, 1, 0, "logs/refs/bisect" },
124 { 0, 1, 0, "logs/refs/rewritten" },
125 { 0, 1, 0, "logs/refs/worktree" },
126 { 0, 1, 1, "lost-found" },
127 { 0, 1, 1, "objects" },
128 { 0, 1, 1, "refs" },
129 { 0, 1, 0, "refs/bisect" },
130 { 0, 1, 0, "refs/rewritten" },
131 { 0, 1, 0, "refs/worktree" },
132 { 0, 1, 1, "remotes" },
133 { 0, 1, 1, "worktrees" },
134 { 0, 1, 1, "rr-cache" },
135 { 0, 1, 1, "svn" },
136 { 0, 0, 1, "config" },
137 { 1, 0, 1, "gc.pid" },
138 { 0, 0, 1, "packed-refs" },
139 { 0, 0, 1, "shallow" },
0701530c 140 { 0, 0, 0, NULL }
c7b3a3d2
NTND
141};
142
4e09cf2a
DT
143/*
144 * A compressed trie. A trie node consists of zero or more characters that
145 * are common to all elements with this prefix, optionally followed by some
146 * children. If value is not NULL, the trie node is a terminal node.
147 *
148 * For example, consider the following set of strings:
149 * abc
150 * def
151 * definite
152 * definition
153 *
832c0e5e 154 * The trie would look like:
4e09cf2a
DT
155 * root: len = 0, children a and d non-NULL, value = NULL.
156 * a: len = 2, contents = bc, value = (data for "abc")
157 * d: len = 2, contents = ef, children i non-NULL, value = (data for "def")
158 * i: len = 3, contents = nit, children e and i non-NULL, value = NULL
159 * e: len = 0, children all NULL, value = (data for "definite")
160 * i: len = 2, contents = on, children all NULL,
161 * value = (data for "definition")
162 */
163struct trie {
164 struct trie *children[256];
165 int len;
166 char *contents;
167 void *value;
168};
169
170static struct trie *make_trie_node(const char *key, void *value)
c7b3a3d2 171{
4e09cf2a
DT
172 struct trie *new_node = xcalloc(1, sizeof(*new_node));
173 new_node->len = strlen(key);
174 if (new_node->len) {
175 new_node->contents = xmalloc(new_node->len);
176 memcpy(new_node->contents, key, new_node->len);
177 }
178 new_node->value = value;
179 return new_node;
180}
c7b3a3d2 181
4e09cf2a
DT
182/*
183 * Add a key/value pair to a trie. The key is assumed to be \0-terminated.
184 * If there was an existing value for this key, return it.
185 */
186static void *add_to_trie(struct trie *root, const char *key, void *value)
187{
188 struct trie *child;
189 void *old;
190 int i;
191
192 if (!*key) {
193 /* we have reached the end of the key */
194 old = root->value;
195 root->value = value;
196 return old;
197 }
198
199 for (i = 0; i < root->len; i++) {
200 if (root->contents[i] == key[i])
201 continue;
202
203 /*
204 * Split this node: child will contain this node's
205 * existing children.
206 */
55d7d158 207 child = xmalloc(sizeof(*child));
4e09cf2a
DT
208 memcpy(child->children, root->children, sizeof(root->children));
209
210 child->len = root->len - i - 1;
211 if (child->len) {
212 child->contents = xstrndup(root->contents + i + 1,
213 child->len);
c7b3a3d2 214 }
4e09cf2a
DT
215 child->value = root->value;
216 root->value = NULL;
217 root->len = i;
218
219 memset(root->children, 0, sizeof(root->children));
220 root->children[(unsigned char)root->contents[i]] = child;
221
222 /* This is the newly-added child. */
223 root->children[(unsigned char)key[i]] =
224 make_trie_node(key + i + 1, value);
225 return NULL;
226 }
227
228 /* We have matched the entire compressed section */
229 if (key[i]) {
230 child = root->children[(unsigned char)key[root->len]];
231 if (child) {
232 return add_to_trie(child, key + root->len + 1, value);
233 } else {
234 child = make_trie_node(key + root->len + 1, value);
235 root->children[(unsigned char)key[root->len]] = child;
236 return NULL;
c7b3a3d2
NTND
237 }
238 }
4e09cf2a
DT
239
240 old = root->value;
241 root->value = value;
242 return old;
243}
244
7cb8c929 245typedef int (*match_fn)(const char *unmatched, void *value, void *baton);
4e09cf2a
DT
246
247/*
248 * Search a trie for some key. Find the longest /-or-\0-terminated
7cb8c929
SG
249 * prefix of the key for which the trie contains a value. If there is
250 * no such prefix, return -1. Otherwise call fn with the unmatched
251 * portion of the key and the found value. If fn returns 0 or
252 * positive, then return its return value. If fn returns negative,
253 * then call fn with the next-longest /-terminated prefix of the key
254 * (i.e. a parent directory) for which the trie contains a value, and
255 * handle its return value the same way. If there is no shorter
256 * /-terminated prefix with a value left, then return the negative
257 * return value of the most recent fn invocation.
4e09cf2a
DT
258 *
259 * The key is partially normalized: consecutive slashes are skipped.
260 *
7cb8c929
SG
261 * For example, consider the trie containing only [logs,
262 * logs/refs/bisect], both with values, but not logs/refs.
4e09cf2a 263 *
7cb8c929
SG
264 * | key | unmatched | prefix to node | return value |
265 * |--------------------|----------------|------------------|--------------|
266 * | a | not called | n/a | -1 |
267 * | logstore | not called | n/a | -1 |
268 * | logs | \0 | logs | as per fn |
269 * | logs/ | / | logs | as per fn |
270 * | logs/refs | /refs | logs | as per fn |
271 * | logs/refs/ | /refs/ | logs | as per fn |
272 * | logs/refs/b | /refs/b | logs | as per fn |
273 * | logs/refs/bisected | /refs/bisected | logs | as per fn |
274 * | logs/refs/bisect | \0 | logs/refs/bisect | as per fn |
275 * | logs/refs/bisect/ | / | logs/refs/bisect | as per fn |
276 * | logs/refs/bisect/a | /a | logs/refs/bisect | as per fn |
277 * | (If fn in the previous line returns -1, then fn is called once more:) |
278 * | logs/refs/bisect/a | /refs/bisect/a | logs | as per fn |
279 * |--------------------|----------------|------------------|--------------|
4e09cf2a
DT
280 */
281static int trie_find(struct trie *root, const char *key, match_fn fn,
282 void *baton)
283{
284 int i;
285 int result;
286 struct trie *child;
287
288 if (!*key) {
289 /* we have reached the end of the key */
290 if (root->value && !root->len)
291 return fn(key, root->value, baton);
292 else
293 return -1;
294 }
295
296 for (i = 0; i < root->len; i++) {
297 /* Partial path normalization: skip consecutive slashes. */
298 if (key[i] == '/' && key[i+1] == '/') {
299 key++;
300 continue;
301 }
302 if (root->contents[i] != key[i])
303 return -1;
304 }
305
306 /* Matched the entire compressed section */
307 key += i;
f45f88b2 308 if (!*key) {
4e09cf2a 309 /* End of key */
f45f88b2
SG
310 if (root->value)
311 return fn(key, root->value, baton);
312 else
313 return -1;
314 }
4e09cf2a
DT
315
316 /* Partial path normalization: skip consecutive slashes */
317 while (key[0] == '/' && key[1] == '/')
318 key++;
319
320 child = root->children[(unsigned char)*key];
321 if (child)
322 result = trie_find(child, key + 1, fn, baton);
323 else
324 result = -1;
325
326 if (result >= 0 || (*key != '/' && *key != 0))
327 return result;
328 if (root->value)
329 return fn(key, root->value, baton);
330 else
331 return -1;
332}
333
334static struct trie common_trie;
335static int common_trie_done_setup;
336
337static void init_common_trie(void)
338{
339 struct common_dir *p;
340
341 if (common_trie_done_setup)
342 return;
343
c72fc40d
SG
344 for (p = common_list; p->path; p++)
345 add_to_trie(&common_trie, p->path, p);
4e09cf2a
DT
346
347 common_trie_done_setup = 1;
348}
349
350/*
351 * Helper function for update_common_dir: returns 1 if the dir
352 * prefix is common.
353 */
d3dcfa04
JK
354static int check_common(const char *unmatched, void *value,
355 void *baton UNUSED)
4e09cf2a
DT
356{
357 struct common_dir *dir = value;
358
4e09cf2a 359 if (dir->is_dir && (unmatched[0] == 0 || unmatched[0] == '/'))
c72fc40d 360 return dir->is_common;
4e09cf2a
DT
361
362 if (!dir->is_dir && unmatched[0] == 0)
c72fc40d 363 return dir->is_common;
4e09cf2a
DT
364
365 return 0;
366}
367
1c630bad
JH
368static void update_common_dir(struct strbuf *buf, int git_dir_len,
369 const char *common_dir)
4e09cf2a
DT
370{
371 char *base = buf->buf + git_dir_len;
76a53d64
JS
372 int has_lock_suffix = strbuf_strip_suffix(buf, LOCK_SUFFIX);
373
4e09cf2a
DT
374 init_common_trie();
375 if (trie_find(&common_trie, base, check_common, NULL) > 0)
1c630bad 376 replace_dir(buf, git_dir_len, common_dir);
76a53d64
JS
377
378 if (has_lock_suffix)
379 strbuf_addstr(buf, LOCK_SUFFIX);
c7b3a3d2
NTND
380}
381
77a6d840
NTND
382void report_linked_checkout_garbage(void)
383{
384 struct strbuf sb = STRBUF_INIT;
0701530c 385 const struct common_dir *p;
77a6d840
NTND
386 int len;
387
c14c234f 388 if (!the_repository->different_commondir)
77a6d840
NTND
389 return;
390 strbuf_addf(&sb, "%s/", get_git_dir());
391 len = sb.len;
c72fc40d
SG
392 for (p = common_list; p->path; p++) {
393 const char *path = p->path;
0701530c 394 if (p->ignore_garbage)
77a6d840
NTND
395 continue;
396 strbuf_setlen(&sb, len);
397 strbuf_addstr(&sb, path);
398 if (file_exists(sb.buf))
0a489b06 399 report_garbage(PACKDIR_FILE_GARBAGE, sb.buf);
77a6d840
NTND
400 }
401 strbuf_release(&sb);
fe2d7776
AR
402}
403
f9a8a47e
BW
404static void adjust_git_path(const struct repository *repo,
405 struct strbuf *buf, int git_dir_len)
557bd833
NTND
406{
407 const char *base = buf->buf + git_dir_len;
c14c234f 408 if (is_dir_file(base, "info", "grafts"))
557bd833 409 strbuf_splice(buf, 0, buf->len,
f9a8a47e 410 repo->graft_file, strlen(repo->graft_file));
c14c234f 411 else if (!strcmp(base, "index"))
557bd833 412 strbuf_splice(buf, 0, buf->len,
f9a8a47e 413 repo->index_file, strlen(repo->index_file));
c14c234f 414 else if (dir_prefix(base, "objects"))
f0eaf638 415 replace_dir(buf, git_dir_len + 7, repo->objects->odb->path);
9445b492
JS
416 else if (git_hooks_path && dir_prefix(base, "hooks"))
417 replace_dir(buf, git_dir_len + 5, git_hooks_path);
f9a8a47e
BW
418 else if (repo->different_commondir)
419 update_common_dir(buf, git_dir_len, repo->commondir);
557bd833
NTND
420}
421
f9a8a47e
BW
422static void strbuf_worktree_gitdir(struct strbuf *buf,
423 const struct repository *repo,
424 const struct worktree *wt)
425{
426 if (!wt)
427 strbuf_addstr(buf, repo->gitdir);
428 else if (!wt->id)
429 strbuf_addstr(buf, repo->commondir);
430 else
431 strbuf_git_common_path(buf, repo, "worktrees/%s", wt->id);
432}
433
434static void do_git_path(const struct repository *repo,
435 const struct worktree *wt, struct strbuf *buf,
2e641d58 436 const char *fmt, va_list args)
fe2d7776 437{
557bd833 438 int gitdir_len;
f9a8a47e 439 strbuf_worktree_gitdir(buf, repo, wt);
4ef9caf5
NTND
440 if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
441 strbuf_addch(buf, '/');
557bd833 442 gitdir_len = buf->len;
4ef9caf5 443 strbuf_vaddf(buf, fmt, args);
54310733
BW
444 if (!wt)
445 adjust_git_path(repo, buf, gitdir_len);
4ef9caf5 446 strbuf_cleanup_path(buf);
fe2d7776
AR
447}
448
3181d863
BW
449char *repo_git_path(const struct repository *repo,
450 const char *fmt, ...)
451{
452 struct strbuf path = STRBUF_INIT;
453 va_list args;
454 va_start(args, fmt);
455 do_git_path(repo, NULL, &path, fmt, args);
456 va_end(args);
457 return strbuf_detach(&path, NULL);
458}
459
460void strbuf_repo_git_path(struct strbuf *sb,
461 const struct repository *repo,
462 const char *fmt, ...)
463{
464 va_list args;
465 va_start(args, fmt);
466 do_git_path(repo, NULL, sb, fmt, args);
467 va_end(args);
468}
469
bb3788ce
JK
470char *git_path_buf(struct strbuf *buf, const char *fmt, ...)
471{
472 va_list args;
473 strbuf_reset(buf);
474 va_start(args, fmt);
f9a8a47e 475 do_git_path(the_repository, NULL, buf, fmt, args);
bb3788ce
JK
476 va_end(args);
477 return buf->buf;
478}
479
1a83c240 480void strbuf_git_path(struct strbuf *sb, const char *fmt, ...)
aba13e7c
AR
481{
482 va_list args;
483 va_start(args, fmt);
f9a8a47e 484 do_git_path(the_repository, NULL, sb, fmt, args);
aba13e7c 485 va_end(args);
aba13e7c
AR
486}
487
57a23b77 488const char *git_path(const char *fmt, ...)
aba13e7c 489{
57a23b77 490 struct strbuf *pathname = get_pathname();
aba13e7c
AR
491 va_list args;
492 va_start(args, fmt);
f9a8a47e 493 do_git_path(the_repository, NULL, pathname, fmt, args);
aba13e7c 494 va_end(args);
57a23b77 495 return pathname->buf;
aba13e7c
AR
496}
497
aba13e7c 498char *git_pathdup(const char *fmt, ...)
21cf3227 499{
4ef9caf5 500 struct strbuf path = STRBUF_INIT;
21cf3227 501 va_list args;
21cf3227 502 va_start(args, fmt);
f9a8a47e 503 do_git_path(the_repository, NULL, &path, fmt, args);
21cf3227 504 va_end(args);
4ef9caf5 505 return strbuf_detach(&path, NULL);
21cf3227
HKNN
506}
507
21cf3227 508char *mkpathdup(const char *fmt, ...)
26c8a533 509{
21cf3227 510 struct strbuf sb = STRBUF_INIT;
26c8a533 511 va_list args;
26c8a533 512 va_start(args, fmt);
21cf3227 513 strbuf_vaddf(&sb, fmt, args);
26c8a533 514 va_end(args);
4ef9caf5
NTND
515 strbuf_cleanup_path(&sb);
516 return strbuf_detach(&sb, NULL);
26c8a533
LT
517}
518
dcf69262 519const char *mkpath(const char *fmt, ...)
26c8a533 520{
26c8a533 521 va_list args;
4ef9caf5 522 struct strbuf *pathname = get_pathname();
26c8a533 523 va_start(args, fmt);
4ef9caf5 524 strbuf_vaddf(pathname, fmt, args);
26c8a533 525 va_end(args);
4ef9caf5 526 return cleanup_path(pathname->buf);
26c8a533 527}
f2db68ed 528
2e641d58
NTND
529const char *worktree_git_path(const struct worktree *wt, const char *fmt, ...)
530{
531 struct strbuf *pathname = get_pathname();
532 va_list args;
533 va_start(args, fmt);
f9a8a47e 534 do_git_path(the_repository, wt, pathname, fmt, args);
2e641d58
NTND
535 va_end(args);
536 return pathname->buf;
537}
538
b42b0c09
BW
539static void do_worktree_path(const struct repository *repo,
540 struct strbuf *buf,
541 const char *fmt, va_list args)
542{
543 strbuf_addstr(buf, repo->worktree);
544 if(buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
545 strbuf_addch(buf, '/');
546
547 strbuf_vaddf(buf, fmt, args);
548 strbuf_cleanup_path(buf);
549}
550
551char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
552{
553 struct strbuf path = STRBUF_INIT;
554 va_list args;
555
556 if (!repo->worktree)
557 return NULL;
558
559 va_start(args, fmt);
560 do_worktree_path(repo, &path, fmt, args);
561 va_end(args);
562
563 return strbuf_detach(&path, NULL);
564}
565
566void strbuf_repo_worktree_path(struct strbuf *sb,
567 const struct repository *repo,
568 const char *fmt, ...)
569{
570 va_list args;
571
572 if (!repo->worktree)
573 return;
574
575 va_start(args, fmt);
576 do_worktree_path(repo, sb, fmt, args);
577 va_end(args);
578}
579
99b43a61 580/* Returns 0 on success, negative on failure. */
99b43a61
JK
581static int do_submodule_path(struct strbuf *buf, const char *path,
582 const char *fmt, va_list args)
0bad611b 583{
11f9dd71
MK
584 struct strbuf git_submodule_common_dir = STRBUF_INIT;
585 struct strbuf git_submodule_dir = STRBUF_INIT;
bbbb7de7 586 int ret;
0bad611b 587
bbbb7de7
NTND
588 ret = submodule_to_gitdir(&git_submodule_dir, path);
589 if (ret)
590 goto cleanup;
0bad611b 591
bbbb7de7
NTND
592 strbuf_complete(&git_submodule_dir, '/');
593 strbuf_addbuf(buf, &git_submodule_dir);
4ef9caf5 594 strbuf_vaddf(buf, fmt, args);
11f9dd71
MK
595
596 if (get_common_dir_noenv(&git_submodule_common_dir, git_submodule_dir.buf))
597 update_common_dir(buf, git_submodule_dir.len, git_submodule_common_dir.buf);
598
4ef9caf5 599 strbuf_cleanup_path(buf);
11f9dd71 600
99b43a61 601cleanup:
11f9dd71
MK
602 strbuf_release(&git_submodule_dir);
603 strbuf_release(&git_submodule_common_dir);
bbbb7de7 604 return ret;
f5895fd3
JK
605}
606
f5895fd3
JK
607char *git_pathdup_submodule(const char *path, const char *fmt, ...)
608{
99b43a61 609 int err;
f5895fd3
JK
610 va_list args;
611 struct strbuf buf = STRBUF_INIT;
612 va_start(args, fmt);
99b43a61 613 err = do_submodule_path(&buf, path, fmt, args);
f5895fd3 614 va_end(args);
99b43a61
JK
615 if (err) {
616 strbuf_release(&buf);
617 return NULL;
618 }
f5895fd3
JK
619 return strbuf_detach(&buf, NULL);
620}
621
99b43a61
JK
622int strbuf_git_path_submodule(struct strbuf *buf, const char *path,
623 const char *fmt, ...)
f5895fd3 624{
99b43a61 625 int err;
f5895fd3
JK
626 va_list args;
627 va_start(args, fmt);
99b43a61 628 err = do_submodule_path(buf, path, fmt, args);
f5895fd3 629 va_end(args);
99b43a61
JK
630
631 return err;
f5895fd3
JK
632}
633
b337172c
BW
634static void do_git_common_path(const struct repository *repo,
635 struct strbuf *buf,
15cdfea7
NTND
636 const char *fmt,
637 va_list args)
638{
b337172c 639 strbuf_addstr(buf, repo->commondir);
15cdfea7
NTND
640 if (buf->len && !is_dir_sep(buf->buf[buf->len - 1]))
641 strbuf_addch(buf, '/');
642 strbuf_vaddf(buf, fmt, args);
643 strbuf_cleanup_path(buf);
644}
645
646const char *git_common_path(const char *fmt, ...)
647{
648 struct strbuf *pathname = get_pathname();
649 va_list args;
650 va_start(args, fmt);
b337172c 651 do_git_common_path(the_repository, pathname, fmt, args);
15cdfea7
NTND
652 va_end(args);
653 return pathname->buf;
654}
655
b337172c
BW
656void strbuf_git_common_path(struct strbuf *sb,
657 const struct repository *repo,
658 const char *fmt, ...)
15cdfea7
NTND
659{
660 va_list args;
661 va_start(args, fmt);
b337172c 662 do_git_common_path(repo, sb, fmt, args);
15cdfea7
NTND
663 va_end(args);
664}
665
c847f537 666int validate_headref(const char *path)
0870ca7f
JH
667{
668 struct stat st;
7eb4b9d0
JK
669 char buffer[256];
670 const char *refname;
0bca165f 671 struct object_id oid;
0104ca09
HO
672 int fd;
673 ssize_t len;
0870ca7f
JH
674
675 if (lstat(path, &st) < 0)
676 return -1;
677
678 /* Make sure it is a "refs/.." symlink */
679 if (S_ISLNK(st.st_mode)) {
680 len = readlink(path, buffer, sizeof(buffer)-1);
222b1673 681 if (len >= 5 && !memcmp("refs/", buffer, 5))
0870ca7f
JH
682 return 0;
683 return -1;
684 }
685
686 /*
687 * Anything else, just open it and try to see if it is a symbolic ref.
688 */
689 fd = open(path, O_RDONLY);
690 if (fd < 0)
691 return -1;
93d26e4c 692 len = read_in_full(fd, buffer, sizeof(buffer)-1);
0870ca7f
JH
693 close(fd);
694
6e68c914
JK
695 if (len < 0)
696 return -1;
697 buffer[len] = '\0';
698
0870ca7f
JH
699 /*
700 * Is it a symbolic ref?
701 */
7eb4b9d0
JK
702 if (skip_prefix(buffer, "ref:", &refname)) {
703 while (isspace(*refname))
704 refname++;
705 if (starts_with(refname, "refs/"))
c847f537
JH
706 return 0;
707 }
708
709 /*
710 * Is this a detached HEAD?
711 */
0bca165f 712 if (!get_oid_hex(buffer, &oid))
0870ca7f 713 return 0;
c847f537 714
0870ca7f
JH
715 return -1;
716}
717
395de250 718static struct passwd *getpw_str(const char *username, size_t len)
54f4b874 719{
d79374c7 720 struct passwd *pw;
5c0b13f8 721 char *username_z = xmemdupz(username, len);
395de250
MM
722 pw = getpwnam(username_z);
723 free(username_z);
724 return pw;
725}
54f4b874 726
395de250 727/*
789f6f22
JS
728 * Return a string with ~ and ~user expanded via getpw*. Returns NULL on getpw
729 * failure or if path is NULL.
4aad2f16 730 *
644e6b2c 731 * If real_home is true, strbuf_realpath($HOME) is used in the `~/` expansion.
e394a160
JS
732 *
733 * If the path starts with `%(prefix)/`, the remainder is interpreted as
734 * relative to where Git is installed, and expanded to the absolute path.
395de250 735 */
a03b097d 736char *interpolate_path(const char *path, int real_home)
395de250
MM
737{
738 struct strbuf user_path = STRBUF_INIT;
395de250
MM
739 const char *to_copy = path;
740
afe8a907 741 if (!path)
395de250 742 goto return_null;
e394a160
JS
743
744 if (skip_prefix(path, "%(prefix)/", &path))
745 return system_path(path);
746
395de250 747 if (path[0] == '~') {
53ec551c 748 const char *first_slash = strchrnul(path, '/');
395de250
MM
749 const char *username = path + 1;
750 size_t username_len = first_slash - username;
df2a79f4
MM
751 if (username_len == 0) {
752 const char *home = getenv("HOME");
79bf1490
JN
753 if (!home)
754 goto return_null;
4aad2f16 755 if (real_home)
fa2bb344 756 strbuf_add_real_path(&user_path, home);
4aad2f16
NTND
757 else
758 strbuf_addstr(&user_path, home);
5ca6b7bb
JS
759#ifdef GIT_WINDOWS_NATIVE
760 convert_slashes(user_path.buf);
761#endif
df2a79f4
MM
762 } else {
763 struct passwd *pw = getpw_str(username, username_len);
764 if (!pw)
765 goto return_null;
cedc61a9 766 strbuf_addstr(&user_path, pw->pw_dir);
54f4b874 767 }
395de250 768 to_copy = first_slash;
d79374c7 769 }
cedc61a9 770 strbuf_addstr(&user_path, to_copy);
395de250
MM
771 return strbuf_detach(&user_path, NULL);
772return_null:
773 strbuf_release(&user_path);
774 return NULL;
54f4b874
AE
775}
776
d79374c7
JH
777/*
778 * First, one directory to try is determined by the following algorithm.
779 *
780 * (0) If "strict" is given, the path is used as given and no DWIM is
781 * done. Otherwise:
782 * (1) "~/path" to mean path under the running user's home directory;
783 * (2) "~user/path" to mean path under named user's home directory;
784 * (3) "relative/path" to mean cwd relative directory; or
785 * (4) "/absolute/path" to mean absolute directory.
786 *
c8c3f1d0
PT
787 * Unless "strict" is given, we check "%s/.git", "%s", "%s.git/.git", "%s.git"
788 * in this order. We select the first one that is a valid git repository, and
789 * chdir() to it. If none match, or we fail to chdir, we return NULL.
d79374c7
JH
790 *
791 * If all goes well, we return the directory we used to chdir() (but
792 * before ~user is expanded), avoiding getcwd() resolving symbolic
793 * links. User relative paths are also returned as they are given,
794 * except DWIM suffixing.
795 */
1c64b48e 796const char *enter_repo(const char *path, int strict)
54f4b874 797{
e9ba6781
JK
798 static struct strbuf validated_path = STRBUF_INIT;
799 static struct strbuf used_path = STRBUF_INIT;
d79374c7
JH
800
801 if (!path)
54f4b874
AE
802 return NULL;
803
d79374c7
JH
804 if (!strict) {
805 static const char *suffix[] = {
b3256eb8 806 "/.git", "", ".git/.git", ".git", NULL,
d79374c7 807 };
03106768 808 const char *gitfile;
d79374c7
JH
809 int len = strlen(path);
810 int i;
1c64b48e 811 while ((1 < len) && (path[len-1] == '/'))
d79374c7 812 len--;
1c64b48e 813
e9ba6781
JK
814 /*
815 * We can handle arbitrary-sized buffers, but this remains as a
816 * sanity check on untrusted input.
817 */
d79374c7 818 if (PATH_MAX <= len)
54f4b874 819 return NULL;
1c64b48e 820
e9ba6781
JK
821 strbuf_reset(&used_path);
822 strbuf_reset(&validated_path);
823 strbuf_add(&used_path, path, len);
824 strbuf_add(&validated_path, path, len);
825
826 if (used_path.buf[0] == '~') {
a03b097d 827 char *newpath = interpolate_path(used_path.buf, 0);
e9ba6781 828 if (!newpath)
d79374c7 829 return NULL;
e9ba6781
JK
830 strbuf_attach(&used_path, newpath, strlen(newpath),
831 strlen(newpath));
d79374c7 832 }
d79374c7 833 for (i = 0; suffix[i]; i++) {
b3256eb8 834 struct stat st;
e9ba6781
JK
835 size_t baselen = used_path.len;
836 strbuf_addstr(&used_path, suffix[i]);
837 if (!stat(used_path.buf, &st) &&
b3256eb8 838 (S_ISREG(st.st_mode) ||
e9ba6781
JK
839 (S_ISDIR(st.st_mode) && is_git_directory(used_path.buf)))) {
840 strbuf_addstr(&validated_path, suffix[i]);
d79374c7
JH
841 break;
842 }
e9ba6781 843 strbuf_setlen(&used_path, baselen);
d79374c7 844 }
03106768
PH
845 if (!suffix[i])
846 return NULL;
78891795 847 gitfile = read_gitfile(used_path.buf);
e9ba6781
JK
848 if (gitfile) {
849 strbuf_reset(&used_path);
850 strbuf_addstr(&used_path, gitfile);
851 }
852 if (chdir(used_path.buf))
0870ca7f 853 return NULL;
e9ba6781 854 path = validated_path.buf;
0870ca7f 855 }
1f5fbe1f
NTND
856 else {
857 const char *gitfile = read_gitfile(path);
858 if (gitfile)
859 path = gitfile;
860 if (chdir(path))
861 return NULL;
862 }
54f4b874 863
0f64cc40 864 if (is_git_directory(".")) {
0915a5b4 865 set_git_dir(".", 0);
cfe3917c 866 check_repository_format(NULL);
d79374c7 867 return path;
54f4b874
AE
868 }
869
870 return NULL;
871}
138086a7 872
cbe43b84 873static int calc_shared_perm(int mode)
138086a7 874{
cbe43b84 875 int tweak;
138086a7 876
7875acb6
JK
877 if (get_shared_repository() < 0)
878 tweak = -get_shared_repository();
5a688fe4 879 else
7875acb6 880 tweak = get_shared_repository();
5a688fe4
JH
881
882 if (!(mode & S_IWUSR))
883 tweak &= ~0222;
884 if (mode & S_IXUSR)
885 /* Copy read bits to execute bits */
886 tweak |= (tweak & 0444) >> 2;
7875acb6 887 if (get_shared_repository() < 0)
5a688fe4
JH
888 mode = (mode & ~0777) | tweak;
889 else
8c6202d8 890 mode |= tweak;
06cbe855 891
cbe43b84
TB
892 return mode;
893}
894
895
896int adjust_shared_perm(const char *path)
897{
898 int old_mode, new_mode;
899
7875acb6 900 if (!get_shared_repository())
cbe43b84
TB
901 return 0;
902 if (get_st_mode_bits(path, &old_mode) < 0)
903 return -1;
904
905 new_mode = calc_shared_perm(old_mode);
906 if (S_ISDIR(old_mode)) {
06cbe855 907 /* Copy read bits to execute bits */
cbe43b84 908 new_mode |= (new_mode & 0444) >> 2;
671bbf7b
JH
909
910 /*
911 * g+s matters only if any extra access is granted
912 * based on group membership.
913 */
914 if (FORCE_DIR_SET_GID && (new_mode & 060))
915 new_mode |= FORCE_DIR_SET_GID;
06cbe855
HO
916 }
917
cbe43b84
TB
918 if (((old_mode ^ new_mode) & ~S_IFMT) &&
919 chmod(path, (new_mode & ~S_IFMT)) < 0)
138086a7
JH
920 return -2;
921 return 0;
922}
e5392c51 923
eb33876c
DT
924void safe_create_dir(const char *dir, int share)
925{
926 if (mkdir(dir, 0777) < 0) {
927 if (errno != EEXIST) {
928 perror(dir);
929 exit(1);
930 }
931 }
932 else if (share && adjust_shared_perm(dir))
933 die(_("Could not make %s writable by group"), dir);
934}
935
7fbd4221
JX
936static int have_same_root(const char *path1, const char *path2)
937{
938 int is_abs1, is_abs2;
939
940 is_abs1 = is_absolute_path(path1);
941 is_abs2 = is_absolute_path(path2);
942 return (is_abs1 && is_abs2 && tolower(path1[0]) == tolower(path2[0])) ||
943 (!is_abs1 && !is_abs2);
944}
945
e02ca72f
JX
946/*
947 * Give path as relative to prefix.
948 *
949 * The strbuf may or may not be used, so do not assume it contains the
950 * returned path.
951 */
952const char *relative_path(const char *in, const char *prefix,
953 struct strbuf *sb)
044bbbcb 954{
e02ca72f
JX
955 int in_len = in ? strlen(in) : 0;
956 int prefix_len = prefix ? strlen(prefix) : 0;
957 int in_off = 0;
958 int prefix_off = 0;
288123f0
JH
959 int i = 0, j = 0;
960
e02ca72f
JX
961 if (!in_len)
962 return "./";
963 else if (!prefix_len)
964 return in;
965
2f36eed9 966 if (have_same_root(in, prefix))
7fbd4221 967 /* bypass dos_drive, for "c:" is identical to "C:" */
2f36eed9
JS
968 i = j = has_dos_drive_prefix(in);
969 else {
7fbd4221
JX
970 return in;
971 }
972
e02ca72f
JX
973 while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
974 if (is_dir_sep(prefix[i])) {
975 while (is_dir_sep(prefix[i]))
288123f0 976 i++;
e02ca72f
JX
977 while (is_dir_sep(in[j]))
978 j++;
979 prefix_off = i;
980 in_off = j;
981 } else {
982 i++;
983 j++;
984 }
985 }
986
987 if (
988 /* "prefix" seems like prefix of "in" */
989 i >= prefix_len &&
990 /*
991 * but "/foo" is not a prefix of "/foobar"
992 * (i.e. prefix not end with '/')
993 */
994 prefix_off < prefix_len) {
995 if (j >= in_len) {
996 /* in="/a/b", prefix="/a/b" */
997 in_off = in_len;
998 } else if (is_dir_sep(in[j])) {
999 /* in="/a/b/c", prefix="/a/b" */
1000 while (is_dir_sep(in[j]))
288123f0 1001 j++;
e02ca72f
JX
1002 in_off = j;
1003 } else {
1004 /* in="/a/bbb/c", prefix="/a/b" */
1005 i = prefix_off;
1006 }
1007 } else if (
1008 /* "in" is short than "prefix" */
1009 j >= in_len &&
1010 /* "in" not end with '/' */
1011 in_off < in_len) {
1012 if (is_dir_sep(prefix[i])) {
1013 /* in="/a/b", prefix="/a/b/c/" */
1014 while (is_dir_sep(prefix[i]))
1015 i++;
1016 in_off = in_len;
1017 }
1018 }
1019 in += in_off;
1020 in_len -= in_off;
1021
1022 if (i >= prefix_len) {
1023 if (!in_len)
1024 return "./";
1025 else
1026 return in;
1027 }
1028
1029 strbuf_reset(sb);
1030 strbuf_grow(sb, in_len);
1031
1032 while (i < prefix_len) {
1033 if (is_dir_sep(prefix[i])) {
1034 strbuf_addstr(sb, "../");
1035 while (is_dir_sep(prefix[i]))
1036 i++;
288123f0 1037 continue;
288123f0
JH
1038 }
1039 i++;
288123f0 1040 }
e02ca72f
JX
1041 if (!is_dir_sep(prefix[prefix_len - 1]))
1042 strbuf_addstr(sb, "../");
1043
1044 strbuf_addstr(sb, in);
1045
1046 return sb->buf;
044bbbcb 1047}
ae299be0 1048
41894ae3
JX
1049/*
1050 * A simpler implementation of relative_path
1051 *
1052 * Get relative path by removing "prefix" from "in". This function
1053 * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
1054 * to increase performance when traversing the path to work_tree.
1055 */
1056const char *remove_leading_path(const char *in, const char *prefix)
1057{
46357688 1058 static struct strbuf buf = STRBUF_INIT;
41894ae3
JX
1059 int i = 0, j = 0;
1060
1061 if (!prefix || !prefix[0])
1062 return in;
1063 while (prefix[i]) {
1064 if (is_dir_sep(prefix[i])) {
1065 if (!is_dir_sep(in[j]))
1066 return in;
1067 while (is_dir_sep(prefix[i]))
1068 i++;
1069 while (is_dir_sep(in[j]))
1070 j++;
1071 continue;
1072 } else if (in[j] != prefix[i]) {
1073 return in;
1074 }
1075 i++;
1076 j++;
1077 }
1078 if (
1079 /* "/foo" is a prefix of "/foo" */
1080 in[j] &&
1081 /* "/foo" is not a prefix of "/foobar" */
1082 !is_dir_sep(prefix[i-1]) && !is_dir_sep(in[j])
1083 )
1084 return in;
1085 while (is_dir_sep(in[j]))
1086 j++;
46357688
JK
1087
1088 strbuf_reset(&buf);
41894ae3 1089 if (!in[j])
46357688 1090 strbuf_addstr(&buf, ".");
41894ae3 1091 else
46357688
JK
1092 strbuf_addstr(&buf, in + j);
1093 return buf.buf;
41894ae3
JX
1094}
1095
ae299be0 1096/*
f2a782b8 1097 * It is okay if dst == src, but they should not overlap otherwise.
9734b74a
JK
1098 * The "dst" buffer must be at least as long as "src"; normalizing may shrink
1099 * the size of the path, but will never grow it.
ae299be0 1100 *
f2a782b8
JS
1101 * Performs the following normalizations on src, storing the result in dst:
1102 * - Ensures that components are separated by '/' (Windows only)
7814fbe3 1103 * - Squashes sequences of '/' except "//server/share" on Windows
ae299be0
DR
1104 * - Removes "." components.
1105 * - Removes ".." components, and the components the precede them.
f2a782b8
JS
1106 * Returns failure (non-zero) if a ".." component appears as first path
1107 * component anytime during the normalization. Otherwise, returns success (0).
ae299be0
DR
1108 *
1109 * Note that this function is purely textual. It does not follow symlinks,
1110 * verify the existence of the path, or make any system calls.
645a29c4
NTND
1111 *
1112 * prefix_len != NULL is for a specific case of prefix_pathspec():
1113 * assume that src == dst and src[0..prefix_len-1] is already
1114 * normalized, any time "../" eats up to the prefix_len part,
1115 * prefix_len is reduced. In the end prefix_len is the remaining
1116 * prefix that has not been overridden by user pathspec.
b2a7123b
RD
1117 *
1118 * NEEDSWORK: This function doesn't perform normalization w.r.t. trailing '/'.
1119 * For everything but the root folder itself, the normalized path should not
1120 * end with a '/', then the callers need to be fixed up accordingly.
1121 *
ae299be0 1122 */
645a29c4 1123int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
ae299be0 1124{
f3cad0ad 1125 char *dst0;
7814fbe3 1126 const char *end;
ae299be0 1127
7814fbe3
JS
1128 /*
1129 * Copy initial part of absolute path: "/", "C:/", "//server/share/".
1130 */
1131 end = src + offset_1st_component(src);
1132 while (src < end) {
1133 char c = *src++;
1134 if (is_dir_sep(c))
1135 c = '/';
1136 *dst++ = c;
1137 }
f3cad0ad 1138 dst0 = dst;
ae299be0 1139
7814fbe3
JS
1140 while (is_dir_sep(*src))
1141 src++;
f3cad0ad
JS
1142
1143 for (;;) {
1144 char c = *src;
1145
1146 /*
1147 * A path component that begins with . could be
1148 * special:
1149 * (1) "." and ends -- ignore and terminate.
1150 * (2) "./" -- ignore them, eat slash and continue.
1151 * (3) ".." and ends -- strip one and terminate.
1152 * (4) "../" -- strip one, eat slash and continue.
1153 */
1154 if (c == '.') {
1155 if (!src[1]) {
1156 /* (1) */
1157 src++;
1158 } else if (is_dir_sep(src[1])) {
1159 /* (2) */
1160 src += 2;
1161 while (is_dir_sep(*src))
1162 src++;
1163 continue;
1164 } else if (src[1] == '.') {
1165 if (!src[2]) {
1166 /* (3) */
1167 src += 2;
1168 goto up_one;
1169 } else if (is_dir_sep(src[2])) {
1170 /* (4) */
1171 src += 3;
1172 while (is_dir_sep(*src))
1173 src++;
1174 goto up_one;
1175 }
1176 }
1177 }
ae299be0 1178
f3cad0ad
JS
1179 /* copy up to the next '/', and eat all '/' */
1180 while ((c = *src++) != '\0' && !is_dir_sep(c))
1181 *dst++ = c;
1182 if (is_dir_sep(c)) {
1183 *dst++ = '/';
1184 while (is_dir_sep(c))
1185 c = *src++;
1186 src--;
1187 } else if (!c)
1188 break;
1189 continue;
1190
1191 up_one:
1192 /*
1193 * dst0..dst is prefix portion, and dst[-1] is '/';
1194 * go up one level.
1195 */
f42302b4
JS
1196 dst--; /* go to trailing '/' */
1197 if (dst <= dst0)
f3cad0ad 1198 return -1;
f42302b4
JS
1199 /* Windows: dst[-1] cannot be backslash anymore */
1200 while (dst0 < dst && dst[-1] != '/')
1201 dst--;
645a29c4
NTND
1202 if (prefix_len && *prefix_len > dst - dst0)
1203 *prefix_len = dst - dst0;
f3cad0ad 1204 }
ae299be0 1205 *dst = '\0';
f3cad0ad 1206 return 0;
ae299be0 1207}
0454dd93 1208
645a29c4
NTND
1209int normalize_path_copy(char *dst, const char *src)
1210{
1211 return normalize_path_copy_len(dst, src, NULL);
1212}
1213
0454dd93
DR
1214/*
1215 * path = Canonical absolute path
9e2326c7
MH
1216 * prefixes = string_list containing normalized, absolute paths without
1217 * trailing slashes (except for the root directory, which is denoted by "/").
0454dd93 1218 *
9e2326c7 1219 * Determines, for each path in prefixes, whether the "prefix"
0454dd93
DR
1220 * is an ancestor directory of path. Returns the length of the longest
1221 * ancestor directory, excluding any trailing slashes, or -1 if no prefix
31171d9e
MH
1222 * is an ancestor. (Note that this means 0 is returned if prefixes is
1223 * ["/"].) "/foo" is not considered an ancestor of "/foobar". Directories
0454dd93
DR
1224 * are not considered to be their own ancestors. path must be in a
1225 * canonical form: empty components, or "." or ".." components are not
9e2326c7 1226 * allowed.
0454dd93 1227 */
31171d9e 1228int longest_ancestor_length(const char *path, struct string_list *prefixes)
0454dd93 1229{
a5ccdbe4 1230 int i, max_len = -1;
0454dd93 1231
31171d9e 1232 if (!strcmp(path, "/"))
0454dd93
DR
1233 return -1;
1234
31171d9e
MH
1235 for (i = 0; i < prefixes->nr; i++) {
1236 const char *ceil = prefixes->items[i].string;
a5ccdbe4
MH
1237 int len = strlen(ceil);
1238
fdcad5a5
JS
1239 /*
1240 * For root directories (`/`, `C:/`, `//server/share/`)
1241 * adjust the length to exclude the trailing slash.
1242 */
1243 if (len > 0 && ceil[len - 1] == '/')
1244 len--;
1245
1246 if (strncmp(path, ceil, len) ||
1247 path[len] != '/' || !path[len + 1])
9e2326c7 1248 continue; /* no match */
0454dd93 1249
9e2326c7 1250 if (len > max_len)
0454dd93 1251 max_len = len;
0454dd93
DR
1252 }
1253
1254 return max_len;
1255}
4fcc86b0
JS
1256
1257/* strip arbitrary amount of directory separators at end of path */
1258static inline int chomp_trailing_dir_sep(const char *path, int len)
1259{
1260 while (len && is_dir_sep(path[len - 1]))
1261 len--;
1262 return len;
1263}
1264
1265/*
ce17feb1 1266 * If path ends with suffix (complete path components), returns the offset of
1267 * the last character in the path before the suffix (sans trailing directory
1268 * separators), and -1 otherwise.
4fcc86b0 1269 */
ce17feb1 1270static ssize_t stripped_path_suffix_offset(const char *path, const char *suffix)
4fcc86b0
JS
1271{
1272 int path_len = strlen(path), suffix_len = strlen(suffix);
1273
1274 while (suffix_len) {
1275 if (!path_len)
ce17feb1 1276 return -1;
4fcc86b0
JS
1277
1278 if (is_dir_sep(path[path_len - 1])) {
1279 if (!is_dir_sep(suffix[suffix_len - 1]))
ce17feb1 1280 return -1;
4fcc86b0
JS
1281 path_len = chomp_trailing_dir_sep(path, path_len);
1282 suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
1283 }
1284 else if (path[--path_len] != suffix[--suffix_len])
ce17feb1 1285 return -1;
4fcc86b0
JS
1286 }
1287
1288 if (path_len && !is_dir_sep(path[path_len - 1]))
ce17feb1 1289 return -1;
1290 return chomp_trailing_dir_sep(path, path_len);
1291}
1292
1293/*
1294 * Returns true if the path ends with components, considering only complete path
1295 * components, and false otherwise.
1296 */
1297int ends_with_path_components(const char *path, const char *components)
1298{
1299 return stripped_path_suffix_offset(path, components) != -1;
1300}
1301
1302/*
1303 * If path ends with suffix (complete path components), returns the
1304 * part before suffix (sans trailing directory separators).
1305 * Otherwise returns NULL.
1306 */
1307char *strip_path_suffix(const char *path, const char *suffix)
1308{
1309 ssize_t offset = stripped_path_suffix_offset(path, suffix);
1310
1311 return offset == -1 ? NULL : xstrndup(path, offset);
4fcc86b0 1312}
34b6cb8b
SP
1313
1314int daemon_avoid_alias(const char *p)
1315{
1316 int sl, ndot;
1317
1318 /*
1319 * This resurrects the belts and suspenders paranoia check by HPA
1320 * done in <435560F7.4080006@zytor.com> thread, now enter_repo()
9517e6b8 1321 * does not do getcwd() based path canonicalization.
34b6cb8b
SP
1322 *
1323 * sl becomes true immediately after seeing '/' and continues to
1324 * be true as long as dots continue after that without intervening
1325 * non-dot character.
1326 */
1327 if (!p || (*p != '/' && *p != '~'))
1328 return -1;
1329 sl = 1; ndot = 0;
1330 p++;
1331
1332 while (1) {
1333 char ch = *p++;
1334 if (sl) {
1335 if (ch == '.')
1336 ndot++;
1337 else if (ch == '/') {
1338 if (ndot < 3)
1339 /* reject //, /./ and /../ */
1340 return -1;
1341 ndot = 0;
1342 }
1343 else if (ch == 0) {
1344 if (0 < ndot && ndot < 3)
1345 /* reject /.$ and /..$ */
1346 return -1;
1347 return 0;
1348 }
1349 else
1350 sl = ndot = 0;
1351 }
1352 else if (ch == 0)
1353 return 0;
1354 else if (ch == '/') {
1355 sl = 1;
1356 ndot = 0;
1357 }
1358 }
1359}
4bb43de2 1360
525e7fba
JS
1361/*
1362 * On NTFS, we need to be careful to disallow certain synonyms of the `.git/`
1363 * directory:
1364 *
1365 * - For historical reasons, file names that end in spaces or periods are
1366 * automatically trimmed. Therefore, `.git . . ./` is a valid way to refer
1367 * to `.git/`.
1368 *
1369 * - For other historical reasons, file names that do not conform to the 8.3
1370 * format (up to eight characters for the basename, three for the file
1371 * extension, certain characters not allowed such as `+`, etc) are associated
1372 * with a so-called "short name", at least on the `C:` drive by default.
1373 * Which means that `git~1/` is a valid way to refer to `.git/`.
1374 *
1375 * Note: Technically, `.git/` could receive the short name `git~2` if the
1376 * short name `git~1` were already used. In Git, however, we guarantee that
1377 * `.git` is the first item in a directory, therefore it will be associated
1378 * with the short name `git~1` (unless short names are disabled).
1379 *
7c3745fc
JS
1380 * - For yet other historical reasons, NTFS supports so-called "Alternate Data
1381 * Streams", i.e. metadata associated with a given file, referred to via
1382 * `<filename>:<stream-name>:<stream-type>`. There exists a default stream
1383 * type for directories, allowing `.git/` to be accessed via
1384 * `.git::$INDEX_ALLOCATION/`.
1385 *
525e7fba
JS
1386 * When this function returns 1, it indicates that the specified file/directory
1387 * name refers to a `.git` file or directory, or to any of these synonyms, and
1388 * Git should therefore not track it.
1389 *
7c3745fc
JS
1390 * For performance reasons, _all_ Alternate Data Streams of `.git/` are
1391 * forbidden, not just `::$INDEX_ALLOCATION`.
1392 *
525e7fba
JS
1393 * This function is intended to be used by `git fsck` even on platforms where
1394 * the backslash is a regular filename character, therefore it needs to handle
1395 * backlash characters in the provided `name` specially: they are interpreted
1396 * as directory separators.
1397 */
1d1d69bc 1398int is_ntfs_dotgit(const char *name)
1d1d69bc 1399{
3a85dc7d
JS
1400 char c;
1401
1402 /*
1403 * Note that when we don't find `.git` or `git~1` we end up with `name`
1404 * advanced partway through the string. That's okay, though, as we
1405 * return immediately in those cases, without looking at `name` any
1406 * further.
1407 */
1408 c = *(name++);
1409 if (c == '.') {
1410 /* .git */
1411 if (((c = *(name++)) != 'g' && c != 'G') ||
1412 ((c = *(name++)) != 'i' && c != 'I') ||
1413 ((c = *(name++)) != 't' && c != 'T'))
288a74bc 1414 return 0;
3a85dc7d
JS
1415 } else if (c == 'g' || c == 'G') {
1416 /* git ~1 */
1417 if (((c = *(name++)) != 'i' && c != 'I') ||
1418 ((c = *(name++)) != 't' && c != 'T') ||
1419 *(name++) != '~' ||
1420 *(name++) != '1')
1421 return 0;
1422 } else
1d1d69bc 1423 return 0;
3a85dc7d
JS
1424
1425 for (;;) {
1426 c = *(name++);
9fd512c8 1427 if (!c || is_xplatform_dir_sep(c) || c == ':')
3a85dc7d
JS
1428 return 1;
1429 if (c != '.' && c != ' ')
1d1d69bc
JS
1430 return 0;
1431 }
1d1d69bc 1432}
ea19289b 1433
e7cb0b44
JS
1434static int is_ntfs_dot_generic(const char *name,
1435 const char *dotgit_name,
1436 size_t len,
1437 const char *dotgit_ntfs_shortname_prefix)
1438{
1439 int saw_tilde;
1440 size_t i;
1441
1442 if ((name[0] == '.' && !strncasecmp(name + 1, dotgit_name, len))) {
1443 i = len + 1;
1444only_spaces_and_periods:
1445 for (;;) {
1446 char c = name[i++];
91bd4658 1447 if (!c || c == ':')
e7cb0b44
JS
1448 return 1;
1449 if (c != ' ' && c != '.')
1450 return 0;
1451 }
1452 }
1453
1454 /*
1455 * Is it a regular NTFS short name, i.e. shortened to 6 characters,
1456 * followed by ~1, ... ~4?
1457 */
1458 if (!strncasecmp(name, dotgit_name, 6) && name[6] == '~' &&
1459 name[7] >= '1' && name[7] <= '4') {
1460 i = 8;
1461 goto only_spaces_and_periods;
1462 }
1463
1464 /*
1465 * Is it a fall-back NTFS short name (for details, see
1466 * https://en.wikipedia.org/wiki/8.3_filename?
1467 */
1468 for (i = 0, saw_tilde = 0; i < 8; i++)
1469 if (name[i] == '\0')
1470 return 0;
1471 else if (saw_tilde) {
1472 if (name[i] < '0' || name[i] > '9')
1473 return 0;
1474 } else if (name[i] == '~') {
1475 if (name[++i] < '1' || name[i] > '9')
1476 return 0;
1477 saw_tilde = 1;
1478 } else if (i >= 6)
1479 return 0;
30634774 1480 else if (name[i] & 0x80) {
e7cb0b44
JS
1481 /*
1482 * We know our needles contain only ASCII, so we clamp
1483 * here to make the results of tolower() sane.
1484 */
1485 return 0;
1486 } else if (tolower(name[i]) != dotgit_ntfs_shortname_prefix[i])
1487 return 0;
1488
1489 goto only_spaces_and_periods;
1490}
1491
1492/*
1493 * Inline helper to make sure compiler resolves strlen() on literals at
1494 * compile time.
1495 */
1496static inline int is_ntfs_dot_str(const char *name, const char *dotgit_name,
1497 const char *dotgit_ntfs_shortname_prefix)
1498{
1499 return is_ntfs_dot_generic(name, dotgit_name, strlen(dotgit_name),
1500 dotgit_ntfs_shortname_prefix);
1501}
1502
1503int is_ntfs_dotgitmodules(const char *name)
1504{
1505 return is_ntfs_dot_str(name, "gitmodules", "gi7eba");
1506}
1507
1508int is_ntfs_dotgitignore(const char *name)
1509{
1510 return is_ntfs_dot_str(name, "gitignore", "gi250a");
1511}
1512
1513int is_ntfs_dotgitattributes(const char *name)
1514{
1515 return is_ntfs_dot_str(name, "gitattributes", "gi7d29");
1516}
1517
801ed010
JK
1518int is_ntfs_dotmailmap(const char *name)
1519{
1520 return is_ntfs_dot_str(name, "mailmap", "maba30");
1521}
1522
2491f77b
JK
1523int looks_like_command_line_option(const char *str)
1524{
1525 return str && str[0] == '-';
1526}
1527
cb7db5bb 1528char *xdg_config_home_for(const char *subdir, const char *filename)
ea19289b
PT
1529{
1530 const char *home, *config_home;
1531
cb7db5bb 1532 assert(subdir);
ea19289b
PT
1533 assert(filename);
1534 config_home = getenv("XDG_CONFIG_HOME");
1535 if (config_home && *config_home)
cb7db5bb 1536 return mkpathdup("%s/%s/%s", config_home, subdir, filename);
ea19289b
PT
1537
1538 home = getenv("HOME");
1539 if (home)
cb7db5bb
LH
1540 return mkpathdup("%s/.config/%s/%s", home, subdir, filename);
1541
ea19289b
PT
1542 return NULL;
1543}
f932729c 1544
cb7db5bb
LH
1545char *xdg_config_home(const char *filename)
1546{
1547 return xdg_config_home_for("git", filename);
1548}
1549
e7f136bf
DL
1550char *xdg_cache_home(const char *filename)
1551{
1552 const char *home, *cache_home;
1553
1554 assert(filename);
1555 cache_home = getenv("XDG_CACHE_HOME");
1556 if (cache_home && *cache_home)
1557 return mkpathdup("%s/git/%s", cache_home, filename);
1558
1559 home = getenv("HOME");
1560 if (home)
1561 return mkpathdup("%s/.cache/git/%s", home, filename);
1562 return NULL;
1563}
1564
102de880
SB
1565REPO_GIT_PATH_FUNC(squash_msg, "SQUASH_MSG")
1566REPO_GIT_PATH_FUNC(merge_msg, "MERGE_MSG")
1567REPO_GIT_PATH_FUNC(merge_rr, "MERGE_RR")
1568REPO_GIT_PATH_FUNC(merge_mode, "MERGE_MODE")
1569REPO_GIT_PATH_FUNC(merge_head, "MERGE_HEAD")
a03b5553 1570REPO_GIT_PATH_FUNC(merge_autostash, "MERGE_AUTOSTASH")
5291828d 1571REPO_GIT_PATH_FUNC(auto_merge, "AUTO_MERGE")
102de880
SB
1572REPO_GIT_PATH_FUNC(fetch_head, "FETCH_HEAD")
1573REPO_GIT_PATH_FUNC(shallow, "shallow")