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