1use crate::internal::*;
2
3pub struct Store<'a, T: Contents> {
5 pub ptr: *mut Irmin,
6 pub repo: &'a Repo<T>,
7}
8
9impl<'a, T: Contents> Store<'a, T> {
10 pub fn new(repo: &'a Repo<T>) -> Result<Store<'a, T>, Error> {
12 unsafe {
13 let ptr = irmin_main(repo.ptr);
14 check!(repo.ptr, ptr);
15 Ok(Store { ptr, repo })
16 }
17 }
18
19 pub fn of_branch(repo: &'a Repo<T>, branch: impl AsRef<str>) -> Result<Store<'a, T>, Error> {
21 let branch = cstring(branch);
22 unsafe {
23 let ptr = irmin_of_branch(repo.ptr, branch.as_ptr() as *mut _);
24 check!(repo.ptr, ptr);
25 Ok(Store { ptr, repo })
26 }
27 }
28
29 pub fn of_commit(repo: &'a Repo<T>, commit: &Commit) -> Result<Store<'a, T>, Error> {
31 unsafe {
32 let ptr = irmin_of_commit(repo.ptr, commit.ptr);
33 check!(repo.ptr, ptr);
34 Ok(Store { ptr, repo })
35 }
36 }
37
38 pub fn set(&mut self, path: &Path, value: &T, info: Info) -> Result<bool, Error> {
40 let value = value.to_value()?;
41 unsafe {
42 let r = irmin_set(self.ptr, path.ptr, value.ptr as *mut _, info.ptr);
43 check!(self.repo.ptr, r, false);
44 Ok(r)
45 }
46 }
47
48 pub fn test_and_set(
50 &mut self,
51 path: &Path,
52 old: Option<&T>,
53 value: Option<&T>,
54 info: Info,
55 ) -> Result<bool, Error> {
56 let old = match old {
57 Some(value) => Some(value.to_value()?),
58 None => None,
59 };
60 let value = match value {
61 Some(value) => Some(value.to_value()?),
62 None => None,
63 };
64 unsafe {
65 let r = irmin_test_and_set(
66 self.ptr,
67 path.ptr,
68 old.map(|x| x.ptr as *mut _)
69 .unwrap_or_else(std::ptr::null_mut),
70 value
71 .map(|x| x.ptr as *mut _)
72 .unwrap_or_else(std::ptr::null_mut),
73 info.ptr,
74 );
75 check!(self.repo.ptr, r, false);
76 Ok(r)
77 }
78 }
79
80 pub fn set_tree(&mut self, path: &Path, tree: &Tree<T>, info: Info) -> Result<bool, Error> {
82 unsafe {
83 let r = irmin_set_tree(self.ptr, path.ptr, tree.ptr, info.ptr);
84 check!(self.repo.ptr, r, false);
85 Ok(r)
86 }
87 }
88
89 pub fn test_and_set_tree(
91 &mut self,
92 path: &Path,
93 old: Option<&Tree<T>>,
94 tree: Option<&Tree<T>>,
95 info: Info,
96 ) -> Result<bool, Error> {
97 unsafe {
98 let r = irmin_test_and_set_tree(
99 self.ptr,
100 path.ptr,
101 old.map(|x| x.ptr).unwrap_or_else(std::ptr::null_mut),
102 tree.map(|x| x.ptr).unwrap_or_else(std::ptr::null_mut),
103 info.ptr,
104 );
105 check!(self.repo.ptr, r, false);
106 Ok(r)
107 }
108 }
109
110 pub fn find(&self, path: &Path) -> Result<Option<T>, Error> {
112 let r = unsafe { irmin_find(self.ptr, path.ptr) };
113 check_opt!(self.repo.ptr, r);
114 let ty = T::ty()?;
115 let v = Value {
116 ptr: r as *mut _,
117 ty,
118 };
119 let v = T::from_value(&v)?;
120 Ok(Some(v))
121 }
122
123 pub fn find_tree(&self, path: &Path) -> Result<Option<Tree<T>>, Error> {
125 unsafe {
126 let ptr = irmin_find_tree(self.ptr, path.ptr);
127 check_opt!(self.repo.ptr, ptr);
128 let x = Tree {
129 ptr,
130 repo: UntypedRepo::new(self.repo),
131 _t: std::marker::PhantomData,
132 };
133 Ok(Some(x))
134 }
135 }
136
137 pub fn mem(&self, path: &Path) -> bool {
139 unsafe { irmin_mem(self.ptr, path.ptr) }
140 }
141
142 pub fn mem_tree(&self, path: &Path) -> bool {
144 unsafe { irmin_mem_tree(self.ptr, path.ptr) }
145 }
146
147 pub fn remove(&mut self, path: &Path, info: Info) -> bool {
149 unsafe { irmin_remove(self.ptr, path.ptr, info.ptr) }
150 }
151
152 pub fn head(&self) -> Result<Option<Commit<'a>>, Error> {
154 let ptr = unsafe { irmin_get_head(self.ptr) };
155 check_opt!(self.repo.ptr, ptr);
156 Ok(Some(Commit {
157 ptr,
158 repo: UntypedRepo::new(self.repo),
159 }))
160 }
161
162 pub fn set_head(&mut self, c: &Commit) {
164 unsafe { irmin_set_head(self.ptr, c.ptr) }
165 }
166
167 pub fn fast_forward(&mut self, c: &Commit) -> bool {
169 unsafe { irmin_fast_forward(self.ptr, c.ptr) }
170 }
171
172 pub fn merge_with_branch(
174 &mut self,
175 branch: impl AsRef<str>,
176 info: Info,
177 ) -> Result<bool, Error> {
178 let branch = cstring(branch);
179 let r = unsafe { irmin_merge_with_branch(self.ptr, branch.as_ptr() as *mut _, info.ptr) };
180 check!(self.repo.ptr, r, false);
181 Ok(r)
182 }
183
184 pub fn merge_with_commit(&mut self, commit: &Commit, info: Info) -> Result<bool, Error> {
186 let r = unsafe { irmin_merge_with_commit(self.ptr, commit.ptr, info.ptr) };
187 check!(self.repo.ptr, r, false);
188 Ok(r)
189 }
190
191 pub fn merge(&mut self, store: &Store<T>, info: Info) -> Result<bool, Error> {
193 let r = unsafe { irmin_merge_into(self.ptr, store.ptr, info.ptr) };
194 check!(self.repo.ptr, r, false);
195 Ok(r)
196 }
197
198 pub fn list(&self, path: &Path) -> Result<Vec<Path>, Error> {
200 let p = unsafe { irmin_list(self.ptr, path.ptr) };
201 check!(self.repo.ptr, p);
202 let len = unsafe { irmin_path_array_length(self.repo.ptr, p) };
203 let mut dest = Vec::new();
204 for i in 0..len {
205 let path = unsafe { irmin_path_array_get(self.repo.ptr, p, i) };
206 if path.is_null() {
207 continue;
208 }
209 dest.push(Path {
210 ptr: path,
211 repo: UntypedRepo::new(self.repo),
212 })
213 }
214
215 unsafe { irmin_path_array_free(p) }
216
217 Ok(dest)
218 }
219
220 pub fn pull(
223 &mut self,
224 remote: &Remote,
225 depth: Option<i32>,
226 info: Option<&Info>,
227 ) -> Result<Commit, Error> {
228 let info = match info {
229 Some(i) => i.ptr as *mut _,
230 None => std::ptr::null_mut(),
231 };
232 let depth = depth.unwrap_or(-1);
233 let c = unsafe { irmin_pull(self.ptr, depth, remote.ptr, info) };
234 check!(self.repo.ptr, c);
235 Ok(Commit {
236 ptr: c,
237 repo: UntypedRepo::new(self.repo),
238 })
239 }
240
241 pub fn fetch(&mut self, remote: &Remote, depth: Option<i32>) -> Result<Commit, Error> {
243 let depth = depth.unwrap_or(-1);
244 let c = unsafe { irmin_fetch(self.ptr, depth, remote.ptr) };
245 check!(self.repo.ptr, c);
246 Ok(Commit {
247 ptr: c,
248 repo: UntypedRepo::new(self.repo),
249 })
250 }
251
252 pub fn push(&mut self, remote: &Remote, depth: Option<i32>) -> Result<Commit, Error> {
254 let depth = depth.unwrap_or(-1);
255 let c = unsafe { irmin_push(self.ptr, depth, remote.ptr) };
256 check!(self.repo.ptr, c);
257 Ok(Commit {
258 ptr: c,
259 repo: UntypedRepo::new(self.repo),
260 })
261 }
262}
263
264impl<'a, T: Contents> Drop for Store<'a, T> {
265 fn drop(&mut self) {
266 unsafe { irmin_free(self.ptr) }
267 }
268}