Skip to content

Commit 2acf45f

Browse files
jeffhostetlerdscho
authored andcommitted
status: reject deserialize in V2 and conflicts
Teach status deserialize code to reject status cache when printing in porcelain V2 and there are unresolved conflicts in the cache file. A follow-on task might extend the cache format to include this additiona data. See code for longer explanation. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
1 parent 760d513 commit 2acf45f

File tree

2 files changed

+115
-3
lines changed

2 files changed

+115
-3
lines changed

Diff for: t/t7522-serialized-status.sh

+89-1
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,14 @@ test_expect_success 'setup' '
5151
5252
test_oid_cache <<-EOF
5353
branch_oid sha1:68d4a437ea4c2de65800f48c053d4d543b55c410
54+
x_base sha1:587be6b4c3f93f93c489c0111bba5596147a26cb
55+
x_ours sha1:b68025345d5301abad4d9ec9166f455243a0d746
56+
x_theirs sha1:975fbec8256d3e8a3797e7a3611380f27c49f4ac
5457
5558
branch_oid sha256:6b95e4b1ea911dad213f2020840f5e92d3066cf9e38cf35f79412ec58d409ce4
59+
x_base sha256:14f5162e2fe3d240d0d37aaab0f90e4af9a7cfa79639f3bab005b5bfb4174d9f
60+
x_ours sha256:3a404ba030a4afa912155c476a48a253d4b3a43d0098431b6d6ca6e554bd78fb
61+
x_theirs sha256:44dc634218adec09e34f37839b3840bad8c6103693e9216626b32d00e093fa35
5662
EOF
5763
'
5864

@@ -171,7 +177,7 @@ test_expect_success 'verify no-ahead-behind and serialized status integration' '
171177
'
172178

173179
test_expect_success 'verify new --serialize=path mode' '
174-
#test_when_finished "rm serialized_status.dat expect new_change.txt output.1 output.2" &&
180+
test_when_finished "rm serialized_status.dat expect new_change.txt output.1 output.2" &&
175181
cat >expect <<-\EOF &&
176182
? expect
177183
? output.1
@@ -193,6 +199,88 @@ test_expect_success 'verify new --serialize=path mode' '
193199
test_cmp expect output.2
194200
'
195201

202+
test_expect_success 'merge conflicts' '
203+
204+
# create a merge conflict.
205+
206+
git init -b main conflicts &&
207+
echo x >conflicts/x.txt &&
208+
git -C conflicts add x.txt &&
209+
git -C conflicts commit -m x &&
210+
git -C conflicts branch a &&
211+
git -C conflicts branch b &&
212+
git -C conflicts checkout a &&
213+
echo y >conflicts/x.txt &&
214+
git -C conflicts add x.txt &&
215+
git -C conflicts commit -m a &&
216+
git -C conflicts checkout b &&
217+
echo z >conflicts/x.txt &&
218+
git -C conflicts add x.txt &&
219+
git -C conflicts commit -m b &&
220+
test_must_fail git -C conflicts merge --no-commit a &&
221+
222+
# verify that regular status correctly identifies it
223+
# in each format.
224+
225+
cat >expect.v2 <<EOF &&
226+
u UU N... 100644 100644 100644 100644 $(test_oid x_base) $(test_oid x_ours) $(test_oid x_theirs) x.txt
227+
EOF
228+
git -C conflicts status --porcelain=v2 >observed.v2 &&
229+
test_cmp expect.v2 observed.v2 &&
230+
231+
cat >expect.long <<EOF &&
232+
On branch b
233+
You have unmerged paths.
234+
(fix conflicts and run "git commit")
235+
(use "git merge --abort" to abort the merge)
236+
237+
Unmerged paths:
238+
(use "git add <file>..." to mark resolution)
239+
both modified: x.txt
240+
241+
no changes added to commit (use "git add" and/or "git commit -a")
242+
EOF
243+
git -C conflicts status --long >observed.long &&
244+
test_cmp expect.long observed.long &&
245+
246+
cat >expect.short <<EOF &&
247+
UU x.txt
248+
EOF
249+
git -C conflicts status --short >observed.short &&
250+
test_cmp expect.short observed.short &&
251+
252+
# save status data in serialized cache.
253+
254+
git -C conflicts status --serialize >serialized &&
255+
256+
# make some dirt in the worktree so we can tell whether subsequent
257+
# status commands used the cached data or did a fresh status.
258+
259+
echo dirt >conflicts/dirt.txt &&
260+
261+
# run status using the cached data.
262+
263+
git -C conflicts status --long --deserialize=../serialized >observed.long &&
264+
test_cmp expect.long observed.long &&
265+
266+
git -C conflicts status --short --deserialize=../serialized >observed.short &&
267+
test_cmp expect.short observed.short &&
268+
269+
# currently, the cached data does not have enough information about
270+
# merge conflicts for porcelain V2 format. (And V2 format looks at
271+
# the index to get that data, but the whole point of the serialization
272+
# is to avoid reading the index unnecessarily.) So V2 always rejects
273+
# the cached data when there is an unresolved conflict.
274+
275+
cat >expect.v2.dirty <<EOF &&
276+
u UU N... 100644 100644 100644 100644 $(test_oid x_base) $(test_oid x_ours) $(test_oid x_theirs) x.txt
277+
? dirt.txt
278+
EOF
279+
git -C conflicts status --porcelain=v2 --deserialize=../serialized >observed.v2 &&
280+
test_cmp expect.v2.dirty observed.v2
281+
282+
'
283+
196284
test_expect_success 'renames' '
197285
git init -b main rename_test &&
198286
echo OLDNAME >rename_test/OLDNAME &&

Diff for: wt-status-deserialize.c

+26-2
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,8 @@ static int wt_deserialize_v1_header(struct wt_status *s, int fd)
181181
/*
182182
* Build a string-list of (count) <changed-item> lines from the input.
183183
*/
184-
static int wt_deserialize_v1_changed_items(struct wt_status *s, int fd, int count UNUSED)
184+
static int wt_deserialize_v1_changed_items(const struct wt_status *cmd_s,
185+
struct wt_status *s, int fd, int count UNUSED)
185186
{
186187
struct wt_status_serialize_data *sd;
187188
char *p;
@@ -239,6 +240,29 @@ static int wt_deserialize_v1_changed_items(struct wt_status *s, int fd, int coun
239240
oid_to_hex(&d->oid_index),
240241
item->string,
241242
(d->rename_source ? d->rename_source : ""));
243+
244+
if (d->stagemask &&
245+
cmd_s->status_format == STATUS_FORMAT_PORCELAIN_V2) {
246+
/*
247+
* We have an unresolved conflict and the user wants
248+
* to see porcelain V2 output. The cached status data
249+
* does not contain enough information for V2 (because
250+
* the main status computation does not capture it).
251+
* We only get a single change record for the file with
252+
* a single SHA -- we don't get the stage [123] mode
253+
* and SHA data. The V2 detail-line print code looks
254+
* up this information directly from the index. The
255+
* whole point of this serialization cache is to avoid
256+
* reading the index, so the V2 print code gets zeros.
257+
* So we reject the status cache and let the fallback
258+
* code run.
259+
*/
260+
trace_printf_key(
261+
&trace_deserialize,
262+
"reject: V2 format and umerged file: %s",
263+
item->string);
264+
return DESERIALIZE_ERR;
265+
}
242266
}
243267

244268
return DESERIALIZE_OK;
@@ -391,7 +415,7 @@ static int wt_deserialize_v1(const struct wt_status *cmd_s, struct wt_status *s,
391415
while ((line = my_packet_read_line(fd, &line_len))) {
392416
if (skip_prefix(line, "changed ", &arg)) {
393417
nr_changed = (int)strtol(arg, NULL, 10);
394-
if (wt_deserialize_v1_changed_items(s, fd, nr_changed)
418+
if (wt_deserialize_v1_changed_items(cmd_s, s, fd, nr_changed)
395419
== DESERIALIZE_ERR)
396420
return DESERIALIZE_ERR;
397421
continue;

0 commit comments

Comments
 (0)