2222#include "unpack-trees.h"
2323#include "cache-tree.h"
2424#include "resolve-undo.h"
25+ #include "strbuf.h"
26+ #include "quote.h"
2527
2628static const char * const git_reset_usage [] = {
2729 N_ ("git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]" ),
2830 N_ ("git reset [-q] [<tree-ish>] [--] <paths>..." ),
31+ N_ ("EXPERIMENTAL: git reset [-q] [--stdin [-z]] [<tree-ish>]" ),
2932 N_ ("git reset --patch [<tree-ish>] [--] [<paths>...]" ),
3033 NULL
3134};
@@ -268,7 +271,9 @@ static int reset_refs(const char *rev, const struct object_id *oid)
268271int cmd_reset (int argc , const char * * argv , const char * prefix )
269272{
270273 int reset_type = NONE , update_ref_status = 0 , quiet = 0 ;
271- int patch_mode = 0 , unborn ;
274+ int patch_mode = 0 , nul_term_line = 0 , read_from_stdin = 0 , unborn ;
275+ char * * stdin_paths = NULL ;
276+ int stdin_nr = 0 , stdin_alloc = 0 ;
272277 const char * rev ;
273278 struct object_id oid ;
274279 struct pathspec pathspec ;
@@ -290,6 +295,10 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
290295 N_ ("record only the fact that removed paths will be added later" )),
291296 OPT_BOOL (0 , "unmerge" , & unmerge ,
292297 N_ ("recover conflicted stages from an earlier 'git add'" )),
298+ OPT_BOOL ('z' , NULL , & nul_term_line ,
299+ N_ ("EXPERIMENTAL: paths are separated with NUL character" )),
300+ OPT_BOOL (0 , "stdin" , & read_from_stdin ,
301+ N_ ("EXPERIMENTAL: read paths from <stdin>" )),
293302 OPT_END ()
294303 };
295304
@@ -299,6 +308,43 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
299308 PARSE_OPT_KEEP_DASHDASH );
300309 parse_args (& pathspec , argv , prefix , patch_mode , & rev );
301310
311+ if (read_from_stdin ) {
312+ strbuf_getline_fn getline_fn = nul_term_line ?
313+ strbuf_getline_nul : strbuf_getline_lf ;
314+ int flags = PATHSPEC_PREFER_FULL |
315+ PATHSPEC_STRIP_SUBMODULE_SLASH_CHEAP ;
316+ struct strbuf buf = STRBUF_INIT ;
317+ struct strbuf unquoted = STRBUF_INIT ;
318+
319+ if (patch_mode )
320+ die (_ ("--stdin is incompatible with --patch" ));
321+
322+ if (pathspec .nr )
323+ die (_ ("--stdin is incompatible with path arguments" ));
324+
325+ while (getline_fn (& buf , stdin ) != EOF ) {
326+ if (!nul_term_line && buf .buf [0 ] == '"' ) {
327+ strbuf_reset (& unquoted );
328+ if (unquote_c_style (& unquoted , buf .buf , NULL ))
329+ die (_ ("line is badly quoted" ));
330+ strbuf_swap (& buf , & unquoted );
331+ }
332+ ALLOC_GROW (stdin_paths , stdin_nr + 1 , stdin_alloc );
333+ stdin_paths [stdin_nr ++ ] = xstrdup (buf .buf );
334+ strbuf_reset (& buf );
335+ }
336+ strbuf_release (& unquoted );
337+ strbuf_release (& buf );
338+
339+ ALLOC_GROW (stdin_paths , stdin_nr + 1 , stdin_alloc );
340+ stdin_paths [stdin_nr ++ ] = NULL ;
341+ flags |= PATHSPEC_LITERAL_PATH ;
342+ parse_pathspec (& pathspec , 0 , flags , prefix ,
343+ (const char * * )stdin_paths );
344+
345+ } else if (nul_term_line )
346+ die (_ ("-z requires --stdin" ));
347+
302348 unborn = !strcmp (rev , "HEAD" ) && get_sha1 ("HEAD" , oid .hash );
303349 if (unborn ) {
304350 /* reset on unborn branch: treat as reset to empty tree */
@@ -391,5 +437,11 @@ int cmd_reset(int argc, const char **argv, const char *prefix)
391437 if (!pathspec .nr )
392438 remove_branch_state ();
393439
440+ if (stdin_paths ) {
441+ while (stdin_nr )
442+ free (stdin_paths [-- stdin_nr ]);
443+ free (stdin_paths );
444+ }
445+
394446 return update_ref_status ;
395447}
0 commit comments