Skip to content

Commit ca1b935

Browse files
committed
Merge branch 'reset-stdin'
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]>
2 parents 5fa12c0 + dbb2d73 commit ca1b935

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

Documentation/git-reset.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ SYNOPSIS
1010
[verse]
1111
'git reset' [-q] [<tree-ish>] [--] <paths>...
1212
'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
13+
EXPERIMENTAL: 'git reset' [-q] [--stdin [-z]] [<tree-ish>]
1314
'git reset' [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
1415

1516
DESCRIPTION
@@ -100,6 +101,15 @@ OPTIONS
100101
`reset.quiet` config option. `--quiet` and `--no-quiet` will
101102
override the default behavior.
102103

104+
--stdin::
105+
EXPERIMENTAL: Instead of taking list of paths from the
106+
command line, read list of paths from the standard input.
107+
Paths are separated by LF (i.e. one path per line) by
108+
default.
109+
110+
-z::
111+
EXPERIMENTAL: Only meaningful with `--stdin`; paths are
112+
separated with NUL character instead of LF.
103113

104114
EXAMPLES
105115
--------

builtin/reset.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,15 @@
2525
#include "cache-tree.h"
2626
#include "submodule.h"
2727
#include "submodule-config.h"
28+
#include "strbuf.h"
29+
#include "quote.h"
2830

2931
#define REFRESH_INDEX_DELAY_WARNING_IN_MS (2 * 1000)
3032

3133
static const char * const git_reset_usage[] = {
3234
N_("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"),
3335
N_("git reset [-q] [<tree-ish>] [--] <paths>..."),
36+
N_("EXPERIMENTAL: git reset [-q] [--stdin [-z]] [<tree-ish>]"),
3437
N_("git reset --patch [<tree-ish>] [--] [<paths>...]"),
3538
NULL
3639
};
@@ -284,7 +287,9 @@ static int git_reset_config(const char *var, const char *value, void *cb)
284287
int cmd_reset(int argc, const char **argv, const char *prefix)
285288
{
286289
int reset_type = NONE, update_ref_status = 0, quiet = 0;
287-
int patch_mode = 0, unborn;
290+
int patch_mode = 0, nul_term_line = 0, read_from_stdin = 0, unborn;
291+
char **stdin_paths = NULL;
292+
int stdin_nr = 0, stdin_alloc = 0;
288293
const char *rev;
289294
struct object_id oid;
290295
struct pathspec pathspec;
@@ -306,6 +311,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
306311
OPT_BOOL('p', "patch", &patch_mode, N_("select hunks interactively")),
307312
OPT_BOOL('N', "intent-to-add", &intent_to_add,
308313
N_("record only the fact that removed paths will be added later")),
314+
OPT_BOOL('z', NULL, &nul_term_line,
315+
N_("EXPERIMENTAL: paths are separated with NUL character")),
316+
OPT_BOOL(0, "stdin", &read_from_stdin,
317+
N_("EXPERIMENTAL: read paths from <stdin>")),
309318
OPT_END()
310319
};
311320

@@ -316,6 +325,42 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
316325
PARSE_OPT_KEEP_DASHDASH);
317326
parse_args(&pathspec, argv, prefix, patch_mode, &rev);
318327

328+
if (read_from_stdin) {
329+
strbuf_getline_fn getline_fn = nul_term_line ?
330+
strbuf_getline_nul : strbuf_getline_lf;
331+
int flags = PATHSPEC_PREFER_FULL;
332+
struct strbuf buf = STRBUF_INIT;
333+
struct strbuf unquoted = STRBUF_INIT;
334+
335+
if (patch_mode)
336+
die(_("--stdin is incompatible with --patch"));
337+
338+
if (pathspec.nr)
339+
die(_("--stdin is incompatible with path arguments"));
340+
341+
while (getline_fn(&buf, stdin) != EOF) {
342+
if (!nul_term_line && buf.buf[0] == '"') {
343+
strbuf_reset(&unquoted);
344+
if (unquote_c_style(&unquoted, buf.buf, NULL))
345+
die(_("line is badly quoted"));
346+
strbuf_swap(&buf, &unquoted);
347+
}
348+
ALLOC_GROW(stdin_paths, stdin_nr + 1, stdin_alloc);
349+
stdin_paths[stdin_nr++] = xstrdup(buf.buf);
350+
strbuf_reset(&buf);
351+
}
352+
strbuf_release(&unquoted);
353+
strbuf_release(&buf);
354+
355+
ALLOC_GROW(stdin_paths, stdin_nr + 1, stdin_alloc);
356+
stdin_paths[stdin_nr++] = NULL;
357+
flags |= PATHSPEC_LITERAL_PATH;
358+
parse_pathspec(&pathspec, 0, flags, prefix,
359+
(const char **)stdin_paths);
360+
361+
} else if (nul_term_line)
362+
die(_("-z requires --stdin"));
363+
319364
unborn = !strcmp(rev, "HEAD") && get_oid("HEAD", &oid);
320365
if (unborn) {
321366
/* reset on unborn branch: treat as reset to empty tree */
@@ -423,5 +468,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
423468
if (!pathspec.nr)
424469
remove_branch_state(the_repository);
425470

471+
if (stdin_paths) {
472+
while (stdin_nr)
473+
free(stdin_paths[--stdin_nr]);
474+
free(stdin_paths);
475+
}
476+
426477
return update_ref_status;
427478
}

t/t7108-reset-stdin.sh

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#!/bin/sh
2+
3+
test_description='reset --stdin'
4+
5+
. ./test-lib.sh
6+
7+
test_expect_success 'reset --stdin' '
8+
test_commit hello &&
9+
git rm hello.t &&
10+
test -z "$(git ls-files hello.t)" &&
11+
echo hello.t | git reset --stdin &&
12+
test hello.t = "$(git ls-files hello.t)"
13+
'
14+
15+
test_expect_success 'reset --stdin -z' '
16+
test_commit world &&
17+
git rm hello.t world.t &&
18+
test -z "$(git ls-files hello.t world.t)" &&
19+
printf world.tQworld.tQhello.tQ | q_to_nul | git reset --stdin -z &&
20+
printf "hello.t\nworld.t\n" >expect &&
21+
git ls-files >actual &&
22+
test_cmp expect actual
23+
'
24+
25+
test_expect_success '--stdin requires --mixed' '
26+
echo hello.t >list &&
27+
test_must_fail git reset --soft --stdin <list &&
28+
test_must_fail git reset --hard --stdin <list &&
29+
git reset --mixed --stdin <list
30+
'
31+
32+
test_done

0 commit comments

Comments
 (0)