Skip to content

Commit

Permalink
status: serialize to path
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
jeffhostetler authored and vdye committed Jul 19, 2023
1 parent 1765859 commit e421b5c
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 18 deletions.
10 changes: 6 additions & 4 deletions Documentation/git-status.txt
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,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
Expand Down
36 changes: 27 additions & 9 deletions builtin/commit.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,26 +173,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 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).
*
* Request that we serialize our output rather than printing in
* any of the established formats. Optionally specify serialization
* version.
* 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");
Expand Down Expand Up @@ -1595,7 +1603,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"),
Expand Down Expand Up @@ -1721,6 +1729,16 @@ int cmd_status(int argc, const char **argv, const char *prefix)
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);

Expand Down
23 changes: 23 additions & 0 deletions t/t7522-serialized-status.sh
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,27 @@ 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_done
5 changes: 2 additions & 3 deletions wt-status-serialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,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.
*
Expand All @@ -176,9 +176,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;

Expand Down
2 changes: 1 addition & 1 deletion wt-status.c
Original file line number Diff line number Diff line change
Expand Up @@ -2569,7 +2569,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;
}

Expand Down
2 changes: 1 addition & 1 deletion wt-status.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,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
Expand Down

0 comments on commit e421b5c

Please sign in to comment.