diff --git a/Documentation/git-last-modified.adoc b/Documentation/git-last-modified.adoc index 602843e09598a52bf6a8d506f3359f08e9bd39ce..36f72954a516dccf6eb5b5e549acb1f487f7c0ab 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,23 @@ OPTIONS `--recursive`:: Instead of showing tree entries, step into subtrees and show all entries inside them recursively. + See the section "NOTES ABOUT DEPTH" below for more details. `-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. + Setting a positive value implies `--recursive`. + Cannot be combined with wildcards in the pathspec. + See the section "NOTES ABOUT DEPTH" below for more details. + +`-z`:: + Terminate each line with a _NUL_ 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 +56,63 @@ 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 +------------ + +NOTES ABOUT DEPTH +----------------- + +By default this command only shows information about paths at the root level. +When a path that lives in a subtree is provided, information about the top-level +subtree is printed. For example: + +------------ +$ git last-modified -- sub/file + +abcd1234abcd1234abcd1234abcd1234abcd1234 sub +------------ + +To get details about the exact path in a subtree, add option `--recursive`: + +------------ +$ git last-modified --recursive -- sub/file + +5678abca5678abca5678abca5678abca5678abca sub/file +------------ + +This comes with a downside. When the path provided is a tree itself, with +option `--recursive` all paths in that subtree are printed too: + +------------ +$ git last-modified --recursive -- sub/subsub + +1234cdef1234cdef1234cdef1234cdef1234cdef sub/subsub/a +3456cdef3456cdef3456cdef3456cdef3456cdef sub/subsub/b +5678abcd5678abcd5678abcd5678abcd5678abcd sub/subsub/c +------------ + +To stop this command from traversing deeper into trees, add option +`--max-depth=0`: + +------------ +$ git last-modified --recursive --max-depth=0 -- sub/subsub + +3456def3456def3456def3456def3456def3456b sub/subsub +------------ + SEE ALSO -------- linkgit:git-blame[1], diff --git a/builtin/last-modified.c b/builtin/last-modified.c index b0ecbdc5400d137b7e147c8f91f43210cf8236e0..ccb7ff66d486f7058598d1828c901c64ace8834e 100644 --- a/builtin/last-modified.c +++ b/builtin/last-modified.c @@ -23,6 +23,11 @@ #define PARENT1 (1u<<16) /* used instead of SEEN */ #define PARENT2 (1u<<17) /* used instead of BOTTOM, BOUNDARY */ +#define LAST_MODIFIED_INIT { \ + .line_termination = '\n', \ + .max_depth = -1, \ +} + struct last_modified_entry { struct hashmap_entry hashent; struct object_id oid; @@ -55,6 +60,8 @@ struct last_modified { struct rev_info rev; bool recursive; bool show_trees; + int line_termination; + int max_depth; const char **all_paths; size_t all_paths_nr; @@ -165,7 +172,7 @@ 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) + if (lm->line_termination) write_name_quoted(path, stdout, '\n'); else printf("%s%c", path, '\0'); @@ -482,6 +489,12 @@ static int last_modified_init(struct last_modified *lm, struct repository *r, lm->rev.diffopt.flags.recursive = lm->recursive; lm->rev.diffopt.flags.tree_in_recursive = lm->show_trees; + if (lm->max_depth >= 0) { + lm->rev.diffopt.flags.recursive = 1; + lm->rev.diffopt.max_depth = lm->max_depth; + lm->rev.diffopt.max_depth_valid = 1; + } + argc = setup_revisions(argc, argv, &lm->rev, NULL); if (argc > 1) { error(_("unknown last-modified argument: %s"), argv[1]); @@ -507,10 +520,10 @@ int cmd_last_modified(int argc, const char **argv, const char *prefix, struct repository *repo) { int ret; - struct last_modified lm = { 0 }; + struct last_modified lm = LAST_MODIFIED_INIT; const char * const last_modified_usage[] = { - N_("git last-modified [--recursive] [--show-trees] " + N_("git last-modified [--recursive] [--show-trees] [--max-depth=] [-z] " "[] [[--] ...]"), NULL }; @@ -520,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_SET_INT('z', NULL, &lm.line_termination, + N_("lines are separated with NUL character"), '\0'), OPT_END() };