When PushCommand is configured with a RefLeaseSpec that contains an invalid (unparsable) expected object ID, then the RefLeaseSpec is silently ignored, and the push is performed unconditionally.
Actual behavior
The following parameterized JUnit 5 test fails for useInvalidRevision = true.
/**
* Tests the difference between a {@link RefLeaseSpec} with a valid-but-unknown and an invalid
* object reference.
*/
@ParameterizedTest
@ValueSource(booleans = {false, true})
void pushBranchDeletionWithLease(
boolean useInvalidRevision, @TempDir Path upstream, @TempDir Path downstream)
throws GitAPIException {
/* Create a repository with branch `master` and a single commit. */
Git gitUpstream = Git.init().setDirectory(upstream.toFile()).call();
String firstCommit =
gitUpstream
.commit()
.setAllowEmpty(true)
.setAuthor("Author", "Email")
.setMessage("Initial commit")
.call()
.toObjectId()
.name();
/* Create a second repository that has the first as its `origin` remote. */
Git gitDownstream =
Git.cloneRepository().setURI(upstream.toString()).setDirectory(downstream.toFile()).call();
/* Add a second commit to `master` in the downstream repository. */
String secondCommit =
gitDownstream
.commit()
.setAllowEmpty(true)
.setAuthor("Author", "Email")
.setMessage("Second commit")
.call()
.toObjectId()
.name();
/*
* Have the downstream repository attempt to push the second commit to the upstream repository,
* with lease. The lease specifies either a valid-but-unknown revision or an invalid revision.
*/
String target = Constants.R_HEADS + Constants.MASTER;
String expectedRevision =
useInvalidRevision ? "invalid-revision" : "0123456789abcdef0123456789abcdef01234567";
Iterable<PushResult> results =
gitDownstream
.push()
.setRefLeaseSpecs(new RefLeaseSpec(target, expectedRevision))
.setRefSpecs(new RefSpec().setSourceDestination("HEAD", target))
.call();
/*
* In case an invalid revision is specified, then the following assertion fails, as the response
* is `OK` instead.
*/
assertEquals(
RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED,
results.iterator().next().getRemoteUpdate(target).getStatus());
/* In that case the assertions below also fail, as the push did happen. */
String upstreamHead = gitUpstream.log().call().iterator().next().toObjectId().name();
assertNotEquals(secondCommit, upstreamHead);
assertEquals(firstCommit, upstreamHead);
}
Expected behavior
I expect either that the RefLeaseSpec rejects the invalid object ID (preferred), or that the push fails with a REJECTED_REMOTE_CHANGED error. Not sure the Git protocol even allows the latter. C Git seems to do something akin to the former (i.e., fail fast):
# Create a repository with branch `master` and a single commit.
mkdir upstream
git -C upstream init
git -C upstream commit --allow-empty -m 'Initial commit'
# Create a second repository that has the first as its `origin` remote.
git clone upstream downstream
# Add a second commit to `master` in the downstream repository.
git -C downstream commit --allow-empty -m 'Second commit'
# Have the downstream repository attempt to push te second commit to the
# upstream repository, with lease.
#
# When an unknown revision is specified, then the push is rejected:
#
# To /path/to/upstream
# ! [rejected] master -> master (stale info)
# error: failed to push some refs to '/path/to/upstream'
git -C downstream push --force-with-lease=master:0123456789abcdef0123456789abcdef01234567 origin master
# When an _invalid_ revision is specified, then the command isn't even
# executed:
#
# error: cannot parse expected object name 'invalid-revision'
git -C downstream push --force-with-lease=master:invalid-revision origin master
Version
6.10.0
Operating System
Linux/Unix
Bug description
When
PushCommand
is configured with aRefLeaseSpec
that contains an invalid (unparsable)expected
object ID, then theRefLeaseSpec
is silently ignored, and the push is performed unconditionally.Actual behavior
The following parameterized JUnit 5 test fails for
useInvalidRevision = true
.Expected behavior
I expect either that the
RefLeaseSpec
rejects the invalid object ID (preferred), or that the push fails with aREJECTED_REMOTE_CHANGED
error. Not sure the Git protocol even allows the latter. C Git seems to do something akin to the former (i.e., fail fast):Relevant log output
No response
Other information
No response