From: Junio C Hamano Date: Wed, 18 Jan 2017 23:12:14 +0000 (-0800) Subject: Merge branch 'bw/pathspec-cleanup' X-Git-Tag: v2.12.0-rc0~66 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/fe9ec8bdf65657c11f08f8858bb2a707bdf7aafe?ds=inline;hp=-c Merge branch 'bw/pathspec-cleanup' Code clean-up in the pathspec API. * bw/pathspec-cleanup: pathspec: rename prefix_pathspec to init_pathspec_item pathspec: small readability changes pathspec: create strip submodule slash helpers pathspec: create parse_element_magic helper pathspec: create parse_long_magic function pathspec: create parse_short_magic function pathspec: factor global magic into its own function pathspec: simpler logic to prefix original pathspec elements pathspec: always show mnemonic and name in unsupported_magic pathspec: remove unused variable from unsupported_magic pathspec: copy and free owned memory pathspec: remove the deprecated get_pathspec function ls-tree: convert show_recursive to use the pathspec struct interface dir: convert fill_directory to use the pathspec struct interface dir: remove struct path_simplify mv: remove use of deprecated 'get_pathspec()' --- fe9ec8bdf65657c11f08f8858bb2a707bdf7aafe diff --combined builtin/mv.c index 43adf92ba6,4e86dc5234..61d20037ad --- a/builtin/mv.c +++ b/builtin/mv.c @@@ -4,6 -4,7 +4,7 @@@ * Copyright (C) 2006 Johannes Schindelin */ #include "builtin.h" + #include "pathspec.h" #include "lockfile.h" #include "dir.h" #include "cache-tree.h" @@@ -19,31 -20,42 +20,42 @@@ static const char * const builtin_mv_us #define DUP_BASENAME 1 #define KEEP_TRAILING_SLASH 2 - static const char **internal_copy_pathspec(const char *prefix, - const char **pathspec, - int count, unsigned flags) + static const char **internal_prefix_pathspec(const char *prefix, + const char **pathspec, + int count, unsigned flags) { int i; const char **result; + int prefixlen = prefix ? strlen(prefix) : 0; ALLOC_ARRAY(result, count + 1); - COPY_ARRAY(result, pathspec, count); - result[count] = NULL; + + /* Create an intermediate copy of the pathspec based on the flags */ for (i = 0; i < count; i++) { - int length = strlen(result[i]); + int length = strlen(pathspec[i]); int to_copy = length; + char *it; while (!(flags & KEEP_TRAILING_SLASH) && - to_copy > 0 && is_dir_sep(result[i][to_copy - 1])) + to_copy > 0 && is_dir_sep(pathspec[i][to_copy - 1])) to_copy--; - if (to_copy != length || flags & DUP_BASENAME) { - char *it = xmemdupz(result[i], to_copy); - if (flags & DUP_BASENAME) { - result[i] = xstrdup(basename(it)); - free(it); - } else - result[i] = it; + + it = xmemdupz(pathspec[i], to_copy); + if (flags & DUP_BASENAME) { + result[i] = xstrdup(basename(it)); + free(it); + } else { + result[i] = it; } } - return get_pathspec(prefix, result); + result[count] = NULL; + + /* Prefix the pathspec and free the old intermediate strings */ + for (i = 0; i < count; i++) { + const char *match = prefix_path(prefix, prefixlen, result[i]); + free((char *) result[i]); + result[i] = match; + } + + return result; } static const char *add_slash(const char *path) @@@ -126,11 -138,11 +138,11 @@@ int cmd_mv(int argc, const char **argv if (--argc < 1) usage_with_options(builtin_mv_usage, builtin_mv_options); - hold_locked_index(&lock_file, 1); + hold_locked_index(&lock_file, LOCK_DIE_ON_ERROR); if (read_cache() < 0) die(_("index file corrupt")); - source = internal_copy_pathspec(prefix, argv, argc, 0); + source = internal_prefix_pathspec(prefix, argv, argc, 0); modes = xcalloc(argc, sizeof(enum update_mode)); /* * Keep trailing slash, needed to let @@@ -140,16 -152,16 +152,16 @@@ flags = KEEP_TRAILING_SLASH; if (argc == 1 && is_directory(argv[0]) && !is_directory(argv[1])) flags = 0; - dest_path = internal_copy_pathspec(prefix, argv + argc, 1, flags); + dest_path = internal_prefix_pathspec(prefix, argv + argc, 1, flags); submodule_gitfile = xcalloc(argc, sizeof(char *)); if (dest_path[0][0] == '\0') /* special case: "." was normalized to "" */ - destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME); + destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME); else if (!lstat(dest_path[0], &st) && S_ISDIR(st.st_mode)) { dest_path[0] = add_slash(dest_path[0]); - destination = internal_copy_pathspec(dest_path[0], argv, argc, DUP_BASENAME); + destination = internal_prefix_pathspec(dest_path[0], argv, argc, DUP_BASENAME); } else { if (argc != 1) die(_("destination '%s' is not a directory"), dest_path[0]); diff --combined cache.h index c74df70127,0f80e01bde..40f7ddd247 --- a/cache.h +++ b/cache.h @@@ -514,7 -514,6 +514,6 @@@ extern void set_git_work_tree(const cha #define ALTERNATE_DB_ENVIRONMENT "GIT_ALTERNATE_OBJECT_DIRECTORIES" - extern const char **get_pathspec(const char *prefix, const char **pathspec); extern void setup_work_tree(void); extern const char *setup_git_directory_gently(int *); extern const char *setup_git_directory(void); @@@ -670,7 -669,7 +669,7 @@@ extern const char *git_attributes_file extern const char *git_hooks_path; extern int zlib_compression_level; extern int core_compression_level; -extern int core_compression_seen; +extern int pack_compression_level; extern size_t packed_git_window_size; extern size_t packed_git_limit; extern size_t delta_base_cache_limit; @@@ -1064,11 -1063,8 +1063,11 @@@ static inline int is_absolute_path(cons return is_dir_sep(path[0]) || has_dos_drive_prefix(path); } int is_directory(const char *); +char *strbuf_realpath(struct strbuf *resolved, const char *path, + int die_on_error); const char *real_path(const char *path); const char *real_path_if_valid(const char *path); +char *real_pathdup(const char *path); const char *absolute_path(const char *path); const char *remove_leading_path(const char *in, const char *prefix); const char *relative_path(const char *in, const char *prefix, struct strbuf *sb); @@@ -1128,8 -1124,7 +1127,8 @@@ extern int write_sha1_file(const void * extern int hash_sha1_file_literally(const void *buf, unsigned long len, const char *type, unsigned char *sha1, unsigned flags); extern int pretend_sha1_file(void *, unsigned long, enum object_type, unsigned char *); extern int force_object_loose(const unsigned char *sha1, time_t mtime); -extern int git_open(const char *name); +extern int git_open_cloexec(const char *name, int flags); +#define git_open(name) git_open_cloexec(name, O_RDONLY) extern void *map_sha1_file(const unsigned char *sha1, unsigned long *size); extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz); extern int parse_sha1_header(const char *hdr, unsigned long *sizep); @@@ -1694,8 -1689,6 +1693,8 @@@ extern int git_default_config(const cha extern int git_config_from_file(config_fn_t fn, const char *, void *); extern int git_config_from_mem(config_fn_t fn, const enum config_origin_type, const char *name, const char *buf, size_t len, void *data); +extern int git_config_from_blob_sha1(config_fn_t fn, const char *name, + const unsigned char *sha1, void *data); extern void git_config_push_parameter(const char *text); extern int git_config_from_parameters(config_fn_t fn, void *data); extern void git_config(config_fn_t fn, void *); diff --combined dir.c index d872cc1570,bc5ff72167..4ac63bc940 --- a/dir.c +++ b/dir.c @@@ -16,11 -16,6 +16,6 @@@ #include "varint.h" #include "ewah/ewok.h" - struct path_simplify { - int len; - const char *path; - }; - /* * Tells read_directory_recursive how a file or directory should be treated. * Values are ordered by significance, e.g. if a directory contains both @@@ -50,7 -45,7 +45,7 @@@ struct cached_dir static enum path_treatment read_directory_recursive(struct dir_struct *dir, const char *path, int len, struct untracked_cache_dir *untracked, - int check_only, const struct path_simplify *simplify); + int check_only, const struct pathspec *pathspec); static int get_dtype(struct dirent *de, const char *path, int len); int fspathcmp(const char *a, const char *b) @@@ -179,17 -174,21 +174,21 @@@ char *common_prefix(const struct pathsp int fill_directory(struct dir_struct *dir, const struct pathspec *pathspec) { - size_t len; + char *prefix; + size_t prefix_len; /* * Calculate common prefix for the pathspec, and * use that to optimize the directory walk */ - len = common_prefix_len(pathspec); + prefix = common_prefix(pathspec); + prefix_len = prefix ? strlen(prefix) : 0; /* Read the directory and prune it */ - read_directory(dir, pathspec->nr ? pathspec->_raw[0] : "", len, pathspec); - return len; + read_directory(dir, prefix, prefix_len, pathspec); + + free(prefix); + return prefix_len; } int within_depth(const char *name, int namelen, @@@ -1312,7 -1311,7 +1311,7 @@@ static enum exist_status directory_exis static enum path_treatment treat_directory(struct dir_struct *dir, struct untracked_cache_dir *untracked, const char *dirname, int len, int baselen, int exclude, - const struct path_simplify *simplify) + const struct pathspec *pathspec) { /* The "len-1" is to strip the final '/' */ switch (directory_exists_in_index(dirname, len-1)) { @@@ -1341,7 -1340,7 +1340,7 @@@ untracked = lookup_untracked(dir->untracked, untracked, dirname + baselen, len - baselen); return read_directory_recursive(dir, dirname, len, - untracked, 1, simplify); + untracked, 1, pathspec); } /* @@@ -1349,24 -1348,33 +1348,33 @@@ * reading - if the path cannot possibly be in the pathspec, * return true, and we'll skip it early. */ - static int simplify_away(const char *path, int pathlen, const struct path_simplify *simplify) + static int simplify_away(const char *path, int pathlen, + const struct pathspec *pathspec) { - if (simplify) { - for (;;) { - const char *match = simplify->path; - int len = simplify->len; + int i; - if (!match) - break; - if (len > pathlen) - len = pathlen; - if (!memcmp(path, match, len)) - return 0; - simplify++; - } - return 1; + if (!pathspec || !pathspec->nr) + return 0; + + GUARD_PATHSPEC(pathspec, + PATHSPEC_FROMTOP | + PATHSPEC_MAXDEPTH | + PATHSPEC_LITERAL | + PATHSPEC_GLOB | + PATHSPEC_ICASE | + PATHSPEC_EXCLUDE); + + for (i = 0; i < pathspec->nr; i++) { + const struct pathspec_item *item = &pathspec->items[i]; + int len = item->nowildcard_len; + + if (len > pathlen) + len = pathlen; + if (!ps_strncmp(item, item->match, path, len)) + return 0; } - return 0; + + return 1; } /* @@@ -1380,19 -1388,33 +1388,33 @@@ * 2. the path is a directory prefix of some element in the * pathspec */ - static int exclude_matches_pathspec(const char *path, int len, - const struct path_simplify *simplify) - { - if (simplify) { - for (; simplify->path; simplify++) { - if (len == simplify->len - && !memcmp(path, simplify->path, len)) - return 1; - if (len < simplify->len - && simplify->path[len] == '/' - && !memcmp(path, simplify->path, len)) - return 1; - } + static int exclude_matches_pathspec(const char *path, int pathlen, + const struct pathspec *pathspec) + { + int i; + + if (!pathspec || !pathspec->nr) + return 0; + + GUARD_PATHSPEC(pathspec, + PATHSPEC_FROMTOP | + PATHSPEC_MAXDEPTH | + PATHSPEC_LITERAL | + PATHSPEC_GLOB | + PATHSPEC_ICASE | + PATHSPEC_EXCLUDE); + + for (i = 0; i < pathspec->nr; i++) { + const struct pathspec_item *item = &pathspec->items[i]; + int len = item->nowildcard_len; + + if (len == pathlen && + !ps_strncmp(item, item->match, path, pathlen)) + return 1; + if (len > pathlen && + item->match[pathlen] == '/' && + !ps_strncmp(item, item->match, path, pathlen)) + return 1; } return 0; } @@@ -1460,7 -1482,7 +1482,7 @@@ static enum path_treatment treat_one_pa struct untracked_cache_dir *untracked, struct strbuf *path, int baselen, - const struct path_simplify *simplify, + const struct pathspec *pathspec, int dtype, struct dirent *de) { int exclude; @@@ -1512,7 -1534,7 +1534,7 @@@ case DT_DIR: strbuf_addch(path, '/'); return treat_directory(dir, untracked, path->buf, path->len, - baselen, exclude, simplify); + baselen, exclude, pathspec); case DT_REG: case DT_LNK: return exclude ? path_excluded : path_untracked; @@@ -1524,7 -1546,7 +1546,7 @@@ static enum path_treatment treat_path_f struct cached_dir *cdir, struct strbuf *path, int baselen, - const struct path_simplify *simplify) + const struct pathspec *pathspec) { strbuf_setlen(path, baselen); if (!cdir->ucd) { @@@ -1541,7 -1563,7 +1563,7 @@@ * with check_only set. */ return read_directory_recursive(dir, path->buf, path->len, - cdir->ucd, 1, simplify); + cdir->ucd, 1, pathspec); /* * We get path_recurse in the first run when * directory_exists_in_index() returns index_nonexistent. We @@@ -1556,23 -1578,23 +1578,23 @@@ static enum path_treatment treat_path(s struct cached_dir *cdir, struct strbuf *path, int baselen, - const struct path_simplify *simplify) + const struct pathspec *pathspec) { int dtype; struct dirent *de = cdir->de; if (!de) return treat_path_fast(dir, untracked, cdir, path, - baselen, simplify); + baselen, pathspec); if (is_dot_or_dotdot(de->d_name) || !strcmp(de->d_name, ".git")) return path_none; strbuf_setlen(path, baselen); strbuf_addstr(path, de->d_name); - if (simplify_away(path->buf, path->len, simplify)) + if (simplify_away(path->buf, path->len, pathspec)) return path_none; dtype = DTYPE(de); - return treat_one_path(dir, untracked, path, baselen, simplify, dtype, de); + return treat_one_path(dir, untracked, path, baselen, pathspec, dtype, de); } static void add_untracked(struct untracked_cache_dir *dir, const char *name) @@@ -1703,7 -1725,7 +1725,7 @@@ static void close_cached_dir(struct cac static enum path_treatment read_directory_recursive(struct dir_struct *dir, const char *base, int baselen, struct untracked_cache_dir *untracked, int check_only, - const struct path_simplify *simplify) + const struct pathspec *pathspec) { struct cached_dir cdir; enum path_treatment state, subdir_state, dir_state = path_none; @@@ -1719,7 -1741,8 +1741,8 @@@ while (!read_cached_dir(&cdir)) { /* check how the file or directory should be treated */ - state = treat_path(dir, untracked, &cdir, &path, baselen, simplify); + state = treat_path(dir, untracked, &cdir, &path, + baselen, pathspec); if (state > dir_state) dir_state = state; @@@ -1731,8 -1754,9 +1754,9 @@@ path.buf + baselen, path.len - baselen); subdir_state = - read_directory_recursive(dir, path.buf, path.len, - ud, check_only, simplify); + read_directory_recursive(dir, path.buf, + path.len, ud, + check_only, pathspec); if (subdir_state > dir_state) dir_state = subdir_state; } @@@ -1756,7 -1780,7 +1780,7 @@@ else if ((dir->flags & DIR_SHOW_IGNORED_TOO) || ((dir->flags & DIR_COLLECT_IGNORED) && exclude_matches_pathspec(path.buf, path.len, - simplify))) + pathspec))) dir_add_ignored(dir, path.buf, path.len); break; @@@ -1787,36 -1811,9 +1811,9 @@@ static int cmp_name(const void *p1, con return name_compare(e1->name, e1->len, e2->name, e2->len); } - static struct path_simplify *create_simplify(const char **pathspec) - { - int nr, alloc = 0; - struct path_simplify *simplify = NULL; - - if (!pathspec) - return NULL; - - for (nr = 0 ; ; nr++) { - const char *match; - ALLOC_GROW(simplify, nr + 1, alloc); - match = *pathspec++; - if (!match) - break; - simplify[nr].path = match; - simplify[nr].len = simple_length(match); - } - simplify[nr].path = NULL; - simplify[nr].len = 0; - return simplify; - } - - static void free_simplify(struct path_simplify *simplify) - { - free(simplify); - } - static int treat_leading_path(struct dir_struct *dir, const char *path, int len, - const struct path_simplify *simplify) + const struct pathspec *pathspec) { struct strbuf sb = STRBUF_INIT; int baselen, rc = 0; @@@ -1840,9 -1837,9 +1837,9 @@@ strbuf_add(&sb, path, baselen); if (!is_directory(sb.buf)) break; - if (simplify_away(sb.buf, sb.len, simplify)) + if (simplify_away(sb.buf, sb.len, pathspec)) break; - if (treat_one_path(dir, NULL, &sb, baselen, simplify, + if (treat_one_path(dir, NULL, &sb, baselen, pathspec, DT_DIR, NULL) == path_none) break; /* do not recurse into it */ if (len <= baselen) { @@@ -2010,33 -2007,14 +2007,14 @@@ static struct untracked_cache_dir *vali return root; } - int read_directory(struct dir_struct *dir, const char *path, int len, const struct pathspec *pathspec) + int read_directory(struct dir_struct *dir, const char *path, + int len, const struct pathspec *pathspec) { - struct path_simplify *simplify; struct untracked_cache_dir *untracked; - /* - * Check out create_simplify() - */ - if (pathspec) - GUARD_PATHSPEC(pathspec, - PATHSPEC_FROMTOP | - PATHSPEC_MAXDEPTH | - PATHSPEC_LITERAL | - PATHSPEC_GLOB | - PATHSPEC_ICASE | - PATHSPEC_EXCLUDE); - if (has_symlink_leading_path(path, len)) return dir->nr; - /* - * exclude patterns are treated like positive ones in - * create_simplify. Usually exclude patterns should be a - * subset of positive ones, which has no impacts on - * create_simplify(). - */ - simplify = create_simplify(pathspec ? pathspec->_raw : NULL); untracked = validate_untracked_cache(dir, len, pathspec); if (!untracked) /* @@@ -2044,9 -2022,8 +2022,8 @@@ * e.g. prep_exclude() */ dir->untracked = NULL; - if (!len || treat_leading_path(dir, path, len, simplify)) - read_directory_recursive(dir, path, len, untracked, 0, simplify); - free_simplify(simplify); + if (!len || treat_leading_path(dir, path, len, pathspec)) + read_directory_recursive(dir, path, len, untracked, 0, pathspec); QSORT(dir->entries, dir->nr, cmp_name); QSORT(dir->ignored, dir->ignored_nr, cmp_name); if (dir->untracked) { @@@ -2748,40 -2725,3 +2725,40 @@@ void untracked_cache_add_to_index(struc { untracked_cache_invalidate_path(istate, path); } + +/* Update gitfile and core.worktree setting to connect work tree and git dir */ +void connect_work_tree_and_git_dir(const char *work_tree_, const char *git_dir_) +{ + struct strbuf file_name = STRBUF_INIT; + struct strbuf rel_path = STRBUF_INIT; + char *git_dir = xstrdup(real_path(git_dir_)); + char *work_tree = xstrdup(real_path(work_tree_)); + + /* Update gitfile */ + strbuf_addf(&file_name, "%s/.git", work_tree); + write_file(file_name.buf, "gitdir: %s", + relative_path(git_dir, work_tree, &rel_path)); + + /* Update core.worktree setting */ + strbuf_reset(&file_name); + strbuf_addf(&file_name, "%s/config", git_dir); + git_config_set_in_file(file_name.buf, "core.worktree", + relative_path(work_tree, git_dir, &rel_path)); + + strbuf_release(&file_name); + strbuf_release(&rel_path); + free(work_tree); + free(git_dir); +} + +/* + * Migrate the git directory of the given path from old_git_dir to new_git_dir. + */ +void relocate_gitdir(const char *path, const char *old_git_dir, const char *new_git_dir) +{ + if (rename(old_git_dir, new_git_dir) < 0) + die_errno(_("could not migrate git directory from '%s' to '%s'"), + old_git_dir, new_git_dir); + + connect_work_tree_and_git_dir(path, new_git_dir); +}