cpython-ext: add PyPath for references to paths

Summary: `PyPath` is to `PyPathBuf` as `Path` is to `PathBuf` and `str` is to `String`.

Reviewed By: quark-zju

Differential Revision: D19647995

fbshipit-source-id: 841a5f6fea295bc72b00da028ae256ca38578504
This commit is contained in:
Mark Thomas 2020-01-30 17:31:54 -08:00 committed by Facebook Github Bot
parent a634526801
commit 914607cac7
15 changed files with 208 additions and 96 deletions

View File

@ -9,7 +9,7 @@
use blackbox::{self, event::Event, init, log, serde_json, BlackboxOptions, SessionId, ToValue};
use cpython::*;
use cpython_ext::{PyNone, PyPathBuf, ResultPyErrExt};
use cpython_ext::{PyNone, PyPath, ResultPyErrExt};
use std::ops::Deref;
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
@ -20,7 +20,7 @@ pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
"init",
py_fn!(
py,
init_blackbox(path: PyPathBuf, count: u8 = 3, size: u64 = 100000000)
init_blackbox(path: &PyPath, count: u8 = 3, size: u64 = 100000000)
),
)?;
m.add(py, "_logjson", py_fn!(py, log_json(json: String)))?;
@ -55,7 +55,7 @@ def log(value, _dumps=_json.dumps, _logjson=_logjson):
}
/// Initialize the blackbox at the given path.
fn init_blackbox(py: Python, path: PyPathBuf, count: u8, size: u64) -> PyResult<PyNone> {
fn init_blackbox(py: Python, path: &PyPath, count: u8, size: u64) -> PyResult<PyNone> {
let blackbox = BlackboxOptions::new()
.max_bytes_per_log(size)
.max_log_count(count)

View File

@ -12,7 +12,7 @@ use std::cell::RefCell;
use cpython::*;
use ::bookmarkstore::BookmarkStore;
use cpython_ext::{PyNone, PyPathBuf};
use cpython_ext::{PyNone, PyPath};
use types::hgid::HgId;
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
@ -25,9 +25,9 @@ pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
py_class!(class bookmarkstore |py| {
data bm_store: RefCell<BookmarkStore>;
def __new__(_cls, path: PyPathBuf) -> PyResult<bookmarkstore> {
def __new__(_cls, path: &PyPath) -> PyResult<bookmarkstore> {
let bm_store = {
BookmarkStore::new(path.as_ref())
BookmarkStore::new(path.as_path())
.map_err(|e| PyErr::new::<exc::IOError, _>(py, format!("{}", e)))?
};
bookmarkstore::create_instance(py, RefCell::new(bm_store))

View File

@ -15,7 +15,7 @@ use configparser::{
config::{ConfigSet, Options},
hg::{parse_list, ConfigSetHgExt, OptionsHgExt, HGRCPATH},
};
use cpython_ext::{PyNone, PyPathBuf, Str};
use cpython_ext::{PyNone, PyPath, PyPathBuf, Str};
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
let name = [package, "configparser"].join(".");
@ -39,7 +39,7 @@ py_class!(pub class config |py| {
def readpath(
&self,
path: PyPathBuf,
path: &PyPath,
source: String,
sections: Option<Vec<String>>,
remap: Option<Vec<(String, String)>>,

View File

@ -9,7 +9,7 @@
use anyhow::Error;
use cpython::*;
use cpython_ext::{AnyhowResultExt, PyNone, PyPathBuf, ResultPyErrExt};
use cpython_ext::{AnyhowResultExt, PyNone, PyPath, ResultPyErrExt};
use dag::{
id::{Group, Id, VertexName},
idmap::IdMap,
@ -168,9 +168,9 @@ py_class!(class dagindex |py| {
data dag: RefCell<IdDag>;
data map: RefCell<IdMap>;
def __new__(_cls, path: PyPathBuf, segment_size: usize = 16) -> PyResult<dagindex> {
let mut dag = IdDag::open(path.as_ref().join("segment")).map_pyerr(py)?;
let map = IdMap::open(path.as_ref().join("idmap")).map_pyerr(py)?;
def __new__(_cls, path: &PyPath, segment_size: usize = 16) -> PyResult<dagindex> {
let mut dag = IdDag::open(path.as_path().join("segment")).map_pyerr(py)?;
let map = IdMap::open(path.as_path().join("idmap")).map_pyerr(py)?;
dag.set_new_segment_size(segment_size);
Self::create_instance(py, RefCell::new(dag), RefCell::new(map))
}

View File

@ -137,7 +137,7 @@ py_class!(class client |py| {
.stream_trees(streamtrees);
if let Some((cert, key)) = creds {
config = config.client_creds(cert, key).map_err(|e| into_exception(py, e))?;
config = config.client_creds(cert.as_path(), key.as_path()).map_err(|e| into_exception(py, e))?;
}
let inner = EdenApiCurlClient::new(config).map_err(|e| into_exception(py, e))?;

View File

@ -12,7 +12,7 @@ use std::{cell::RefCell, io::Cursor};
use anyhow::Error;
use byteorder::{ReadBytesExt, WriteBytesExt};
use cpython::*;
use cpython_ext::{PyNone, PyPathBuf, ResultPyErrExt};
use cpython_ext::{PyNone, PyPath, ResultPyErrExt};
use thiserror::Error;
use ::mutationstore::{MutationEntry, MutationEntryOrigin, MutationStore, Repair};
@ -183,7 +183,7 @@ py_class!(class mutationentry |py| {
py_class!(class mutationstore |py| {
data mut_store: RefCell<MutationStore>;
def __new__(_cls, path: PyPathBuf) -> PyResult<mutationstore> {
def __new__(_cls, path: &PyPath) -> PyResult<mutationstore> {
let ms = MutationStore::open(path).map_pyerr(py)?;
mutationstore::create_instance(py, RefCell::new(ms))
}

View File

@ -12,7 +12,7 @@ use std::cell::RefCell;
use cpython::*;
use ::nodemap::{NodeMap, NodeSet, Repair};
use cpython_ext::{Bytes, PyNone, PyPathBuf, ResultPyErrExt};
use cpython_ext::{Bytes, PyNone, PyPath, ResultPyErrExt};
use types::node::Node;
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
@ -26,7 +26,7 @@ pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
py_class!(class nodemap |py| {
data log: RefCell<NodeMap>;
def __new__(_cls, path: PyPathBuf) -> PyResult<nodemap> {
def __new__(_cls, path: &PyPath) -> PyResult<nodemap> {
let nodemap = NodeMap::open(path)
.map_err(|e| PyErr::new::<exc::RuntimeError, _>(py, format!("{}", e)))?;
nodemap::create_instance(py, RefCell::new(nodemap))
@ -92,7 +92,7 @@ py_class!(class nodemap |py| {
py_class!(class nodeset |py| {
data set: RefCell<NodeSet>;
def __new__(_cls, path: PyPathBuf) -> PyResult<Self> {
def __new__(_cls, path: &PyPath) -> PyResult<Self> {
let nodeset = NodeSet::open(path).map_pyerr(py)?;
Self::create_instance(py, RefCell::new(nodeset))
}

View File

@ -11,7 +11,7 @@ use std::path::Path;
use cpython::*;
use cpython_ext::error::ResultPyErrExt;
use cpython_ext::{PyPathBuf, Str};
use cpython_ext::{PyPath, PyPathBuf, Str};
use pathmatcher::{DirectoryMatch, GitignoreMatcher, Matcher, TreeMatcher};
use types::RepoPath;
@ -34,18 +34,18 @@ pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
py_class!(class gitignorematcher |py| {
data matcher: GitignoreMatcher;
def __new__(_cls, root: PyPathBuf, global_paths: Vec<PyPathBuf>) -> PyResult<gitignorematcher> {
let global_paths: Vec<&Path> = global_paths.iter().map(AsRef::as_ref).collect();
let matcher = GitignoreMatcher::new(&root, global_paths);
def __new__(_cls, root: &PyPath, global_paths: Vec<PyPathBuf>) -> PyResult<gitignorematcher> {
let global_paths: Vec<&Path> = global_paths.iter().map(PyPathBuf::as_path).collect();
let matcher = GitignoreMatcher::new(root, global_paths);
gitignorematcher::create_instance(py, matcher)
}
def match_relative(&self, path: PyPathBuf, is_dir: bool) -> PyResult<bool> {
Ok(self.matcher(py).match_relative(&path, is_dir))
def match_relative(&self, path: &PyPath, is_dir: bool) -> PyResult<bool> {
Ok(self.matcher(py).match_relative(path, is_dir))
}
def explain(&self, path: PyPathBuf, is_dir: bool) -> PyResult<Str> {
Ok(self.matcher(py).explain(&path, is_dir).into())
def explain(&self, path: &PyPath, is_dir: bool) -> PyResult<Str> {
Ok(self.matcher(py).explain(path, is_dir).into())
}
});
@ -57,12 +57,12 @@ py_class!(class treematcher |py| {
Self::create_instance(py, matcher)
}
def matches(&self, path: PyPathBuf) -> PyResult<bool> {
def matches(&self, path: &PyPath) -> PyResult<bool> {
Ok(self.matcher(py).matches(path))
}
def match_recursive(&self, path: PyPathBuf) -> PyResult<Option<bool>> {
if path.as_ref().as_os_str().is_empty() {
def match_recursive(&self, path: &PyPath) -> PyResult<Option<bool>> {
if path.as_path().as_os_str().is_empty() {
Ok(None)
} else {
Ok(self.matcher(py).match_recursive(path))

View File

@ -13,7 +13,7 @@ use cpython::{
ToPyObject,
};
use cpython_ext::{PyPathBuf, ResultPyErrExt};
use cpython_ext::{PyPath, PyPathBuf, ResultPyErrExt};
use revisionstore::{DataStore, MutableDeltaStore, RemoteDataStore, ToKeys};
use types::{Key, Node};
@ -23,10 +23,10 @@ use crate::pythonutil::{
};
pub trait DataStorePyExt {
fn get_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyBytes>;
fn get_delta_chain_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyList>;
fn get_delta_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyObject>;
fn get_meta_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyDict>;
fn get_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyBytes>;
fn get_delta_chain_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyList>;
fn get_delta_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyObject>;
fn get_meta_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyDict>;
fn get_missing_py(&self, py: Python, keys: &mut PyIterator) -> PyResult<PyList>;
}
@ -38,7 +38,7 @@ pub trait MutableDeltaStorePyExt: DataStorePyExt {
fn add_py(
&self,
py: Python,
name: &PyPathBuf,
name: &PyPath,
node: &PyBytes,
deltabasenode: &PyBytes,
delta: &PyBytes,
@ -52,7 +52,7 @@ pub trait RemoteDataStorePyExt: RemoteDataStore {
}
impl<T: DataStore + ?Sized> DataStorePyExt for T {
fn get_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyBytes> {
fn get_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyBytes> {
let key = to_key(py, name, node)?;
let result = self
.get(&key)
@ -62,7 +62,7 @@ impl<T: DataStore + ?Sized> DataStorePyExt for T {
Ok(PyBytes::new(py, &result[..]))
}
fn get_delta_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyObject> {
fn get_delta_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyObject> {
let key = to_key(py, name, node)?;
let delta = self
.get_delta(&key)
@ -90,7 +90,7 @@ impl<T: DataStore + ?Sized> DataStorePyExt for T {
.into_object())
}
fn get_delta_chain_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyList> {
fn get_delta_chain_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyList> {
let key = to_key(py, name, node)?;
let deltachain = self
.get_delta_chain(&key)
@ -104,7 +104,7 @@ impl<T: DataStore + ?Sized> DataStorePyExt for T {
Ok(PyList::new(py, &pychain[..]))
}
fn get_meta_py(&self, py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<PyDict> {
fn get_meta_py(&self, py: Python, name: &PyPath, node: &PyBytes) -> PyResult<PyDict> {
let key = to_key(py, name, node)?;
let metadata = self
.get_meta(&key)
@ -167,7 +167,7 @@ impl<T: MutableDeltaStore + ?Sized> MutableDeltaStorePyExt for T {
fn add_py(
&self,
py: Python,
name: &PyPathBuf,
name: &PyPath,
node: &PyBytes,
deltabasenode: &PyBytes,
delta: &PyBytes,

View File

@ -105,7 +105,7 @@ fn to_node_info(
// Not only can copyfrom be None, it can also be an empty string. In both cases that means that
// `name` should be used.
let copyfrom = copyfrom.unwrap_or(name);
let p1path = if copyfrom.as_ref().as_os_str().is_empty() {
let p1path = if copyfrom.as_path().as_os_str().is_empty() {
name
} else {
copyfrom

View File

@ -20,7 +20,7 @@ use anyhow::{format_err, Error};
use cpython::*;
use parking_lot::RwLock;
use cpython_ext::{PyErr, PyPathBuf, ResultPyErrExt};
use cpython_ext::{PyErr, PyPath, PyPathBuf, ResultPyErrExt};
use pyconfigparser::config;
use revisionstore::{
repack::{filter_incrementalpacks, list_packs, repack_datapacks, repack_historypacks},
@ -155,11 +155,11 @@ py_class!(class datapack |py| {
def __new__(
_cls,
path: PyPathBuf
path: &PyPath
) -> PyResult<datapack> {
datapack::create_instance(
py,
Box::new(DataPack::new(&path).map_pyerr(py)?),
Box::new(DataPack::new(path).map_pyerr(py)?),
)
}
@ -243,14 +243,14 @@ py_class!(class datapackstore |py| {
data store: Box<DataPackStore>;
data path: PathBuf;
def __new__(_cls, path: PyPathBuf, deletecorruptpacks: bool = false) -> PyResult<datapackstore> {
def __new__(_cls, path: &PyPath, deletecorruptpacks: bool = false) -> PyResult<datapackstore> {
let corruption_policy = if deletecorruptpacks {
CorruptionPolicy::REMOVE
} else {
CorruptionPolicy::IGNORE
};
datapackstore::create_instance(py, Box::new(DataPackStore::new(&path, corruption_policy)), path.to_path_buf())
datapackstore::create_instance(py, Box::new(DataPackStore::new(path, corruption_policy)), path.to_path_buf())
}
def get(&self, name: PyPathBuf, node: &PyBytes) -> PyResult<PyBytes> {
@ -296,11 +296,11 @@ py_class!(class historypack |py| {
def __new__(
_cls,
path: PyPathBuf
path: &PyPath
) -> PyResult<historypack> {
historypack::create_instance(
py,
Box::new(HistoryPack::new(&path).map_pyerr(py)?),
Box::new(HistoryPack::new(path.as_path()).map_pyerr(py)?),
)
}
@ -343,7 +343,7 @@ py_class!(class historypackstore |py| {
CorruptionPolicy::IGNORE
};
historypackstore::create_instance(py, Box::new(HistoryPackStore::new(&path, corruption_policy)), path.to_path_buf())
historypackstore::create_instance(py, Box::new(HistoryPackStore::new(path.as_path(), corruption_policy)), path.to_path_buf())
}
def getnodeinfo(&self, name: PyPathBuf, node: &PyBytes) -> PyResult<PyTuple> {
@ -375,31 +375,31 @@ py_class!(class historypackstore |py| {
py_class!(class indexedlogdatastore |py| {
data store: Box<IndexedLogDataStore>;
def __new__(_cls, path: PyPathBuf) -> PyResult<indexedlogdatastore> {
def __new__(_cls, path: &PyPath) -> PyResult<indexedlogdatastore> {
indexedlogdatastore::create_instance(
py,
Box::new(IndexedLogDataStore::new(&path).map_pyerr(py)?),
Box::new(IndexedLogDataStore::new(path.as_path()).map_pyerr(py)?),
)
}
@staticmethod
def repair(path: PyPathBuf) -> PyResult<PyUnicode> {
py.allow_threads(|| IndexedLogDataStore::repair(path)).map_pyerr(py).map(|s| PyUnicode::new(py, &s))
def repair(path: &PyPath) -> PyResult<PyUnicode> {
py.allow_threads(|| IndexedLogDataStore::repair(path.as_path())).map_pyerr(py).map(|s| PyUnicode::new(py, &s))
}
def getdelta(&self, name: PyPathBuf, node: &PyBytes) -> PyResult<PyObject> {
def getdelta(&self, name: &PyPath, node: &PyBytes) -> PyResult<PyObject> {
let store = self.store(py);
store.get_delta_py(py, &name, node)
store.get_delta_py(py, name, node)
}
def getdeltachain(&self, name: PyPathBuf, node: &PyBytes) -> PyResult<PyList> {
def getdeltachain(&self, name: &PyPath, node: &PyBytes) -> PyResult<PyList> {
let store = self.store(py);
store.get_delta_chain_py(py, &name, node)
store.get_delta_chain_py(py, name, node)
}
def getmeta(&self, name: PyPathBuf, node: &PyBytes) -> PyResult<PyDict> {
def getmeta(&self, name: &PyPath, node: &PyBytes) -> PyResult<PyDict> {
let store = self.store(py);
store.get_meta_py(py, &name, node)
store.get_meta_py(py, name, node)
}
def getmissing(&self, keys: &PyObject) -> PyResult<PyList> {
@ -422,16 +422,16 @@ py_class!(class indexedlogdatastore |py| {
py_class!(class indexedloghistorystore |py| {
data store: Box<IndexedLogHistoryStore>;
def __new__(_cls, path: PyPathBuf) -> PyResult<indexedloghistorystore> {
def __new__(_cls, path: &PyPath) -> PyResult<indexedloghistorystore> {
indexedloghistorystore::create_instance(
py,
Box::new(IndexedLogHistoryStore::new(&path).map_pyerr(py)?),
Box::new(IndexedLogHistoryStore::new(path.as_path()).map_pyerr(py)?),
)
}
@staticmethod
def repair(path: PyPathBuf) -> PyResult<PyUnicode> {
IndexedLogHistoryStore::repair(path).map_pyerr(py).map(|s| PyUnicode::new(py, &s))
def repair(path: &PyPath) -> PyResult<PyUnicode> {
IndexedLogHistoryStore::repair(path.as_path()).map_pyerr(py).map(|s| PyUnicode::new(py, &s))
}
def getmissing(&self, keys: &PyObject) -> PyResult<PyList> {
@ -461,9 +461,12 @@ fn make_mutabledeltastore(
indexedlogpath: Option<PyPathBuf>,
) -> Result<Box<dyn MutableDeltaStore + Send>> {
let store: Box<dyn MutableDeltaStore + Send> = if let Some(packfilepath) = packfilepath {
Box::new(MutableDataPack::new(packfilepath, DataPackVersion::One)?)
Box::new(MutableDataPack::new(
packfilepath.as_path(),
DataPackVersion::One,
)?)
} else if let Some(indexedlogpath) = indexedlogpath {
Box::new(IndexedLogDataStore::new(indexedlogpath)?)
Box::new(IndexedLogDataStore::new(indexedlogpath.as_path())?)
} else {
return Err(format_err!("Foo"));
};
@ -569,7 +572,7 @@ fn make_mutablehistorystore(
) -> Result<Box<dyn MutableHistoryStore + Send>> {
let store: Box<dyn MutableHistoryStore + Send> = if let Some(packfilepath) = packfilepath {
Box::new(MutableHistoryPack::new(
packfilepath,
packfilepath.as_path(),
HistoryPackVersion::One,
)?)
} else {
@ -819,7 +822,7 @@ py_class!(class contentstore |py| {
let mut builder = ContentStoreBuilder::new(&config).remotestore(Box::new(remotestore));
builder = if let Some(path) = path {
builder.local_path(path)
builder.local_path(path.as_path())
} else {
builder.no_local_store()
};
@ -879,7 +882,7 @@ py_class!(class metadatastore |py| {
let mut builder = MetadataStoreBuilder::new(&config).remotestore(Box::new(remotestore));
builder = if let Some(path) = path {
builder.local_path(path)
builder.local_path(path.as_path())
} else {
builder.no_local_store()
};

View File

@ -11,7 +11,7 @@ use cpython::{
ToPyObject,
};
use cpython_ext::{PyErr as ExtPyErr, PyPathBuf, ResultPyErrExt};
use cpython_ext::{PyErr as ExtPyErr, PyPath, PyPathBuf, ResultPyErrExt};
use revisionstore::datastore::{Delta, Metadata};
use types::{Key, Node, RepoPathBuf};
@ -21,13 +21,13 @@ pub fn to_node(py: Python, node: &PyBytes) -> Node {
(&bytes).into()
}
pub fn to_path(py: Python, name: &PyPathBuf) -> PyResult<RepoPathBuf> {
pub fn to_path(py: Python, name: &PyPath) -> PyResult<RepoPathBuf> {
name.to_repo_path()
.map_pyerr(py)
.map(|path| path.to_owned())
}
pub fn to_key(py: Python, name: &PyPathBuf, node: &PyBytes) -> PyResult<Key> {
pub fn to_key(py: Python, name: &PyPath, node: &PyBytes) -> PyResult<Key> {
let node = to_node(py, node);
let path = to_path(py, name)?;
Ok(Key::new(path, node))
@ -42,7 +42,7 @@ pub fn from_key(py: Python, key: &Key) -> (PyPathBuf, PyBytes) {
pub fn to_delta(
py: Python,
name: &PyPathBuf,
name: &PyPath,
node: &PyBytes,
deltabasenode: &PyBytes,
data: &PyBytes,

View File

@ -25,7 +25,7 @@ use std::path::PathBuf;
use anyhow::Error;
use cpython::*;
use cpython_ext::PyNone;
use cpython_ext::{AnyhowResultExt, PyNone, PyPath, PyPathBuf, ResultPyErrExt};
use ::treestate::{
errors::ErrorKind,
@ -35,7 +35,6 @@ use ::treestate::{
treedirstate::TreeDirstate,
treestate::TreeState,
};
use cpython_ext::{AnyhowResultExt, PyPathBuf, ResultPyErrExt};
type Result<T, E = Error> = std::result::Result<T, E>;
@ -427,7 +426,7 @@ py_class!(class treestate |py| {
def __new__(
_cls,
path: PyPathBuf,
path: &PyPath,
root_id: u64
) -> PyResult<treestate> {
let root_id = if root_id == 0 {
@ -446,7 +445,7 @@ py_class!(class treestate |py| {
Ok(root_id.0)
}
def saveas(&self, path: PyPathBuf) -> PyResult<u64> {
def saveas(&self, path: &PyPath) -> PyResult<u64> {
// Save as a new file. Return `BlockId` that can be used in constructor.
let mut state = self.state(py).borrow_mut();
let root_id = convert_result(py, state.write_as(path))?;
@ -469,7 +468,7 @@ py_class!(class treestate |py| {
})
}
def get(&self, path: PyPathBuf, default: Option<(u16, u32, i32, i32, Option<PyPathBuf>)>) -> PyResult<Option<(u16, u32, i32, i32, Option<PyPathBuf>)>> {
def get(&self, path: &PyPath, default: Option<(u16, u32, i32, i32, Option<PyPathBuf>)>) -> PyResult<Option<(u16, u32, i32, i32, Option<PyPathBuf>)>> {
let mut state = self.state(py).borrow_mut();
let path = path.as_utf8_bytes();
@ -485,7 +484,7 @@ py_class!(class treestate |py| {
}
def insert(
&self, path: PyPathBuf, bits: u16, mode: u32, size: i32, mtime: i32, copied: Option<PyPathBuf>
&self, path: &PyPath, bits: u16, mode: u32, size: i32, mtime: i32, copied: Option<PyPathBuf>
) -> PyResult<PyObject> {
let mut flags = StateFlags::from_bits_truncate(bits);
// For special mtime or size, mark them as "NEED_CHECK" automatically.
@ -507,12 +506,12 @@ py_class!(class treestate |py| {
Ok(py.None())
}
def remove(&self, path: PyPathBuf) -> PyResult<bool> {
def remove(&self, path: &PyPath) -> PyResult<bool> {
let mut state = self.state(py).borrow_mut();
convert_result(py, state.remove(path.as_utf8_bytes()))
}
def getdir(&self, path: PyPathBuf) -> PyResult<Option<(u16, u16)>> {
def getdir(&self, path: &PyPath) -> PyResult<Option<(u16, u16)>> {
let mut state = self.state(py).borrow_mut();
let path = path.as_utf8_bytes();
@ -520,7 +519,7 @@ py_class!(class treestate |py| {
Ok(dir.map(|state| (state.union.to_bits(), state.intersection.to_bits())))
}
def hasdir(&self, path: PyPathBuf) -> PyResult<bool> {
def hasdir(&self, path: &PyPath) -> PyResult<bool> {
let mut state = self.state(py).borrow_mut();
let path = path.as_utf8_bytes();
Ok(convert_result(py, state.has_dir(path))?)
@ -570,7 +569,7 @@ py_class!(class treestate |py| {
Ok(result)
}
def tracked(&self, prefix: PyPathBuf) -> PyResult<Vec<PyPathBuf>> {
def tracked(&self, prefix: &PyPath) -> PyResult<Vec<PyPathBuf>> {
// prefix limits the result to given prefix (ex. ["dir1/", "dir2/"]). To get all tracked
// files, set prefix to an empty list.
// Not ideal as a special case. But the returned list is large and it needs to be fast.
@ -612,7 +611,7 @@ py_class!(class treestate |py| {
}
def getfiltered(
&self, path: PyPathBuf, filter: PyObject, filterid: u64
&self, path: &PyPath, filter: PyObject, filterid: u64
) -> PyResult<Vec<PyPathBuf>> {
let mut state = self.state(py).borrow_mut();
@ -632,7 +631,7 @@ py_class!(class treestate |py| {
}
def pathcomplete(
&self, prefix: PyPathBuf, setbits: u16, unsetbits: u16, matchcallback: PyObject,
&self, prefix: &PyPath, setbits: u16, unsetbits: u16, matchcallback: PyObject,
fullpaths: bool
) -> PyResult<PyObject> {
let setbits = StateFlags::from_bits_truncate(setbits);

View File

@ -22,7 +22,7 @@ pub use crate::bytesobject::allocate_pybytes;
pub use crate::error::{format_py_error, AnyhowResultExt, PyErr, ResultPyErrExt};
pub use crate::io::{wrap_pyio, WrappedIO};
pub use crate::none::PyNone;
pub use crate::path::{Error, PyPathBuf};
pub use crate::path::{Error, PyPath, PyPathBuf};
pub use crate::pybuf::SimplePyBuf;
pub use crate::pyset::{pyset_add, pyset_new};
pub use crate::str::Str;

View File

@ -5,11 +5,12 @@
* GNU General Public License version 2.
*/
use std::{
convert::{TryFrom, TryInto},
fmt,
path::{Path, PathBuf},
};
use std::borrow::Borrow;
use std::convert::{TryFrom, TryInto};
use std::fmt;
use std::mem;
use std::ops::Deref;
use std::path::{Path, PathBuf};
use anyhow::Result;
use cpython::*;
@ -25,6 +26,9 @@ use crate::ResultPyErrExt;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Default, Hash, Ord)]
pub struct PyPathBuf(String);
#[derive(Debug, Eq, PartialEq, PartialOrd, Hash, Ord)]
pub struct PyPath(str);
#[derive(Error, Debug)]
pub enum Error {
#[error("{0:?} is not a valid UTF-8 path")]
@ -32,6 +36,14 @@ pub enum Error {
}
impl PyPathBuf {
pub fn as_pypath(&self) -> &PyPath {
self
}
pub fn as_path(&self) -> &Path {
self.0.as_ref()
}
pub fn to_path_buf(&self) -> PathBuf {
Path::new(&self.0).to_path_buf()
}
@ -121,12 +133,6 @@ impl From<String> for PyPathBuf {
}
}
impl AsRef<Path> for PyPathBuf {
fn as_ref(&self) -> &Path {
self.0.as_ref()
}
}
impl<'a> From<&'a RepoPath> for PyPathBuf {
fn from(repo_path: &'a RepoPath) -> PyPathBuf {
PyPathBuf(repo_path.as_str().to_owned())
@ -156,3 +162,107 @@ impl From<PyPathBuf> for String {
path.0
}
}
impl Deref for PyPathBuf {
type Target = PyPath;
fn deref(&self) -> &Self::Target {
unsafe { mem::transmute(&*self.0) }
}
}
impl AsRef<PyPath> for PyPathBuf {
fn as_ref(&self) -> &PyPath {
self
}
}
impl PyPath {
pub fn from_str(s: &str) -> &Self {
unsafe { mem::transmute(s) }
}
pub fn as_path(&self) -> &Path {
self.0.as_ref()
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn as_utf8_bytes(&self) -> &[u8] {
self.0.as_bytes()
}
pub fn to_path_buf(&self) -> PathBuf {
Path::new(&self.0).to_path_buf()
}
pub fn to_repo_path(&self) -> Result<&RepoPath> {
Ok(RepoPath::from_str(&self.0)?)
}
pub fn to_repo_path_buf(&self) -> Result<RepoPathBuf> {
Ok(RepoPathBuf::from_string(self.0.to_string())?)
}
pub fn into_utf8_bytes(&self) -> Vec<u8> {
self.0.into()
}
}
impl ToOwned for PyPath {
type Owned = PyPathBuf;
fn to_owned(&self) -> Self::Owned {
PyPathBuf(self.0.to_string())
}
}
impl Borrow<PyPath> for PyPathBuf {
fn borrow(&self) -> &PyPath {
self
}
}
impl RefFromPyObject for PyPath {
fn with_extracted<F, R>(py: Python, obj: &PyObject, f: F) -> PyResult<R>
where
F: FnOnce(&PyPath) -> R,
{
#[cfg(feature = "python3")]
{
let s = obj.cast_as::<PyUnicode>(py)?.to_string(py)?;
Ok(f(PyPath::from_str(s.as_ref())))
}
#[cfg(feature = "python2")]
{
let s = obj.cast_as::<PyBytes>(py)?.data(py);
let path = local_bytes_to_path(s).map_pyerr(py)?;
let py_path = PyPath::from_str(
path.to_str()
.ok_or_else(|| Error::NonUTF8Path(path.to_path_buf()))
.map_pyerr(py)?,
);
Ok(f(py_path))
}
}
}
impl AsRef<PyPath> for PyPath {
fn as_ref(&self) -> &PyPath {
self
}
}
impl AsRef<Path> for PyPath {
fn as_ref(&self) -> &Path {
self.as_path()
}
}
impl fmt::Display for PyPath {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, formatter)
}
}