##// END OF EJS Templates
hg-core: add `Revlog.get_node_rev`...
Antoine Cezar -
r46105:4f11a67a default
parent child Browse files
Show More
@@ -1,412 +1,438 b''
1 use std::borrow::Cow;
1 use std::borrow::Cow;
2 use std::fs::File;
2 use std::fs::File;
3 use std::io::Read;
3 use std::io::Read;
4 use std::ops::Deref;
4 use std::ops::Deref;
5 use std::path::Path;
5 use std::path::Path;
6
6
7 use byteorder::{BigEndian, ByteOrder};
7 use byteorder::{BigEndian, ByteOrder};
8 use crypto::digest::Digest;
8 use crypto::digest::Digest;
9 use crypto::sha1::Sha1;
9 use crypto::sha1::Sha1;
10 use flate2::read::ZlibDecoder;
10 use flate2::read::ZlibDecoder;
11 use memmap::{Mmap, MmapOptions};
11 use memmap::{Mmap, MmapOptions};
12 use micro_timer::timed;
12 use micro_timer::timed;
13 use zstd;
13 use zstd;
14
14
15 use super::index::Index;
15 use super::index::Index;
16 use super::node::{NODE_BYTES_LENGTH, NULL_NODE_ID};
16 use super::node::{NODE_BYTES_LENGTH, NULL_NODE_ID};
17 use super::patch;
17 use super::patch;
18 use crate::revlog::Revision;
18 use crate::revlog::Revision;
19
19
20 pub enum RevlogError {
20 pub enum RevlogError {
21 IoError(std::io::Error),
21 IoError(std::io::Error),
22 UnsuportedVersion(u16),
22 UnsuportedVersion(u16),
23 InvalidRevision,
23 InvalidRevision,
24 Corrupted,
24 Corrupted,
25 UnknowDataFormat(u8),
25 UnknowDataFormat(u8),
26 }
26 }
27
27
28 fn mmap_open(path: &Path) -> Result<Mmap, std::io::Error> {
28 fn mmap_open(path: &Path) -> Result<Mmap, std::io::Error> {
29 let file = File::open(path)?;
29 let file = File::open(path)?;
30 let mmap = unsafe { MmapOptions::new().map(&file) }?;
30 let mmap = unsafe { MmapOptions::new().map(&file) }?;
31 Ok(mmap)
31 Ok(mmap)
32 }
32 }
33
33
34 /// Read only implementation of revlog.
34 /// Read only implementation of revlog.
35 pub struct Revlog {
35 pub struct Revlog {
36 /// When index and data are not interleaved: bytes of the revlog index.
36 /// When index and data are not interleaved: bytes of the revlog index.
37 /// When index and data are interleaved: bytes of the revlog index and
37 /// When index and data are interleaved: bytes of the revlog index and
38 /// data.
38 /// data.
39 index_bytes: Box<dyn Deref<Target = [u8]> + Send>,
39 index_bytes: Box<dyn Deref<Target = [u8]> + Send>,
40 /// When index and data are not interleaved: bytes of the revlog data
40 /// When index and data are not interleaved: bytes of the revlog data
41 data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>>,
41 data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>>,
42 }
42 }
43
43
44 impl Revlog {
44 impl Revlog {
45 /// Open a revlog index file.
45 /// Open a revlog index file.
46 ///
46 ///
47 /// It will also open the associated data file if index and data are not
47 /// It will also open the associated data file if index and data are not
48 /// interleaved.
48 /// interleaved.
49 #[timed]
49 #[timed]
50 pub fn open(index_path: &Path) -> Result<Self, RevlogError> {
50 pub fn open(index_path: &Path) -> Result<Self, RevlogError> {
51 let index_mmap =
51 let index_mmap =
52 mmap_open(&index_path).map_err(RevlogError::IoError)?;
52 mmap_open(&index_path).map_err(RevlogError::IoError)?;
53
53
54 let version = get_version(&index_mmap);
54 let version = get_version(&index_mmap);
55 if version != 1 {
55 if version != 1 {
56 return Err(RevlogError::UnsuportedVersion(version));
56 return Err(RevlogError::UnsuportedVersion(version));
57 }
57 }
58
58
59 let is_inline = is_inline(&index_mmap);
59 let is_inline = is_inline(&index_mmap);
60
60
61 let index_bytes = Box::new(index_mmap);
61 let index_bytes = Box::new(index_mmap);
62
62
63 // TODO load data only when needed //
63 // TODO load data only when needed //
64 // type annotation required
64 // type annotation required
65 // won't recognize Mmap as Deref<Target = [u8]>
65 // won't recognize Mmap as Deref<Target = [u8]>
66 let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> =
66 let data_bytes: Option<Box<dyn Deref<Target = [u8]> + Send>> =
67 if is_inline {
67 if is_inline {
68 None
68 None
69 } else {
69 } else {
70 let data_path = index_path.with_extension("d");
70 let data_path = index_path.with_extension("d");
71 let data_mmap =
71 let data_mmap =
72 mmap_open(&data_path).map_err(RevlogError::IoError)?;
72 mmap_open(&data_path).map_err(RevlogError::IoError)?;
73 Some(Box::new(data_mmap))
73 Some(Box::new(data_mmap))
74 };
74 };
75
75
76 Ok(Revlog {
76 Ok(Revlog {
77 index_bytes,
77 index_bytes,
78 data_bytes,
78 data_bytes,
79 })
79 })
80 }
80 }
81
81
82 /// Return number of entries of the `Revlog`.
83 pub fn len(&self) -> usize {
84 self.index().len()
85 }
86
87 /// Returns `true` if the `Revlog` has zero `entries`.
88 pub fn is_empty(&self) -> bool {
89 self.index().is_empty()
90 }
91
92 /// Return the full data associated to a node.
93 #[timed]
94 pub fn get_node_rev(&self, node: &[u8]) -> Result<Revision, RevlogError> {
95 let index = self.index();
96 // This is brute force. But it is fast enough for now.
97 // Optimization will come later.
98 for rev in (0..self.len() as Revision).rev() {
99 let index_entry =
100 index.get_entry(rev).ok_or(RevlogError::Corrupted)?;
101 if node == index_entry.hash() {
102 return Ok(rev);
103 }
104 }
105 Err(RevlogError::InvalidRevision)
106 }
107
82 /// Return the full data associated to a revision.
108 /// Return the full data associated to a revision.
83 ///
109 ///
84 /// All entries required to build the final data out of deltas will be
110 /// All entries required to build the final data out of deltas will be
85 /// retrieved as needed, and the deltas will be applied to the inital
111 /// retrieved as needed, and the deltas will be applied to the inital
86 /// snapshot to rebuild the final data.
112 /// snapshot to rebuild the final data.
87 #[timed]
113 #[timed]
88 pub fn get_rev_data(&self, rev: Revision) -> Result<Vec<u8>, RevlogError> {
114 pub fn get_rev_data(&self, rev: Revision) -> Result<Vec<u8>, RevlogError> {
89 // Todo return -> Cow
115 // Todo return -> Cow
90 let mut entry = self.get_entry(rev)?;
116 let mut entry = self.get_entry(rev)?;
91 let mut delta_chain = vec![];
117 let mut delta_chain = vec![];
92 while let Some(base_rev) = entry.base_rev {
118 while let Some(base_rev) = entry.base_rev {
93 delta_chain.push(entry);
119 delta_chain.push(entry);
94 entry = self
120 entry = self
95 .get_entry(base_rev)
121 .get_entry(base_rev)
96 .map_err(|_| RevlogError::Corrupted)?;
122 .map_err(|_| RevlogError::Corrupted)?;
97 }
123 }
98
124
99 // TODO do not look twice in the index
125 // TODO do not look twice in the index
100 let index = self.index();
126 let index = self.index();
101 let index_entry =
127 let index_entry =
102 index.get_entry(rev).ok_or(RevlogError::InvalidRevision)?;
128 index.get_entry(rev).ok_or(RevlogError::InvalidRevision)?;
103
129
104 let data: Vec<u8> = if delta_chain.is_empty() {
130 let data: Vec<u8> = if delta_chain.is_empty() {
105 entry.data()?.into()
131 entry.data()?.into()
106 } else {
132 } else {
107 Revlog::build_data_from_deltas(entry, &delta_chain)?
133 Revlog::build_data_from_deltas(entry, &delta_chain)?
108 };
134 };
109
135
110 if self.check_hash(
136 if self.check_hash(
111 index_entry.p1(),
137 index_entry.p1(),
112 index_entry.p2(),
138 index_entry.p2(),
113 index_entry.hash(),
139 index_entry.hash(),
114 &data,
140 &data,
115 ) {
141 ) {
116 Ok(data)
142 Ok(data)
117 } else {
143 } else {
118 Err(RevlogError::Corrupted)
144 Err(RevlogError::Corrupted)
119 }
145 }
120 }
146 }
121
147
122 /// Check the hash of some given data against the recorded hash.
148 /// Check the hash of some given data against the recorded hash.
123 pub fn check_hash(
149 pub fn check_hash(
124 &self,
150 &self,
125 p1: Revision,
151 p1: Revision,
126 p2: Revision,
152 p2: Revision,
127 expected: &[u8],
153 expected: &[u8],
128 data: &[u8],
154 data: &[u8],
129 ) -> bool {
155 ) -> bool {
130 let index = self.index();
156 let index = self.index();
131 let e1 = index.get_entry(p1);
157 let e1 = index.get_entry(p1);
132 let h1 = match e1 {
158 let h1 = match e1 {
133 Some(ref entry) => entry.hash(),
159 Some(ref entry) => entry.hash(),
134 None => &NULL_NODE_ID,
160 None => &NULL_NODE_ID,
135 };
161 };
136 let e2 = index.get_entry(p2);
162 let e2 = index.get_entry(p2);
137 let h2 = match e2 {
163 let h2 = match e2 {
138 Some(ref entry) => entry.hash(),
164 Some(ref entry) => entry.hash(),
139 None => &NULL_NODE_ID,
165 None => &NULL_NODE_ID,
140 };
166 };
141
167
142 hash(data, &h1, &h2).as_slice() == expected
168 hash(data, &h1, &h2).as_slice() == expected
143 }
169 }
144
170
145 /// Build the full data of a revision out its snapshot
171 /// Build the full data of a revision out its snapshot
146 /// and its deltas.
172 /// and its deltas.
147 #[timed]
173 #[timed]
148 fn build_data_from_deltas(
174 fn build_data_from_deltas(
149 snapshot: RevlogEntry,
175 snapshot: RevlogEntry,
150 deltas: &[RevlogEntry],
176 deltas: &[RevlogEntry],
151 ) -> Result<Vec<u8>, RevlogError> {
177 ) -> Result<Vec<u8>, RevlogError> {
152 let snapshot = snapshot.data()?;
178 let snapshot = snapshot.data()?;
153 let deltas = deltas
179 let deltas = deltas
154 .iter()
180 .iter()
155 .rev()
181 .rev()
156 .map(RevlogEntry::data)
182 .map(RevlogEntry::data)
157 .collect::<Result<Vec<Cow<'_, [u8]>>, RevlogError>>()?;
183 .collect::<Result<Vec<Cow<'_, [u8]>>, RevlogError>>()?;
158 let patches: Vec<_> =
184 let patches: Vec<_> =
159 deltas.iter().map(|d| patch::PatchList::new(d)).collect();
185 deltas.iter().map(|d| patch::PatchList::new(d)).collect();
160 let patch = patch::fold_patch_lists(&patches);
186 let patch = patch::fold_patch_lists(&patches);
161 Ok(patch.apply(&snapshot))
187 Ok(patch.apply(&snapshot))
162 }
188 }
163
189
164 /// Return the revlog index.
190 /// Return the revlog index.
165 fn index(&self) -> Index {
191 fn index(&self) -> Index {
166 let is_inline = self.data_bytes.is_none();
192 let is_inline = self.data_bytes.is_none();
167 Index::new(&self.index_bytes, is_inline)
193 Index::new(&self.index_bytes, is_inline)
168 }
194 }
169
195
170 /// Return the revlog data.
196 /// Return the revlog data.
171 fn data(&self) -> &[u8] {
197 fn data(&self) -> &[u8] {
172 match self.data_bytes {
198 match self.data_bytes {
173 Some(ref data_bytes) => &data_bytes,
199 Some(ref data_bytes) => &data_bytes,
174 None => &self.index_bytes,
200 None => &self.index_bytes,
175 }
201 }
176 }
202 }
177
203
178 /// Get an entry of the revlog.
204 /// Get an entry of the revlog.
179 fn get_entry(&self, rev: Revision) -> Result<RevlogEntry, RevlogError> {
205 fn get_entry(&self, rev: Revision) -> Result<RevlogEntry, RevlogError> {
180 let index = self.index();
206 let index = self.index();
181 let index_entry =
207 let index_entry =
182 index.get_entry(rev).ok_or(RevlogError::InvalidRevision)?;
208 index.get_entry(rev).ok_or(RevlogError::InvalidRevision)?;
183 let start = index_entry.offset();
209 let start = index_entry.offset();
184 let end = start + index_entry.compressed_len();
210 let end = start + index_entry.compressed_len();
185 let entry = RevlogEntry {
211 let entry = RevlogEntry {
186 rev,
212 rev,
187 bytes: &self.data()[start..end],
213 bytes: &self.data()[start..end],
188 compressed_len: index_entry.compressed_len(),
214 compressed_len: index_entry.compressed_len(),
189 uncompressed_len: index_entry.uncompressed_len(),
215 uncompressed_len: index_entry.uncompressed_len(),
190 base_rev: if index_entry.base_revision() == rev {
216 base_rev: if index_entry.base_revision() == rev {
191 None
217 None
192 } else {
218 } else {
193 Some(index_entry.base_revision())
219 Some(index_entry.base_revision())
194 },
220 },
195 };
221 };
196 Ok(entry)
222 Ok(entry)
197 }
223 }
198 }
224 }
199
225
200 /// The revlog entry's bytes and the necessary informations to extract
226 /// The revlog entry's bytes and the necessary informations to extract
201 /// the entry's data.
227 /// the entry's data.
202 #[derive(Debug)]
228 #[derive(Debug)]
203 pub struct RevlogEntry<'a> {
229 pub struct RevlogEntry<'a> {
204 rev: Revision,
230 rev: Revision,
205 bytes: &'a [u8],
231 bytes: &'a [u8],
206 compressed_len: usize,
232 compressed_len: usize,
207 uncompressed_len: usize,
233 uncompressed_len: usize,
208 base_rev: Option<Revision>,
234 base_rev: Option<Revision>,
209 }
235 }
210
236
211 impl<'a> RevlogEntry<'a> {
237 impl<'a> RevlogEntry<'a> {
212 /// Extract the data contained in the entry.
238 /// Extract the data contained in the entry.
213 pub fn data(&self) -> Result<Cow<'_, [u8]>, RevlogError> {
239 pub fn data(&self) -> Result<Cow<'_, [u8]>, RevlogError> {
214 if self.bytes.is_empty() {
240 if self.bytes.is_empty() {
215 return Ok(Cow::Borrowed(&[]));
241 return Ok(Cow::Borrowed(&[]));
216 }
242 }
217 match self.bytes[0] {
243 match self.bytes[0] {
218 // Revision data is the entirety of the entry, including this
244 // Revision data is the entirety of the entry, including this
219 // header.
245 // header.
220 b'\0' => Ok(Cow::Borrowed(self.bytes)),
246 b'\0' => Ok(Cow::Borrowed(self.bytes)),
221 // Raw revision data follows.
247 // Raw revision data follows.
222 b'u' => Ok(Cow::Borrowed(&self.bytes[1..])),
248 b'u' => Ok(Cow::Borrowed(&self.bytes[1..])),
223 // zlib (RFC 1950) data.
249 // zlib (RFC 1950) data.
224 b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data())),
250 b'x' => Ok(Cow::Owned(self.uncompressed_zlib_data())),
225 // zstd data.
251 // zstd data.
226 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data())),
252 b'\x28' => Ok(Cow::Owned(self.uncompressed_zstd_data())),
227 format_type => Err(RevlogError::UnknowDataFormat(format_type)),
253 format_type => Err(RevlogError::UnknowDataFormat(format_type)),
228 }
254 }
229 }
255 }
230
256
231 fn uncompressed_zlib_data(&self) -> Vec<u8> {
257 fn uncompressed_zlib_data(&self) -> Vec<u8> {
232 let mut decoder = ZlibDecoder::new(self.bytes);
258 let mut decoder = ZlibDecoder::new(self.bytes);
233 if self.is_delta() {
259 if self.is_delta() {
234 let mut buf = Vec::with_capacity(self.compressed_len);
260 let mut buf = Vec::with_capacity(self.compressed_len);
235 decoder.read_to_end(&mut buf).expect("corrupted zlib data");
261 decoder.read_to_end(&mut buf).expect("corrupted zlib data");
236 buf
262 buf
237 } else {
263 } else {
238 let mut buf = vec![0; self.uncompressed_len];
264 let mut buf = vec![0; self.uncompressed_len];
239 decoder.read_exact(&mut buf).expect("corrupted zlib data");
265 decoder.read_exact(&mut buf).expect("corrupted zlib data");
240 buf
266 buf
241 }
267 }
242 }
268 }
243
269
244 fn uncompressed_zstd_data(&self) -> Vec<u8> {
270 fn uncompressed_zstd_data(&self) -> Vec<u8> {
245 if self.is_delta() {
271 if self.is_delta() {
246 let mut buf = Vec::with_capacity(self.compressed_len);
272 let mut buf = Vec::with_capacity(self.compressed_len);
247 zstd::stream::copy_decode(self.bytes, &mut buf)
273 zstd::stream::copy_decode(self.bytes, &mut buf)
248 .expect("corrupted zstd data");
274 .expect("corrupted zstd data");
249 buf
275 buf
250 } else {
276 } else {
251 let mut buf = vec![0; self.uncompressed_len];
277 let mut buf = vec![0; self.uncompressed_len];
252 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
278 let len = zstd::block::decompress_to_buffer(self.bytes, &mut buf)
253 .expect("corrupted zstd data");
279 .expect("corrupted zstd data");
254 assert_eq!(len, self.uncompressed_len, "corrupted zstd data");
280 assert_eq!(len, self.uncompressed_len, "corrupted zstd data");
255 buf
281 buf
256 }
282 }
257 }
283 }
258
284
259 /// Tell if the entry is a snapshot or a delta
285 /// Tell if the entry is a snapshot or a delta
260 /// (influences on decompression).
286 /// (influences on decompression).
261 fn is_delta(&self) -> bool {
287 fn is_delta(&self) -> bool {
262 self.base_rev.is_some()
288 self.base_rev.is_some()
263 }
289 }
264 }
290 }
265
291
266 /// Value of the inline flag.
292 /// Value of the inline flag.
267 pub fn is_inline(index_bytes: &[u8]) -> bool {
293 pub fn is_inline(index_bytes: &[u8]) -> bool {
268 match &index_bytes[0..=1] {
294 match &index_bytes[0..=1] {
269 [0, 0] | [0, 2] => false,
295 [0, 0] | [0, 2] => false,
270 _ => true,
296 _ => true,
271 }
297 }
272 }
298 }
273
299
274 /// Format version of the revlog.
300 /// Format version of the revlog.
275 pub fn get_version(index_bytes: &[u8]) -> u16 {
301 pub fn get_version(index_bytes: &[u8]) -> u16 {
276 BigEndian::read_u16(&index_bytes[2..=3])
302 BigEndian::read_u16(&index_bytes[2..=3])
277 }
303 }
278
304
279 /// Calculate the hash of a revision given its data and its parents.
305 /// Calculate the hash of a revision given its data and its parents.
280 fn hash(data: &[u8], p1_hash: &[u8], p2_hash: &[u8]) -> Vec<u8> {
306 fn hash(data: &[u8], p1_hash: &[u8], p2_hash: &[u8]) -> Vec<u8> {
281 let mut hasher = Sha1::new();
307 let mut hasher = Sha1::new();
282 let (a, b) = (p1_hash, p2_hash);
308 let (a, b) = (p1_hash, p2_hash);
283 if a > b {
309 if a > b {
284 hasher.input(b);
310 hasher.input(b);
285 hasher.input(a);
311 hasher.input(a);
286 } else {
312 } else {
287 hasher.input(a);
313 hasher.input(a);
288 hasher.input(b);
314 hasher.input(b);
289 }
315 }
290 hasher.input(data);
316 hasher.input(data);
291 let mut hash = vec![0; NODE_BYTES_LENGTH];
317 let mut hash = vec![0; NODE_BYTES_LENGTH];
292 hasher.result(&mut hash);
318 hasher.result(&mut hash);
293 hash
319 hash
294 }
320 }
295
321
296 #[cfg(test)]
322 #[cfg(test)]
297 mod tests {
323 mod tests {
298 use super::*;
324 use super::*;
299
325
300 use super::super::index::IndexEntryBuilder;
326 use super::super::index::IndexEntryBuilder;
301
327
302 #[cfg(test)]
328 #[cfg(test)]
303 pub struct RevlogBuilder {
329 pub struct RevlogBuilder {
304 version: u16,
330 version: u16,
305 is_general_delta: bool,
331 is_general_delta: bool,
306 is_inline: bool,
332 is_inline: bool,
307 offset: usize,
333 offset: usize,
308 index: Vec<Vec<u8>>,
334 index: Vec<Vec<u8>>,
309 data: Vec<Vec<u8>>,
335 data: Vec<Vec<u8>>,
310 }
336 }
311
337
312 #[cfg(test)]
338 #[cfg(test)]
313 impl RevlogBuilder {
339 impl RevlogBuilder {
314 pub fn new() -> Self {
340 pub fn new() -> Self {
315 Self {
341 Self {
316 version: 2,
342 version: 2,
317 is_inline: false,
343 is_inline: false,
318 is_general_delta: true,
344 is_general_delta: true,
319 offset: 0,
345 offset: 0,
320 index: vec![],
346 index: vec![],
321 data: vec![],
347 data: vec![],
322 }
348 }
323 }
349 }
324
350
325 pub fn with_inline(&mut self, value: bool) -> &mut Self {
351 pub fn with_inline(&mut self, value: bool) -> &mut Self {
326 self.is_inline = value;
352 self.is_inline = value;
327 self
353 self
328 }
354 }
329
355
330 pub fn with_general_delta(&mut self, value: bool) -> &mut Self {
356 pub fn with_general_delta(&mut self, value: bool) -> &mut Self {
331 self.is_general_delta = value;
357 self.is_general_delta = value;
332 self
358 self
333 }
359 }
334
360
335 pub fn with_version(&mut self, value: u16) -> &mut Self {
361 pub fn with_version(&mut self, value: u16) -> &mut Self {
336 self.version = value;
362 self.version = value;
337 self
363 self
338 }
364 }
339
365
340 pub fn push(
366 pub fn push(
341 &mut self,
367 &mut self,
342 mut index: IndexEntryBuilder,
368 mut index: IndexEntryBuilder,
343 data: Vec<u8>,
369 data: Vec<u8>,
344 ) -> &mut Self {
370 ) -> &mut Self {
345 if self.index.is_empty() {
371 if self.index.is_empty() {
346 index.is_first(true);
372 index.is_first(true);
347 index.with_general_delta(self.is_general_delta);
373 index.with_general_delta(self.is_general_delta);
348 index.with_inline(self.is_inline);
374 index.with_inline(self.is_inline);
349 index.with_version(self.version);
375 index.with_version(self.version);
350 } else {
376 } else {
351 index.with_offset(self.offset);
377 index.with_offset(self.offset);
352 }
378 }
353 self.index.push(index.build());
379 self.index.push(index.build());
354 self.offset += data.len();
380 self.offset += data.len();
355 self.data.push(data);
381 self.data.push(data);
356 self
382 self
357 }
383 }
358
384
359 pub fn build_inline(&self) -> Vec<u8> {
385 pub fn build_inline(&self) -> Vec<u8> {
360 let mut bytes =
386 let mut bytes =
361 Vec::with_capacity(self.index.len() + self.data.len());
387 Vec::with_capacity(self.index.len() + self.data.len());
362 for (index, data) in self.index.iter().zip(self.data.iter()) {
388 for (index, data) in self.index.iter().zip(self.data.iter()) {
363 bytes.extend(index);
389 bytes.extend(index);
364 bytes.extend(data);
390 bytes.extend(data);
365 }
391 }
366 bytes
392 bytes
367 }
393 }
368 }
394 }
369
395
370 #[test]
396 #[test]
371 fn is_not_inline_when_no_inline_flag_test() {
397 fn is_not_inline_when_no_inline_flag_test() {
372 let bytes = RevlogBuilder::new()
398 let bytes = RevlogBuilder::new()
373 .with_general_delta(false)
399 .with_general_delta(false)
374 .with_inline(false)
400 .with_inline(false)
375 .push(IndexEntryBuilder::new(), vec![])
401 .push(IndexEntryBuilder::new(), vec![])
376 .build_inline();
402 .build_inline();
377
403
378 assert_eq!(is_inline(&bytes), false)
404 assert_eq!(is_inline(&bytes), false)
379 }
405 }
380
406
381 #[test]
407 #[test]
382 fn is_inline_when_inline_flag_test() {
408 fn is_inline_when_inline_flag_test() {
383 let bytes = RevlogBuilder::new()
409 let bytes = RevlogBuilder::new()
384 .with_general_delta(false)
410 .with_general_delta(false)
385 .with_inline(true)
411 .with_inline(true)
386 .push(IndexEntryBuilder::new(), vec![])
412 .push(IndexEntryBuilder::new(), vec![])
387 .build_inline();
413 .build_inline();
388
414
389 assert_eq!(is_inline(&bytes), true)
415 assert_eq!(is_inline(&bytes), true)
390 }
416 }
391
417
392 #[test]
418 #[test]
393 fn is_inline_when_inline_and_generaldelta_flags_test() {
419 fn is_inline_when_inline_and_generaldelta_flags_test() {
394 let bytes = RevlogBuilder::new()
420 let bytes = RevlogBuilder::new()
395 .with_general_delta(true)
421 .with_general_delta(true)
396 .with_inline(true)
422 .with_inline(true)
397 .push(IndexEntryBuilder::new(), vec![])
423 .push(IndexEntryBuilder::new(), vec![])
398 .build_inline();
424 .build_inline();
399
425
400 assert_eq!(is_inline(&bytes), true)
426 assert_eq!(is_inline(&bytes), true)
401 }
427 }
402
428
403 #[test]
429 #[test]
404 fn version_test() {
430 fn version_test() {
405 let bytes = RevlogBuilder::new()
431 let bytes = RevlogBuilder::new()
406 .with_version(1)
432 .with_version(1)
407 .push(IndexEntryBuilder::new(), vec![])
433 .push(IndexEntryBuilder::new(), vec![])
408 .build_inline();
434 .build_inline();
409
435
410 assert_eq!(get_version(&bytes), 1)
436 assert_eq!(get_version(&bytes), 1)
411 }
437 }
412 }
438 }
General Comments 0
You need to be logged in to leave comments. Login now