mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 15:27:13 +03:00
44343769f8
Summary: We want to rename away from "mercurial". Rather than rename the "mercurial" Python package, we opted to just collapse it into the parent "edenscm" package. This is also a step towards further organizing we want to do around the new project name. To ease the transition wrt hotfixes, we now replace "edenscm.mercurial" with "mercurial" to fix imports within base64-python extensions. Reviewed By: sggutier Differential Revision: D38943169 fbshipit-source-id: 03fa18079c51e2f7fac05d65b127095da3ab7c99
153 lines
5.5 KiB
Python
153 lines
5.5 KiB
Python
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
#
|
|
# This software may be used and distributed according to the terms of the
|
|
# GNU General Public License version 2.
|
|
|
|
"""clone utilities that aims for Mononoke compatibility"""
|
|
|
|
import bindings
|
|
|
|
from . import bookmarks as bookmod, changelog2, error, streamclone
|
|
from .i18n import _
|
|
from .node import hex
|
|
|
|
|
|
def revlogclone(source, repo):
|
|
"""clone from source into an empty remotefilelog repo using revlog changelog"""
|
|
|
|
with repo.wlock(), repo.lock(), repo.transaction("clone"):
|
|
if any(
|
|
repo.svfs.tryread(name)
|
|
for name in ["00changelog.i", "bookmarks", "remotenames"]
|
|
):
|
|
raise error.Abort(_("clone: repo %s is not empty") % repo.root)
|
|
|
|
repo.requirements.add("remotefilelog")
|
|
repo._writerequirements()
|
|
|
|
# Invalidate the local changelog length metadata.
|
|
repo.svfs.tryunlink("00changelog.len")
|
|
|
|
repo.ui.status(_("fetching changelog\n"))
|
|
with repo.conn(source) as conn:
|
|
# Assume the remote server supports streamclone.
|
|
peer = conn.peer
|
|
fp = peer.stream_out(shallow=True)
|
|
|
|
l = fp.readline()
|
|
if l.strip() != b"0":
|
|
raise error.ResponseError(
|
|
_("unexpected response from remote server:"), l
|
|
)
|
|
|
|
l = fp.readline()
|
|
try:
|
|
filecount, bytecount = list(map(int, l.split(b" ", 1)))
|
|
except (ValueError, TypeError):
|
|
raise error.ResponseError(
|
|
_("unexpected response from remote server:"), l
|
|
)
|
|
|
|
# Get 00changelog.{i,d}. This does not write bookmarks or remotenames.
|
|
streamclone.consumev1(repo, fp, filecount, bytecount)
|
|
# repo.changelog needs to be reloaded.
|
|
repo.invalidate()
|
|
repo.invalidatechangelog()
|
|
|
|
# Fetch selected remote bookmarks.
|
|
repo.ui.status(_("fetching selected remote bookmarks\n"))
|
|
remote = bookmod.remotenameforurl(repo.ui, repo.ui.paths.getpath(source).rawloc)
|
|
assert remote is not None
|
|
repo.pull(
|
|
source, bookmarknames=bookmod.selectivepullbookmarknames(repo, remote)
|
|
)
|
|
|
|
|
|
def emergencyclone(source, repo):
|
|
"""clone only 1 single commit for emergency commit+push use-cases
|
|
|
|
The commit graph will be incomplete and there is no way to complete the
|
|
history without reclone. Accessing older commits (ex. checking out an
|
|
older commit, logging file or directory history) is likely broken!
|
|
|
|
This can be potentially useful if the server has issues with its commit
|
|
graph components.
|
|
"""
|
|
with repo.wlock(), repo.lock(), repo.transaction("emergencyclone"):
|
|
if any(repo.svfs.tryread(name) for name in ["bookmarks", "remotenames", "tip"]):
|
|
raise error.Abort(_("clone: repo %s is not empty") % repo.root)
|
|
|
|
repo.requirements.add("remotefilelog")
|
|
repo._writerequirements()
|
|
|
|
repo.storerequirements.add("lazytextchangelog")
|
|
repo.storerequirements.add("emergencychangelog")
|
|
repo._writestorerequirements()
|
|
|
|
mainbookmark = bookmod.mainbookmark(repo)
|
|
|
|
repo.ui.warn(
|
|
_(
|
|
"warning: cloning as emergency commit+push use-case only! "
|
|
"accessing older commits is broken!\n"
|
|
)
|
|
)
|
|
|
|
repo.ui.status(_("resolving %s\n") % mainbookmark)
|
|
with repo.conn(source) as conn:
|
|
peer = conn.peer
|
|
mainnode = peer.lookup(mainbookmark)
|
|
|
|
# Write a DAG with one commit.
|
|
cl = changelog2.changelog.opensegments(repo, repo.ui.uiconfig())
|
|
# Pretend the "mainnode" does not have parents.
|
|
cl.inner.addgraphnodes([(mainnode, [])])
|
|
# Write to the "master" group.
|
|
cl.inner.flush([mainnode])
|
|
|
|
# Update references
|
|
remote = bookmod.remotenameforurl(
|
|
repo.ui, repo.ui.paths.getpath(source).rawloc
|
|
)
|
|
fullname = "%s/%s" % (remote, mainbookmark)
|
|
repo.svfs.write(
|
|
"remotenames", bookmod.encoderemotenames({fullname: mainnode})
|
|
)
|
|
repo.svfs.write("tip", mainnode)
|
|
|
|
repo.ui.status(_("added %s: %s\n") % (mainbookmark, hex(mainnode)))
|
|
|
|
repo.invalidate()
|
|
repo.invalidatechangelog()
|
|
|
|
|
|
def segmentsclone(source, repo):
|
|
"""clone using segmented changelog's CloneData
|
|
|
|
This produces a repo with lazy commit hashes.
|
|
"""
|
|
with repo.wlock(), repo.lock(), repo.transaction("clone"):
|
|
changelog2.migrateto(repo, "lazy")
|
|
repo.requirements.add("remotefilelog")
|
|
repo._writerequirements()
|
|
|
|
remote = bookmod.remotenameforurl(repo.ui, repo.ui.paths.getpath(source).rawloc)
|
|
bookmarks = bookmod.selectivepullbookmarknames(repo, remote)
|
|
|
|
repo.ui.status(_("populating main commit graph\n"))
|
|
if repo.ui.configbool("clone", "nativepull"):
|
|
bindings.exchange.clone(
|
|
repo.edenapi, repo.metalog(), repo.changelog.inner, bookmarks
|
|
)
|
|
else:
|
|
clonedata = repo.edenapi.clonedata()
|
|
repo.changelog.inner.importclonedata(clonedata)
|
|
tip = repo.changelog.dag.all().first()
|
|
if tip:
|
|
repo.ui.status(_("tip commit: %s\n") % hex(tip))
|
|
repo.svfs.write("tip", tip)
|
|
|
|
repo.ui.status(_("fetching selected remote bookmarks\n"))
|
|
assert remote is not None
|
|
repo.pull(source, bookmarknames=bookmarks)
|