Teach status serialization to take an optional pathname on
the command line to direct that cache data be written there
rather than to stdout.  When used this way, normal status
results will still be written to stdout.

When no path is given, only binary serialization data is
written to stdout.

Usage:
    git status --serialize[=<path>]

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
This commit is contained in:
Jeff Hostetler 2018-02-02 14:17:05 -05:00 коммит произвёл Johannes Schindelin
Родитель 5883f07892
Коммит e6ee448d11
6 изменённых файлов: 72 добавлений и 18 удалений

Просмотреть файл

@ -151,10 +151,12 @@ ignored, then the directory is not shown, but all contents are shown.
threshold.
See also linkgit:git-diff[1] `--find-renames`.
--serialize[=<version>]::
(EXPERIMENTAL) Serialize raw status results to stdout in a
format suitable for use by `--deserialize`. Valid values for
`<version>` are "1" and "v1".
--serialize[=<path>]::
(EXPERIMENTAL) Serialize raw status results to a file or stdout
in a format suitable for use by `--deserialize`. If a path is
given, serialize data will be written to that path *and* normal
status output will be written to stdout. If path is omitted,
only binary serialization data will be written to stdout.
--deserialize[=<path>]::
(EXPERIMENTAL) Deserialize raw status results from a file or

Просмотреть файл

@ -168,26 +168,34 @@ static int opt_parse_porcelain(const struct option *opt, const char *arg, int un
}
static int do_serialize = 0;
static char *serialize_path = NULL;
static int do_implicit_deserialize = 0;
static int do_explicit_deserialize = 0;
static char *deserialize_path = NULL;
/*
* --serialize | --serialize=1 | --serialize=v1
* --serialize | --serialize=<path>
*
* Request that we serialize our output rather than printing in
* any of the established formats. Optionally specify serialization
* version.
* Request that we serialize status output rather than or in addition to
* printing in any of the established formats.
*
* Without a path, we write binary serialization data to stdout (and omit
* the normal status output).
*
* With a path, we write binary serialization data to the <path> and then
* write normal status output.
*/
static int opt_parse_serialize(const struct option *opt, const char *arg, int unset)
{
enum wt_status_format *value = (enum wt_status_format *)opt->value;
if (unset || !arg)
*value = STATUS_FORMAT_SERIALIZE_V1;
else if (!strcmp(arg, "v1") || !strcmp(arg, "1"))
*value = STATUS_FORMAT_SERIALIZE_V1;
else
die("unsupported serialize version '%s'", arg);
if (arg) {
free(serialize_path);
serialize_path = xstrdup(arg);
}
if (do_explicit_deserialize)
die("cannot mix --serialize and --deserialize");
@ -1615,7 +1623,7 @@ int cmd_status(int argc, const char **argv, const char *prefix)
N_("version"), N_("machine-readable output"),
PARSE_OPT_OPTARG, opt_parse_porcelain),
{ OPTION_CALLBACK, 0, "serialize", &status_format,
N_("version"), N_("serialize raw status data to stdout"),
N_("path"), N_("serialize raw status data to path or stdout"),
PARSE_OPT_OPTARG | PARSE_OPT_NONEG, opt_parse_serialize },
{ OPTION_CALLBACK, 0, "deserialize", NULL,
N_("path"), N_("deserialize raw status data from file"),
@ -1741,6 +1749,16 @@ skip_init:
if (s.relative_paths)
s.prefix = prefix;
if (serialize_path) {
int fd_serialize = xopen(serialize_path,
O_WRONLY | O_CREAT | O_TRUNC, 0666);
if (fd_serialize < 0)
die_errno(_("could not serialize to '%s'"),
serialize_path);
wt_status_serialize_v1(fd_serialize, &s);
close(fd_serialize);
}
wt_status_print(&s);
wt_status_collect_free_buffers(&s);

Просмотреть файл

@ -170,4 +170,39 @@ test_expect_success 'verify no-ahead-behind and serialized status integration' '
test_cmp expect output
'
test_expect_success 'verify new --serialize=path mode' '
#test_when_finished "rm serialized_status.dat expect new_change.txt output.1 output.2" &&
cat >expect <<-\EOF &&
? expect
? output.1
? untracked/
? untracked_1.txt
EOF
git checkout -b serialize_path_branch main --track >/dev/null &&
touch alt_branch_changes.txt &&
git add alt_branch_changes.txt &&
test_tick &&
git commit -m"New commit on serialize_path_branch" &&
git status --porcelain=v2 --serialize=serialized_status.dat >output.1 &&
touch new_change.txt &&
git status --porcelain=v2 --deserialize=serialized_status.dat >output.2 &&
test_cmp expect output.1 &&
test_cmp expect output.2
'
test_expect_success 'renames' '
git init -b main rename_test &&
echo OLDNAME >rename_test/OLDNAME &&
git -C rename_test add OLDNAME &&
git -C rename_test commit -m OLDNAME &&
git -C rename_test mv OLDNAME NEWNAME &&
git -C rename_test status --serialize=renamed.dat >output.1 &&
echo DIRT >rename_test/DIRT &&
git -C rename_test status --deserialize=renamed.dat >output.2 &&
test_cmp output.1 output.2
'
test_done

Просмотреть файл

@ -169,7 +169,7 @@ static inline void wt_serialize_v1_ignored(struct wt_status *s, int fd,
}
/*
* Serialize the list of changes to stdout. The goal of this
* Serialize the list of changes to the given file. The goal of this
* is to just serialize the key fields in wt_status so that a
* later command can rebuilt it and do the printing.
*
@ -178,9 +178,8 @@ static inline void wt_serialize_v1_ignored(struct wt_status *s, int fd,
* is relatively quick for the status consumer to compute
* as necessary.
*/
void wt_status_serialize_v1(struct wt_status *s)
void wt_status_serialize_v1(int fd, struct wt_status *s)
{
int fd = 1; /* we always write to stdout */
struct string_list_item *iter;
int k;

Просмотреть файл

@ -2580,7 +2580,7 @@ void wt_status_print(struct wt_status *s)
wt_longstatus_print(s);
break;
case STATUS_FORMAT_SERIALIZE_V1:
wt_status_serialize_v1(s);
wt_status_serialize_v1(1, s);
break;
}

Просмотреть файл

@ -224,7 +224,7 @@ struct wt_status_serialize_data
* Serialize computed status scan results using "version 1" format
* to the given file.
*/
void wt_status_serialize_v1(struct wt_status *s);
void wt_status_serialize_v1(int fd, struct wt_status *s);
/*
* Deserialize existing status results from the given file and