mirror of
https://github.com/facebook/sapling.git
synced 2024-10-06 06:47:41 +03:00
refencode: replace Python reference parsing with Rust
Summary: Use Rust refencode to encode and decode commit references in Python. This removes duplicated implementation. Reviewed By: DurhamG Differential Revision: D33237327 fbshipit-source-id: 2e4baa5a422fa562f355da2a82633d5b02c78a7d
This commit is contained in:
parent
1c04d3a663
commit
743b81ef16
@ -16,6 +16,8 @@ import errno
|
||||
import struct
|
||||
import typing
|
||||
|
||||
import bindings
|
||||
|
||||
from . import (
|
||||
encoding,
|
||||
error,
|
||||
@ -78,51 +80,36 @@ class bmstore(dict):
|
||||
nm = repo.changelog.nodemap
|
||||
tonode = bin # force local lookup
|
||||
setitem = dict.__setitem__
|
||||
with _getbkfile(repo) as bkfile:
|
||||
data = bkfile.read()
|
||||
decoded = bindings.refencode.decodebookmarks(data)
|
||||
try:
|
||||
with _getbkfile(repo) as bkfile:
|
||||
for line in bkfile:
|
||||
line = decodeutf8(line)
|
||||
line = line.strip()
|
||||
if not line:
|
||||
continue
|
||||
try:
|
||||
sha, refspec = line.split(" ", 1)
|
||||
node = tonode(sha)
|
||||
except (TypeError, ValueError):
|
||||
# TypeError:
|
||||
# - bin(...)
|
||||
# ValueError:
|
||||
# - node in nm, for non-20-bytes entry
|
||||
# - split(...), for string without ' '
|
||||
repo.ui.warn(_("malformed line in .hg/bookmarks: %r\n") % line)
|
||||
for refspec, node in sorted(decoded.items()):
|
||||
if node in nm:
|
||||
refspec = encoding.tolocal(refspec)
|
||||
setitem(self, refspec, node)
|
||||
else:
|
||||
# This might happen if:
|
||||
# - changelog was loaded, bookmarks are not loaded
|
||||
# - bookmarks was changed to point to unknown nodes
|
||||
# - bookmarks are loaded
|
||||
#
|
||||
# Try to mitigate by reloading changelog.
|
||||
repo.invalidate()
|
||||
nm = repo.changelog.nodemap
|
||||
if node in nm:
|
||||
refspec = encoding.tolocal(refspec)
|
||||
setitem(self, refspec, node)
|
||||
repo.ui.log("features", feature="fix-bookmark-changelog-order")
|
||||
else:
|
||||
if node in nm:
|
||||
refspec = encoding.tolocal(refspec)
|
||||
setitem(self, refspec, node)
|
||||
else:
|
||||
# This might happen if:
|
||||
# - changelog was loaded, bookmarks are not loaded
|
||||
# - bookmarks was changed to point to unknown nodes
|
||||
# - bookmarks are loaded
|
||||
#
|
||||
# Try to mitigate by reloading changelog.
|
||||
repo.invalidate()
|
||||
nm = repo.changelog.nodemap
|
||||
if node in nm:
|
||||
refspec = encoding.tolocal(refspec)
|
||||
setitem(self, refspec, node)
|
||||
repo.ui.log(
|
||||
"features", feature="fix-bookmark-changelog-order"
|
||||
)
|
||||
else:
|
||||
repo.ui.log(
|
||||
"features",
|
||||
feature="fix-bookmark-changelog-order-failed",
|
||||
)
|
||||
repo.ui.warn(
|
||||
_("unknown reference in .hg/bookmarks: %s %s\n")
|
||||
% (refspec, sha)
|
||||
)
|
||||
repo.ui.log(
|
||||
"features",
|
||||
feature="fix-bookmark-changelog-order-failed",
|
||||
)
|
||||
repo.ui.warn(
|
||||
_("unknown reference in .hg/bookmarks: %s %s\n")
|
||||
% (refspec, hex(node))
|
||||
)
|
||||
|
||||
except IOError as inst:
|
||||
if inst.errno != errno.ENOENT:
|
||||
@ -205,9 +192,8 @@ class bmstore(dict):
|
||||
self._aclean = True
|
||||
|
||||
def _write(self, fp):
|
||||
for name, node in sorted(pycompat.iteritems(self)):
|
||||
name = encoding.fromlocal(name)
|
||||
fp.write(encodeutf8("%s %s\n" % (hex(node), name)))
|
||||
encoded = bindings.refencode.encodebookmarks(self)
|
||||
fp.write(encoded)
|
||||
self._clean = True
|
||||
self._repo.invalidatevolatilesets()
|
||||
|
||||
@ -1152,35 +1138,8 @@ def saveremotenames(repo, remotebookmarks, override=True):
|
||||
repo.invalidatevolatilesets()
|
||||
|
||||
|
||||
def decoderemotenames(data):
|
||||
# type: (bytes) -> typing.Dict[str, bytes]
|
||||
"""Decode remotenames into {fullname: node}
|
||||
|
||||
The fullname can further be split by `splitremotename`.
|
||||
"""
|
||||
result = {}
|
||||
for line in decodeutf8(data).splitlines():
|
||||
try:
|
||||
hexnode, nametype, fullname = line.split(" ", 2)
|
||||
except ValueError:
|
||||
raise error.CorruptedState(_("corrupt entry in remotenames: %s") % (line,))
|
||||
# Ignore 'default-push' names. See https://fburl.com/1rft34i8.
|
||||
if fullname.startswith("default-push/"):
|
||||
continue
|
||||
if nametype != "bookmarks":
|
||||
continue
|
||||
result[fullname] = bin(hexnode)
|
||||
return result
|
||||
|
||||
|
||||
def encoderemotenames(fullnamenodes):
|
||||
# type: typing.List[typing.Tuple[str, bytes]] -> (bytes)
|
||||
"""Encode {fullname: node} to remotenames format."""
|
||||
content = "".join(
|
||||
"%s bookmarks %s\n" % (hex(node), name)
|
||||
for name, node in sorted(fullnamenodes.items())
|
||||
)
|
||||
return encodeutf8(content)
|
||||
encoderemotenames = bindings.refencode.encoderemotenames
|
||||
decoderemotenames = bindings.refencode.decoderemotenames
|
||||
|
||||
|
||||
class lazyremotenamedict(pycompat.Mapping):
|
||||
|
@ -43,24 +43,8 @@ def stoptracking(repo):
|
||||
repo.svfs.write("visibleheads", b"")
|
||||
|
||||
|
||||
# Supported file format version.
|
||||
# Version 1 is:
|
||||
# * A single line containing "v1"
|
||||
# * A list of node hashes for each visible head, one per line.
|
||||
FORMAT_VERSION = "v1"
|
||||
|
||||
|
||||
def encodeheads(heads):
|
||||
return encodeutf8(
|
||||
"%s\n%s" % (FORMAT_VERSION, "".join("%s\n" % node.hex(h) for h in heads))
|
||||
)
|
||||
|
||||
|
||||
def decodeheads(data):
|
||||
lines = decodeutf8(data).splitlines()
|
||||
if lines and lines[0].strip() != FORMAT_VERSION:
|
||||
raise error.Abort("invalid visibleheads file format %r" % lines[0])
|
||||
return [node.bin(head.strip()) for head in lines[1:]]
|
||||
encodeheads = bindings.refencode.encodevisibleheads
|
||||
decodeheads = bindings.refencode.decodevisibleheads
|
||||
|
||||
|
||||
class visibleheads(object):
|
||||
|
@ -49,6 +49,7 @@ pypathmatcher = { path = "modules/pypathmatcher" }
|
||||
pypprint = { path = "modules/pypprint" }
|
||||
pyprocess = { path = "modules/pyprocess" }
|
||||
pyprogress = { path = "modules/pyprogress" }
|
||||
pyrefencode = { path = "modules/pyrefencode" }
|
||||
pyregex = { path = "modules/pyregex" }
|
||||
pyrenderdag = { path = "modules/pyrenderdag" }
|
||||
pyrevisionstore = { path = "modules/pyrevisionstore" }
|
||||
|
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "pyrefencode"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
cpython_ext = { path = "../../../../lib/cpython-ext", default-features = false }
|
||||
cpython = { version = "0.7", default-features = false }
|
||||
refencode = { path = "../../../../lib/refencode" }
|
||||
|
||||
[features]
|
||||
python2 = ["cpython/python27-sys", "cpython_ext/python2"]
|
||||
python3 = ["cpython/python3-sys", "cpython_ext/python3"]
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This software may be used and distributed according to the terms of the
|
||||
* GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use cpython::*;
|
||||
use cpython_ext::convert::Serde;
|
||||
use cpython_ext::ResultPyErrExt;
|
||||
use refencode::HgId;
|
||||
|
||||
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
|
||||
let name = [package, "refencode"].join(".");
|
||||
let m = PyModule::new(py, &name)?;
|
||||
|
||||
m.add(
|
||||
py,
|
||||
"decodebookmarks",
|
||||
py_fn!(py, decodebookmarks(data: PyBytes)),
|
||||
)?;
|
||||
m.add(
|
||||
py,
|
||||
"decoderemotenames",
|
||||
py_fn!(py, decoderemotenames(data: PyBytes)),
|
||||
)?;
|
||||
m.add(
|
||||
py,
|
||||
"decodevisibleheads",
|
||||
py_fn!(py, decodevisibleheads(data: PyBytes)),
|
||||
)?;
|
||||
|
||||
m.add(
|
||||
py,
|
||||
"encodebookmarks",
|
||||
py_fn!(
|
||||
py,
|
||||
encodebookmarks(namenodes: Serde<BTreeMap<String, HgId>>)
|
||||
),
|
||||
)?;
|
||||
m.add(
|
||||
py,
|
||||
"encoderemotenames",
|
||||
py_fn!(
|
||||
py,
|
||||
encoderemotenames(namenodes: Serde<BTreeMap<String, HgId>>)
|
||||
),
|
||||
)?;
|
||||
m.add(
|
||||
py,
|
||||
"encodevisibleheads",
|
||||
py_fn!(py, encodevisibleheads(namenodes: Serde<Vec<HgId>>)),
|
||||
)?;
|
||||
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
fn decodebookmarks(py: Python, data: PyBytes) -> PyResult<Serde<BTreeMap<String, HgId>>> {
|
||||
let data = data.data(py);
|
||||
let decoded = refencode::decode_bookmarks(data).map_pyerr(py)?;
|
||||
Ok(Serde(decoded))
|
||||
}
|
||||
|
||||
fn decoderemotenames(py: Python, data: PyBytes) -> PyResult<Serde<BTreeMap<String, HgId>>> {
|
||||
let data = data.data(py);
|
||||
let decoded = refencode::decode_remotenames(data).map_pyerr(py)?;
|
||||
Ok(Serde(decoded))
|
||||
}
|
||||
|
||||
fn decodevisibleheads(py: Python, data: PyBytes) -> PyResult<Serde<Vec<HgId>>> {
|
||||
let data = data.data(py);
|
||||
let decoded = refencode::decode_visibleheads(data).map_pyerr(py)?;
|
||||
Ok(Serde(decoded))
|
||||
}
|
||||
|
||||
fn encodebookmarks(py: Python, namenodes: Serde<BTreeMap<String, HgId>>) -> PyResult<PyBytes> {
|
||||
let encoded = refencode::encode_bookmarks(&namenodes.0);
|
||||
Ok(PyBytes::new(py, encoded.as_ref()))
|
||||
}
|
||||
|
||||
fn encoderemotenames(py: Python, namenodes: Serde<BTreeMap<String, HgId>>) -> PyResult<PyBytes> {
|
||||
let encoded = refencode::encode_remotenames(&namenodes.0);
|
||||
Ok(PyBytes::new(py, encoded.as_ref()))
|
||||
}
|
||||
|
||||
fn encodevisibleheads(py: Python, nodes: Serde<Vec<HgId>>) -> PyResult<PyBytes> {
|
||||
let encoded = refencode::encode_visibleheads(&nodes.0);
|
||||
Ok(PyBytes::new(py, encoded.as_ref()))
|
||||
}
|
@ -49,6 +49,7 @@ pub(crate) fn populate_module(py: Python<'_>, module: &PyModule) -> PyResult<PyN
|
||||
m.add(py, "pprint", pypprint::init_module(py, &name)?)?;
|
||||
m.add(py, "process", pyprocess::init_module(py, &name)?)?;
|
||||
m.add(py, "progress", pyprogress::init_module(py, &name)?)?;
|
||||
m.add(py, "refencode", pyrefencode::init_module(py, &name)?)?;
|
||||
m.add(py, "regex", pyregex::init_module(py, &name)?)?;
|
||||
m.add(py, "renderdag", pyrenderdag::init_module(py, &name)?)?;
|
||||
m.add(
|
||||
|
Loading…
Reference in New Issue
Block a user