mirror of
https://github.com/facebook/sapling.git
synced 2024-10-07 15:27:13 +03:00
bindings: add bindings for metalog
Summary: Expose metalog APIs to Python. Reviewed By: kulshrax Differential Revision: D18273001 fbshipit-source-id: b8fbf0c22a925e3e5373498076a3392901c00aed
This commit is contained in:
parent
ec7157bef5
commit
f0e8dee2ac
@ -22,6 +22,7 @@ pydag = { path = "modules/pydag" }
|
||||
pyedenapi = { path = "modules/pyedenapi" }
|
||||
pylz4 = { path = "modules/pylz4" }
|
||||
pymanifest = { path = "modules/pymanifest" }
|
||||
pymetalog = { path = "modules/pymetalog" }
|
||||
pymutationstore = { path = "modules/pymutationstore" }
|
||||
pynodemap = { path = "modules/pynodemap" }
|
||||
pypathmatcher = { path = "modules/pypathmatcher" }
|
||||
|
11
edenscmnative/bindings/modules/pymetalog/Cargo.toml
Normal file
11
edenscmnative/bindings/modules/pymetalog/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "pymetalog"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
cpython = { version = "0.3", features = ["python27-sys"], default-features = false }
|
||||
cpython-ext = { path = "../../../../lib/cpython-ext" }
|
||||
cpython-failure = { path = "../../../../lib/cpython-failure" }
|
||||
encoding = { path = "../../../../lib/encoding" }
|
||||
metalog = { path = "../../../../lib/metalog" }
|
104
edenscmnative/bindings/modules/pymetalog/src/lib.rs
Normal file
104
edenscmnative/bindings/modules/pymetalog/src/lib.rs
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use ::metalog::{CommitOptions, Id20, MetaLog};
|
||||
use cpython::*;
|
||||
use cpython_ext::Bytes;
|
||||
use cpython_failure::ResultPyErrExt;
|
||||
use std::cell::RefCell;
|
||||
use std::time::SystemTime;
|
||||
|
||||
pub fn init_module(py: Python, package: &str) -> PyResult<PyModule> {
|
||||
let name = [package, "metalog"].join(".");
|
||||
let m = PyModule::new(py, &name)?;
|
||||
m.add_class::<metalog>(py)?;
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
py_class!(class metalog |py| {
|
||||
data log: RefCell<MetaLog>;
|
||||
|
||||
def __new__(_cls, path: String, root: Option<Bytes> = None) -> PyResult<Self> {
|
||||
let root = root.and_then(|s| Id20::from_slice(s.as_ref()).ok());
|
||||
let log = MetaLog::open(&path, root).map_pyerr::<exc::IOError>(py)?;
|
||||
Self::create_instance(py, RefCell::new(log))
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def listroots(path: String) -> PyResult<Vec<Bytes>> {
|
||||
let root_ids = MetaLog::list_roots(&path).map_pyerr::<exc::IOError>(py)?;
|
||||
Ok(root_ids.into_iter().map(|id| Bytes::from(id.as_ref().to_vec())).collect())
|
||||
}
|
||||
|
||||
/// Lookup an item by key. Return None if the key does not exist.
|
||||
def get(&self, key: &str) -> PyResult<Option<Bytes>> {
|
||||
let log = self.log(py).borrow();
|
||||
let data = log.get(key).map_pyerr::<exc::IOError>(py)?;
|
||||
Ok(data.map(Bytes::from))
|
||||
}
|
||||
|
||||
/// Set an item. Return the Id of value.
|
||||
def set(&self, key: &str, value: Bytes) -> PyResult<Bytes> {
|
||||
let mut log = self.log(py).borrow_mut();
|
||||
let id = log.set(key, value.as_ref()).map_pyerr::<exc::IOError>(py)?;
|
||||
Ok(Bytes::from(id.as_ref().to_vec()))
|
||||
}
|
||||
|
||||
/// Remove an item. Does not raise if the key does not exist.
|
||||
def remove(&self, key: &str) -> PyResult<PyObject> {
|
||||
let mut log = self.log(py).borrow_mut();
|
||||
log.remove(key).map_pyerr::<exc::IOError>(py)?;
|
||||
Ok(py.None())
|
||||
}
|
||||
|
||||
/// Get all keys.
|
||||
def keys(&self) -> PyResult<Vec<Bytes>> {
|
||||
let keys = self.log(py).borrow()
|
||||
.keys().iter().map(|s| Bytes::from(s.as_bytes().to_vec())).collect();
|
||||
Ok(keys)
|
||||
}
|
||||
|
||||
/// Write pending data to disk. Raise if race condition is detected.
|
||||
def commit(&self, message: &str, time: Option<u64> = None, pending: bool = false) -> PyResult<Bytes> {
|
||||
let mut opts = CommitOptions::default();
|
||||
opts.detached = pending;
|
||||
opts.timestamp = time.unwrap_or_else(|| {
|
||||
SystemTime::now()
|
||||
.duration_since(SystemTime::UNIX_EPOCH)
|
||||
.map(|d| d.as_secs()).unwrap_or(0)
|
||||
});
|
||||
opts.message = message;
|
||||
let id = self.log(py).borrow_mut().commit(opts).map_pyerr::<exc::IOError>(py)?;
|
||||
Ok(Bytes::from(id.as_ref().to_vec()))
|
||||
}
|
||||
|
||||
/// Why the change was made.
|
||||
def message(&self) -> PyResult<Bytes> {
|
||||
Ok(Bytes::from(self.log(py).borrow().message().to_string()))
|
||||
}
|
||||
|
||||
/// When the change was made.
|
||||
def timestamp(&self) -> PyResult<u64> {
|
||||
Ok(self.log(py).borrow().timestamp())
|
||||
}
|
||||
|
||||
def __getitem__(&self, key: String) -> PyResult<Option<Bytes>> {
|
||||
self.get(py, &key)
|
||||
}
|
||||
|
||||
def __setitem__(&self, key: String, value: Bytes) -> PyResult<()> {
|
||||
self.set(py, &key, value)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
def __delitem__(&self, key: String) -> PyResult<()> {
|
||||
self.remove(py, &key)?;
|
||||
Ok(())
|
||||
}
|
||||
});
|
@ -28,6 +28,7 @@ pub fn populate_module(py: Python<'_>, module: &PyModule) -> PyResult<PyObject>
|
||||
m.add(py, "edenapi", pyedenapi::init_module(py, &name)?)?;
|
||||
m.add(py, "lz4", pylz4::init_module(py, &name)?)?;
|
||||
m.add(py, "manifest", pymanifest::init_module(py, &name)?)?;
|
||||
m.add(py, "metalog", pymetalog::init_module(py, &name)?)?;
|
||||
m.add(
|
||||
py,
|
||||
"mutationstore",
|
||||
|
Loading…
Reference in New Issue
Block a user