Skip to content

Commit

Permalink
Merge branch 'reset-stdin'
Browse files Browse the repository at this point in the history
This topic branch adds the (experimental) --stdin/-z options to `git
reset`. Those patches are still under review in the upstream Git project,
but are already merged in their experimental form into Git for Windows'
`master` branch, in preparation for a MinGit-only release.

Signed-off-by: Johannes Schindelin <[email protected]>
  • Loading branch information
dscho committed Apr 12, 2017
2 parents e7dd180 + 4beab89 commit 135bf92
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
10 changes: 10 additions & 0 deletions Documentation/git-reset.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ SYNOPSIS
[verse]
'git reset' [-q] [<tree-ish>] [--] <paths>...
'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
EXPERIMENTAL: 'git reset' [-q] [--stdin [-z]] [<tree-ish>]
'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]

DESCRIPTION
Expand Down Expand Up @@ -97,6 +98,15 @@ OPTIONS
--quiet::
Be quiet, only report errors.

--stdin::
EXPERIMENTAL: Instead of taking list of paths from the
command line, read list of paths from the standard input.
Paths are separated by LF (i.e. one path per line) by
default.

-z::
EXPERIMENTAL: Only meaningful with `--stdin`; paths are
separated with NUL character instead of LF.

EXAMPLES
--------
Expand Down
54 changes: 53 additions & 1 deletion builtin/reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,13 @@
#include "parse-options.h"
#include "unpack-trees.h"
#include "cache-tree.h"
#include "strbuf.h"
#include "quote.h"

static const char * const git_reset_usage[] = {
N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
N_("EXPERIMENTAL: git reset [-q] [--stdin [-z]] [<tree-ish>]"),
N_("git reset --patch [<tree-ish>] [--] [<paths>...]"),
NULL
};
Expand Down Expand Up @@ -267,7 +270,9 @@ static int reset_refs(const char *rev, const struct object_id *oid)
int cmd_reset(int argc, const char **argv, const char *prefix)
{
int reset_type = NONE, update_ref_status = 0, quiet = 0;
int patch_mode = 0, unborn;
int patch_mode = 0, nul_term_line = 0, read_from_stdin = 0, unborn;
char **stdin_paths = NULL;
int stdin_nr = 0, stdin_alloc = 0;
const char *rev;
struct object_id oid;
struct pathspec pathspec;
Expand All @@ -286,6 +291,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
OPT_BOOL('N', "intent-to-add", &intent_to_add,
N_("record only the fact that removed paths will be added later")),
OPT_BOOL('z', NULL, &nul_term_line,
N_("EXPERIMENTAL: paths are separated with NUL character")),
OPT_BOOL(0, "stdin", &read_from_stdin,
N_("EXPERIMENTAL: read paths from <stdin>")),
OPT_END()
};

Expand All @@ -295,6 +304,43 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
PARSE_OPT_KEEP_DASHDASH);
parse_args(&pathspec, argv, prefix, patch_mode, &rev);

if (read_from_stdin) {
strbuf_getline_fn getline_fn = nul_term_line ?
strbuf_getline_nul : strbuf_getline_lf;
int flags = PATHSPEC_PREFER_FULL |
PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP;
struct strbuf buf = STRBUF_INIT;
struct strbuf unquoted = STRBUF_INIT;

if (patch_mode)
die(_("--stdin is incompatible with --patch"));

if (pathspec.nr)
die(_("--stdin is incompatible with path arguments"));

while (getline_fn(&buf, stdin) != EOF) {
if (!nul_term_line && buf.buf[0] == '"') {
strbuf_reset(&unquoted);
if (unquote_c_style(&unquoted, buf.buf, NULL))
die(_("line is badly quoted"));
strbuf_swap(&buf, &unquoted);
}
ALLOC_GROW(stdin_paths, stdin_nr + 1, stdin_alloc);
stdin_paths[stdin_nr++] = xstrdup(buf.buf);
strbuf_reset(&buf);
}
strbuf_release(&unquoted);
strbuf_release(&buf);

ALLOC_GROW(stdin_paths, stdin_nr + 1, stdin_alloc);
stdin_paths[stdin_nr++] = NULL;
flags |= PATHSPEC_LITERAL_PATH;
parse_pathspec(&pathspec, 0, flags, prefix,
(const char **)stdin_paths);

} else if (nul_term_line)
die(_("-z requires --stdin"));

unborn = !strcmp(rev, "HEAD") && get_sha1("HEAD", oid.hash);
if (unborn) {
/* reset on unborn branch: treat as reset to empty tree */
Expand Down Expand Up @@ -385,5 +431,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
if (!pathspec.nr)
remove_branch_state();

if (stdin_paths) {
while (stdin_nr)
free(stdin_paths[--stdin_nr]);
free(stdin_paths);
}

return update_ref_status;
}
32 changes: 32 additions & 0 deletions t/t7108-reset-stdin.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/sh

test_description='reset --stdin'

. ./test-lib.sh

test_expect_success 'reset --stdin' '
test_commit hello &&
git rm hello.t &&
test -z "$(git ls-files hello.t)" &&
echo hello.t | git reset --stdin &&
test hello.t = "$(git ls-files hello.t)"
'

test_expect_success 'reset --stdin -z' '
test_commit world &&
git rm hello.t world.t &&
test -z "$(git ls-files hello.t world.t)" &&
printf world.tQworld.tQhello.tQ | q_to_nul | git reset --stdin -z &&
printf "hello.t\nworld.t\n" >expect &&
git ls-files >actual &&
test_cmp expect actual
'

test_expect_success '--stdin requires --mixed' '
echo hello.t >list &&
test_must_fail git reset --soft --stdin <list &&
test_must_fail git reset --hard --stdin <list &&
git reset --mixed --stdin <list
'

test_done

0 comments on commit 135bf92

Please sign in to comment.