Show More
@@ -1,105 +1,105 b'' | |||||
1 | // Copyright 2018 Georges Racinet <gracinet@anybox.fr> |
|
1 | // Copyright 2018 Georges Racinet <gracinet@anybox.fr> | |
2 | // |
|
2 | // | |
3 | // This software may be used and distributed according to the terms of the |
|
3 | // This software may be used and distributed according to the terms of the | |
4 | // GNU General Public License version 2 or any later version. |
|
4 | // GNU General Public License version 2 or any later version. | |
5 | mod ancestors; |
|
5 | mod ancestors; | |
6 | pub mod dagops; |
|
6 | pub mod dagops; | |
7 | pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors}; |
|
7 | pub use ancestors::{AncestorsIterator, LazyAncestors, MissingAncestors}; | |
8 | mod dirstate; |
|
8 | mod dirstate; | |
9 | pub mod discovery; |
|
9 | pub mod discovery; | |
10 | pub mod testing; // unconditionally built, for use from integration tests |
|
10 | pub mod testing; // unconditionally built, for use from integration tests | |
11 | pub use dirstate::{ |
|
11 | pub use dirstate::{ | |
12 | dirs_multiset::DirsMultiset, |
|
12 | dirs_multiset::DirsMultiset, | |
13 | parsers::{pack_dirstate, parse_dirstate}, |
|
13 | parsers::{pack_dirstate, parse_dirstate}, | |
14 | CopyVec, CopyVecEntry, DirsIterable, DirstateEntry, DirstateParents, |
|
14 | CopyVec, CopyVecEntry, DirsIterable, DirstateEntry, DirstateParents, | |
15 | DirstateVec, |
|
15 | DirstateVec, | |
16 | }; |
|
16 | }; | |
17 | mod filepatterns; |
|
17 | mod filepatterns; | |
18 | mod utils; |
|
18 | pub mod utils; | |
19 |
|
19 | |||
20 | pub use filepatterns::{ |
|
20 | pub use filepatterns::{ | |
21 | build_single_regex, read_pattern_file, PatternSyntax, PatternTuple, |
|
21 | build_single_regex, read_pattern_file, PatternSyntax, PatternTuple, | |
22 | }; |
|
22 | }; | |
23 |
|
23 | |||
24 | /// Mercurial revision numbers |
|
24 | /// Mercurial revision numbers | |
25 | /// |
|
25 | /// | |
26 | /// As noted in revlog.c, revision numbers are actually encoded in |
|
26 | /// As noted in revlog.c, revision numbers are actually encoded in | |
27 | /// 4 bytes, and are liberally converted to ints, whence the i32 |
|
27 | /// 4 bytes, and are liberally converted to ints, whence the i32 | |
28 | pub type Revision = i32; |
|
28 | pub type Revision = i32; | |
29 |
|
29 | |||
30 | /// Marker expressing the absence of a parent |
|
30 | /// Marker expressing the absence of a parent | |
31 | /// |
|
31 | /// | |
32 | /// Independently of the actual representation, `NULL_REVISION` is guaranteed |
|
32 | /// Independently of the actual representation, `NULL_REVISION` is guaranteed | |
33 | /// to be smaller that all existing revisions. |
|
33 | /// to be smaller that all existing revisions. | |
34 | pub const NULL_REVISION: Revision = -1; |
|
34 | pub const NULL_REVISION: Revision = -1; | |
35 |
|
35 | |||
36 | /// Same as `mercurial.node.wdirrev` |
|
36 | /// Same as `mercurial.node.wdirrev` | |
37 | /// |
|
37 | /// | |
38 | /// This is also equal to `i32::max_value()`, but it's better to spell |
|
38 | /// This is also equal to `i32::max_value()`, but it's better to spell | |
39 | /// it out explicitely, same as in `mercurial.node` |
|
39 | /// it out explicitely, same as in `mercurial.node` | |
40 | pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff; |
|
40 | pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff; | |
41 |
|
41 | |||
42 | /// The simplest expression of what we need of Mercurial DAGs. |
|
42 | /// The simplest expression of what we need of Mercurial DAGs. | |
43 | pub trait Graph { |
|
43 | pub trait Graph { | |
44 | /// Return the two parents of the given `Revision`. |
|
44 | /// Return the two parents of the given `Revision`. | |
45 | /// |
|
45 | /// | |
46 | /// Each of the parents can be independently `NULL_REVISION` |
|
46 | /// Each of the parents can be independently `NULL_REVISION` | |
47 | fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>; |
|
47 | fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>; | |
48 | } |
|
48 | } | |
49 |
|
49 | |||
50 | pub type LineNumber = usize; |
|
50 | pub type LineNumber = usize; | |
51 |
|
51 | |||
52 | #[derive(Clone, Debug, PartialEq)] |
|
52 | #[derive(Clone, Debug, PartialEq)] | |
53 | pub enum GraphError { |
|
53 | pub enum GraphError { | |
54 | ParentOutOfRange(Revision), |
|
54 | ParentOutOfRange(Revision), | |
55 | WorkingDirectoryUnsupported, |
|
55 | WorkingDirectoryUnsupported, | |
56 | } |
|
56 | } | |
57 |
|
57 | |||
58 | #[derive(Clone, Debug, PartialEq)] |
|
58 | #[derive(Clone, Debug, PartialEq)] | |
59 | pub enum DirstateParseError { |
|
59 | pub enum DirstateParseError { | |
60 | TooLittleData, |
|
60 | TooLittleData, | |
61 | Overflow, |
|
61 | Overflow, | |
62 | CorruptedEntry(String), |
|
62 | CorruptedEntry(String), | |
63 | } |
|
63 | } | |
64 |
|
64 | |||
65 | #[derive(Debug, PartialEq)] |
|
65 | #[derive(Debug, PartialEq)] | |
66 | pub enum DirstatePackError { |
|
66 | pub enum DirstatePackError { | |
67 | CorruptedEntry(String), |
|
67 | CorruptedEntry(String), | |
68 | CorruptedParent, |
|
68 | CorruptedParent, | |
69 | BadSize(usize, usize), |
|
69 | BadSize(usize, usize), | |
70 | } |
|
70 | } | |
71 |
|
71 | |||
72 | #[derive(Debug, PartialEq)] |
|
72 | #[derive(Debug, PartialEq)] | |
73 | pub enum DirstateMapError { |
|
73 | pub enum DirstateMapError { | |
74 | PathNotFound(Vec<u8>), |
|
74 | PathNotFound(Vec<u8>), | |
75 | EmptyPath, |
|
75 | EmptyPath, | |
76 | } |
|
76 | } | |
77 |
|
77 | |||
78 | impl From<std::io::Error> for DirstatePackError { |
|
78 | impl From<std::io::Error> for DirstatePackError { | |
79 | fn from(e: std::io::Error) -> Self { |
|
79 | fn from(e: std::io::Error) -> Self { | |
80 | DirstatePackError::CorruptedEntry(e.to_string()) |
|
80 | DirstatePackError::CorruptedEntry(e.to_string()) | |
81 | } |
|
81 | } | |
82 | } |
|
82 | } | |
83 |
|
83 | |||
84 | impl From<std::io::Error> for DirstateParseError { |
|
84 | impl From<std::io::Error> for DirstateParseError { | |
85 | fn from(e: std::io::Error) -> Self { |
|
85 | fn from(e: std::io::Error) -> Self { | |
86 | DirstateParseError::CorruptedEntry(e.to_string()) |
|
86 | DirstateParseError::CorruptedEntry(e.to_string()) | |
87 | } |
|
87 | } | |
88 | } |
|
88 | } | |
89 |
|
89 | |||
90 | #[derive(Debug)] |
|
90 | #[derive(Debug)] | |
91 | pub enum PatternError { |
|
91 | pub enum PatternError { | |
92 | UnsupportedSyntax(String), |
|
92 | UnsupportedSyntax(String), | |
93 | } |
|
93 | } | |
94 |
|
94 | |||
95 | #[derive(Debug)] |
|
95 | #[derive(Debug)] | |
96 | pub enum PatternFileError { |
|
96 | pub enum PatternFileError { | |
97 | IO(std::io::Error), |
|
97 | IO(std::io::Error), | |
98 | Pattern(PatternError, LineNumber), |
|
98 | Pattern(PatternError, LineNumber), | |
99 | } |
|
99 | } | |
100 |
|
100 | |||
101 | impl From<std::io::Error> for PatternFileError { |
|
101 | impl From<std::io::Error> for PatternFileError { | |
102 | fn from(e: std::io::Error) -> Self { |
|
102 | fn from(e: std::io::Error) -> Self { | |
103 | PatternFileError::IO(e) |
|
103 | PatternFileError::IO(e) | |
104 | } |
|
104 | } | |
105 | } |
|
105 | } |
@@ -1,45 +1,76 b'' | |||||
1 | pub mod files; |
|
1 | pub mod files; | |
2 |
|
2 | |||
|
3 | /// Replaces the `from` slice with the `to` slice inside the `buf` slice. | |||
|
4 | /// | |||
|
5 | /// # Examples | |||
|
6 | /// | |||
|
7 | /// ``` | |||
|
8 | /// use crate::hg::utils::replace_slice; | |||
|
9 | /// let mut line = b"I hate writing tests!".to_vec(); | |||
|
10 | /// replace_slice(&mut line, b"hate", b"love"); | |||
|
11 | /// assert_eq!( | |||
|
12 | /// line, | |||
|
13 | /// b"I love writing tests!".to_vec() | |||
|
14 | ///); | |||
|
15 | /// | |||
|
16 | /// ``` | |||
3 | pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T]) |
|
17 | pub fn replace_slice<T>(buf: &mut [T], from: &[T], to: &[T]) | |
4 | where |
|
18 | where | |
5 | T: Clone + PartialEq, |
|
19 | T: Clone + PartialEq, | |
6 | { |
|
20 | { | |
7 | if buf.len() < from.len() || from.len() != to.len() { |
|
21 | assert_eq!(from.len(), to.len()); | |
|
22 | if buf.len() < from.len() { | |||
8 | return; |
|
23 | return; | |
9 | } |
|
24 | } | |
10 | for i in 0..=buf.len() - from.len() { |
|
25 | for i in 0..=buf.len() - from.len() { | |
11 | if buf[i..].starts_with(from) { |
|
26 | if buf[i..].starts_with(from) { | |
12 | buf[i..(i + from.len())].clone_from_slice(to); |
|
27 | buf[i..(i + from.len())].clone_from_slice(to); | |
13 | } |
|
28 | } | |
14 | } |
|
29 | } | |
15 | } |
|
30 | } | |
16 |
|
31 | |||
17 | pub trait SliceExt { |
|
32 | pub trait SliceExt { | |
|
33 | fn trim_end(&self) -> &Self; | |||
|
34 | fn trim_start(&self) -> &Self; | |||
18 | fn trim(&self) -> &Self; |
|
35 | fn trim(&self) -> &Self; | |
19 | fn trim_end(&self) -> &Self; |
|
|||
20 | } |
|
36 | } | |
21 |
|
37 | |||
22 | fn is_not_whitespace(c: &u8) -> bool { |
|
38 | fn is_not_whitespace(c: &u8) -> bool { | |
23 | !(*c as char).is_whitespace() |
|
39 | !(*c as char).is_whitespace() | |
24 | } |
|
40 | } | |
25 |
|
41 | |||
26 | impl SliceExt for [u8] { |
|
42 | impl SliceExt for [u8] { | |
27 | fn trim(&self) -> &[u8] { |
|
|||
28 | if let Some(first) = self.iter().position(is_not_whitespace) { |
|
|||
29 | if let Some(last) = self.iter().rposition(is_not_whitespace) { |
|
|||
30 | &self[first..last + 1] |
|
|||
31 | } else { |
|
|||
32 | unreachable!(); |
|
|||
33 | } |
|
|||
34 | } else { |
|
|||
35 | &[] |
|
|||
36 | } |
|
|||
37 | } |
|
|||
38 | fn trim_end(&self) -> &[u8] { |
|
43 | fn trim_end(&self) -> &[u8] { | |
39 | if let Some(last) = self.iter().rposition(is_not_whitespace) { |
|
44 | if let Some(last) = self.iter().rposition(is_not_whitespace) { | |
40 | &self[..last + 1] |
|
45 | &self[..last + 1] | |
41 | } else { |
|
46 | } else { | |
42 | &[] |
|
47 | &[] | |
43 | } |
|
48 | } | |
44 | } |
|
49 | } | |
|
50 | fn trim_start(&self) -> &[u8] { | |||
|
51 | if let Some(first) = self.iter().position(is_not_whitespace) { | |||
|
52 | &self[first..] | |||
|
53 | } else { | |||
|
54 | &[] | |||
|
55 | } | |||
|
56 | } | |||
|
57 | ||||
|
58 | /// ``` | |||
|
59 | /// use hg::utils::SliceExt; | |||
|
60 | /// assert_eq!( | |||
|
61 | /// b" to trim ".trim(), | |||
|
62 | /// b"to trim" | |||
|
63 | /// ); | |||
|
64 | /// assert_eq!( | |||
|
65 | /// b"to trim ".trim(), | |||
|
66 | /// b"to trim" | |||
|
67 | /// ); | |||
|
68 | /// assert_eq!( | |||
|
69 | /// b" to trim".trim(), | |||
|
70 | /// b"to trim" | |||
|
71 | /// ); | |||
|
72 | /// ``` | |||
|
73 | fn trim(&self) -> &[u8] { | |||
|
74 | self.trim_start().trim_end() | |||
|
75 | } | |||
45 | } |
|
76 | } |
General Comments 0
You need to be logged in to leave comments.
Login now