mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
add: convert to use parse_pathspec
Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
931eab64ad
commit
5a76aff1a6
103
builtin/add.c
103
builtin/add.c
|
@ -226,21 +226,6 @@ static char *prune_directory(struct dir_struct *dir, const char **pathspec,
|
||||||
return seen;
|
return seen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Checks the index to see whether any path in pathspec refers to
|
|
||||||
* something inside a submodule. If so, dies with an error message.
|
|
||||||
*/
|
|
||||||
static void treat_gitlinks(const char **pathspec)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!pathspec || !*pathspec)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; pathspec[i]; i++)
|
|
||||||
pathspec[i] = check_path_for_gitlink(pathspec[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void refresh(int verbose, const char **pathspec)
|
static void refresh(int verbose, const char **pathspec)
|
||||||
{
|
{
|
||||||
char *seen;
|
char *seen;
|
||||||
|
@ -258,25 +243,6 @@ static void refresh(int verbose, const char **pathspec)
|
||||||
free(seen);
|
free(seen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Normalizes argv relative to prefix, via get_pathspec(), and then
|
|
||||||
* runs die_if_path_beyond_symlink() on each path in the normalized
|
|
||||||
* list.
|
|
||||||
*/
|
|
||||||
static const char **validate_pathspec(const char **argv, const char *prefix)
|
|
||||||
{
|
|
||||||
const char **pathspec = get_pathspec(prefix, argv);
|
|
||||||
|
|
||||||
if (pathspec) {
|
|
||||||
const char **p;
|
|
||||||
for (p = pathspec; *p; p++) {
|
|
||||||
die_if_path_beyond_symlink(*p, prefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pathspec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int run_add_interactive(const char *revision, const char *patch_mode,
|
int run_add_interactive(const char *revision, const char *patch_mode,
|
||||||
const char **pathspec)
|
const char **pathspec)
|
||||||
{
|
{
|
||||||
|
@ -308,17 +274,23 @@ int run_add_interactive(const char *revision, const char *patch_mode,
|
||||||
|
|
||||||
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
|
int interactive_add(int argc, const char **argv, const char *prefix, int patch)
|
||||||
{
|
{
|
||||||
const char **pathspec = NULL;
|
struct pathspec pathspec;
|
||||||
|
|
||||||
if (argc) {
|
/*
|
||||||
pathspec = validate_pathspec(argv, prefix);
|
* git-add--interactive itself does not parse pathspec. It
|
||||||
if (!pathspec)
|
* simply passes the pathspec to other builtin commands. Let's
|
||||||
return -1;
|
* hope all of them support all magic, or we'll need to limit
|
||||||
}
|
* the magic here. There is still a problem with prefix. But
|
||||||
|
* that'll be worked on later on.
|
||||||
|
*/
|
||||||
|
parse_pathspec(&pathspec, PATHSPEC_ALL_MAGIC & ~PATHSPEC_FROMTOP,
|
||||||
|
PATHSPEC_PREFER_FULL |
|
||||||
|
PATHSPEC_SYMLINK_LEADING_PATH,
|
||||||
|
prefix, argv);
|
||||||
|
|
||||||
return run_add_interactive(NULL,
|
return run_add_interactive(NULL,
|
||||||
patch ? "--patch" : NULL,
|
patch ? "--patch" : NULL,
|
||||||
pathspec);
|
pathspec.raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int edit_patch(int argc, const char **argv, const char *prefix)
|
static int edit_patch(int argc, const char **argv, const char *prefix)
|
||||||
|
@ -445,7 +417,7 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int exit_status = 0;
|
int exit_status = 0;
|
||||||
int newfd;
|
int newfd;
|
||||||
const char **pathspec;
|
struct pathspec pathspec;
|
||||||
struct dir_struct dir;
|
struct dir_struct dir;
|
||||||
int flags;
|
int flags;
|
||||||
int add_new_files;
|
int add_new_files;
|
||||||
|
@ -526,11 +498,19 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
|
fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
pathspec = validate_pathspec(argv, prefix);
|
|
||||||
|
|
||||||
if (read_cache() < 0)
|
if (read_cache() < 0)
|
||||||
die(_("index file corrupt"));
|
die(_("index file corrupt"));
|
||||||
treat_gitlinks(pathspec);
|
|
||||||
|
/*
|
||||||
|
* Check the "pathspec '%s' did not match any files" block
|
||||||
|
* below before enabling new magic.
|
||||||
|
*/
|
||||||
|
parse_pathspec(&pathspec, 0,
|
||||||
|
PATHSPEC_PREFER_FULL |
|
||||||
|
PATHSPEC_SYMLINK_LEADING_PATH |
|
||||||
|
PATHSPEC_STRIP_SUBMODULE_SLASH_EXPENSIVE,
|
||||||
|
prefix, argv);
|
||||||
|
|
||||||
if (add_new_files) {
|
if (add_new_files) {
|
||||||
int baselen;
|
int baselen;
|
||||||
|
@ -543,34 +523,40 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This picks up the paths that are not tracked */
|
/* This picks up the paths that are not tracked */
|
||||||
baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec);
|
baselen = fill_directory(&dir, implicit_dot ? NULL : pathspec.raw);
|
||||||
if (pathspec)
|
if (pathspec.nr)
|
||||||
seen = prune_directory(&dir, pathspec, baselen,
|
seen = prune_directory(&dir, pathspec.raw, baselen,
|
||||||
implicit_dot ? WARN_IMPLICIT_DOT : 0);
|
implicit_dot ? WARN_IMPLICIT_DOT : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (refresh_only) {
|
if (refresh_only) {
|
||||||
refresh(verbose, pathspec);
|
refresh(verbose, pathspec.raw);
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
if (implicit_dot && prefix)
|
if (implicit_dot && prefix)
|
||||||
refresh_cache(REFRESH_QUIET);
|
refresh_cache(REFRESH_QUIET);
|
||||||
|
|
||||||
if (pathspec) {
|
if (pathspec.nr) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!seen)
|
if (!seen)
|
||||||
seen = find_pathspecs_matching_against_index(pathspec);
|
seen = find_pathspecs_matching_against_index(pathspec.raw);
|
||||||
for (i = 0; pathspec[i]; i++) {
|
|
||||||
if (!seen[i] && pathspec[i][0]
|
/*
|
||||||
&& !file_exists(pathspec[i])) {
|
* file_exists() assumes exact match
|
||||||
|
*/
|
||||||
|
GUARD_PATHSPEC(&pathspec, PATHSPEC_FROMTOP);
|
||||||
|
|
||||||
|
for (i = 0; pathspec.raw[i]; i++) {
|
||||||
|
if (!seen[i] && pathspec.raw[i][0]
|
||||||
|
&& !file_exists(pathspec.raw[i])) {
|
||||||
if (ignore_missing) {
|
if (ignore_missing) {
|
||||||
int dtype = DT_UNKNOWN;
|
int dtype = DT_UNKNOWN;
|
||||||
if (is_excluded(&dir, pathspec[i], &dtype))
|
if (is_excluded(&dir, pathspec.raw[i], &dtype))
|
||||||
dir_add_ignored(&dir, pathspec[i], strlen(pathspec[i]));
|
dir_add_ignored(&dir, pathspec.raw[i], strlen(pathspec.raw[i]));
|
||||||
} else
|
} else
|
||||||
die(_("pathspec '%s' did not match any files"),
|
die(_("pathspec '%s' did not match any files"),
|
||||||
pathspec[i]);
|
pathspec.raw[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(seen);
|
free(seen);
|
||||||
|
@ -586,10 +572,11 @@ int cmd_add(int argc, const char **argv, const char *prefix)
|
||||||
*/
|
*/
|
||||||
update_data.implicit_dot = prefix;
|
update_data.implicit_dot = prefix;
|
||||||
update_data.implicit_dot_len = strlen(prefix);
|
update_data.implicit_dot_len = strlen(prefix);
|
||||||
pathspec = NULL;
|
free_pathspec(&pathspec);
|
||||||
|
memset(&pathspec, 0, sizeof(pathspec));
|
||||||
}
|
}
|
||||||
update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
|
update_data.flags = flags & ~ADD_CACHE_IMPLICIT_DOT;
|
||||||
update_files_in_cache(prefix, pathspec, &update_data);
|
update_files_in_cache(prefix, pathspec.raw, &update_data);
|
||||||
|
|
||||||
exit_status |= !!update_data.add_errors;
|
exit_status |= !!update_data.add_errors;
|
||||||
if (add_new_files)
|
if (add_new_files)
|
||||||
|
|
43
pathspec.c
43
pathspec.c
|
@ -57,49 +57,6 @@ char *find_pathspecs_matching_against_index(const char **pathspec)
|
||||||
return seen;
|
return seen;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Check the index to see whether path refers to a submodule, or
|
|
||||||
* something inside a submodule. If the former, returns the path with
|
|
||||||
* any trailing slash stripped. If the latter, dies with an error
|
|
||||||
* message.
|
|
||||||
*/
|
|
||||||
const char *check_path_for_gitlink(const char *path)
|
|
||||||
{
|
|
||||||
int i, path_len = strlen(path);
|
|
||||||
for (i = 0; i < active_nr; i++) {
|
|
||||||
struct cache_entry *ce = active_cache[i];
|
|
||||||
if (S_ISGITLINK(ce->ce_mode)) {
|
|
||||||
int ce_len = ce_namelen(ce);
|
|
||||||
if (path_len <= ce_len || path[ce_len] != '/' ||
|
|
||||||
memcmp(ce->name, path, ce_len))
|
|
||||||
/* path does not refer to this
|
|
||||||
* submodule or anything inside it */
|
|
||||||
continue;
|
|
||||||
if (path_len == ce_len + 1) {
|
|
||||||
/* path refers to submodule;
|
|
||||||
* strip trailing slash */
|
|
||||||
return xstrndup(ce->name, ce_len);
|
|
||||||
} else {
|
|
||||||
die (_("Path '%s' is in submodule '%.*s'"),
|
|
||||||
path, ce_len, ce->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dies if the given path refers to a file inside a symlinked
|
|
||||||
* directory in the index.
|
|
||||||
*/
|
|
||||||
void die_if_path_beyond_symlink(const char *path, const char *prefix)
|
|
||||||
{
|
|
||||||
if (has_symlink_leading_path(path, strlen(path))) {
|
|
||||||
int len = prefix ? strlen(prefix) : 0;
|
|
||||||
die(_("'%s' is beyond a symbolic link"), path + len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Magic pathspec
|
* Magic pathspec
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue