mirror of
https://github.com/facebook/sapling.git
synced 2024-10-12 01:39:21 +03:00
a98f532abd
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
169 lines
4.4 KiB
Raku
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]
|
|
|