mirror of
https://github.com/facebook/sapling.git
synced 2024-10-05 14:28:17 +03:00
push: add '--force' support
Summary: force pushrebase is basically a plain push, this diff also adds check for mutation metadata. To keep public commit data clean, server prefer to remove mutation metadata. Reviewed By: quark-zju Differential Revision: D52141515 fbshipit-source-id: aeca404b482cc94d538aa051d89f5ac202a0a5b1
This commit is contained in:
parent
4ea1e5038f
commit
90de8eba1d
@ -323,11 +323,8 @@ Test a non-forward push
|
||||
│
|
||||
~
|
||||
$ hgedenapi push --force -r . --to master_bookmark_2 --non-forward-move --pushvar NON_FAST_FORWARD=true
|
||||
fallback reason: --force is not supported by EdenApi push yet
|
||||
pushing rev 589551466f25 to destination mononoke://$LOCALIP:$LOCAL_PORT/repo bookmark master_bookmark_2
|
||||
searching for changes
|
||||
no changes found
|
||||
updating bookmark master_bookmark_2
|
||||
pushing rev 589551466f25 to destination https://localhost:*/edenapi/ bookmark master_bookmark_2 (glob)
|
||||
moving remote bookmark master_bookmark_2 from eb388b759fde to 589551466f25
|
||||
$ log -r "20::"
|
||||
o merge 10 and 12 [public;rev=25;eb388b759fde] default/master_bookmark
|
||||
├─╮
|
||||
@ -391,13 +388,15 @@ Test non-fast-forward force pushrebase
|
||||
~
|
||||
-- we don't need to pass --pushvar NON_FAST_FORWARD if we're doing a force pushrebase
|
||||
$ hgedenapi push -r . -f --to newbook
|
||||
fallback reason: --force is not supported by EdenApi push yet
|
||||
pushing rev 4899f9112d9b to destination mononoke://$LOCALIP:$LOCAL_PORT/repo bookmark newbook
|
||||
searching for changes
|
||||
adding changesets
|
||||
adding manifests
|
||||
adding file changes
|
||||
updating bookmark newbook
|
||||
pushing rev 4899f9112d9b to destination https://localhost:*/edenapi/ bookmark newbook (glob)
|
||||
edenapi: queue 1 commit for upload
|
||||
edenapi: queue 1 file for upload
|
||||
edenapi: uploaded 1 file
|
||||
edenapi: queue 1 tree for upload
|
||||
edenapi: uploaded 1 tree
|
||||
edenapi: uploading commit '4899f9112d9b79c3ecbc343169db37fbe1efdd20'...
|
||||
edenapi: uploaded 1 changeset
|
||||
moving remote bookmark newbook from 7a037594e202 to 4899f9112d9b
|
||||
-- "20 draft newbook" gets moved to 26 and 20 gets hidden.
|
||||
$ log -r "20::"
|
||||
@ 26 [public;rev=27;4899f9112d9b] default/newbook
|
||||
@ -428,27 +427,20 @@ Test non-fast-forward force pushrebase
|
||||
4899f9112d9b79c3ecbc343169db37fbe1efdd20
|
||||
$ cd ../repo2
|
||||
|
||||
-- Check that a force pushrebase with mutation markers is a fail
|
||||
Check that a force pushrebase with mutation markers.
|
||||
$ echo SPARTACUS > sum_ego && hg ci -qAm 27
|
||||
$ echo SPARTACUS! > sum_ego && hg amend --config mutation.enabled=true --config mutation.record=true
|
||||
$ hgedenapi push -r . -f --to newbook
|
||||
fallback reason: --force is not supported by EdenApi push yet
|
||||
pushing rev * to destination mononoke://$LOCALIP:$LOCAL_PORT/repo bookmark newbook (glob)
|
||||
searching for changes
|
||||
remote: Command failed
|
||||
remote: Error:
|
||||
remote: Forced push blocked because it contains mutation metadata.
|
||||
remote: You can remove the metadata from a commit with `hg amend --config mutation.record=false`.
|
||||
remote: For more help, please contact the Source Control team at https://fburl.com/27qnuyl2
|
||||
remote:
|
||||
remote: Root cause:
|
||||
remote: Forced push blocked because it contains mutation metadata.
|
||||
remote: You can remove the metadata from a commit with `hg amend --config mutation.record=false`.
|
||||
remote: For more help, please contact the Source Control team at https://fburl.com/27qnuyl2
|
||||
remote:
|
||||
remote: Debug context:
|
||||
remote: "Forced push blocked because it contains mutation metadata.\nYou can remove the metadata from a commit with `hg amend --config mutation.record=false`.\nFor more help, please contact the Source Control team at https://fburl.com/27qnuyl2"
|
||||
abort: unexpected EOL, expected netstring digit
|
||||
$ hgedenapi push -r . -f --to newbook --config push.check-mutation=true
|
||||
pushing rev * to destination https://localhost:*/edenapi/ bookmark newbook (glob)
|
||||
edenapi: queue 1 commit for upload
|
||||
edenapi: queue 1 file for upload
|
||||
edenapi: uploaded 1 file
|
||||
edenapi: queue 1 tree for upload
|
||||
edenapi: uploaded 1 tree
|
||||
edenapi: uploading commit '*'... (glob)
|
||||
edenapi: uploaded 1 changeset
|
||||
abort: forced push blocked because commit * contains mutation metadata (glob)
|
||||
(use 'hg amend --config mutation.record=false' to remove the metadata)
|
||||
[255]
|
||||
|
||||
Check that we can replace a file with a directory
|
||||
|
@ -12,6 +12,9 @@ from .i18n import _
|
||||
from .node import bin, hex, nullhex, short
|
||||
|
||||
|
||||
MUTATION_KEYS = {"mutpred", "mutuser", "mutdate", "mutop", "mutsplit"}
|
||||
|
||||
|
||||
def get_edenapi_for_dest(repo, _dest):
|
||||
"""Get an EdenApi instance for the given destination."""
|
||||
if not repo.ui.configbool("push", "edenapi"):
|
||||
@ -32,11 +35,6 @@ def get_edenapi_for_dest(repo, _dest):
|
||||
|
||||
def push(repo, dest, head_node, remote_bookmark, force=False, opargs=None):
|
||||
"""Push via EdenApi (HTTP)"""
|
||||
if force:
|
||||
raise error.UnsupportedEdenApiPush(
|
||||
_("--force is not supported by EdenApi push yet")
|
||||
)
|
||||
|
||||
ui = repo.ui
|
||||
edenapi = get_edenapi_for_dest(repo, dest)
|
||||
opargs = opargs or {}
|
||||
@ -78,30 +76,36 @@ def push(repo, dest, head_node, remote_bookmark, force=False, opargs=None):
|
||||
% remote_bookmark
|
||||
)
|
||||
|
||||
if repo[head_node].phase() == phases.public:
|
||||
# if the head is already a public commit, then do a plain push (no pushrebase)
|
||||
plain_push(repo, edenapi, remote_bookmark, head_node, bookmark_node, opargs)
|
||||
if force or repo[head_node].phase() == phases.public:
|
||||
# if the head is already a public commit or force is set, then do a plain
|
||||
# push (no pushrebase)
|
||||
plain_push(
|
||||
repo, edenapi, remote_bookmark, head_node, bookmark_node, force, opargs
|
||||
)
|
||||
else:
|
||||
# update the exiting bookmark with push rebase
|
||||
return push_rebase(repo, dest, head_node, draft_nodes, remote_bookmark, opargs)
|
||||
|
||||
|
||||
def plain_push(repo, edenapi, bookmark, to_node, from_node, opargs=None):
|
||||
def plain_push(repo, edenapi, bookmark, to_node, from_node, force, opargs=None):
|
||||
"""Plain push without rebasing."""
|
||||
pushvars = parse_pushvars(opargs.get("pushvars"))
|
||||
|
||||
# setbookmark api server logic does not check if it's a non fast-forward move,
|
||||
# let's check it in the client side as a workaround for now
|
||||
is_ancestor = repo.dageval(lambda: isancestor(from_node, to_node))
|
||||
if not is_ancestor:
|
||||
if not is_true(pushvars.get("NON_FAST_FORWARD")):
|
||||
raise error.Abort(
|
||||
_(
|
||||
"non-fast-forward push to remote bookmark %s from %s to %s "
|
||||
"(set pushvar NON_FAST_FORWARD=true for a non-fast-forward move)"
|
||||
if force:
|
||||
check_mutation_metadata(repo, to_node)
|
||||
else:
|
||||
# setbookmark api server logic does not check if it's a non fast-forward move,
|
||||
# let's check it in the client side as a workaround for now
|
||||
is_ancestor = repo.dageval(lambda: isancestor(from_node, to_node))
|
||||
if not is_ancestor:
|
||||
if not is_true(pushvars.get("NON_FAST_FORWARD")):
|
||||
raise error.Abort(
|
||||
_(
|
||||
"non-fast-forward push to remote bookmark %s from %s to %s "
|
||||
"(set pushvar NON_FAST_FORWARD=true for a non-fast-forward move)"
|
||||
)
|
||||
% (bookmark, short(from_node), short(to_node)),
|
||||
)
|
||||
% (bookmark, short(from_node), short(to_node)),
|
||||
)
|
||||
|
||||
repo.ui.status(
|
||||
_("moving remote bookmark %s from %s to %s\n")
|
||||
@ -256,5 +260,30 @@ def parse_pushvars(pushvars_strs: Optional[List[str]]) -> List[Tuple[str, str]]:
|
||||
return pushvars
|
||||
|
||||
|
||||
def check_mutation_metadata(repo, to_node):
|
||||
"""Check if the given commits have mutation metadata. If so, abort."""
|
||||
# context: https://github.com/facebook/sapling/blob/fb09c14ae6d1a134259f66d9997d1af21c605c07/eden/mononoke/repo_client/unbundle/src/resolver.rs#L616
|
||||
# this logic is probably not be needed nowadays (disabled by default), but we
|
||||
# keep it here just in case.
|
||||
if not repo.ui.configbool("push", "check-mutation"):
|
||||
return
|
||||
|
||||
draft_nodes = repo.dageval(lambda: only([to_node], public()))
|
||||
for node in draft_nodes:
|
||||
ctx = repo[node]
|
||||
if ctx.extra().keys() & MUTATION_KEYS:
|
||||
hint = _(
|
||||
"use 'hg amend --config mutation.record=false' to remove the metadata"
|
||||
)
|
||||
support = repo.ui.config("ui", "supportcontact")
|
||||
if support:
|
||||
hint += _(" or contact %s for help") % support
|
||||
raise error.Abort(
|
||||
_("forced push blocked because commit %s contains mutation metadata")
|
||||
% ctx,
|
||||
hint=hint,
|
||||
)
|
||||
|
||||
|
||||
def is_true(s: Optional[str]) -> bool:
|
||||
return s == "true" or s == "True"
|
||||
|
Loading…
Reference in New Issue
Block a user