git/path.c

/*
 * Utilities for paths and pathnames
 */

#define USE_THE_REPOSITORY_VARIABLE

#include "git-compat-util.h"
#include "abspath.h"
#include "environment.h"
#include "gettext.h"
#include "repository.h"
#include "strbuf.h"
#include "string-list.h"
#include "dir.h"
#include "worktree.h"
#include "setup.h"
#include "submodule-config.h"
#include "path.h"
#include "packfile.h"
#include "object-store-ll.h"
#include "lockfile.h"
#include "exec-cmd.h"

static int get_st_mode_bits(const char *path, int *mode)
{}

struct strbuf *get_pathname(void)
{}

static const char *cleanup_path(const char *path)
{}

static void strbuf_cleanup_path(struct strbuf *sb)
{}

static int dir_prefix(const char *buf, const char *dir)
{}

/* $buf =~ m|$dir/+$file| but without regex */
static int is_dir_file(const char *buf, const char *dir, const char *file)
{}

static void replace_dir(struct strbuf *buf, int len, const char *newdir)
{}

struct common_dir {};

static struct common_dir common_list[] =;

/*
 * A compressed trie.  A trie node consists of zero or more characters that
 * are common to all elements with this prefix, optionally followed by some
 * children.  If value is not NULL, the trie node is a terminal node.
 *
 * For example, consider the following set of strings:
 * abc
 * def
 * definite
 * definition
 *
 * The trie would look like:
 * root: len = 0, children a and d non-NULL, value = NULL.
 *    a: len = 2, contents = bc, value = (data for "abc")
 *    d: len = 2, contents = ef, children i non-NULL, value = (data for "def")
 *       i: len = 3, contents = nit, children e and i non-NULL, value = NULL
 *           e: len = 0, children all NULL, value = (data for "definite")
 *           i: len = 2, contents = on, children all NULL,
 *              value = (data for "definition")
 */
struct trie {};

static struct trie *make_trie_node(const char *key, void *value)
{}

/*
 * Add a key/value pair to a trie.  The key is assumed to be \0-terminated.
 * If there was an existing value for this key, return it.
 */
static void *add_to_trie(struct trie *root, const char *key, void *value)
{}

match_fn;

/*
 * Search a trie for some key.  Find the longest /-or-\0-terminated
 * prefix of the key for which the trie contains a value.  If there is
 * no such prefix, return -1.  Otherwise call fn with the unmatched
 * portion of the key and the found value.  If fn returns 0 or
 * positive, then return its return value.  If fn returns negative,
 * then call fn with the next-longest /-terminated prefix of the key
 * (i.e. a parent directory) for which the trie contains a value, and
 * handle its return value the same way.  If there is no shorter
 * /-terminated prefix with a value left, then return the negative
 * return value of the most recent fn invocation.
 *
 * The key is partially normalized: consecutive slashes are skipped.
 *
 * For example, consider the trie containing only [logs,
 * logs/refs/bisect], both with values, but not logs/refs.
 *
 * | key                | unmatched      | prefix to node   | return value |
 * |--------------------|----------------|------------------|--------------|
 * | a                  | not called     | n/a              | -1           |
 * | logstore           | not called     | n/a              | -1           |
 * | logs               | \0             | logs             | as per fn    |
 * | logs/              | /              | logs             | as per fn    |
 * | logs/refs          | /refs          | logs             | as per fn    |
 * | logs/refs/         | /refs/         | logs             | as per fn    |
 * | logs/refs/b        | /refs/b        | logs             | as per fn    |
 * | logs/refs/bisected | /refs/bisected | logs             | as per fn    |
 * | logs/refs/bisect   | \0             | logs/refs/bisect | as per fn    |
 * | logs/refs/bisect/  | /              | logs/refs/bisect | as per fn    |
 * | logs/refs/bisect/a | /a             | logs/refs/bisect | as per fn    |
 * | (If fn in the previous line returns -1, then fn is called once more:) |
 * | logs/refs/bisect/a | /refs/bisect/a | logs             | as per fn    |
 * |--------------------|----------------|------------------|--------------|
 */
static int trie_find(struct trie *root, const char *key, match_fn fn,
		     void *baton)
{}

static struct trie common_trie;
static int common_trie_done_setup;

static void init_common_trie(void)
{}

/*
 * Helper function for update_common_dir: returns 1 if the dir
 * prefix is common.
 */
static int check_common(const char *unmatched, void *value,
			void *baton UNUSED)
{}

static void update_common_dir(struct strbuf *buf, int git_dir_len,
			      const char *common_dir)
{}

void report_linked_checkout_garbage(struct repository *r)
{}

static void adjust_git_path(const struct repository *repo,
			    struct strbuf *buf, int git_dir_len)
{}

static void strbuf_worktree_gitdir(struct strbuf *buf,
				   const struct repository *repo,
				   const struct worktree *wt)
{}

void repo_git_pathv(const struct repository *repo,
		    const struct worktree *wt, struct strbuf *buf,
		    const char *fmt, va_list args)
{}

char *repo_git_path(const struct repository *repo,
		    const char *fmt, ...)
{}

void strbuf_repo_git_path(struct strbuf *sb,
			  const struct repository *repo,
			  const char *fmt, ...)
{}

char *mkpathdup(const char *fmt, ...)
{}

const char *mkpath(const char *fmt, ...)
{}

const char *worktree_git_path(struct repository *r,
			      const struct worktree *wt, const char *fmt, ...)
{}

static void do_worktree_path(const struct repository *repo,
			     struct strbuf *buf,
			     const char *fmt, va_list args)
{}

char *repo_worktree_path(const struct repository *repo, const char *fmt, ...)
{}

void strbuf_repo_worktree_path(struct strbuf *sb,
			       const struct repository *repo,
			       const char *fmt, ...)
{}

/* Returns 0 on success, negative on failure. */
static int do_submodule_path(struct strbuf *buf, const char *path,
			     const char *fmt, va_list args)
{}

char *git_pathdup_submodule(const char *path, const char *fmt, ...)
{}

int strbuf_git_path_submodule(struct strbuf *buf, const char *path,
			      const char *fmt, ...)
{}

void repo_common_pathv(const struct repository *repo,
		       struct strbuf *sb,
		       const char *fmt,
		       va_list args)
{}

void strbuf_git_common_path(struct strbuf *sb,
			    const struct repository *repo,
			    const char *fmt, ...)
{}

static struct passwd *getpw_str(const char *username, size_t len)
{}

/*
 * Return a string with ~ and ~user expanded via getpw*. Returns NULL on getpw
 * failure or if path is NULL.
 *
 * If real_home is true, strbuf_realpath($HOME) is used in the `~/` expansion.
 *
 * If the path starts with `%(prefix)/`, the remainder is interpreted as
 * relative to where Git is installed, and expanded to the absolute path.
 */
char *interpolate_path(const char *path, int real_home)
{}

/*
 * First, one directory to try is determined by the following algorithm.
 *
 * (0) If "strict" is given, the path is used as given and no DWIM is
 *     done. Otherwise:
 * (1) "~/path" to mean path under the running user's home directory;
 * (2) "~user/path" to mean path under named user's home directory;
 * (3) "relative/path" to mean cwd relative directory; or
 * (4) "/absolute/path" to mean absolute directory.
 *
 * Unless "strict" is given, we check "%s/.git", "%s", "%s.git/.git", "%s.git"
 * in this order. We select the first one that is a valid git repository, and
 * chdir() to it. If none match, or we fail to chdir, we return NULL.
 *
 * If all goes well, we return the directory we used to chdir() (but
 * before ~user is expanded), avoiding getcwd() resolving symbolic
 * links.  User relative paths are also returned as they are given,
 * except DWIM suffixing.
 */
const char *enter_repo(const char *path, int strict)
{}

int calc_shared_perm(int mode)
{}


int adjust_shared_perm(const char *path)
{}

void safe_create_dir(const char *dir, int share)
{}

static int have_same_root(const char *path1, const char *path2)
{}

/*
 * Give path as relative to prefix.
 *
 * The strbuf may or may not be used, so do not assume it contains the
 * returned path.
 */
const char *relative_path(const char *in, const char *prefix,
			  struct strbuf *sb)
{}

/*
 * A simpler implementation of relative_path
 *
 * Get relative path by removing "prefix" from "in". This function
 * first appears in v1.5.6-1-g044bbbc, and makes git_dir shorter
 * to increase performance when traversing the path to work_tree.
 */
const char *remove_leading_path(const char *in, const char *prefix)
{}

/*
 * It is okay if dst == src, but they should not overlap otherwise.
 * The "dst" buffer must be at least as long as "src"; normalizing may shrink
 * the size of the path, but will never grow it.
 *
 * Performs the following normalizations on src, storing the result in dst:
 * - Ensures that components are separated by '/' (Windows only)
 * - Squashes sequences of '/' except "//server/share" on Windows
 * - Removes "." components.
 * - Removes ".." components, and the components the precede them.
 * Returns failure (non-zero) if a ".." component appears as first path
 * component anytime during the normalization. Otherwise, returns success (0).
 *
 * Note that this function is purely textual.  It does not follow symlinks,
 * verify the existence of the path, or make any system calls.
 *
 * prefix_len != NULL is for a specific case of prefix_pathspec():
 * assume that src == dst and src[0..prefix_len-1] is already
 * normalized, any time "../" eats up to the prefix_len part,
 * prefix_len is reduced. In the end prefix_len is the remaining
 * prefix that has not been overridden by user pathspec.
 *
 * NEEDSWORK: This function doesn't perform normalization w.r.t. trailing '/'.
 * For everything but the root folder itself, the normalized path should not
 * end with a '/', then the callers need to be fixed up accordingly.
 *
 */
int normalize_path_copy_len(char *dst, const char *src, int *prefix_len)
{}

int normalize_path_copy(char *dst, const char *src)
{}

int strbuf_normalize_path(struct strbuf *src)
{}

/*
 * path = Canonical absolute path
 * prefixes = string_list containing normalized, absolute paths without
 * trailing slashes (except for the root directory, which is denoted by "/").
 *
 * Determines, for each path in prefixes, whether the "prefix"
 * is an ancestor directory of path.  Returns the length of the longest
 * ancestor directory, excluding any trailing slashes, or -1 if no prefix
 * is an ancestor.  (Note that this means 0 is returned if prefixes is
 * ["/"].) "/foo" is not considered an ancestor of "/foobar".  Directories
 * are not considered to be their own ancestors.  path must be in a
 * canonical form: empty components, or "." or ".." components are not
 * allowed.
 */
int longest_ancestor_length(const char *path, struct string_list *prefixes)
{}

/* strip arbitrary amount of directory separators at end of path */
static inline int chomp_trailing_dir_sep(const char *path, int len)
{}

/*
 * If path ends with suffix (complete path components), returns the offset of
 * the last character in the path before the suffix (sans trailing directory
 * separators), and -1 otherwise.
 */
static ssize_t stripped_path_suffix_offset(const char *path, const char *suffix)
{}

/*
 * Returns true if the path ends with components, considering only complete path
 * components, and false otherwise.
 */
int ends_with_path_components(const char *path, const char *components)
{}

/*
 * If path ends with suffix (complete path components), returns the
 * part before suffix (sans trailing directory separators).
 * Otherwise returns NULL.
 */
char *strip_path_suffix(const char *path, const char *suffix)
{}

int daemon_avoid_alias(const char *p)
{}

/*
 * On NTFS, we need to be careful to disallow certain synonyms of the `.git/`
 * directory:
 *
 * - For historical reasons, file names that end in spaces or periods are
 *   automatically trimmed. Therefore, `.git . . ./` is a valid way to refer
 *   to `.git/`.
 *
 * - For other historical reasons, file names that do not conform to the 8.3
 *   format (up to eight characters for the basename, three for the file
 *   extension, certain characters not allowed such as `+`, etc) are associated
 *   with a so-called "short name", at least on the `C:` drive by default.
 *   Which means that `git~1/` is a valid way to refer to `.git/`.
 *
 *   Note: Technically, `.git/` could receive the short name `git~2` if the
 *   short name `git~1` were already used. In Git, however, we guarantee that
 *   `.git` is the first item in a directory, therefore it will be associated
 *   with the short name `git~1` (unless short names are disabled).
 *
 * - For yet other historical reasons, NTFS supports so-called "Alternate Data
 *   Streams", i.e. metadata associated with a given file, referred to via
 *   `<filename>:<stream-name>:<stream-type>`. There exists a default stream
 *   type for directories, allowing `.git/` to be accessed via
 *   `.git::$INDEX_ALLOCATION/`.
 *
 * When this function returns 1, it indicates that the specified file/directory
 * name refers to a `.git` file or directory, or to any of these synonyms, and
 * Git should therefore not track it.
 *
 * For performance reasons, _all_ Alternate Data Streams of `.git/` are
 * forbidden, not just `::$INDEX_ALLOCATION`.
 *
 * This function is intended to be used by `git fsck` even on platforms where
 * the backslash is a regular filename character, therefore it needs to handle
 * backlash characters in the provided `name` specially: they are interpreted
 * as directory separators.
 */
int is_ntfs_dotgit(const char *name)
{}

static int is_ntfs_dot_generic(const char *name,
			       const char *dotgit_name,
			       size_t len,
			       const char *dotgit_ntfs_shortname_prefix)
{}

/*
 * Inline helper to make sure compiler resolves strlen() on literals at
 * compile time.
 */
static inline int is_ntfs_dot_str(const char *name, const char *dotgit_name,
				  const char *dotgit_ntfs_shortname_prefix)
{}

int is_ntfs_dotgitmodules(const char *name)
{}

int is_ntfs_dotgitignore(const char *name)
{}

int is_ntfs_dotgitattributes(const char *name)
{}

int is_ntfs_dotmailmap(const char *name)
{}

int looks_like_command_line_option(const char *str)
{}

char *xdg_config_home_for(const char *subdir, const char *filename)
{}

char *xdg_config_home(const char *filename)
{}

char *xdg_cache_home(const char *filename)
{}

REPO_GIT_PATH_FUNC()
REPO_GIT_PATH_FUNC()
REPO_GIT_PATH_FUNC()
REPO_GIT_PATH_FUNC()
REPO_GIT_PATH_FUNC()
REPO_GIT_PATH_FUNC()
REPO_GIT_PATH_FUNC()