Merge branch 'am/pathspec-from-file'
A few commands learned to take the pathspec from the standard input or a named file, instead of taking it as the command line arguments. * am/pathspec-from-file: commit: support the --pathspec-from-file option doc: commit: synchronize <pathspec> description reset: support the `--pathspec-from-file` option doc: reset: synchronize <pathspec> description pathspec: add new function to parse file parse-options.h: add new options `--pathspec-from-file`, `--pathspec-file-nul`
This commit is contained in:
commit
c58ae96fc4
@ -13,7 +13,8 @@ SYNOPSIS
|
|||||||
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
|
[-F <file> | -m <msg>] [--reset-author] [--allow-empty]
|
||||||
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
|
[--allow-empty-message] [--no-verify] [-e] [--author=<author>]
|
||||||
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
|
[--date=<date>] [--cleanup=<mode>] [--[no-]status]
|
||||||
[-i | -o] [-S[<keyid>]] [--] [<file>...]
|
[-i | -o] [--pathspec-from-file=<file> [--pathspec-file-nul]]
|
||||||
|
[-S[<keyid>]] [--] [<pathspec>...]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
@ -278,6 +279,19 @@ FROM UPSTREAM REBASE" section in linkgit:git-rebase[1].)
|
|||||||
already been staged. If used together with `--allow-empty`
|
already been staged. If used together with `--allow-empty`
|
||||||
paths are also not required, and an empty commit will be created.
|
paths are also not required, and an empty commit will be created.
|
||||||
|
|
||||||
|
--pathspec-from-file=<file>::
|
||||||
|
Pathspec is passed in `<file>` instead of commandline args. If
|
||||||
|
`<file>` is exactly `-` then standard input is used. Pathspec
|
||||||
|
elements are separated by LF or CR/LF. Pathspec elements can be
|
||||||
|
quoted as explained for the configuration variable `core.quotePath`
|
||||||
|
(see linkgit:git-config[1]). See also `--pathspec-file-nul` and
|
||||||
|
global `--literal-pathspecs`.
|
||||||
|
|
||||||
|
--pathspec-file-nul::
|
||||||
|
Only meaningful with `--pathspec-from-file`. Pathspec elements are
|
||||||
|
separated with NUL character and all other characters are taken
|
||||||
|
literally (including newlines and quotes).
|
||||||
|
|
||||||
-u[<mode>]::
|
-u[<mode>]::
|
||||||
--untracked-files[=<mode>]::
|
--untracked-files[=<mode>]::
|
||||||
Show untracked files.
|
Show untracked files.
|
||||||
@ -345,12 +359,13 @@ changes to tracked files.
|
|||||||
\--::
|
\--::
|
||||||
Do not interpret any more arguments as options.
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
<file>...::
|
<pathspec>...::
|
||||||
When files are given on the command line, the command
|
When pathspec is given on the command line, commit the contents of
|
||||||
commits the contents of the named files, without
|
the files that match the pathspec without recording the changes
|
||||||
recording the changes already staged. The contents of
|
already added to the index. The contents of these files are also
|
||||||
these files are also staged for the next commit on top
|
staged for the next commit on top of what have been staged before.
|
||||||
of what have been staged before.
|
+
|
||||||
|
For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
|
||||||
|
|
||||||
:git-commit: 1
|
:git-commit: 1
|
||||||
include::date-formats.txt[]
|
include::date-formats.txt[]
|
||||||
|
@ -8,34 +8,36 @@ git-reset - Reset current HEAD to the specified state
|
|||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git reset' [-q] [<tree-ish>] [--] <paths>...
|
'git reset' [-q] [<tree-ish>] [--] <pathspec>...
|
||||||
'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
|
'git reset' [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]
|
||||||
|
'git reset' (--patch | -p) [<tree-ish>] [--] [<pathspec>...]
|
||||||
'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
|
'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
In the first and second form, copy entries from `<tree-ish>` to the index.
|
In the first three forms, copy entries from `<tree-ish>` to the index.
|
||||||
In the third form, set the current branch head (`HEAD`) to `<commit>`,
|
In the last form, set the current branch head (`HEAD`) to `<commit>`,
|
||||||
optionally modifying index and working tree to match.
|
optionally modifying index and working tree to match.
|
||||||
The `<tree-ish>`/`<commit>` defaults to `HEAD` in all forms.
|
The `<tree-ish>`/`<commit>` defaults to `HEAD` in all forms.
|
||||||
|
|
||||||
'git reset' [-q] [<tree-ish>] [--] <paths>...::
|
'git reset' [-q] [<tree-ish>] [--] <pathspec>...::
|
||||||
This form resets the index entries for all `<paths>` to their
|
'git reset' [-q] [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]::
|
||||||
state at `<tree-ish>`. (It does not affect the working tree or
|
These forms reset the index entries for all paths that match the
|
||||||
the current branch.)
|
`<pathspec>` to their state at `<tree-ish>`. (It does not affect
|
||||||
|
the working tree or the current branch.)
|
||||||
+
|
+
|
||||||
This means that `git reset <paths>` is the opposite of `git add
|
This means that `git reset <pathspec>` is the opposite of `git add
|
||||||
<paths>`. This command is equivalent to
|
<pathspec>`. This command is equivalent to
|
||||||
`git restore [--source=<tree-ish>] --staged <paths>...`.
|
`git restore [--source=<tree-ish>] --staged <pathspec>...`.
|
||||||
+
|
+
|
||||||
After running `git reset <paths>` to update the index entry, you can
|
After running `git reset <pathspec>` to update the index entry, you can
|
||||||
use linkgit:git-restore[1] to check the contents out of the index to
|
use linkgit:git-restore[1] to check the contents out of the index to
|
||||||
the working tree. Alternatively, using linkgit:git-restore[1]
|
the working tree. Alternatively, using linkgit:git-restore[1]
|
||||||
and specifying a commit with `--source`, you
|
and specifying a commit with `--source`, you
|
||||||
can copy the contents of a path out of a commit to the index and to the
|
can copy the contents of a path out of a commit to the index and to the
|
||||||
working tree in one go.
|
working tree in one go.
|
||||||
|
|
||||||
'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]::
|
'git reset' (--patch | -p) [<tree-ish>] [--] [<pathspec>...]::
|
||||||
Interactively select hunks in the difference between the index
|
Interactively select hunks in the difference between the index
|
||||||
and `<tree-ish>` (defaults to `HEAD`). The chosen hunks are applied
|
and `<tree-ish>` (defaults to `HEAD`). The chosen hunks are applied
|
||||||
in reverse to the index.
|
in reverse to the index.
|
||||||
@ -101,6 +103,26 @@ OPTIONS
|
|||||||
`reset.quiet` config option. `--quiet` and `--no-quiet` will
|
`reset.quiet` config option. `--quiet` and `--no-quiet` will
|
||||||
override the default behavior.
|
override the default behavior.
|
||||||
|
|
||||||
|
--pathspec-from-file=<file>::
|
||||||
|
Pathspec is passed in `<file>` instead of commandline args. If
|
||||||
|
`<file>` is exactly `-` then standard input is used. Pathspec
|
||||||
|
elements are separated by LF or CR/LF. Pathspec elements can be
|
||||||
|
quoted as explained for the configuration variable `core.quotePath`
|
||||||
|
(see linkgit:git-config[1]). See also `--pathspec-file-nul` and
|
||||||
|
global `--literal-pathspecs`.
|
||||||
|
|
||||||
|
--pathspec-file-nul::
|
||||||
|
Only meaningful with `--pathspec-from-file`. Pathspec elements are
|
||||||
|
separated with NUL character and all other characters are taken
|
||||||
|
literally (including newlines and quotes).
|
||||||
|
|
||||||
|
\--::
|
||||||
|
Do not interpret any more arguments as options.
|
||||||
|
|
||||||
|
<pathspec>...::
|
||||||
|
Limits the paths affected by the operation.
|
||||||
|
+
|
||||||
|
For more details, see the 'pathspec' entry in linkgit:gitglossary[7].
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
@ -107,9 +107,9 @@ static int all, also, interactive, patch_interactive, only, amend, signoff;
|
|||||||
static int edit_flag = -1; /* unspecified */
|
static int edit_flag = -1; /* unspecified */
|
||||||
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
|
static int quiet, verbose, no_verify, allow_empty, dry_run, renew_authorship;
|
||||||
static int config_commit_verbose = -1; /* unspecified */
|
static int config_commit_verbose = -1; /* unspecified */
|
||||||
static int no_post_rewrite, allow_empty_message;
|
static int no_post_rewrite, allow_empty_message, pathspec_file_nul;
|
||||||
static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
|
static char *untracked_files_arg, *force_date, *ignore_submodule_arg, *ignored_arg;
|
||||||
static char *sign_commit;
|
static char *sign_commit, *pathspec_from_file;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The default commit message cleanup mode will remove the lines
|
* The default commit message cleanup mode will remove the lines
|
||||||
@ -343,6 +343,23 @@ static const char *prepare_index(int argc, const char **argv, const char *prefix
|
|||||||
PATHSPEC_PREFER_FULL,
|
PATHSPEC_PREFER_FULL,
|
||||||
prefix, argv);
|
prefix, argv);
|
||||||
|
|
||||||
|
if (pathspec_from_file) {
|
||||||
|
if (interactive)
|
||||||
|
die(_("--pathspec-from-file is incompatible with --interactive/--patch"));
|
||||||
|
|
||||||
|
if (pathspec.nr)
|
||||||
|
die(_("--pathspec-from-file is incompatible with pathspec arguments"));
|
||||||
|
|
||||||
|
parse_pathspec_file(&pathspec, 0,
|
||||||
|
PATHSPEC_PREFER_FULL,
|
||||||
|
prefix, pathspec_from_file, pathspec_file_nul);
|
||||||
|
} else if (pathspec_file_nul) {
|
||||||
|
die(_("--pathspec-file-nul requires --pathspec-from-file"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pathspec.nr && (also || (only && !amend && !allow_empty)))
|
||||||
|
die(_("No paths with --include/--only does not make sense."));
|
||||||
|
|
||||||
if (read_cache_preload(&pathspec) < 0)
|
if (read_cache_preload(&pathspec) < 0)
|
||||||
die(_("index file corrupt"));
|
die(_("index file corrupt"));
|
||||||
|
|
||||||
@ -1198,8 +1215,6 @@ static int parse_and_validate_options(int argc, const char *argv[],
|
|||||||
|
|
||||||
if (also + only + all + interactive > 1)
|
if (also + only + all + interactive > 1)
|
||||||
die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
|
die(_("Only one of --include/--only/--all/--interactive/--patch can be used."));
|
||||||
if (argc == 0 && (also || (only && !amend && !allow_empty)))
|
|
||||||
die(_("No paths with --include/--only does not make sense."));
|
|
||||||
cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
|
cleanup_mode = get_cleanup_mode(cleanup_arg, use_editor);
|
||||||
|
|
||||||
handle_untracked_files_arg(s);
|
handle_untracked_files_arg(s);
|
||||||
@ -1513,6 +1528,8 @@ int cmd_commit(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
|
OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
|
||||||
OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
|
OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass post-rewrite hook")),
|
||||||
{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
|
{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, N_("mode"), N_("show untracked files, optional modes: all, normal, no. (Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
|
||||||
|
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||||
|
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||||
/* end commit contents options */
|
/* end commit contents options */
|
||||||
|
|
||||||
OPT_HIDDEN_BOOL(0, "allow-empty", &allow_empty,
|
OPT_HIDDEN_BOOL(0, "allow-empty", &allow_empty,
|
||||||
|
@ -30,8 +30,9 @@
|
|||||||
|
|
||||||
static const char * const git_reset_usage[] = {
|
static const char * const git_reset_usage[] = {
|
||||||
N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
|
N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
|
||||||
N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
|
N_("git reset [-q] [<tree-ish>] [--] <pathspec>..."),
|
||||||
N_("git reset --patch [<tree-ish>] [--] [<paths>...]"),
|
N_("git reset [-q] [--pathspec-from-file [--pathspec-file-nul]] [<tree-ish>]"),
|
||||||
|
N_("git reset --patch [<tree-ish>] [--] [<pathspec>...]"),
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -284,8 +285,8 @@ static int git_reset_config(const char *var, const char *value, void *cb)
|
|||||||
int cmd_reset(int argc, const char **argv, const char *prefix)
|
int cmd_reset(int argc, const char **argv, const char *prefix)
|
||||||
{
|
{
|
||||||
int reset_type = NONE, update_ref_status = 0, quiet = 0;
|
int reset_type = NONE, update_ref_status = 0, quiet = 0;
|
||||||
int patch_mode = 0, unborn;
|
int patch_mode = 0, pathspec_file_nul = 0, unborn;
|
||||||
const char *rev;
|
const char *rev, *pathspec_from_file = NULL;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
struct pathspec pathspec;
|
struct pathspec pathspec;
|
||||||
int intent_to_add = 0;
|
int intent_to_add = 0;
|
||||||
@ -306,6 +307,8 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
|
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
|
||||||
OPT_BOOL('N', "intent-to-add", &intent_to_add,
|
OPT_BOOL('N', "intent-to-add", &intent_to_add,
|
||||||
N_("record only the fact that removed paths will be added later")),
|
N_("record only the fact that removed paths will be added later")),
|
||||||
|
OPT_PATHSPEC_FROM_FILE(&pathspec_from_file),
|
||||||
|
OPT_PATHSPEC_FILE_NUL(&pathspec_file_nul),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -316,6 +319,20 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
|
|||||||
PARSE_OPT_KEEP_DASHDASH);
|
PARSE_OPT_KEEP_DASHDASH);
|
||||||
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
|
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
|
||||||
|
|
||||||
|
if (pathspec_from_file) {
|
||||||
|
if (patch_mode)
|
||||||
|
die(_("--pathspec-from-file is incompatible with --patch"));
|
||||||
|
|
||||||
|
if (pathspec.nr)
|
||||||
|
die(_("--pathspec-from-file is incompatible with pathspec arguments"));
|
||||||
|
|
||||||
|
parse_pathspec_file(&pathspec, 0,
|
||||||
|
PATHSPEC_PREFER_FULL,
|
||||||
|
prefix, pathspec_from_file, pathspec_file_nul);
|
||||||
|
} else if (pathspec_file_nul) {
|
||||||
|
die(_("--pathspec-file-nul requires --pathspec-from-file"));
|
||||||
|
}
|
||||||
|
|
||||||
unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
|
unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
|
||||||
if (unborn) {
|
if (unborn) {
|
||||||
/* reset on unborn branch: treat as reset to empty tree */
|
/* reset on unborn branch: treat as reset to empty tree */
|
||||||
|
@ -330,5 +330,7 @@ int parse_opt_passthru_argv(const struct option *, const char *, int);
|
|||||||
#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
|
#define OPT_WITH(v, h) _OPT_CONTAINS_OR_WITH("with", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
|
||||||
#define OPT_WITHOUT(v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
|
#define OPT_WITHOUT(v, h) _OPT_CONTAINS_OR_WITH("without", v, h, PARSE_OPT_HIDDEN | PARSE_OPT_NONEG)
|
||||||
#define OPT_CLEANUP(v) OPT_STRING(0, "cleanup", v, N_("mode"), N_("how to strip spaces and #comments from message"))
|
#define OPT_CLEANUP(v) OPT_STRING(0, "cleanup", v, N_("mode"), N_("how to strip spaces and #comments from message"))
|
||||||
|
#define OPT_PATHSPEC_FROM_FILE(v) OPT_FILENAME(0, "pathspec-from-file", v, N_("read pathspec from file"))
|
||||||
|
#define OPT_PATHSPEC_FILE_NUL(v) OPT_BOOL(0, "pathspec-file-nul", v, N_("with --pathspec-from-file, pathspec elements are separated with NUL character"))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
38
pathspec.c
38
pathspec.c
@ -3,6 +3,8 @@
|
|||||||
#include "dir.h"
|
#include "dir.h"
|
||||||
#include "pathspec.h"
|
#include "pathspec.h"
|
||||||
#include "attr.h"
|
#include "attr.h"
|
||||||
|
#include "argv-array.h"
|
||||||
|
#include "quote.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Finds which of the given pathspecs match items in the index.
|
* Finds which of the given pathspecs match items in the index.
|
||||||
@ -613,6 +615,42 @@ void parse_pathspec(struct pathspec *pathspec,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse_pathspec_file(struct pathspec *pathspec, unsigned magic_mask,
|
||||||
|
unsigned flags, const char *prefix,
|
||||||
|
const char *file, int nul_term_line)
|
||||||
|
{
|
||||||
|
struct argv_array parsed_file = ARGV_ARRAY_INIT;
|
||||||
|
strbuf_getline_fn getline_fn = nul_term_line ? strbuf_getline_nul :
|
||||||
|
strbuf_getline;
|
||||||
|
struct strbuf buf = STRBUF_INIT;
|
||||||
|
struct strbuf unquoted = STRBUF_INIT;
|
||||||
|
FILE *in;
|
||||||
|
|
||||||
|
if (!strcmp(file, "-"))
|
||||||
|
in = stdin;
|
||||||
|
else
|
||||||
|
in = xfopen(file, "r");
|
||||||
|
|
||||||
|
while (getline_fn(&buf, in) != EOF) {
|
||||||
|
if (!nul_term_line && buf.buf[0] == '"') {
|
||||||
|
strbuf_reset(&unquoted);
|
||||||
|
if (unquote_c_style(&unquoted, buf.buf, NULL))
|
||||||
|
die(_("line is badly quoted: %s"), buf.buf);
|
||||||
|
strbuf_swap(&buf, &unquoted);
|
||||||
|
}
|
||||||
|
argv_array_push(&parsed_file, buf.buf);
|
||||||
|
strbuf_reset(&buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
strbuf_release(&unquoted);
|
||||||
|
strbuf_release(&buf);
|
||||||
|
if (in != stdin)
|
||||||
|
fclose(in);
|
||||||
|
|
||||||
|
parse_pathspec(pathspec, magic_mask, flags, prefix, parsed_file.argv);
|
||||||
|
argv_array_clear(&parsed_file);
|
||||||
|
}
|
||||||
|
|
||||||
void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
|
void copy_pathspec(struct pathspec *dst, const struct pathspec *src)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
|
10
pathspec.h
10
pathspec.h
@ -85,6 +85,16 @@ void parse_pathspec(struct pathspec *pathspec,
|
|||||||
unsigned flags,
|
unsigned flags,
|
||||||
const char *prefix,
|
const char *prefix,
|
||||||
const char **args);
|
const char **args);
|
||||||
|
/*
|
||||||
|
* Same as parse_pathspec() but uses file as input.
|
||||||
|
* When 'file' is exactly "-" it uses 'stdin' instead.
|
||||||
|
*/
|
||||||
|
void parse_pathspec_file(struct pathspec *pathspec,
|
||||||
|
unsigned magic_mask,
|
||||||
|
unsigned flags,
|
||||||
|
const char *prefix,
|
||||||
|
const char *file,
|
||||||
|
int nul_term_line);
|
||||||
void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
|
void copy_pathspec(struct pathspec *dst, const struct pathspec *src);
|
||||||
void clear_pathspec(struct pathspec *);
|
void clear_pathspec(struct pathspec *);
|
||||||
|
|
||||||
|
155
t/t7107-reset-pathspec-file.sh
Executable file
155
t/t7107-reset-pathspec-file.sh
Executable file
@ -0,0 +1,155 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='reset --pathspec-from-file'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_tick
|
||||||
|
|
||||||
|
test_expect_success setup '
|
||||||
|
echo A >fileA.t &&
|
||||||
|
echo B >fileB.t &&
|
||||||
|
echo C >fileC.t &&
|
||||||
|
echo D >fileD.t &&
|
||||||
|
git add . &&
|
||||||
|
git commit --include . -m "Commit" &&
|
||||||
|
git tag checkpoint
|
||||||
|
'
|
||||||
|
|
||||||
|
restore_checkpoint () {
|
||||||
|
git reset --hard checkpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_expect () {
|
||||||
|
git status --porcelain -- fileA.t fileB.t fileC.t fileD.t >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success '--pathspec-from-file from stdin' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t &&
|
||||||
|
echo fileA.t | git reset --pathspec-from-file=- &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--pathspec-from-file from file' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t &&
|
||||||
|
echo fileA.t >list &&
|
||||||
|
git reset --pathspec-from-file=list &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'NUL delimiters' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t fileB.t &&
|
||||||
|
printf "fileA.t\0fileB.t\0" | git reset --pathspec-from-file=- --pathspec-file-nul &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
D fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'LF delimiters' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t fileB.t &&
|
||||||
|
printf "fileA.t\nfileB.t\n" | git reset --pathspec-from-file=- &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
D fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'no trailing delimiter' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t fileB.t &&
|
||||||
|
printf "fileA.t\nfileB.t" | git reset --pathspec-from-file=- &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
D fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'CRLF delimiters' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t fileB.t &&
|
||||||
|
printf "fileA.t\r\nfileB.t\r\n" | git reset --pathspec-from-file=- &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
D fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'quotes' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t &&
|
||||||
|
printf "\"file\\101.t\"" | git reset --pathspec-from-file=- &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'quotes not compatible with --pathspec-file-nul' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t &&
|
||||||
|
printf "\"file\\101.t\"" >list &&
|
||||||
|
# Note: "git reset" has not yet learned to fail on wrong pathspecs
|
||||||
|
git reset --pathspec-from-file=list --pathspec-file-nul &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
EOF
|
||||||
|
test_must_fail verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--pathspec-from-file is not compatible with --soft or --hard' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t &&
|
||||||
|
echo fileA.t >list &&
|
||||||
|
test_must_fail git reset --soft --pathspec-from-file=list &&
|
||||||
|
test_must_fail git reset --hard --pathspec-from-file=list
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'only touches what was listed' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
git rm fileA.t fileB.t fileC.t fileD.t &&
|
||||||
|
printf "fileB.t\nfileC.t\n" | git reset --pathspec-from-file=- &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
D fileA.t
|
||||||
|
D fileB.t
|
||||||
|
D fileC.t
|
||||||
|
D fileD.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
130
t/t7526-commit-pathspec-file.sh
Executable file
130
t/t7526-commit-pathspec-file.sh
Executable file
@ -0,0 +1,130 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
test_description='commit --pathspec-from-file'
|
||||||
|
|
||||||
|
. ./test-lib.sh
|
||||||
|
|
||||||
|
test_tick
|
||||||
|
|
||||||
|
test_expect_success setup '
|
||||||
|
test_commit file0 &&
|
||||||
|
git tag checkpoint &&
|
||||||
|
|
||||||
|
echo A >fileA.t &&
|
||||||
|
echo B >fileB.t &&
|
||||||
|
echo C >fileC.t &&
|
||||||
|
echo D >fileD.t &&
|
||||||
|
git add fileA.t fileB.t fileC.t fileD.t
|
||||||
|
'
|
||||||
|
|
||||||
|
restore_checkpoint () {
|
||||||
|
git reset --soft checkpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
verify_expect () {
|
||||||
|
git diff-tree --no-commit-id --name-status -r HEAD >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
}
|
||||||
|
|
||||||
|
test_expect_success '--pathspec-from-file from stdin' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
echo fileA.t | git commit --pathspec-from-file=- -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success '--pathspec-from-file from file' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
echo fileA.t >list &&
|
||||||
|
git commit --pathspec-from-file=list -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'NUL delimiters' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "fileA.t\0fileB.t\0" | git commit --pathspec-from-file=- --pathspec-file-nul -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
A fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'LF delimiters' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "fileA.t\nfileB.t\n" | git commit --pathspec-from-file=- -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
A fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'no trailing delimiter' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "fileA.t\nfileB.t" | git commit --pathspec-from-file=- -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
A fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'CRLF delimiters' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "fileA.t\r\nfileB.t\r\n" | git commit --pathspec-from-file=- -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
A fileB.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'quotes' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "\"file\\101.t\"" | git commit --pathspec-from-file=- -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileA.t
|
||||||
|
EOF
|
||||||
|
verify_expect expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'quotes not compatible with --pathspec-file-nul' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "\"file\\101.t\"" >list &&
|
||||||
|
test_must_fail git commit --pathspec-from-file=list --pathspec-file-nul -m "Commit"
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'only touches what was listed' '
|
||||||
|
restore_checkpoint &&
|
||||||
|
|
||||||
|
printf "fileB.t\nfileC.t\n" | git commit --pathspec-from-file=- -m "Commit" &&
|
||||||
|
|
||||||
|
cat >expect <<-\EOF &&
|
||||||
|
A fileB.t
|
||||||
|
A fileC.t
|
||||||
|
EOF
|
||||||
|
verify_expect
|
||||||
|
'
|
||||||
|
|
||||||
|
test_done
|
Loading…
Reference in New Issue
Block a user