diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc index 602843e095..57136baf3b 100644 --- a/Documentation/git-last-modified.adoc +++ b/Documentation/git-last-modified.adoc @@ -9,7 +9,8 @@ git-last-modified - EXPERIMENTAL: Show when files were last modified SYNOPSIS -------- [synopsis] -git last-modified [--recursive] [--show-trees] [] [[--] ...] +git last-modified [--recursive] [--show-trees] [--max-depth=] [-z] + [] [[--] ...] DESCRIPTION ----------- @@ -26,12 +27,22 @@ OPTIONS `--recursive`:: Instead of showing tree entries, step into subtrees and show all entries inside them recursively. + This is identical as setting `--max-depth=-1`. `-t`:: `--show-trees`:: Show tree entries even when recursing into them. It has no effect without `--recursive`. +`--max-depth=`:: + For each pathspec given on the command line, descend at most `` + levels of directories. A negative value means no limit. + The default depth is 0. + Cannot be combined with wildcards in the pathspec. + +`-z`:: + Terminate each line with a _NUL_ character rather than a newline. + ``:: Only traverse commits in the specified revision range. When no `` is specified, it defaults to `HEAD` (i.e. the whole @@ -44,6 +55,22 @@ OPTIONS Without an optional path parameter, all files and subdirectories in path traversal the are included in the output. +OUTPUT +------ + +The output is in the format: + +------------ + TAB LF +------------ + +If a path contains any special characters, the path is C-style quoted. To +avoid quoting, pass option `-z` to terminate each line with a NUL. + +------------ + TAB NUL +------------ + SEE ALSO -------- linkgit:git-blame[1], diff --git a/builtin/last-modified.c b/builtin/last-modified.c index 5366cedd0f..d7c33f1784 100644 --- a/builtin/last-modified.c +++ b/builtin/last-modified.c @@ -55,6 +55,8 @@ struct last_modified { struct rev_info rev; bool recursive; bool show_trees; + bool null_termination; + int max_depth; const char **all_paths; size_t all_paths_nr; @@ -174,10 +176,10 @@ static void last_modified_emit(struct last_modified *lm, putchar('^'); printf("%s\t", oid_to_hex(&commit->object.oid)); - if (lm->rev.diffopt.line_termination) - write_name_quoted(path, stdout, '\n'); - else + if (lm->null_termination) printf("%s%c", path, '\0'); + else + write_name_quoted(path, stdout, '\n'); } static void mark_path(const char *path, const struct object_id *oid, @@ -488,8 +490,10 @@ static int last_modified_init(struct last_modified *lm, struct repository *r, lm->rev.no_commit_id = 1; lm->rev.diff = 1; lm->rev.diffopt.flags.no_recursive_diff_tree_combined = 1; - lm->rev.diffopt.flags.recursive = lm->recursive; + lm->rev.diffopt.flags.recursive = 1; lm->rev.diffopt.flags.tree_in_recursive = lm->show_trees; + lm->rev.diffopt.max_depth = lm->max_depth; + lm->rev.diffopt.max_depth_valid = !lm->recursive && lm->max_depth >= 0; argc = setup_revisions(argc, argv, &lm->rev, NULL); if (argc > 1) { @@ -519,8 +523,8 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, struct last_modified lm = { 0 }; const char * const last_modified_usage[] = { - N_("git last-modified [--recursive] [--show-trees] " - "[] [[--] ...]"), + N_("git last-modified [--recursive] [--show-trees] [--max-depth=] [-z]\n" + " [] [[--] ...]"), NULL }; @@ -529,6 +533,10 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, N_("recurse into subtrees")), OPT_BOOL('t', "show-trees", &lm.show_trees, N_("show tree entries when recursing into subtrees")), + OPT_INTEGER_F(0, "max-depth", &lm.max_depth, + N_("maximum tree depth to recurse"), PARSE_OPT_NONEG), + OPT_BOOL('z', NULL, &lm.null_termination, + N_("lines are separated with NUL character")), OPT_END() }; diff --git a/t/t8020-last-modified.sh b/t/t8020-last-modified.sh index 22635de447..41594f2034 100755 --- a/t/t8020-last-modified.sh +++ b/t/t8020-last-modified.sh @@ -101,6 +101,41 @@ test_expect_success 'last-modified subdir recursive' ' EOF ' +test_expect_success 'last-modified subdir non-recursive' ' + check_last_modified a <<-\EOF + 3 a + EOF +' + +test_expect_success 'last-modified path in subdir non-recursive' ' + check_last_modified a/file <<-\EOF + 2 a/file + EOF +' + +test_expect_success 'last-modified subdir with wildcard non-recursive' ' + check_last_modified a/* <<-\EOF + 3 a/b + 2 a/file + EOF +' + +test_expect_success 'last-modified with negative max-depth' ' + check_last_modified --max-depth=-1 <<-\EOF + 3 a/b/file + 2 a/file + 1 file + EOF +' + +test_expect_success 'last-modified with max-depth of 1' ' + check_last_modified --max-depth=1 <<-\EOF + 3 a/b + 2 a/file + 1 file + EOF +' + test_expect_success 'last-modified from non-HEAD commit' ' check_last_modified HEAD^ <<-\EOF 2 a