sapling/tests/integration/test-pushrebase-discovery.t
Stanislau Hlebik a98f532abd mononoke: fix of the discovery problem
Summary:
This is the test to cover tricky case in the discovery logic.
Previously Mononoke's known() wireproto method returned `true` for both public
and draft commits. The problem was in that it affects pushrebase.

There are a few problems with the current setup. A push command like `hg push
-r HASH --to BOOK` may actually do two things - it can either move a bookmark
on the server or do a pushrebase. What it does depends on how discovery phase
of the push finishes.

Each `hg push` starts with a discovery algorithm that tries to figure out what commits
to send to the server. If client decides that server already has all the
commits then it'll just move the bookmark, otherwise it'll run the pushrebase.

During discovery client sends wireproto `known()` method to the server
with a list of commit hashes, and server returns a list of booleans telling if
a server knows the commit or not. Before this diff Mononoke returned true for
both draft commits and public commits, while Mercurial returned true it only
for public commits.

So if Mononoke already has a draft commit (it might have it because the commit was created
via `hg pushbackup` or was created in the previous unsuccessful push attempt),
then hg client discovery will decide to move a bookmark instead of
pushrebasing, which in the case of master bookmark might have disastrous
consequences.

To fix it let's  return false for draft commits, and also implement `knownnodes` which return true for draft commits (a better name for these methods would be `knownpublic` and `known`).

Note though that in order to trigger the problem the position of the bookmark on the server
should be different from the position of the bookmark on the client. This is
because of short-circuting in the hg client discovery logic (see
https://fburl.com/s5r76yle).

The potential downside of the change is that we'll fetch bookmarks more often,
but we'll add bookmark cache later if necessary.

Reviewed By: ikostia

Differential Revision: D14560355

fbshipit-source-id: b943714199576e14a32e87f325ae8059d95cb8ed
2019-03-25 02:20:53 -07:00

169 lines
4.4 KiB
Raku

This is the test to cover tricky case in the discovery logic.
Previously Mononoke's known() wireproto method returned `true` for both public and
draft commits. The problem was in that it affects pushrebase. If Mononoke
returns true for a draft commit and client runs `hg push -r HASH --to BOOK`,
then hg client logic may decide to just move a bookmark instead of running the
actual pushrebase.
$ . $TESTDIR/library.sh
setup configuration
$ setup_common_config
$ cd "$TESTTMP/mononoke-config"
$ cat >> repos/repo/server.toml <<CONFIG
> [[bookmarks]]
> name="master_bookmark"
> CONFIG
$ mkdir -p common/hooks
$ cat > common/hooks/failing_hook.lua <<CONFIG
> hook = function (ctx)
> return false, "failed"
> end
> CONFIG
$ register_hook failing_hook common/hooks/failing_hook.lua PerChangeset <(
> echo 'bypass_pushvar="BYPASS_REVIEW=true"'
> )
setup common configuration
$ cd $TESTTMP
$ cat >> $HGRCPATH <<EOF
> [ui]
> ssh="$DUMMYSSH"
> [extensions]
> amend=
> infinitepush=
> infinitepushbackup=
> EOF
Setup helpers
$ log() {
> hg log -G -T "{desc} [{phase};rev={rev};{node|short}] {remotenames}" "$@"
> }
setup repo
$ hg init repo-hg
$ cd repo-hg
$ setup_hg_server
$ hg debugdrawdag <<EOF
> C
> |
> B
> |
> A
> EOF
create master bookmark
$ hg bookmark master_bookmark -r tip
blobimport them into Mononoke storage and start Mononoke
$ cd ..
$ blobimport repo-hg/.hg repo
start mononoke
$ mononoke
$ wait_for_mononoke $TESTTMP/repo
Clone the repo
$ hgclone_treemanifest ssh://user@dummy/repo-hg repo2 --noupdate --config extensions.remotenames= -q
$ hgclone_treemanifest ssh://user@dummy/repo-hg repo3 --noupdate --config extensions.remotenames= -q
$ cd repo2
$ setup_hg_client
$ cat >> .hg/hgrc <<EOF
> [extensions]
> pushrebase =
> remotenames =
> EOF
$ hg up -q 0
$ echo 1 > 1 && hg addremove -q
$ hg ci -m 'to push'
Unsuccessful push creates a draft commit on the server
$ hgmn push -r . --to master_bookmark
remote: * Session with Mononoke started with uuid: * (glob)
pushing rev 812eca0823f9 to destination ssh://user@dummy/repo bookmark master_bookmark
searching for changes
remote: Command failed
remote: Error:
remote: hooks failed:
remote: failing_hook for 812eca0823f97743f8d85cdef5cf338b54cebb01: failed
remote: Root cause:
remote: ErrorMessage {
remote: msg: "hooks failed:\nfailing_hook for 812eca0823f97743f8d85cdef5cf338b54cebb01: failed"
remote: }
abort: stream ended unexpectedly (got 0 bytes, expected 4)
[255]
In order to hit an edge case the master on the server needs to point to another commit.
Let's make a push
$ cd ../repo3
$ setup_hg_client
$ cat >> .hg/hgrc <<EOF
> [extensions]
> pushrebase =
> remotenames =
> [remotenames]
> EOF
$ hg up -q 0
$ echo 2 > 2 && hg addremove -q
$ hg ci -m 'to push2'
$ hgmn push -r . --to master_bookmark --pushvar BYPASS_REVIEW=true -q
Now let's push the same commit again but with a bypass. It should pushrebase,
not move a bookmark
$ cd ../repo2
$ hgmn push -r . --to master_bookmark --pushvar BYPASS_REVIEW=true -q
$ hgmn up -q master_bookmark
$ log
@ to push [public;rev=5;a6205c464622] default/master_bookmark
|
o to push2 [public;rev=4;854b7c3bdd1f]
|
| o to push [draft;rev=3;812eca0823f9]
| |
o | C [public;rev=2;26805aba1e60]
| |
o | B [public;rev=1;112478962961]
|/
o A [public;rev=0;426bada5c675]
The same procedure, but with commit cloud commit
$ hg up -q 0
$ echo commitcloud > commitcloud && hg addremove -q
$ hg ci -m commitcloud
$ hgmn pushbackup -q
Move master again
$ cd ../repo3
$ hg up -q 0
$ echo 3 > 3 && hg addremove -q
$ hg ci -m 'to push3'
$ hgmn push -r . --to master_bookmark --pushvar BYPASS_REVIEW=true -q
Now let's push commit cloud commit. Again, it should do pushrebase
$ cd ../repo2
$ hgmn push -r . --to master_bookmark --pushvar BYPASS_REVIEW=true -q
$ hgmn up -q master_bookmark
$ log
@ commitcloud [public;rev=8;3308f3bd8048] default/master_bookmark
|
o to push3 [public;rev=7;c3f020572849]
|
| o commitcloud [draft;rev=6;17f29bea0858]
| |
o | to push [public;rev=5;a6205c464622]
| |
o | to push2 [public;rev=4;854b7c3bdd1f]
| |
| | o to push [draft;rev=3;812eca0823f9]
| |/
o | C [public;rev=2;26805aba1e60]
| |
o | B [public;rev=1;112478962961]
|/
o A [public;rev=0;426bada5c675]