|
@@
-1,679
+1,682
b''
|
|
1
|
// dirstate_map.rs
|
|
1
|
// dirstate_map.rs
|
|
2
|
//
|
|
2
|
//
|
|
3
|
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
|
|
3
|
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
|
|
4
|
//
|
|
4
|
//
|
|
5
|
// This software may be used and distributed according to the terms of the
|
|
5
|
// This software may be used and distributed according to the terms of the
|
|
6
|
// GNU General Public License version 2 or any later version.
|
|
6
|
// GNU General Public License version 2 or any later version.
|
|
7
|
|
|
7
|
|
|
8
|
//! Bindings for the `hg::dirstate::dirstate_map` file provided by the
|
|
8
|
//! Bindings for the `hg::dirstate::dirstate_map` file provided by the
|
|
9
|
//! `hg-core` package.
|
|
9
|
//! `hg-core` package.
|
|
10
|
|
|
10
|
|
|
11
|
use std::cell::{RefCell, RefMut};
|
|
11
|
use std::cell::{RefCell, RefMut};
|
|
12
|
use std::convert::TryInto;
|
|
12
|
use std::convert::TryInto;
|
|
13
|
|
|
13
|
|
|
14
|
use cpython::{
|
|
14
|
use cpython::{
|
|
15
|
exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList,
|
|
15
|
exc, ObjectProtocol, PyBool, PyBytes, PyClone, PyDict, PyErr, PyList,
|
|
16
|
PyObject, PyResult, PySet, PyString, Python, PythonObject, ToPyObject,
|
|
16
|
PyObject, PyResult, PySet, PyString, Python, PythonObject, ToPyObject,
|
|
17
|
UnsafePyLeaked,
|
|
17
|
UnsafePyLeaked,
|
|
18
|
};
|
|
18
|
};
|
|
19
|
|
|
19
|
|
|
20
|
use crate::{
|
|
20
|
use crate::{
|
|
21
|
dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
|
|
21
|
dirstate::copymap::{CopyMap, CopyMapItemsIterator, CopyMapKeysIterator},
|
|
22
|
dirstate::make_dirstate_item,
|
|
22
|
dirstate::make_dirstate_item,
|
|
23
|
dirstate::make_dirstate_item_raw,
|
|
23
|
dirstate::make_dirstate_item_raw,
|
|
24
|
dirstate::non_normal_entries::{
|
|
24
|
dirstate::non_normal_entries::{
|
|
25
|
NonNormalEntries, NonNormalEntriesIterator,
|
|
25
|
NonNormalEntries, NonNormalEntriesIterator,
|
|
26
|
},
|
|
26
|
},
|
|
27
|
parsers::dirstate_parents_to_pytuple,
|
|
|
|
|
28
|
pybytes_deref::PyBytesDeref,
|
|
27
|
pybytes_deref::PyBytesDeref,
|
|
29
|
};
|
|
28
|
};
|
|
30
|
use hg::{
|
|
29
|
use hg::{
|
|
31
|
dirstate::parsers::Timestamp,
|
|
30
|
dirstate::parsers::Timestamp,
|
|
32
|
dirstate::MTIME_UNSET,
|
|
31
|
dirstate::MTIME_UNSET,
|
|
33
|
dirstate::SIZE_NON_NORMAL,
|
|
32
|
dirstate::SIZE_NON_NORMAL,
|
|
34
|
dirstate_tree::dirstate_map::DirstateMap as TreeDirstateMap,
|
|
33
|
dirstate_tree::dirstate_map::DirstateMap as TreeDirstateMap,
|
|
35
|
dirstate_tree::dispatch::DirstateMapMethods,
|
|
34
|
dirstate_tree::dispatch::DirstateMapMethods,
|
|
36
|
dirstate_tree::on_disk::DirstateV2ParseError,
|
|
35
|
dirstate_tree::on_disk::DirstateV2ParseError,
|
|
37
|
dirstate_tree::owning::OwningDirstateMap,
|
|
36
|
dirstate_tree::owning::OwningDirstateMap,
|
|
38
|
revlog::Node,
|
|
37
|
revlog::Node,
|
|
39
|
utils::files::normalize_case,
|
|
38
|
utils::files::normalize_case,
|
|
40
|
utils::hg_path::{HgPath, HgPathBuf},
|
|
39
|
utils::hg_path::{HgPath, HgPathBuf},
|
|
41
|
DirstateEntry, DirstateError, DirstateMap as RustDirstateMap,
|
|
40
|
DirstateEntry, DirstateError, DirstateMap as RustDirstateMap,
|
|
42
|
DirstateParents, EntryState, StateMapIter,
|
|
41
|
DirstateParents, EntryState, StateMapIter,
|
|
43
|
};
|
|
42
|
};
|
|
44
|
|
|
43
|
|
|
45
|
// TODO
|
|
44
|
// TODO
|
|
46
|
// This object needs to share references to multiple members of its Rust
|
|
45
|
// This object needs to share references to multiple members of its Rust
|
|
47
|
// inner struct, namely `copy_map`, `dirs` and `all_dirs`.
|
|
46
|
// inner struct, namely `copy_map`, `dirs` and `all_dirs`.
|
|
48
|
// Right now `CopyMap` is done, but it needs to have an explicit reference
|
|
47
|
// Right now `CopyMap` is done, but it needs to have an explicit reference
|
|
49
|
// to `RustDirstateMap` which itself needs to have an encapsulation for
|
|
48
|
// to `RustDirstateMap` which itself needs to have an encapsulation for
|
|
50
|
// every method in `CopyMap` (copymapcopy, etc.).
|
|
49
|
// every method in `CopyMap` (copymapcopy, etc.).
|
|
51
|
// This is ugly and hard to maintain.
|
|
50
|
// This is ugly and hard to maintain.
|
|
52
|
// The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
|
|
51
|
// The same logic applies to `dirs` and `all_dirs`, however the `Dirs`
|
|
53
|
// `py_class!` is already implemented and does not mention
|
|
52
|
// `py_class!` is already implemented and does not mention
|
|
54
|
// `RustDirstateMap`, rightfully so.
|
|
53
|
// `RustDirstateMap`, rightfully so.
|
|
55
|
// All attributes also have to have a separate refcount data attribute for
|
|
54
|
// All attributes also have to have a separate refcount data attribute for
|
|
56
|
// leaks, with all methods that go along for reference sharing.
|
|
55
|
// leaks, with all methods that go along for reference sharing.
|
|
57
|
py_class!(pub class DirstateMap |py| {
|
|
56
|
py_class!(pub class DirstateMap |py| {
|
|
58
|
@shared data inner: Box<dyn DirstateMapMethods + Send>;
|
|
57
|
@shared data inner: Box<dyn DirstateMapMethods + Send>;
|
|
59
|
|
|
58
|
|
|
60
|
/// Returns a `(dirstate_map, parents)` tuple
|
|
59
|
/// Returns a `(dirstate_map, parents)` tuple
|
|
61
|
@staticmethod
|
|
60
|
@staticmethod
|
|
62
|
def new_v1(
|
|
61
|
def new_v1(
|
|
63
|
use_dirstate_tree: bool,
|
|
62
|
use_dirstate_tree: bool,
|
|
64
|
on_disk: PyBytes,
|
|
63
|
on_disk: PyBytes,
|
|
65
|
) -> PyResult<PyObject> {
|
|
64
|
) -> PyResult<PyObject> {
|
|
66
|
let (inner, parents) = if use_dirstate_tree {
|
|
65
|
let (inner, parents) = if use_dirstate_tree {
|
|
67
|
let on_disk = PyBytesDeref::new(py, on_disk);
|
|
66
|
let on_disk = PyBytesDeref::new(py, on_disk);
|
|
68
|
let mut map = OwningDirstateMap::new_empty(on_disk);
|
|
67
|
let mut map = OwningDirstateMap::new_empty(on_disk);
|
|
69
|
let (on_disk, map_placeholder) = map.get_mut_pair();
|
|
68
|
let (on_disk, map_placeholder) = map.get_mut_pair();
|
|
70
|
|
|
69
|
|
|
71
|
let (actual_map, parents) = TreeDirstateMap::new_v1(on_disk)
|
|
70
|
let (actual_map, parents) = TreeDirstateMap::new_v1(on_disk)
|
|
72
|
.map_err(|e| dirstate_error(py, e))?;
|
|
71
|
.map_err(|e| dirstate_error(py, e))?;
|
|
73
|
*map_placeholder = actual_map;
|
|
72
|
*map_placeholder = actual_map;
|
|
74
|
(Box::new(map) as _, parents)
|
|
73
|
(Box::new(map) as _, parents)
|
|
75
|
} else {
|
|
74
|
} else {
|
|
76
|
let bytes = on_disk.data(py);
|
|
75
|
let bytes = on_disk.data(py);
|
|
77
|
let mut map = RustDirstateMap::default();
|
|
76
|
let mut map = RustDirstateMap::default();
|
|
78
|
let parents = map.read(bytes).map_err(|e| dirstate_error(py, e))?;
|
|
77
|
let parents = map.read(bytes).map_err(|e| dirstate_error(py, e))?;
|
|
79
|
(Box::new(map) as _, parents)
|
|
78
|
(Box::new(map) as _, parents)
|
|
80
|
};
|
|
79
|
};
|
|
81
|
let map = Self::create_instance(py, inner)?;
|
|
80
|
let map = Self::create_instance(py, inner)?;
|
|
82
|
let parents = parents.map(|p| dirstate_parents_to_pytuple(py, &p));
|
|
81
|
let parents = parents.map(|p| {
|
|
|
|
|
82
|
let p1 = PyBytes::new(py, p.p1.as_bytes());
|
|
|
|
|
83
|
let p2 = PyBytes::new(py, p.p2.as_bytes());
|
|
|
|
|
84
|
(p1, p2)
|
|
|
|
|
85
|
});
|
|
83
|
Ok((map, parents).to_py_object(py).into_object())
|
|
86
|
Ok((map, parents).to_py_object(py).into_object())
|
|
84
|
}
|
|
87
|
}
|
|
85
|
|
|
88
|
|
|
86
|
/// Returns a DirstateMap
|
|
89
|
/// Returns a DirstateMap
|
|
87
|
@staticmethod
|
|
90
|
@staticmethod
|
|
88
|
def new_v2(
|
|
91
|
def new_v2(
|
|
89
|
on_disk: PyBytes,
|
|
92
|
on_disk: PyBytes,
|
|
90
|
data_size: usize,
|
|
93
|
data_size: usize,
|
|
91
|
tree_metadata: PyBytes,
|
|
94
|
tree_metadata: PyBytes,
|
|
92
|
) -> PyResult<PyObject> {
|
|
95
|
) -> PyResult<PyObject> {
|
|
93
|
let dirstate_error = |e: DirstateError| {
|
|
96
|
let dirstate_error = |e: DirstateError| {
|
|
94
|
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
|
|
97
|
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
|
|
95
|
};
|
|
98
|
};
|
|
96
|
let on_disk = PyBytesDeref::new(py, on_disk);
|
|
99
|
let on_disk = PyBytesDeref::new(py, on_disk);
|
|
97
|
let mut map = OwningDirstateMap::new_empty(on_disk);
|
|
100
|
let mut map = OwningDirstateMap::new_empty(on_disk);
|
|
98
|
let (on_disk, map_placeholder) = map.get_mut_pair();
|
|
101
|
let (on_disk, map_placeholder) = map.get_mut_pair();
|
|
99
|
*map_placeholder = TreeDirstateMap::new_v2(
|
|
102
|
*map_placeholder = TreeDirstateMap::new_v2(
|
|
100
|
on_disk, data_size, tree_metadata.data(py),
|
|
103
|
on_disk, data_size, tree_metadata.data(py),
|
|
101
|
).map_err(dirstate_error)?;
|
|
104
|
).map_err(dirstate_error)?;
|
|
102
|
let map = Self::create_instance(py, Box::new(map))?;
|
|
105
|
let map = Self::create_instance(py, Box::new(map))?;
|
|
103
|
Ok(map.into_object())
|
|
106
|
Ok(map.into_object())
|
|
104
|
}
|
|
107
|
}
|
|
105
|
|
|
108
|
|
|
106
|
def clear(&self) -> PyResult<PyObject> {
|
|
109
|
def clear(&self) -> PyResult<PyObject> {
|
|
107
|
self.inner(py).borrow_mut().clear();
|
|
110
|
self.inner(py).borrow_mut().clear();
|
|
108
|
Ok(py.None())
|
|
111
|
Ok(py.None())
|
|
109
|
}
|
|
112
|
}
|
|
110
|
|
|
113
|
|
|
111
|
def get(
|
|
114
|
def get(
|
|
112
|
&self,
|
|
115
|
&self,
|
|
113
|
key: PyObject,
|
|
116
|
key: PyObject,
|
|
114
|
default: Option<PyObject> = None
|
|
117
|
default: Option<PyObject> = None
|
|
115
|
) -> PyResult<Option<PyObject>> {
|
|
118
|
) -> PyResult<Option<PyObject>> {
|
|
116
|
let key = key.extract::<PyBytes>(py)?;
|
|
119
|
let key = key.extract::<PyBytes>(py)?;
|
|
117
|
match self
|
|
120
|
match self
|
|
118
|
.inner(py)
|
|
121
|
.inner(py)
|
|
119
|
.borrow()
|
|
122
|
.borrow()
|
|
120
|
.get(HgPath::new(key.data(py)))
|
|
123
|
.get(HgPath::new(key.data(py)))
|
|
121
|
.map_err(|e| v2_error(py, e))?
|
|
124
|
.map_err(|e| v2_error(py, e))?
|
|
122
|
{
|
|
125
|
{
|
|
123
|
Some(entry) => {
|
|
126
|
Some(entry) => {
|
|
124
|
Ok(Some(make_dirstate_item(py, &entry)?))
|
|
127
|
Ok(Some(make_dirstate_item(py, &entry)?))
|
|
125
|
},
|
|
128
|
},
|
|
126
|
None => Ok(default)
|
|
129
|
None => Ok(default)
|
|
127
|
}
|
|
130
|
}
|
|
128
|
}
|
|
131
|
}
|
|
129
|
|
|
132
|
|
|
130
|
def set_v1(&self, path: PyObject, item: PyObject) -> PyResult<PyObject> {
|
|
133
|
def set_v1(&self, path: PyObject, item: PyObject) -> PyResult<PyObject> {
|
|
131
|
let f = path.extract::<PyBytes>(py)?;
|
|
134
|
let f = path.extract::<PyBytes>(py)?;
|
|
132
|
let filename = HgPath::new(f.data(py));
|
|
135
|
let filename = HgPath::new(f.data(py));
|
|
133
|
let state = item.getattr(py, "state")?.extract::<PyBytes>(py)?;
|
|
136
|
let state = item.getattr(py, "state")?.extract::<PyBytes>(py)?;
|
|
134
|
let state = state.data(py)[0];
|
|
137
|
let state = state.data(py)[0];
|
|
135
|
let entry = DirstateEntry {
|
|
138
|
let entry = DirstateEntry {
|
|
136
|
state: state.try_into().expect("state is always valid"),
|
|
139
|
state: state.try_into().expect("state is always valid"),
|
|
137
|
mtime: item.getattr(py, "mtime")?.extract(py)?,
|
|
140
|
mtime: item.getattr(py, "mtime")?.extract(py)?,
|
|
138
|
size: item.getattr(py, "size")?.extract(py)?,
|
|
141
|
size: item.getattr(py, "size")?.extract(py)?,
|
|
139
|
mode: item.getattr(py, "mode")?.extract(py)?,
|
|
142
|
mode: item.getattr(py, "mode")?.extract(py)?,
|
|
140
|
};
|
|
143
|
};
|
|
141
|
self.inner(py).borrow_mut().set_v1(filename, entry);
|
|
144
|
self.inner(py).borrow_mut().set_v1(filename, entry);
|
|
142
|
Ok(py.None())
|
|
145
|
Ok(py.None())
|
|
143
|
}
|
|
146
|
}
|
|
144
|
|
|
147
|
|
|
145
|
def addfile(
|
|
148
|
def addfile(
|
|
146
|
&self,
|
|
149
|
&self,
|
|
147
|
f: PyObject,
|
|
150
|
f: PyObject,
|
|
148
|
mode: PyObject,
|
|
151
|
mode: PyObject,
|
|
149
|
size: PyObject,
|
|
152
|
size: PyObject,
|
|
150
|
mtime: PyObject,
|
|
153
|
mtime: PyObject,
|
|
151
|
added: PyObject,
|
|
154
|
added: PyObject,
|
|
152
|
merged: PyObject,
|
|
155
|
merged: PyObject,
|
|
153
|
from_p2: PyObject,
|
|
156
|
from_p2: PyObject,
|
|
154
|
possibly_dirty: PyObject,
|
|
157
|
possibly_dirty: PyObject,
|
|
155
|
) -> PyResult<PyObject> {
|
|
158
|
) -> PyResult<PyObject> {
|
|
156
|
let f = f.extract::<PyBytes>(py)?;
|
|
159
|
let f = f.extract::<PyBytes>(py)?;
|
|
157
|
let filename = HgPath::new(f.data(py));
|
|
160
|
let filename = HgPath::new(f.data(py));
|
|
158
|
let mode = if mode.is_none(py) {
|
|
161
|
let mode = if mode.is_none(py) {
|
|
159
|
// fallback default value
|
|
162
|
// fallback default value
|
|
160
|
0
|
|
163
|
0
|
|
161
|
} else {
|
|
164
|
} else {
|
|
162
|
mode.extract(py)?
|
|
165
|
mode.extract(py)?
|
|
163
|
};
|
|
166
|
};
|
|
164
|
let size = if size.is_none(py) {
|
|
167
|
let size = if size.is_none(py) {
|
|
165
|
// fallback default value
|
|
168
|
// fallback default value
|
|
166
|
SIZE_NON_NORMAL
|
|
169
|
SIZE_NON_NORMAL
|
|
167
|
} else {
|
|
170
|
} else {
|
|
168
|
size.extract(py)?
|
|
171
|
size.extract(py)?
|
|
169
|
};
|
|
172
|
};
|
|
170
|
let mtime = if mtime.is_none(py) {
|
|
173
|
let mtime = if mtime.is_none(py) {
|
|
171
|
// fallback default value
|
|
174
|
// fallback default value
|
|
172
|
MTIME_UNSET
|
|
175
|
MTIME_UNSET
|
|
173
|
} else {
|
|
176
|
} else {
|
|
174
|
mtime.extract(py)?
|
|
177
|
mtime.extract(py)?
|
|
175
|
};
|
|
178
|
};
|
|
176
|
let entry = DirstateEntry {
|
|
179
|
let entry = DirstateEntry {
|
|
177
|
// XXX Arbitrary default value since the value is determined later
|
|
180
|
// XXX Arbitrary default value since the value is determined later
|
|
178
|
state: EntryState::Normal,
|
|
181
|
state: EntryState::Normal,
|
|
179
|
mode: mode,
|
|
182
|
mode: mode,
|
|
180
|
size: size,
|
|
183
|
size: size,
|
|
181
|
mtime: mtime,
|
|
184
|
mtime: mtime,
|
|
182
|
};
|
|
185
|
};
|
|
183
|
let added = added.extract::<PyBool>(py)?.is_true();
|
|
186
|
let added = added.extract::<PyBool>(py)?.is_true();
|
|
184
|
let merged = merged.extract::<PyBool>(py)?.is_true();
|
|
187
|
let merged = merged.extract::<PyBool>(py)?.is_true();
|
|
185
|
let from_p2 = from_p2.extract::<PyBool>(py)?.is_true();
|
|
188
|
let from_p2 = from_p2.extract::<PyBool>(py)?.is_true();
|
|
186
|
let possibly_dirty = possibly_dirty.extract::<PyBool>(py)?.is_true();
|
|
189
|
let possibly_dirty = possibly_dirty.extract::<PyBool>(py)?.is_true();
|
|
187
|
self.inner(py).borrow_mut().add_file(
|
|
190
|
self.inner(py).borrow_mut().add_file(
|
|
188
|
filename,
|
|
191
|
filename,
|
|
189
|
entry,
|
|
192
|
entry,
|
|
190
|
added,
|
|
193
|
added,
|
|
191
|
merged,
|
|
194
|
merged,
|
|
192
|
from_p2,
|
|
195
|
from_p2,
|
|
193
|
possibly_dirty
|
|
196
|
possibly_dirty
|
|
194
|
).and(Ok(py.None())).or_else(|e: DirstateError| {
|
|
197
|
).and(Ok(py.None())).or_else(|e: DirstateError| {
|
|
195
|
Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
|
|
198
|
Err(PyErr::new::<exc::ValueError, _>(py, e.to_string()))
|
|
196
|
})
|
|
199
|
})
|
|
197
|
}
|
|
200
|
}
|
|
198
|
|
|
201
|
|
|
199
|
def removefile(
|
|
202
|
def removefile(
|
|
200
|
&self,
|
|
203
|
&self,
|
|
201
|
f: PyObject,
|
|
204
|
f: PyObject,
|
|
202
|
in_merge: PyObject
|
|
205
|
in_merge: PyObject
|
|
203
|
) -> PyResult<PyObject> {
|
|
206
|
) -> PyResult<PyObject> {
|
|
204
|
self.inner(py).borrow_mut()
|
|
207
|
self.inner(py).borrow_mut()
|
|
205
|
.remove_file(
|
|
208
|
.remove_file(
|
|
206
|
HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
|
|
209
|
HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
|
|
207
|
in_merge.extract::<PyBool>(py)?.is_true(),
|
|
210
|
in_merge.extract::<PyBool>(py)?.is_true(),
|
|
208
|
)
|
|
211
|
)
|
|
209
|
.or_else(|_| {
|
|
212
|
.or_else(|_| {
|
|
210
|
Err(PyErr::new::<exc::OSError, _>(
|
|
213
|
Err(PyErr::new::<exc::OSError, _>(
|
|
211
|
py,
|
|
214
|
py,
|
|
212
|
"Dirstate error".to_string(),
|
|
215
|
"Dirstate error".to_string(),
|
|
213
|
))
|
|
216
|
))
|
|
214
|
})?;
|
|
217
|
})?;
|
|
215
|
Ok(py.None())
|
|
218
|
Ok(py.None())
|
|
216
|
}
|
|
219
|
}
|
|
217
|
|
|
220
|
|
|
218
|
def dropfile(
|
|
221
|
def dropfile(
|
|
219
|
&self,
|
|
222
|
&self,
|
|
220
|
f: PyObject,
|
|
223
|
f: PyObject,
|
|
221
|
) -> PyResult<PyBool> {
|
|
224
|
) -> PyResult<PyBool> {
|
|
222
|
self.inner(py).borrow_mut()
|
|
225
|
self.inner(py).borrow_mut()
|
|
223
|
.drop_file(
|
|
226
|
.drop_file(
|
|
224
|
HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
|
|
227
|
HgPath::new(f.extract::<PyBytes>(py)?.data(py)),
|
|
225
|
)
|
|
228
|
)
|
|
226
|
.and_then(|b| Ok(b.to_py_object(py)))
|
|
229
|
.and_then(|b| Ok(b.to_py_object(py)))
|
|
227
|
.or_else(|e| {
|
|
230
|
.or_else(|e| {
|
|
228
|
Err(PyErr::new::<exc::OSError, _>(
|
|
231
|
Err(PyErr::new::<exc::OSError, _>(
|
|
229
|
py,
|
|
232
|
py,
|
|
230
|
format!("Dirstate error: {}", e.to_string()),
|
|
233
|
format!("Dirstate error: {}", e.to_string()),
|
|
231
|
))
|
|
234
|
))
|
|
232
|
})
|
|
235
|
})
|
|
233
|
}
|
|
236
|
}
|
|
234
|
|
|
237
|
|
|
235
|
def clearambiguoustimes(
|
|
238
|
def clearambiguoustimes(
|
|
236
|
&self,
|
|
239
|
&self,
|
|
237
|
files: PyObject,
|
|
240
|
files: PyObject,
|
|
238
|
now: PyObject
|
|
241
|
now: PyObject
|
|
239
|
) -> PyResult<PyObject> {
|
|
242
|
) -> PyResult<PyObject> {
|
|
240
|
let files: PyResult<Vec<HgPathBuf>> = files
|
|
243
|
let files: PyResult<Vec<HgPathBuf>> = files
|
|
241
|
.iter(py)?
|
|
244
|
.iter(py)?
|
|
242
|
.map(|filename| {
|
|
245
|
.map(|filename| {
|
|
243
|
Ok(HgPathBuf::from_bytes(
|
|
246
|
Ok(HgPathBuf::from_bytes(
|
|
244
|
filename?.extract::<PyBytes>(py)?.data(py),
|
|
247
|
filename?.extract::<PyBytes>(py)?.data(py),
|
|
245
|
))
|
|
248
|
))
|
|
246
|
})
|
|
249
|
})
|
|
247
|
.collect();
|
|
250
|
.collect();
|
|
248
|
self.inner(py)
|
|
251
|
self.inner(py)
|
|
249
|
.borrow_mut()
|
|
252
|
.borrow_mut()
|
|
250
|
.clear_ambiguous_times(files?, now.extract(py)?)
|
|
253
|
.clear_ambiguous_times(files?, now.extract(py)?)
|
|
251
|
.map_err(|e| v2_error(py, e))?;
|
|
254
|
.map_err(|e| v2_error(py, e))?;
|
|
252
|
Ok(py.None())
|
|
255
|
Ok(py.None())
|
|
253
|
}
|
|
256
|
}
|
|
254
|
|
|
257
|
|
|
255
|
def other_parent_entries(&self) -> PyResult<PyObject> {
|
|
258
|
def other_parent_entries(&self) -> PyResult<PyObject> {
|
|
256
|
let mut inner_shared = self.inner(py).borrow_mut();
|
|
259
|
let mut inner_shared = self.inner(py).borrow_mut();
|
|
257
|
let set = PySet::empty(py)?;
|
|
260
|
let set = PySet::empty(py)?;
|
|
258
|
for path in inner_shared.iter_other_parent_paths() {
|
|
261
|
for path in inner_shared.iter_other_parent_paths() {
|
|
259
|
let path = path.map_err(|e| v2_error(py, e))?;
|
|
262
|
let path = path.map_err(|e| v2_error(py, e))?;
|
|
260
|
set.add(py, PyBytes::new(py, path.as_bytes()))?;
|
|
263
|
set.add(py, PyBytes::new(py, path.as_bytes()))?;
|
|
261
|
}
|
|
264
|
}
|
|
262
|
Ok(set.into_object())
|
|
265
|
Ok(set.into_object())
|
|
263
|
}
|
|
266
|
}
|
|
264
|
|
|
267
|
|
|
265
|
def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
|
|
268
|
def non_normal_entries(&self) -> PyResult<NonNormalEntries> {
|
|
266
|
NonNormalEntries::from_inner(py, self.clone_ref(py))
|
|
269
|
NonNormalEntries::from_inner(py, self.clone_ref(py))
|
|
267
|
}
|
|
270
|
}
|
|
268
|
|
|
271
|
|
|
269
|
def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
|
|
272
|
def non_normal_entries_contains(&self, key: PyObject) -> PyResult<bool> {
|
|
270
|
let key = key.extract::<PyBytes>(py)?;
|
|
273
|
let key = key.extract::<PyBytes>(py)?;
|
|
271
|
self.inner(py)
|
|
274
|
self.inner(py)
|
|
272
|
.borrow_mut()
|
|
275
|
.borrow_mut()
|
|
273
|
.non_normal_entries_contains(HgPath::new(key.data(py)))
|
|
276
|
.non_normal_entries_contains(HgPath::new(key.data(py)))
|
|
274
|
.map_err(|e| v2_error(py, e))
|
|
277
|
.map_err(|e| v2_error(py, e))
|
|
275
|
}
|
|
278
|
}
|
|
276
|
|
|
279
|
|
|
277
|
def non_normal_entries_display(&self) -> PyResult<PyString> {
|
|
280
|
def non_normal_entries_display(&self) -> PyResult<PyString> {
|
|
278
|
let mut inner = self.inner(py).borrow_mut();
|
|
281
|
let mut inner = self.inner(py).borrow_mut();
|
|
279
|
let paths = inner
|
|
282
|
let paths = inner
|
|
280
|
.iter_non_normal_paths()
|
|
283
|
.iter_non_normal_paths()
|
|
281
|
.collect::<Result<Vec<_>, _>>()
|
|
284
|
.collect::<Result<Vec<_>, _>>()
|
|
282
|
.map_err(|e| v2_error(py, e))?;
|
|
285
|
.map_err(|e| v2_error(py, e))?;
|
|
283
|
let formatted = format!("NonNormalEntries: {}", hg::utils::join_display(paths, ", "));
|
|
286
|
let formatted = format!("NonNormalEntries: {}", hg::utils::join_display(paths, ", "));
|
|
284
|
Ok(PyString::new(py, &formatted))
|
|
287
|
Ok(PyString::new(py, &formatted))
|
|
285
|
}
|
|
288
|
}
|
|
286
|
|
|
289
|
|
|
287
|
def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
|
|
290
|
def non_normal_entries_remove(&self, key: PyObject) -> PyResult<PyObject> {
|
|
288
|
let key = key.extract::<PyBytes>(py)?;
|
|
291
|
let key = key.extract::<PyBytes>(py)?;
|
|
289
|
let key = key.data(py);
|
|
292
|
let key = key.data(py);
|
|
290
|
let was_present = self
|
|
293
|
let was_present = self
|
|
291
|
.inner(py)
|
|
294
|
.inner(py)
|
|
292
|
.borrow_mut()
|
|
295
|
.borrow_mut()
|
|
293
|
.non_normal_entries_remove(HgPath::new(key));
|
|
296
|
.non_normal_entries_remove(HgPath::new(key));
|
|
294
|
if !was_present {
|
|
297
|
if !was_present {
|
|
295
|
let msg = String::from_utf8_lossy(key);
|
|
298
|
let msg = String::from_utf8_lossy(key);
|
|
296
|
Err(PyErr::new::<exc::KeyError, _>(py, msg))
|
|
299
|
Err(PyErr::new::<exc::KeyError, _>(py, msg))
|
|
297
|
} else {
|
|
300
|
} else {
|
|
298
|
Ok(py.None())
|
|
301
|
Ok(py.None())
|
|
299
|
}
|
|
302
|
}
|
|
300
|
}
|
|
303
|
}
|
|
301
|
|
|
304
|
|
|
302
|
def non_normal_entries_discard(&self, key: PyObject) -> PyResult<PyObject>
|
|
305
|
def non_normal_entries_discard(&self, key: PyObject) -> PyResult<PyObject>
|
|
303
|
{
|
|
306
|
{
|
|
304
|
let key = key.extract::<PyBytes>(py)?;
|
|
307
|
let key = key.extract::<PyBytes>(py)?;
|
|
305
|
self
|
|
308
|
self
|
|
306
|
.inner(py)
|
|
309
|
.inner(py)
|
|
307
|
.borrow_mut()
|
|
310
|
.borrow_mut()
|
|
308
|
.non_normal_entries_remove(HgPath::new(key.data(py)));
|
|
311
|
.non_normal_entries_remove(HgPath::new(key.data(py)));
|
|
309
|
Ok(py.None())
|
|
312
|
Ok(py.None())
|
|
310
|
}
|
|
313
|
}
|
|
311
|
|
|
314
|
|
|
312
|
def non_normal_entries_add(&self, key: PyObject) -> PyResult<PyObject> {
|
|
315
|
def non_normal_entries_add(&self, key: PyObject) -> PyResult<PyObject> {
|
|
313
|
let key = key.extract::<PyBytes>(py)?;
|
|
316
|
let key = key.extract::<PyBytes>(py)?;
|
|
314
|
self
|
|
317
|
self
|
|
315
|
.inner(py)
|
|
318
|
.inner(py)
|
|
316
|
.borrow_mut()
|
|
319
|
.borrow_mut()
|
|
317
|
.non_normal_entries_add(HgPath::new(key.data(py)));
|
|
320
|
.non_normal_entries_add(HgPath::new(key.data(py)));
|
|
318
|
Ok(py.None())
|
|
321
|
Ok(py.None())
|
|
319
|
}
|
|
322
|
}
|
|
320
|
|
|
323
|
|
|
321
|
def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
|
|
324
|
def non_normal_or_other_parent_paths(&self) -> PyResult<PyList> {
|
|
322
|
let mut inner = self.inner(py).borrow_mut();
|
|
325
|
let mut inner = self.inner(py).borrow_mut();
|
|
323
|
|
|
326
|
|
|
324
|
let ret = PyList::new(py, &[]);
|
|
327
|
let ret = PyList::new(py, &[]);
|
|
325
|
for filename in inner.non_normal_or_other_parent_paths() {
|
|
328
|
for filename in inner.non_normal_or_other_parent_paths() {
|
|
326
|
let filename = filename.map_err(|e| v2_error(py, e))?;
|
|
329
|
let filename = filename.map_err(|e| v2_error(py, e))?;
|
|
327
|
let as_pystring = PyBytes::new(py, filename.as_bytes());
|
|
330
|
let as_pystring = PyBytes::new(py, filename.as_bytes());
|
|
328
|
ret.append(py, as_pystring.into_object());
|
|
331
|
ret.append(py, as_pystring.into_object());
|
|
329
|
}
|
|
332
|
}
|
|
330
|
Ok(ret)
|
|
333
|
Ok(ret)
|
|
331
|
}
|
|
334
|
}
|
|
332
|
|
|
335
|
|
|
333
|
def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
|
|
336
|
def non_normal_entries_iter(&self) -> PyResult<NonNormalEntriesIterator> {
|
|
334
|
// Make sure the sets are defined before we no longer have a mutable
|
|
337
|
// Make sure the sets are defined before we no longer have a mutable
|
|
335
|
// reference to the dmap.
|
|
338
|
// reference to the dmap.
|
|
336
|
self.inner(py)
|
|
339
|
self.inner(py)
|
|
337
|
.borrow_mut()
|
|
340
|
.borrow_mut()
|
|
338
|
.set_non_normal_other_parent_entries(false);
|
|
341
|
.set_non_normal_other_parent_entries(false);
|
|
339
|
|
|
342
|
|
|
340
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
343
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
341
|
|
|
344
|
|
|
342
|
NonNormalEntriesIterator::from_inner(py, unsafe {
|
|
345
|
NonNormalEntriesIterator::from_inner(py, unsafe {
|
|
343
|
leaked_ref.map(py, |o| {
|
|
346
|
leaked_ref.map(py, |o| {
|
|
344
|
o.iter_non_normal_paths_panic()
|
|
347
|
o.iter_non_normal_paths_panic()
|
|
345
|
})
|
|
348
|
})
|
|
346
|
})
|
|
349
|
})
|
|
347
|
}
|
|
350
|
}
|
|
348
|
|
|
351
|
|
|
349
|
def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
|
|
352
|
def hastrackeddir(&self, d: PyObject) -> PyResult<PyBool> {
|
|
350
|
let d = d.extract::<PyBytes>(py)?;
|
|
353
|
let d = d.extract::<PyBytes>(py)?;
|
|
351
|
Ok(self.inner(py).borrow_mut()
|
|
354
|
Ok(self.inner(py).borrow_mut()
|
|
352
|
.has_tracked_dir(HgPath::new(d.data(py)))
|
|
355
|
.has_tracked_dir(HgPath::new(d.data(py)))
|
|
353
|
.map_err(|e| {
|
|
356
|
.map_err(|e| {
|
|
354
|
PyErr::new::<exc::ValueError, _>(py, e.to_string())
|
|
357
|
PyErr::new::<exc::ValueError, _>(py, e.to_string())
|
|
355
|
})?
|
|
358
|
})?
|
|
356
|
.to_py_object(py))
|
|
359
|
.to_py_object(py))
|
|
357
|
}
|
|
360
|
}
|
|
358
|
|
|
361
|
|
|
359
|
def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
|
|
362
|
def hasdir(&self, d: PyObject) -> PyResult<PyBool> {
|
|
360
|
let d = d.extract::<PyBytes>(py)?;
|
|
363
|
let d = d.extract::<PyBytes>(py)?;
|
|
361
|
Ok(self.inner(py).borrow_mut()
|
|
364
|
Ok(self.inner(py).borrow_mut()
|
|
362
|
.has_dir(HgPath::new(d.data(py)))
|
|
365
|
.has_dir(HgPath::new(d.data(py)))
|
|
363
|
.map_err(|e| {
|
|
366
|
.map_err(|e| {
|
|
364
|
PyErr::new::<exc::ValueError, _>(py, e.to_string())
|
|
367
|
PyErr::new::<exc::ValueError, _>(py, e.to_string())
|
|
365
|
})?
|
|
368
|
})?
|
|
366
|
.to_py_object(py))
|
|
369
|
.to_py_object(py))
|
|
367
|
}
|
|
370
|
}
|
|
368
|
|
|
371
|
|
|
369
|
def write_v1(
|
|
372
|
def write_v1(
|
|
370
|
&self,
|
|
373
|
&self,
|
|
371
|
p1: PyObject,
|
|
374
|
p1: PyObject,
|
|
372
|
p2: PyObject,
|
|
375
|
p2: PyObject,
|
|
373
|
now: PyObject
|
|
376
|
now: PyObject
|
|
374
|
) -> PyResult<PyBytes> {
|
|
377
|
) -> PyResult<PyBytes> {
|
|
375
|
let now = Timestamp(now.extract(py)?);
|
|
378
|
let now = Timestamp(now.extract(py)?);
|
|
376
|
|
|
379
|
|
|
377
|
let mut inner = self.inner(py).borrow_mut();
|
|
380
|
let mut inner = self.inner(py).borrow_mut();
|
|
378
|
let parents = DirstateParents {
|
|
381
|
let parents = DirstateParents {
|
|
379
|
p1: extract_node_id(py, &p1)?,
|
|
382
|
p1: extract_node_id(py, &p1)?,
|
|
380
|
p2: extract_node_id(py, &p2)?,
|
|
383
|
p2: extract_node_id(py, &p2)?,
|
|
381
|
};
|
|
384
|
};
|
|
382
|
let result = inner.pack_v1(parents, now);
|
|
385
|
let result = inner.pack_v1(parents, now);
|
|
383
|
match result {
|
|
386
|
match result {
|
|
384
|
Ok(packed) => Ok(PyBytes::new(py, &packed)),
|
|
387
|
Ok(packed) => Ok(PyBytes::new(py, &packed)),
|
|
385
|
Err(_) => Err(PyErr::new::<exc::OSError, _>(
|
|
388
|
Err(_) => Err(PyErr::new::<exc::OSError, _>(
|
|
386
|
py,
|
|
389
|
py,
|
|
387
|
"Dirstate error".to_string(),
|
|
390
|
"Dirstate error".to_string(),
|
|
388
|
)),
|
|
391
|
)),
|
|
389
|
}
|
|
392
|
}
|
|
390
|
}
|
|
393
|
}
|
|
391
|
|
|
394
|
|
|
392
|
/// Returns new data together with whether that data should be appended to
|
|
395
|
/// Returns new data together with whether that data should be appended to
|
|
393
|
/// the existing data file whose content is at `self.on_disk` (True),
|
|
396
|
/// the existing data file whose content is at `self.on_disk` (True),
|
|
394
|
/// instead of written to a new data file (False).
|
|
397
|
/// instead of written to a new data file (False).
|
|
395
|
def write_v2(
|
|
398
|
def write_v2(
|
|
396
|
&self,
|
|
399
|
&self,
|
|
397
|
now: PyObject,
|
|
400
|
now: PyObject,
|
|
398
|
can_append: bool,
|
|
401
|
can_append: bool,
|
|
399
|
) -> PyResult<PyObject> {
|
|
402
|
) -> PyResult<PyObject> {
|
|
400
|
let now = Timestamp(now.extract(py)?);
|
|
403
|
let now = Timestamp(now.extract(py)?);
|
|
401
|
|
|
404
|
|
|
402
|
let mut inner = self.inner(py).borrow_mut();
|
|
405
|
let mut inner = self.inner(py).borrow_mut();
|
|
403
|
let result = inner.pack_v2(now, can_append);
|
|
406
|
let result = inner.pack_v2(now, can_append);
|
|
404
|
match result {
|
|
407
|
match result {
|
|
405
|
Ok((packed, tree_metadata, append)) => {
|
|
408
|
Ok((packed, tree_metadata, append)) => {
|
|
406
|
let packed = PyBytes::new(py, &packed);
|
|
409
|
let packed = PyBytes::new(py, &packed);
|
|
407
|
let tree_metadata = PyBytes::new(py, &tree_metadata);
|
|
410
|
let tree_metadata = PyBytes::new(py, &tree_metadata);
|
|
408
|
let tuple = (packed, tree_metadata, append);
|
|
411
|
let tuple = (packed, tree_metadata, append);
|
|
409
|
Ok(tuple.to_py_object(py).into_object())
|
|
412
|
Ok(tuple.to_py_object(py).into_object())
|
|
410
|
},
|
|
413
|
},
|
|
411
|
Err(_) => Err(PyErr::new::<exc::OSError, _>(
|
|
414
|
Err(_) => Err(PyErr::new::<exc::OSError, _>(
|
|
412
|
py,
|
|
415
|
py,
|
|
413
|
"Dirstate error".to_string(),
|
|
416
|
"Dirstate error".to_string(),
|
|
414
|
)),
|
|
417
|
)),
|
|
415
|
}
|
|
418
|
}
|
|
416
|
}
|
|
419
|
}
|
|
417
|
|
|
420
|
|
|
418
|
def filefoldmapasdict(&self) -> PyResult<PyDict> {
|
|
421
|
def filefoldmapasdict(&self) -> PyResult<PyDict> {
|
|
419
|
let dict = PyDict::new(py);
|
|
422
|
let dict = PyDict::new(py);
|
|
420
|
for item in self.inner(py).borrow_mut().iter() {
|
|
423
|
for item in self.inner(py).borrow_mut().iter() {
|
|
421
|
let (path, entry) = item.map_err(|e| v2_error(py, e))?;
|
|
424
|
let (path, entry) = item.map_err(|e| v2_error(py, e))?;
|
|
422
|
if entry.state != EntryState::Removed {
|
|
425
|
if entry.state != EntryState::Removed {
|
|
423
|
let key = normalize_case(path);
|
|
426
|
let key = normalize_case(path);
|
|
424
|
let value = path;
|
|
427
|
let value = path;
|
|
425
|
dict.set_item(
|
|
428
|
dict.set_item(
|
|
426
|
py,
|
|
429
|
py,
|
|
427
|
PyBytes::new(py, key.as_bytes()).into_object(),
|
|
430
|
PyBytes::new(py, key.as_bytes()).into_object(),
|
|
428
|
PyBytes::new(py, value.as_bytes()).into_object(),
|
|
431
|
PyBytes::new(py, value.as_bytes()).into_object(),
|
|
429
|
)?;
|
|
432
|
)?;
|
|
430
|
}
|
|
433
|
}
|
|
431
|
}
|
|
434
|
}
|
|
432
|
Ok(dict)
|
|
435
|
Ok(dict)
|
|
433
|
}
|
|
436
|
}
|
|
434
|
|
|
437
|
|
|
435
|
def __len__(&self) -> PyResult<usize> {
|
|
438
|
def __len__(&self) -> PyResult<usize> {
|
|
436
|
Ok(self.inner(py).borrow().len())
|
|
439
|
Ok(self.inner(py).borrow().len())
|
|
437
|
}
|
|
440
|
}
|
|
438
|
|
|
441
|
|
|
439
|
def __contains__(&self, key: PyObject) -> PyResult<bool> {
|
|
442
|
def __contains__(&self, key: PyObject) -> PyResult<bool> {
|
|
440
|
let key = key.extract::<PyBytes>(py)?;
|
|
443
|
let key = key.extract::<PyBytes>(py)?;
|
|
441
|
self.inner(py)
|
|
444
|
self.inner(py)
|
|
442
|
.borrow()
|
|
445
|
.borrow()
|
|
443
|
.contains_key(HgPath::new(key.data(py)))
|
|
446
|
.contains_key(HgPath::new(key.data(py)))
|
|
444
|
.map_err(|e| v2_error(py, e))
|
|
447
|
.map_err(|e| v2_error(py, e))
|
|
445
|
}
|
|
448
|
}
|
|
446
|
|
|
449
|
|
|
447
|
def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
|
|
450
|
def __getitem__(&self, key: PyObject) -> PyResult<PyObject> {
|
|
448
|
let key = key.extract::<PyBytes>(py)?;
|
|
451
|
let key = key.extract::<PyBytes>(py)?;
|
|
449
|
let key = HgPath::new(key.data(py));
|
|
452
|
let key = HgPath::new(key.data(py));
|
|
450
|
match self
|
|
453
|
match self
|
|
451
|
.inner(py)
|
|
454
|
.inner(py)
|
|
452
|
.borrow()
|
|
455
|
.borrow()
|
|
453
|
.get(key)
|
|
456
|
.get(key)
|
|
454
|
.map_err(|e| v2_error(py, e))?
|
|
457
|
.map_err(|e| v2_error(py, e))?
|
|
455
|
{
|
|
458
|
{
|
|
456
|
Some(entry) => {
|
|
459
|
Some(entry) => {
|
|
457
|
Ok(make_dirstate_item(py, &entry)?)
|
|
460
|
Ok(make_dirstate_item(py, &entry)?)
|
|
458
|
},
|
|
461
|
},
|
|
459
|
None => Err(PyErr::new::<exc::KeyError, _>(
|
|
462
|
None => Err(PyErr::new::<exc::KeyError, _>(
|
|
460
|
py,
|
|
463
|
py,
|
|
461
|
String::from_utf8_lossy(key.as_bytes()),
|
|
464
|
String::from_utf8_lossy(key.as_bytes()),
|
|
462
|
)),
|
|
465
|
)),
|
|
463
|
}
|
|
466
|
}
|
|
464
|
}
|
|
467
|
}
|
|
465
|
|
|
468
|
|
|
466
|
def keys(&self) -> PyResult<DirstateMapKeysIterator> {
|
|
469
|
def keys(&self) -> PyResult<DirstateMapKeysIterator> {
|
|
467
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
470
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
468
|
DirstateMapKeysIterator::from_inner(
|
|
471
|
DirstateMapKeysIterator::from_inner(
|
|
469
|
py,
|
|
472
|
py,
|
|
470
|
unsafe { leaked_ref.map(py, |o| o.iter()) },
|
|
473
|
unsafe { leaked_ref.map(py, |o| o.iter()) },
|
|
471
|
)
|
|
474
|
)
|
|
472
|
}
|
|
475
|
}
|
|
473
|
|
|
476
|
|
|
474
|
def items(&self) -> PyResult<DirstateMapItemsIterator> {
|
|
477
|
def items(&self) -> PyResult<DirstateMapItemsIterator> {
|
|
475
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
478
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
476
|
DirstateMapItemsIterator::from_inner(
|
|
479
|
DirstateMapItemsIterator::from_inner(
|
|
477
|
py,
|
|
480
|
py,
|
|
478
|
unsafe { leaked_ref.map(py, |o| o.iter()) },
|
|
481
|
unsafe { leaked_ref.map(py, |o| o.iter()) },
|
|
479
|
)
|
|
482
|
)
|
|
480
|
}
|
|
483
|
}
|
|
481
|
|
|
484
|
|
|
482
|
def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
|
|
485
|
def __iter__(&self) -> PyResult<DirstateMapKeysIterator> {
|
|
483
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
486
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
484
|
DirstateMapKeysIterator::from_inner(
|
|
487
|
DirstateMapKeysIterator::from_inner(
|
|
485
|
py,
|
|
488
|
py,
|
|
486
|
unsafe { leaked_ref.map(py, |o| o.iter()) },
|
|
489
|
unsafe { leaked_ref.map(py, |o| o.iter()) },
|
|
487
|
)
|
|
490
|
)
|
|
488
|
}
|
|
491
|
}
|
|
489
|
|
|
492
|
|
|
490
|
// TODO all copymap* methods, see docstring above
|
|
493
|
// TODO all copymap* methods, see docstring above
|
|
491
|
def copymapcopy(&self) -> PyResult<PyDict> {
|
|
494
|
def copymapcopy(&self) -> PyResult<PyDict> {
|
|
492
|
let dict = PyDict::new(py);
|
|
495
|
let dict = PyDict::new(py);
|
|
493
|
for item in self.inner(py).borrow().copy_map_iter() {
|
|
496
|
for item in self.inner(py).borrow().copy_map_iter() {
|
|
494
|
let (key, value) = item.map_err(|e| v2_error(py, e))?;
|
|
497
|
let (key, value) = item.map_err(|e| v2_error(py, e))?;
|
|
495
|
dict.set_item(
|
|
498
|
dict.set_item(
|
|
496
|
py,
|
|
499
|
py,
|
|
497
|
PyBytes::new(py, key.as_bytes()),
|
|
500
|
PyBytes::new(py, key.as_bytes()),
|
|
498
|
PyBytes::new(py, value.as_bytes()),
|
|
501
|
PyBytes::new(py, value.as_bytes()),
|
|
499
|
)?;
|
|
502
|
)?;
|
|
500
|
}
|
|
503
|
}
|
|
501
|
Ok(dict)
|
|
504
|
Ok(dict)
|
|
502
|
}
|
|
505
|
}
|
|
503
|
|
|
506
|
|
|
504
|
def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
|
|
507
|
def copymapgetitem(&self, key: PyObject) -> PyResult<PyBytes> {
|
|
505
|
let key = key.extract::<PyBytes>(py)?;
|
|
508
|
let key = key.extract::<PyBytes>(py)?;
|
|
506
|
match self
|
|
509
|
match self
|
|
507
|
.inner(py)
|
|
510
|
.inner(py)
|
|
508
|
.borrow()
|
|
511
|
.borrow()
|
|
509
|
.copy_map_get(HgPath::new(key.data(py)))
|
|
512
|
.copy_map_get(HgPath::new(key.data(py)))
|
|
510
|
.map_err(|e| v2_error(py, e))?
|
|
513
|
.map_err(|e| v2_error(py, e))?
|
|
511
|
{
|
|
514
|
{
|
|
512
|
Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())),
|
|
515
|
Some(copy) => Ok(PyBytes::new(py, copy.as_bytes())),
|
|
513
|
None => Err(PyErr::new::<exc::KeyError, _>(
|
|
516
|
None => Err(PyErr::new::<exc::KeyError, _>(
|
|
514
|
py,
|
|
517
|
py,
|
|
515
|
String::from_utf8_lossy(key.data(py)),
|
|
518
|
String::from_utf8_lossy(key.data(py)),
|
|
516
|
)),
|
|
519
|
)),
|
|
517
|
}
|
|
520
|
}
|
|
518
|
}
|
|
521
|
}
|
|
519
|
def copymap(&self) -> PyResult<CopyMap> {
|
|
522
|
def copymap(&self) -> PyResult<CopyMap> {
|
|
520
|
CopyMap::from_inner(py, self.clone_ref(py))
|
|
523
|
CopyMap::from_inner(py, self.clone_ref(py))
|
|
521
|
}
|
|
524
|
}
|
|
522
|
|
|
525
|
|
|
523
|
def copymaplen(&self) -> PyResult<usize> {
|
|
526
|
def copymaplen(&self) -> PyResult<usize> {
|
|
524
|
Ok(self.inner(py).borrow().copy_map_len())
|
|
527
|
Ok(self.inner(py).borrow().copy_map_len())
|
|
525
|
}
|
|
528
|
}
|
|
526
|
def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
|
|
529
|
def copymapcontains(&self, key: PyObject) -> PyResult<bool> {
|
|
527
|
let key = key.extract::<PyBytes>(py)?;
|
|
530
|
let key = key.extract::<PyBytes>(py)?;
|
|
528
|
self.inner(py)
|
|
531
|
self.inner(py)
|
|
529
|
.borrow()
|
|
532
|
.borrow()
|
|
530
|
.copy_map_contains_key(HgPath::new(key.data(py)))
|
|
533
|
.copy_map_contains_key(HgPath::new(key.data(py)))
|
|
531
|
.map_err(|e| v2_error(py, e))
|
|
534
|
.map_err(|e| v2_error(py, e))
|
|
532
|
}
|
|
535
|
}
|
|
533
|
def copymapget(
|
|
536
|
def copymapget(
|
|
534
|
&self,
|
|
537
|
&self,
|
|
535
|
key: PyObject,
|
|
538
|
key: PyObject,
|
|
536
|
default: Option<PyObject>
|
|
539
|
default: Option<PyObject>
|
|
537
|
) -> PyResult<Option<PyObject>> {
|
|
540
|
) -> PyResult<Option<PyObject>> {
|
|
538
|
let key = key.extract::<PyBytes>(py)?;
|
|
541
|
let key = key.extract::<PyBytes>(py)?;
|
|
539
|
match self
|
|
542
|
match self
|
|
540
|
.inner(py)
|
|
543
|
.inner(py)
|
|
541
|
.borrow()
|
|
544
|
.borrow()
|
|
542
|
.copy_map_get(HgPath::new(key.data(py)))
|
|
545
|
.copy_map_get(HgPath::new(key.data(py)))
|
|
543
|
.map_err(|e| v2_error(py, e))?
|
|
546
|
.map_err(|e| v2_error(py, e))?
|
|
544
|
{
|
|
547
|
{
|
|
545
|
Some(copy) => Ok(Some(
|
|
548
|
Some(copy) => Ok(Some(
|
|
546
|
PyBytes::new(py, copy.as_bytes()).into_object(),
|
|
549
|
PyBytes::new(py, copy.as_bytes()).into_object(),
|
|
547
|
)),
|
|
550
|
)),
|
|
548
|
None => Ok(default),
|
|
551
|
None => Ok(default),
|
|
549
|
}
|
|
552
|
}
|
|
550
|
}
|
|
553
|
}
|
|
551
|
def copymapsetitem(
|
|
554
|
def copymapsetitem(
|
|
552
|
&self,
|
|
555
|
&self,
|
|
553
|
key: PyObject,
|
|
556
|
key: PyObject,
|
|
554
|
value: PyObject
|
|
557
|
value: PyObject
|
|
555
|
) -> PyResult<PyObject> {
|
|
558
|
) -> PyResult<PyObject> {
|
|
556
|
let key = key.extract::<PyBytes>(py)?;
|
|
559
|
let key = key.extract::<PyBytes>(py)?;
|
|
557
|
let value = value.extract::<PyBytes>(py)?;
|
|
560
|
let value = value.extract::<PyBytes>(py)?;
|
|
558
|
self.inner(py)
|
|
561
|
self.inner(py)
|
|
559
|
.borrow_mut()
|
|
562
|
.borrow_mut()
|
|
560
|
.copy_map_insert(
|
|
563
|
.copy_map_insert(
|
|
561
|
HgPathBuf::from_bytes(key.data(py)),
|
|
564
|
HgPathBuf::from_bytes(key.data(py)),
|
|
562
|
HgPathBuf::from_bytes(value.data(py)),
|
|
565
|
HgPathBuf::from_bytes(value.data(py)),
|
|
563
|
)
|
|
566
|
)
|
|
564
|
.map_err(|e| v2_error(py, e))?;
|
|
567
|
.map_err(|e| v2_error(py, e))?;
|
|
565
|
Ok(py.None())
|
|
568
|
Ok(py.None())
|
|
566
|
}
|
|
569
|
}
|
|
567
|
def copymappop(
|
|
570
|
def copymappop(
|
|
568
|
&self,
|
|
571
|
&self,
|
|
569
|
key: PyObject,
|
|
572
|
key: PyObject,
|
|
570
|
default: Option<PyObject>
|
|
573
|
default: Option<PyObject>
|
|
571
|
) -> PyResult<Option<PyObject>> {
|
|
574
|
) -> PyResult<Option<PyObject>> {
|
|
572
|
let key = key.extract::<PyBytes>(py)?;
|
|
575
|
let key = key.extract::<PyBytes>(py)?;
|
|
573
|
match self
|
|
576
|
match self
|
|
574
|
.inner(py)
|
|
577
|
.inner(py)
|
|
575
|
.borrow_mut()
|
|
578
|
.borrow_mut()
|
|
576
|
.copy_map_remove(HgPath::new(key.data(py)))
|
|
579
|
.copy_map_remove(HgPath::new(key.data(py)))
|
|
577
|
.map_err(|e| v2_error(py, e))?
|
|
580
|
.map_err(|e| v2_error(py, e))?
|
|
578
|
{
|
|
581
|
{
|
|
579
|
Some(_) => Ok(None),
|
|
582
|
Some(_) => Ok(None),
|
|
580
|
None => Ok(default),
|
|
583
|
None => Ok(default),
|
|
581
|
}
|
|
584
|
}
|
|
582
|
}
|
|
585
|
}
|
|
583
|
|
|
586
|
|
|
584
|
def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
|
|
587
|
def copymapiter(&self) -> PyResult<CopyMapKeysIterator> {
|
|
585
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
588
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
586
|
CopyMapKeysIterator::from_inner(
|
|
589
|
CopyMapKeysIterator::from_inner(
|
|
587
|
py,
|
|
590
|
py,
|
|
588
|
unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
|
|
591
|
unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
|
|
589
|
)
|
|
592
|
)
|
|
590
|
}
|
|
593
|
}
|
|
591
|
|
|
594
|
|
|
592
|
def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
|
|
595
|
def copymapitemsiter(&self) -> PyResult<CopyMapItemsIterator> {
|
|
593
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
596
|
let leaked_ref = self.inner(py).leak_immutable();
|
|
594
|
CopyMapItemsIterator::from_inner(
|
|
597
|
CopyMapItemsIterator::from_inner(
|
|
595
|
py,
|
|
598
|
py,
|
|
596
|
unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
|
|
599
|
unsafe { leaked_ref.map(py, |o| o.copy_map_iter()) },
|
|
597
|
)
|
|
600
|
)
|
|
598
|
}
|
|
601
|
}
|
|
599
|
|
|
602
|
|
|
600
|
def tracked_dirs(&self) -> PyResult<PyList> {
|
|
603
|
def tracked_dirs(&self) -> PyResult<PyList> {
|
|
601
|
let dirs = PyList::new(py, &[]);
|
|
604
|
let dirs = PyList::new(py, &[]);
|
|
602
|
for path in self.inner(py).borrow_mut().iter_tracked_dirs()
|
|
605
|
for path in self.inner(py).borrow_mut().iter_tracked_dirs()
|
|
603
|
.map_err(|e |dirstate_error(py, e))?
|
|
606
|
.map_err(|e |dirstate_error(py, e))?
|
|
604
|
{
|
|
607
|
{
|
|
605
|
let path = path.map_err(|e| v2_error(py, e))?;
|
|
608
|
let path = path.map_err(|e| v2_error(py, e))?;
|
|
606
|
let path = PyBytes::new(py, path.as_bytes());
|
|
609
|
let path = PyBytes::new(py, path.as_bytes());
|
|
607
|
dirs.append(py, path.into_object())
|
|
610
|
dirs.append(py, path.into_object())
|
|
608
|
}
|
|
611
|
}
|
|
609
|
Ok(dirs)
|
|
612
|
Ok(dirs)
|
|
610
|
}
|
|
613
|
}
|
|
611
|
|
|
614
|
|
|
612
|
def debug_iter(&self) -> PyResult<PyList> {
|
|
615
|
def debug_iter(&self) -> PyResult<PyList> {
|
|
613
|
let dirs = PyList::new(py, &[]);
|
|
616
|
let dirs = PyList::new(py, &[]);
|
|
614
|
for item in self.inner(py).borrow().debug_iter() {
|
|
617
|
for item in self.inner(py).borrow().debug_iter() {
|
|
615
|
let (path, (state, mode, size, mtime)) =
|
|
618
|
let (path, (state, mode, size, mtime)) =
|
|
616
|
item.map_err(|e| v2_error(py, e))?;
|
|
619
|
item.map_err(|e| v2_error(py, e))?;
|
|
617
|
let path = PyBytes::new(py, path.as_bytes());
|
|
620
|
let path = PyBytes::new(py, path.as_bytes());
|
|
618
|
let item = make_dirstate_item_raw(py, state, mode, size, mtime)?;
|
|
621
|
let item = make_dirstate_item_raw(py, state, mode, size, mtime)?;
|
|
619
|
dirs.append(py, (path, item).to_py_object(py).into_object())
|
|
622
|
dirs.append(py, (path, item).to_py_object(py).into_object())
|
|
620
|
}
|
|
623
|
}
|
|
621
|
Ok(dirs)
|
|
624
|
Ok(dirs)
|
|
622
|
}
|
|
625
|
}
|
|
623
|
});
|
|
626
|
});
|
|
624
|
|
|
627
|
|
|
625
|
impl DirstateMap {
|
|
628
|
impl DirstateMap {
|
|
626
|
pub fn get_inner_mut<'a>(
|
|
629
|
pub fn get_inner_mut<'a>(
|
|
627
|
&'a self,
|
|
630
|
&'a self,
|
|
628
|
py: Python<'a>,
|
|
631
|
py: Python<'a>,
|
|
629
|
) -> RefMut<'a, Box<dyn DirstateMapMethods + Send>> {
|
|
632
|
) -> RefMut<'a, Box<dyn DirstateMapMethods + Send>> {
|
|
630
|
self.inner(py).borrow_mut()
|
|
633
|
self.inner(py).borrow_mut()
|
|
631
|
}
|
|
634
|
}
|
|
632
|
fn translate_key(
|
|
635
|
fn translate_key(
|
|
633
|
py: Python,
|
|
636
|
py: Python,
|
|
634
|
res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
|
|
637
|
res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
|
|
635
|
) -> PyResult<Option<PyBytes>> {
|
|
638
|
) -> PyResult<Option<PyBytes>> {
|
|
636
|
let (f, _entry) = res.map_err(|e| v2_error(py, e))?;
|
|
639
|
let (f, _entry) = res.map_err(|e| v2_error(py, e))?;
|
|
637
|
Ok(Some(PyBytes::new(py, f.as_bytes())))
|
|
640
|
Ok(Some(PyBytes::new(py, f.as_bytes())))
|
|
638
|
}
|
|
641
|
}
|
|
639
|
fn translate_key_value(
|
|
642
|
fn translate_key_value(
|
|
640
|
py: Python,
|
|
643
|
py: Python,
|
|
641
|
res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
|
|
644
|
res: Result<(&HgPath, DirstateEntry), DirstateV2ParseError>,
|
|
642
|
) -> PyResult<Option<(PyBytes, PyObject)>> {
|
|
645
|
) -> PyResult<Option<(PyBytes, PyObject)>> {
|
|
643
|
let (f, entry) = res.map_err(|e| v2_error(py, e))?;
|
|
646
|
let (f, entry) = res.map_err(|e| v2_error(py, e))?;
|
|
644
|
Ok(Some((
|
|
647
|
Ok(Some((
|
|
645
|
PyBytes::new(py, f.as_bytes()),
|
|
648
|
PyBytes::new(py, f.as_bytes()),
|
|
646
|
make_dirstate_item(py, &entry)?,
|
|
649
|
make_dirstate_item(py, &entry)?,
|
|
647
|
)))
|
|
650
|
)))
|
|
648
|
}
|
|
651
|
}
|
|
649
|
}
|
|
652
|
}
|
|
650
|
|
|
653
|
|
|
651
|
py_shared_iterator!(
|
|
654
|
py_shared_iterator!(
|
|
652
|
DirstateMapKeysIterator,
|
|
655
|
DirstateMapKeysIterator,
|
|
653
|
UnsafePyLeaked<StateMapIter<'static>>,
|
|
656
|
UnsafePyLeaked<StateMapIter<'static>>,
|
|
654
|
DirstateMap::translate_key,
|
|
657
|
DirstateMap::translate_key,
|
|
655
|
Option<PyBytes>
|
|
658
|
Option<PyBytes>
|
|
656
|
);
|
|
659
|
);
|
|
657
|
|
|
660
|
|
|
658
|
py_shared_iterator!(
|
|
661
|
py_shared_iterator!(
|
|
659
|
DirstateMapItemsIterator,
|
|
662
|
DirstateMapItemsIterator,
|
|
660
|
UnsafePyLeaked<StateMapIter<'static>>,
|
|
663
|
UnsafePyLeaked<StateMapIter<'static>>,
|
|
661
|
DirstateMap::translate_key_value,
|
|
664
|
DirstateMap::translate_key_value,
|
|
662
|
Option<(PyBytes, PyObject)>
|
|
665
|
Option<(PyBytes, PyObject)>
|
|
663
|
);
|
|
666
|
);
|
|
664
|
|
|
667
|
|
|
665
|
fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> {
|
|
668
|
fn extract_node_id(py: Python, obj: &PyObject) -> PyResult<Node> {
|
|
666
|
let bytes = obj.extract::<PyBytes>(py)?;
|
|
669
|
let bytes = obj.extract::<PyBytes>(py)?;
|
|
667
|
match bytes.data(py).try_into() {
|
|
670
|
match bytes.data(py).try_into() {
|
|
668
|
Ok(s) => Ok(s),
|
|
671
|
Ok(s) => Ok(s),
|
|
669
|
Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
|
|
672
|
Err(e) => Err(PyErr::new::<exc::ValueError, _>(py, e.to_string())),
|
|
670
|
}
|
|
673
|
}
|
|
671
|
}
|
|
674
|
}
|
|
672
|
|
|
675
|
|
|
673
|
pub(super) fn v2_error(py: Python<'_>, _: DirstateV2ParseError) -> PyErr {
|
|
676
|
pub(super) fn v2_error(py: Python<'_>, _: DirstateV2ParseError) -> PyErr {
|
|
674
|
PyErr::new::<exc::ValueError, _>(py, "corrupted dirstate-v2")
|
|
677
|
PyErr::new::<exc::ValueError, _>(py, "corrupted dirstate-v2")
|
|
675
|
}
|
|
678
|
}
|
|
676
|
|
|
679
|
|
|
677
|
fn dirstate_error(py: Python<'_>, e: DirstateError) -> PyErr {
|
|
680
|
fn dirstate_error(py: Python<'_>, e: DirstateError) -> PyErr {
|
|
678
|
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
|
|
681
|
PyErr::new::<exc::OSError, _>(py, format!("Dirstate error: {:?}", e))
|
|
679
|
}
|
|
682
|
}
|