Merge branch 'kh/format-rev-more-options' into seen
The experimental 'git format-rev' has been taught a few more formatting options. * kh/format-rev-more-options: format-rev: learn --abbrev, --color, and --date doc: rev-list-options.adoc: factor out --date alts format-rev: factor option variables into a struct format-rev: place BUG calls first in callback format-rev: use lower case for opts descriptionseen
commit
c0d6a4d68a
|
|
@ -9,7 +9,7 @@ git-format-rev - EXPERIMENTAL: Pretty format revisions on demand
|
|||
SYNOPSIS
|
||||
--------
|
||||
[synopsis]
|
||||
(EXPERIMENTAL!) git format-rev --stdin-mode=<mode> --format=<pretty> [--[no-]notes=<ref>] [-z] [--[no-]null-output] [--[no-]null-input]
|
||||
(EXPERIMENTAL!) git format-rev [<options>] --stdin-mode=<mode> --format=<pretty>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
|
@ -33,8 +33,8 @@ OPTIONS
|
|||
The argument `rev` is also accepted.
|
||||
|
||||
`text`;; Formats all commit object names found in freeform text. These
|
||||
must be full object names, i.e. abbreviated hexadecimal object
|
||||
names will not be interpreted.
|
||||
must be full object names, i.e. abbreviated hexadecimal (_hex_)
|
||||
object names will not be interpreted.
|
||||
+
|
||||
Anything that is parsed as an object name but that is not found to be a
|
||||
commit object name is left alone (echoed).
|
||||
|
|
@ -76,6 +76,44 @@ This is useful if the output could contain newlines, for example if the
|
|||
+
|
||||
This is useful if the input revision expressions could contain newlines.
|
||||
|
||||
`--color[=<when>]`::
|
||||
`--no-color`::
|
||||
Respect color formatting. The default color behavior is
|
||||
`auto`. Bare `--color` is the same as `--color=always`.
|
||||
+
|
||||
Giving `--no-color` is the same as `--color=never`.
|
||||
+
|
||||
_<when>_ must be one of:
|
||||
+
|
||||
--
|
||||
`always`;;
|
||||
Always use color, even if the output is something like a file.
|
||||
`never`;;
|
||||
Never use color.
|
||||
`auto`;;
|
||||
Use color when the output is a terminal but not when the output
|
||||
is something like a file.
|
||||
--
|
||||
|
||||
`--abbrev[=<n>]`::
|
||||
`--no-abbrev`::
|
||||
Abbreviate the commit hex output. Without _<n>_ it will find the
|
||||
minimum length which can describe the commit uniquely, with some
|
||||
extra slack. Giving _<n>_ specifies the minimum length; a longer
|
||||
length will be used if needed.
|
||||
+
|
||||
Giving `--no-abbrev` will turn off abbreviation, showing the full commit
|
||||
hex output.
|
||||
+
|
||||
Note that some pretty formats use `--abbrev`. This behavior can be
|
||||
controlled with these two options.
|
||||
|
||||
`--date=<format>`::
|
||||
Date format for pretty formats. Note that date atoms like `%aI`
|
||||
are not affected. This option cannot be negated.
|
||||
+
|
||||
include::rev-list-option-date-alternatives.adoc[]
|
||||
|
||||
[[io]]
|
||||
INPUT AND OUTPUT FORMAT
|
||||
-----------------------
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
--
|
||||
`--date=relative` shows dates relative to the current time,
|
||||
e.g. ``2 hours ago''. The `-local` option has no effect for
|
||||
`--date=relative`.
|
||||
|
||||
`--date=local` is an alias for `--date=default-local`.
|
||||
|
||||
`--date=iso` (or `--date=iso8601`) shows timestamps in a ISO 8601-like format.
|
||||
The differences to the strict ISO 8601 format are:
|
||||
|
||||
- a space instead of the `T` date/time delimiter
|
||||
- a space between time and time zone
|
||||
- no colon between hours and minutes of the time zone
|
||||
|
||||
`--date=iso-strict` (or `--date=iso8601-strict`) shows timestamps in strict
|
||||
ISO 8601 format.
|
||||
|
||||
`--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822
|
||||
format, often found in email messages.
|
||||
|
||||
`--date=short` shows only the date, but not the time, in `YYYY-MM-DD` format.
|
||||
|
||||
`--date=raw` shows the date as seconds since the epoch (1970-01-01
|
||||
00:00:00 UTC), followed by a space, and then the timezone as an offset
|
||||
from UTC (a `+` or `-` with four digits; the first two are hours, and
|
||||
the second two are minutes). I.e., as if the timestamp were formatted
|
||||
with `strftime("%s %z")`).
|
||||
Note that the `-local` option does not affect the seconds-since-epoch
|
||||
value (which is always measured in UTC), but does switch the accompanying
|
||||
timezone value.
|
||||
|
||||
`--date=human` shows the timezone if the timezone does not match the
|
||||
current time-zone, and doesn't print the whole date if that matches
|
||||
(ie skip printing year for dates that are "this year", but also skip
|
||||
the whole date itself if it's in the last few days and we can just say
|
||||
what weekday it was). For older dates the hour and minute is also
|
||||
omitted.
|
||||
|
||||
`--date=unix` shows the date as a Unix epoch timestamp (seconds since
|
||||
1970). As with `--raw`, this is always in UTC and therefore `-local`
|
||||
has no effect.
|
||||
|
||||
`--date=format:<format>` feeds the _<format>_ to your system `strftime`,
|
||||
except for `%s`, `%z`, and `%Z`, which are handled internally.
|
||||
Use `--date=format:%c` to show the date in your system locale's
|
||||
preferred format. See the `strftime`(3) manual for a complete list of
|
||||
format placeholders. When using `-local`, the correct syntax is
|
||||
`--date=format-local:<format>`.
|
||||
|
||||
`--date=default` is the default format, and is based on ctime(3)
|
||||
output. It shows a single line with three-letter day of the week,
|
||||
three-letter month, day-of-month, hour-minute-seconds in "HH:MM:SS"
|
||||
format, followed by 4-digit year, plus timezone information, unless
|
||||
the local time zone is used, e.g. `Thu Jan 1 00:00:00 1970 +0000`.
|
||||
--
|
||||
|
|
@ -1132,61 +1132,7 @@ include::pretty-options.adoc[]
|
|||
author's). If `-local` is appended to the format (e.g.,
|
||||
`iso-local`), the user's local time zone is used instead.
|
||||
+
|
||||
--
|
||||
`--date=relative` shows dates relative to the current time,
|
||||
e.g. ``2 hours ago''. The `-local` option has no effect for
|
||||
`--date=relative`.
|
||||
|
||||
`--date=local` is an alias for `--date=default-local`.
|
||||
|
||||
`--date=iso` (or `--date=iso8601`) shows timestamps in a ISO 8601-like format.
|
||||
The differences to the strict ISO 8601 format are:
|
||||
|
||||
- a space instead of the `T` date/time delimiter
|
||||
- a space between time and time zone
|
||||
- no colon between hours and minutes of the time zone
|
||||
|
||||
`--date=iso-strict` (or `--date=iso8601-strict`) shows timestamps in strict
|
||||
ISO 8601 format.
|
||||
|
||||
`--date=rfc` (or `--date=rfc2822`) shows timestamps in RFC 2822
|
||||
format, often found in email messages.
|
||||
|
||||
`--date=short` shows only the date, but not the time, in `YYYY-MM-DD` format.
|
||||
|
||||
`--date=raw` shows the date as seconds since the epoch (1970-01-01
|
||||
00:00:00 UTC), followed by a space, and then the timezone as an offset
|
||||
from UTC (a `+` or `-` with four digits; the first two are hours, and
|
||||
the second two are minutes). I.e., as if the timestamp were formatted
|
||||
with `strftime("%s %z")`).
|
||||
Note that the `-local` option does not affect the seconds-since-epoch
|
||||
value (which is always measured in UTC), but does switch the accompanying
|
||||
timezone value.
|
||||
|
||||
`--date=human` shows the timezone if the timezone does not match the
|
||||
current time-zone, and doesn't print the whole date if that matches
|
||||
(ie skip printing year for dates that are "this year", but also skip
|
||||
the whole date itself if it's in the last few days and we can just say
|
||||
what weekday it was). For older dates the hour and minute is also
|
||||
omitted.
|
||||
|
||||
`--date=unix` shows the date as a Unix epoch timestamp (seconds since
|
||||
1970). As with `--raw`, this is always in UTC and therefore `-local`
|
||||
has no effect.
|
||||
|
||||
`--date=format:<format>` feeds the _<format>_ to your system `strftime`,
|
||||
except for `%s`, `%z`, and `%Z`, which are handled internally.
|
||||
Use `--date=format:%c` to show the date in your system locale's
|
||||
preferred format. See the `strftime`(3) manual for a complete list of
|
||||
format placeholders. When using `-local`, the correct syntax is
|
||||
`--date=format-local:<format>`.
|
||||
|
||||
`--date=default` is the default format, and is based on ctime(3)
|
||||
output. It shows a single line with three-letter day of the week,
|
||||
three-letter month, day-of-month, hour-minute-seconds in "HH:MM:SS"
|
||||
format, followed by 4-digit year, plus timezone information, unless
|
||||
the local time zone is used, e.g. `Thu Jan 1 00:00:00 1970 +0000`.
|
||||
--
|
||||
include::rev-list-option-date-alternatives.adoc[]
|
||||
|
||||
ifdef::git-rev-list[]
|
||||
`--header`::
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "revision.h"
|
||||
#include "notes.h"
|
||||
#include "write-or-die.h"
|
||||
#include "date.h"
|
||||
|
||||
/*
|
||||
* One day. See the 'name a rev shortly after epoch' test in t6120 when
|
||||
|
|
@ -772,20 +773,36 @@ int cmd_name_rev(int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct format_nul_data {
|
||||
struct format_rev_data {
|
||||
const char *format;
|
||||
const char *stdin_mode;
|
||||
bool nul_input;
|
||||
bool nul_output;
|
||||
struct string_list notes;
|
||||
struct rev_info rev;
|
||||
int color;
|
||||
};
|
||||
|
||||
static int format_nul_cb(const struct option *option,
|
||||
const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct format_nul_data *data = option->value;
|
||||
data->nul_input = 1;
|
||||
data->nul_output = 1;
|
||||
struct format_rev_data *data = option->value;
|
||||
BUG_ON_OPT_NEG(unset);
|
||||
BUG_ON_OPT_ARG(arg);
|
||||
data->nul_input = 1;
|
||||
data->nul_output = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int date_cb(const struct option *option,
|
||||
const char *arg,
|
||||
int unset)
|
||||
{
|
||||
struct rev_info *data = option->value;
|
||||
BUG_ON_OPT_NEG(unset);
|
||||
parse_date_format(arg, &data->date_mode);
|
||||
data->date_mode_explicit = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -802,9 +819,8 @@ static enum stdin_mode parse_stdin_mode(const char *stdin_mode)
|
|||
}
|
||||
|
||||
static char const *const format_rev_usage[] = {
|
||||
N_("(EXPERIMENTAL!) git format-rev --stdin-mode=<mode> "
|
||||
"--format=<pretty> [--[no-]notes=<ref>] "
|
||||
"[-z] [--[no-]null-output] [--[no-]null-input]"),
|
||||
N_("(EXPERIMENTAL!) git format-rev [<options>] "
|
||||
"--stdin-mode=<mode> --format=<pretty>"),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -813,32 +829,37 @@ int cmd_format_rev(int argc,
|
|||
const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
{
|
||||
const char *format = NULL;
|
||||
struct format_rev_data data = {
|
||||
.notes = STRING_LIST_INIT_NODUP,
|
||||
.rev = REV_INFO_INIT,
|
||||
.color = GIT_COLOR_AUTO,
|
||||
};
|
||||
enum stdin_mode stdin_mode;
|
||||
const char *stdin_mode_arg = NULL;
|
||||
struct format_nul_data nul_data = { 0, 0 };
|
||||
char output_terminator;
|
||||
strbuf_getline_fn getline_fn;
|
||||
struct display_notes_opt format_notes_opt;
|
||||
struct rev_info format_rev = REV_INFO_INIT;
|
||||
struct pretty_format format_pp = { 0 };
|
||||
struct string_list notes = STRING_LIST_INIT_NODUP;
|
||||
struct strbuf scratch_buf = STRBUF_INIT;
|
||||
struct command cmd;
|
||||
struct option opts[] = {
|
||||
OPT_STRING(0, "format", &format, N_("format"),
|
||||
OPT_STRING(0, "format", &data.format, N_("format"),
|
||||
N_("pretty format to use")),
|
||||
OPT_STRING(0, "stdin-mode", &stdin_mode_arg, N_("stdin-mode"),
|
||||
OPT_STRING(0, "stdin-mode", &data.stdin_mode, N_("stdin-mode"),
|
||||
N_("how revs are processed")),
|
||||
OPT_STRING_LIST(0, "notes", ¬es, N_("notes"),
|
||||
OPT_STRING_LIST(0, "notes", &data.notes, N_("notes"),
|
||||
N_("display notes for pretty format")),
|
||||
OPT_CALLBACK_F('z', "null", &nul_data, N_("z"),
|
||||
N_("Use NUL for input and output termination"),
|
||||
OPT__ABBREV(&data.rev.abbrev),
|
||||
OPT__COLOR(&data.color, N_("use colored output")),
|
||||
OPT_CALLBACK_F(0, "date", &data.rev, N_("date"),
|
||||
N_("date format"),
|
||||
PARSE_OPT_NONEG, date_cb),
|
||||
OPT_CALLBACK_F('z', "null", &data, N_("z"),
|
||||
N_("use NUL for input and output termination"),
|
||||
PARSE_OPT_NOARG | PARSE_OPT_NONEG, format_nul_cb),
|
||||
OPT_BOOL(0, "null-input", &nul_data.nul_input,
|
||||
N_("Use NUL for input termination")),
|
||||
OPT_BOOL(0, "null-output", &nul_data.nul_output,
|
||||
N_("Use NUL for output termination")),
|
||||
OPT_BOOL(0, "null-input", &data.nul_input,
|
||||
N_("use NUL for input termination")),
|
||||
OPT_BOOL(0, "null-output", &data.nul_output,
|
||||
N_("use NUL for output termination")),
|
||||
OPT_END(),
|
||||
};
|
||||
|
||||
|
|
@ -849,32 +870,32 @@ int cmd_format_rev(int argc,
|
|||
usage_with_options(format_rev_usage, opts);
|
||||
}
|
||||
|
||||
if (!format)
|
||||
if (!data.format)
|
||||
die(_("'%s' is required"), "--format");
|
||||
if (!stdin_mode_arg)
|
||||
if (!data.stdin_mode)
|
||||
die(_("'%s' is required"), "--stdin-mode");
|
||||
|
||||
getline_fn = nul_data.nul_input ? strbuf_getline_nul : strbuf_getline_lf;
|
||||
output_terminator = nul_data.nul_output ? '\0' : '\n';
|
||||
getline_fn = data.nul_input ? strbuf_getline_nul : strbuf_getline_lf;
|
||||
output_terminator = data.nul_output ? '\0' : '\n';
|
||||
|
||||
init_display_notes(&format_notes_opt);
|
||||
stdin_mode = parse_stdin_mode(stdin_mode_arg);
|
||||
stdin_mode = parse_stdin_mode(data.stdin_mode);
|
||||
|
||||
get_commit_format(format, &format_rev);
|
||||
format_pp.ctx.rev = &format_rev;
|
||||
format_pp.ctx.fmt = format_rev.commit_format;
|
||||
format_pp.ctx.abbrev = format_rev.abbrev;
|
||||
format_pp.ctx.date_mode_explicit = format_rev.date_mode_explicit;
|
||||
format_pp.ctx.date_mode = format_rev.date_mode;
|
||||
format_pp.ctx.color = GIT_COLOR_AUTO;
|
||||
get_commit_format(data.format, &data.rev);
|
||||
format_pp.ctx.rev = &data.rev;
|
||||
format_pp.ctx.fmt = data.rev.commit_format;
|
||||
format_pp.ctx.abbrev = data.rev.abbrev;
|
||||
format_pp.ctx.date_mode_explicit = data.rev.date_mode_explicit;
|
||||
format_pp.ctx.date_mode = data.rev.date_mode;
|
||||
format_pp.ctx.color = data.color;
|
||||
|
||||
userformat_find_requirements(format,
|
||||
userformat_find_requirements(data.format,
|
||||
&format_pp.want);
|
||||
if (format_pp.want.notes) {
|
||||
int ignore_show_notes = 0;
|
||||
struct string_list_item *n;
|
||||
|
||||
for_each_string_list_item(n, ¬es)
|
||||
for_each_string_list_item(n, &data.notes)
|
||||
enable_ref_display_notes(&format_notes_opt,
|
||||
&ignore_show_notes,
|
||||
n->string);
|
||||
|
|
@ -933,8 +954,9 @@ int cmd_format_rev(int argc,
|
|||
BUG("uncovered case: %d", stdin_mode);
|
||||
}
|
||||
|
||||
date_mode_release(&data.rev.date_mode);
|
||||
strbuf_release(&scratch_buf);
|
||||
string_list_clear(¬es, 0);
|
||||
string_list_clear(&data.notes, 0);
|
||||
release_display_notes(&format_notes_opt);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1017,4 +1017,62 @@ do
|
|||
'
|
||||
done <stdin-modes
|
||||
|
||||
format_rev_cmp_log () {
|
||||
opts="$1"
|
||||
format=reference
|
||||
cat >input <<-\EOF &&
|
||||
third
|
||||
second
|
||||
first
|
||||
EOF
|
||||
git -C repo-format log --stdin --no-walk \
|
||||
--format="$format" "$opts" >expect <input &&
|
||||
git -C repo-format format-rev --stdin-mode=revs \
|
||||
--format="$format" "$opts" >actual <input &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
format_rev_err_cmp_log () {
|
||||
opts="$1"
|
||||
format=reference
|
||||
# No input since we ought to fail while parsing options
|
||||
test_must_fail git -C repo-format log --stdin --no-walk \
|
||||
--format="$format" "$opts" 2>expect &&
|
||||
test_must_fail git -C repo-format format-rev \
|
||||
--stdin-mode=revs --format="$format" "$opts" 2>actual &&
|
||||
test_cmp expect actual
|
||||
}
|
||||
|
||||
test_expect_success 'format-rev --color' '
|
||||
format_rev_cmp_log --color=always &&
|
||||
format_rev_cmp_log --color &&
|
||||
format_rev_cmp_log --no-color &&
|
||||
format_rev_err_cmp_log --color=not-valid
|
||||
'
|
||||
|
||||
test_expect_success 'format-rev --abbrev' '
|
||||
format_rev_cmp_log --abbrev &&
|
||||
format_rev_cmp_log --abbrev=31 &&
|
||||
format_rev_cmp_log --no-abbrev
|
||||
'
|
||||
|
||||
test_expect_success 'format-rev --date' '
|
||||
format_rev_cmp_log --date=relative &&
|
||||
format_rev_cmp_log --date=iso-strict &&
|
||||
# This also tests the only case where we need to release
|
||||
# the data for the parsed format
|
||||
format_rev_cmp_log --date="format:%c" &&
|
||||
format_rev_err_cmp_log --date=not-valid &&
|
||||
# Test --date (no arg) next
|
||||
# We cannot compare the output to git-log(1)
|
||||
# because that command uses a slightly different
|
||||
# error message (different library)
|
||||
cat >expect <<-EOF &&
|
||||
error: option \`date${SQ} requires a value
|
||||
EOF
|
||||
test_must_fail git -C repo-format format-rev \
|
||||
--stdin-mode=revs --format="$format" --date 2>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
|||
Loading…
Reference in New Issue