##// END OF EJS Templates
rust-dirstate-status: add first Rust implementation of `dirstate.status`...
Raphaël Gomès -
r43565:99394e6c default
parent child Browse files
Show More
@@ -0,0 +1,248 b''
1 // status.rs
2 //
3 // Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
4 //
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.
7
8 //! Rust implementation of dirstate.status (dirstate.py).
9 //! It is currently missing a lot of functionality compared to the Python one
10 //! and will only be triggered in narrow cases.
11
12 use crate::utils::files::HgMetadata;
13 use crate::utils::hg_path::{hg_path_to_path_buf, HgPath, HgPathBuf};
14 use crate::{DirstateEntry, DirstateMap, EntryState};
15 use rayon::prelude::*;
16 use std::collections::HashMap;
17 use std::fs::Metadata;
18 use std::path::Path;
19
20 /// Get stat data about the files explicitly specified by match.
21 /// TODO subrepos
22 fn walk_explicit(
23 files: &[impl AsRef<HgPath> + Sync],
24 dmap: &DirstateMap,
25 root_dir: impl AsRef<Path> + Sync,
26 ) -> std::io::Result<HashMap<HgPathBuf, Option<HgMetadata>>> {
27 let mut results = HashMap::new();
28
29 // A tuple of the normalized filename and the `Result` of the call to
30 // `symlink_metadata` for separate handling.
31 type WalkTuple<'a> = (&'a HgPath, std::io::Result<Metadata>);
32
33 let stats_res: std::io::Result<Vec<WalkTuple>> = files
34 .par_iter()
35 .map(|filename| {
36 // TODO normalization
37 let normalized = filename.as_ref();
38
39 let target_filename =
40 root_dir.as_ref().join(hg_path_to_path_buf(normalized)?);
41
42 Ok((normalized, target_filename.symlink_metadata()))
43 })
44 .collect();
45
46 for res in stats_res? {
47 match res {
48 (normalized, Ok(stat)) => {
49 if stat.is_file() {
50 results.insert(
51 normalized.to_owned(),
52 Some(HgMetadata::from_metadata(stat)),
53 );
54 } else {
55 if dmap.contains_key(normalized) {
56 results.insert(normalized.to_owned(), None);
57 }
58 }
59 }
60 (normalized, Err(_)) => {
61 if dmap.contains_key(normalized) {
62 results.insert(normalized.to_owned(), None);
63 }
64 }
65 };
66 }
67
68 Ok(results)
69 }
70
71 // Stat all entries in the `DirstateMap` and return their new metadata.
72 pub fn stat_dmap_entries(
73 dmap: &DirstateMap,
74 results: &HashMap<HgPathBuf, Option<HgMetadata>>,
75 root_dir: impl AsRef<Path> + Sync,
76 ) -> std::io::Result<Vec<(HgPathBuf, Option<HgMetadata>)>> {
77 dmap.par_iter()
78 .filter_map(
79 // Getting file metadata is costly, so we don't do it if the
80 // file is already present in the results, hence `filter_map`
81 |(filename, _)| -> Option<
82 std::io::Result<(HgPathBuf, Option<HgMetadata>)>
83 > {
84 if results.contains_key(filename) {
85 return None;
86 }
87 let meta = match hg_path_to_path_buf(filename) {
88 Ok(p) => root_dir.as_ref().join(p).symlink_metadata(),
89 Err(e) => return Some(Err(e.into())),
90 };
91
92 Some(match meta {
93 Ok(ref m)
94 if !(m.file_type().is_file()
95 || m.file_type().is_symlink()) =>
96 {
97 Ok((filename.to_owned(), None))
98 }
99 Ok(m) => Ok((
100 filename.to_owned(),
101 Some(HgMetadata::from_metadata(m)),
102 )),
103 Err(ref e)
104 if e.kind() == std::io::ErrorKind::NotFound
105 || e.raw_os_error() == Some(20) =>
106 {
107 // Rust does not yet have an `ErrorKind` for
108 // `NotADirectory` (errno 20)
109 // It happens if the dirstate contains `foo/bar` and
110 // foo is not a directory
111 Ok((filename.to_owned(), None))
112 }
113 Err(e) => Err(e),
114 })
115 },
116 )
117 .collect()
118 }
119
120 pub struct StatusResult {
121 pub modified: Vec<HgPathBuf>,
122 pub added: Vec<HgPathBuf>,
123 pub removed: Vec<HgPathBuf>,
124 pub deleted: Vec<HgPathBuf>,
125 pub clean: Vec<HgPathBuf>,
126 // TODO ignored
127 // TODO unknown
128 }
129
130 fn build_response(
131 dmap: &DirstateMap,
132 list_clean: bool,
133 last_normal_time: i64,
134 check_exec: bool,
135 results: HashMap<HgPathBuf, Option<HgMetadata>>,
136 ) -> (Vec<HgPathBuf>, StatusResult) {
137 let mut lookup = vec![];
138 let mut modified = vec![];
139 let mut added = vec![];
140 let mut removed = vec![];
141 let mut deleted = vec![];
142 let mut clean = vec![];
143
144 for (filename, metadata_option) in results.into_iter() {
145 let DirstateEntry {
146 state,
147 mode,
148 mtime,
149 size,
150 } = match dmap.get(&filename) {
151 None => {
152 continue;
153 }
154 Some(e) => *e,
155 };
156
157 match metadata_option {
158 None => {
159 match state {
160 EntryState::Normal
161 | EntryState::Merged
162 | EntryState::Added => deleted.push(filename),
163 EntryState::Removed => removed.push(filename),
164 _ => {}
165 };
166 }
167 Some(HgMetadata {
168 st_mode,
169 st_size,
170 st_mtime,
171 ..
172 }) => {
173 match state {
174 EntryState::Normal => {
175 // Dates and times that are outside the 31-bit signed
176 // range are compared modulo 2^31. This should prevent
177 // it from behaving badly with very large files or
178 // corrupt dates while still having a high probability
179 // of detecting changes. (issue2608)
180 let range_mask = 0x7fffffff;
181
182 let size_changed = (size != st_size as i32)
183 && size != (st_size as i32 & range_mask);
184 let mode_changed = (mode ^ st_mode as i32) & 0o100
185 != 0o000
186 && check_exec;
187 if size >= 0
188 && (size_changed || mode_changed)
189 || size == -2 // other parent
190 || dmap.copy_map.contains_key(&filename)
191 {
192 modified.push(filename);
193 } else if mtime != st_mtime as i32
194 && mtime != (st_mtime as i32 & range_mask)
195 {
196 lookup.push(filename);
197 } else if st_mtime == last_normal_time {
198 // the file may have just been marked as normal and
199 // it may have changed in the same second without
200 // changing its size. This can happen if we quickly
201 // do multiple commits. Force lookup, so we don't
202 // miss such a racy file change.
203 lookup.push(filename);
204 } else if list_clean {
205 clean.push(filename);
206 }
207 }
208 EntryState::Merged => modified.push(filename),
209 EntryState::Added => added.push(filename),
210 EntryState::Removed => removed.push(filename),
211 EntryState::Unknown => {}
212 }
213 }
214 }
215 }
216
217 (
218 lookup,
219 StatusResult {
220 modified,
221 added,
222 removed,
223 deleted,
224 clean,
225 },
226 )
227 }
228
229 pub fn status(
230 dmap: &DirstateMap,
231 root_dir: impl AsRef<Path> + Sync + Copy,
232 files: &[impl AsRef<HgPath> + Sync],
233 list_clean: bool,
234 last_normal_time: i64,
235 check_exec: bool,
236 ) -> std::io::Result<(Vec<HgPathBuf>, StatusResult)> {
237 let mut results = walk_explicit(files, &dmap, root_dir)?;
238
239 results.extend(stat_dmap_entries(&dmap, &results, root_dir)?);
240
241 Ok(build_response(
242 &dmap,
243 list_clean,
244 last_normal_time,
245 check_exec,
246 results,
247 ))
248 }
@@ -1,334 +1,440 b''
1 # This file is automatically @generated by Cargo.
1 # This file is automatically @generated by Cargo.
2 # It is not intended for manual editing.
2 # It is not intended for manual editing.
3 [[package]]
3 [[package]]
4 name = "aho-corasick"
4 name = "aho-corasick"
5 version = "0.6.9"
5 version = "0.7.6"
6 source = "registry+https://github.com/rust-lang/crates.io-index"
6 source = "registry+https://github.com/rust-lang/crates.io-index"
7 dependencies = [
7 dependencies = [
8 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
8 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
9 ]
10
11 [[package]]
12 name = "arrayvec"
13 version = "0.4.12"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
15 dependencies = [
16 "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
9 ]
17 ]
10
18
11 [[package]]
19 [[package]]
12 name = "autocfg"
20 name = "autocfg"
13 version = "0.1.2"
21 version = "0.1.6"
14 source = "registry+https://github.com/rust-lang/crates.io-index"
22 source = "registry+https://github.com/rust-lang/crates.io-index"
15
23
16 [[package]]
24 [[package]]
17 name = "bitflags"
25 name = "bitflags"
18 version = "1.0.4"
26 version = "1.2.1"
19 source = "registry+https://github.com/rust-lang/crates.io-index"
27 source = "registry+https://github.com/rust-lang/crates.io-index"
20
28
21 [[package]]
29 [[package]]
22 name = "byteorder"
30 name = "byteorder"
23 version = "1.3.1"
31 version = "1.3.2"
32 source = "registry+https://github.com/rust-lang/crates.io-index"
33
34 [[package]]
35 name = "cfg-if"
36 version = "0.1.10"
24 source = "registry+https://github.com/rust-lang/crates.io-index"
37 source = "registry+https://github.com/rust-lang/crates.io-index"
25
38
26 [[package]]
39 [[package]]
27 name = "cloudabi"
40 name = "cloudabi"
28 version = "0.0.3"
41 version = "0.0.3"
29 source = "registry+https://github.com/rust-lang/crates.io-index"
42 source = "registry+https://github.com/rust-lang/crates.io-index"
30 dependencies = [
43 dependencies = [
31 "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
44 "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
32 ]
45 ]
33
46
34 [[package]]
47 [[package]]
35 name = "cpython"
48 name = "cpython"
36 version = "0.3.0"
49 version = "0.3.0"
37 source = "registry+https://github.com/rust-lang/crates.io-index"
50 source = "registry+https://github.com/rust-lang/crates.io-index"
38 dependencies = [
51 dependencies = [
39 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
52 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
40 "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
53 "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
41 "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
54 "python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
42 "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
55 "python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
43 ]
56 ]
44
57
45 [[package]]
58 [[package]]
59 name = "crossbeam-deque"
60 version = "0.7.1"
61 source = "registry+https://github.com/rust-lang/crates.io-index"
62 dependencies = [
63 "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
64 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
65 ]
66
67 [[package]]
68 name = "crossbeam-epoch"
69 version = "0.7.2"
70 source = "registry+https://github.com/rust-lang/crates.io-index"
71 dependencies = [
72 "arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
73 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
74 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
75 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
76 "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
77 "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
78 ]
79
80 [[package]]
81 name = "crossbeam-queue"
82 version = "0.1.2"
83 source = "registry+https://github.com/rust-lang/crates.io-index"
84 dependencies = [
85 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
86 ]
87
88 [[package]]
89 name = "crossbeam-utils"
90 version = "0.6.6"
91 source = "registry+https://github.com/rust-lang/crates.io-index"
92 dependencies = [
93 "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
94 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
95 ]
96
97 [[package]]
98 name = "either"
99 version = "1.5.3"
100 source = "registry+https://github.com/rust-lang/crates.io-index"
101
102 [[package]]
46 name = "fuchsia-cprng"
103 name = "fuchsia-cprng"
47 version = "0.1.0"
104 version = "0.1.1"
48 source = "registry+https://github.com/rust-lang/crates.io-index"
105 source = "registry+https://github.com/rust-lang/crates.io-index"
49
106
50 [[package]]
107 [[package]]
51 name = "hg-core"
108 name = "hg-core"
52 version = "0.1.0"
109 version = "0.1.0"
53 dependencies = [
110 dependencies = [
54 "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
111 "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
55 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
112 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
56 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
113 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
57 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
114 "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
58 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
115 "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
59 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
116 "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
117 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
60 ]
118 ]
61
119
62 [[package]]
120 [[package]]
63 name = "hg-cpython"
121 name = "hg-cpython"
64 version = "0.1.0"
122 version = "0.1.0"
65 dependencies = [
123 dependencies = [
66 "cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
124 "cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
67 "hg-core 0.1.0",
125 "hg-core 0.1.0",
68 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
126 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
69 ]
127 ]
70
128
71 [[package]]
129 [[package]]
72 name = "hgdirectffi"
130 name = "hgdirectffi"
73 version = "0.1.0"
131 version = "0.1.0"
74 dependencies = [
132 dependencies = [
75 "hg-core 0.1.0",
133 "hg-core 0.1.0",
76 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
134 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
77 ]
135 ]
78
136
79 [[package]]
137 [[package]]
80 name = "lazy_static"
138 name = "lazy_static"
81 version = "1.3.0"
139 version = "1.4.0"
82 source = "registry+https://github.com/rust-lang/crates.io-index"
140 source = "registry+https://github.com/rust-lang/crates.io-index"
83
141
84 [[package]]
142 [[package]]
85 name = "libc"
143 name = "libc"
86 version = "0.2.45"
144 version = "0.2.64"
87 source = "registry+https://github.com/rust-lang/crates.io-index"
145 source = "registry+https://github.com/rust-lang/crates.io-index"
88
146
89 [[package]]
147 [[package]]
90 name = "memchr"
148 name = "memchr"
91 version = "2.2.0"
149 version = "2.2.1"
150 source = "registry+https://github.com/rust-lang/crates.io-index"
151
152 [[package]]
153 name = "memoffset"
154 version = "0.5.1"
155 source = "registry+https://github.com/rust-lang/crates.io-index"
156 dependencies = [
157 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
158 ]
159
160 [[package]]
161 name = "nodrop"
162 version = "0.1.14"
92 source = "registry+https://github.com/rust-lang/crates.io-index"
163 source = "registry+https://github.com/rust-lang/crates.io-index"
93
164
94 [[package]]
165 [[package]]
95 name = "num-traits"
166 name = "num-traits"
96 version = "0.2.6"
167 version = "0.2.8"
97 source = "registry+https://github.com/rust-lang/crates.io-index"
168 source = "registry+https://github.com/rust-lang/crates.io-index"
169 dependencies = [
170 "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
171 ]
172
173 [[package]]
174 name = "num_cpus"
175 version = "1.10.1"
176 source = "registry+https://github.com/rust-lang/crates.io-index"
177 dependencies = [
178 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
179 ]
98
180
99 [[package]]
181 [[package]]
100 name = "python27-sys"
182 name = "python27-sys"
101 version = "0.3.0"
183 version = "0.3.0"
102 source = "registry+https://github.com/rust-lang/crates.io-index"
184 source = "registry+https://github.com/rust-lang/crates.io-index"
103 dependencies = [
185 dependencies = [
104 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
186 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
105 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
187 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
106 ]
188 ]
107
189
108 [[package]]
190 [[package]]
109 name = "python3-sys"
191 name = "python3-sys"
110 version = "0.3.0"
192 version = "0.3.0"
111 source = "registry+https://github.com/rust-lang/crates.io-index"
193 source = "registry+https://github.com/rust-lang/crates.io-index"
112 dependencies = [
194 dependencies = [
113 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
195 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
114 "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
196 "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
115 ]
197 ]
116
198
117 [[package]]
199 [[package]]
118 name = "rand"
200 name = "rand"
119 version = "0.6.5"
201 version = "0.6.5"
120 source = "registry+https://github.com/rust-lang/crates.io-index"
202 source = "registry+https://github.com/rust-lang/crates.io-index"
121 dependencies = [
203 dependencies = [
122 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
204 "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
123 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
205 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
124 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
206 "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
125 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
207 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
126 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
208 "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
127 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
209 "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
128 "rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
210 "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
129 "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
211 "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
130 "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
212 "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
131 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
213 "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
132 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
214 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
133 ]
215 ]
134
216
135 [[package]]
217 [[package]]
136 name = "rand_chacha"
218 name = "rand_chacha"
137 version = "0.1.1"
219 version = "0.1.1"
138 source = "registry+https://github.com/rust-lang/crates.io-index"
220 source = "registry+https://github.com/rust-lang/crates.io-index"
139 dependencies = [
221 dependencies = [
140 "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
222 "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
141 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
223 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
142 ]
224 ]
143
225
144 [[package]]
226 [[package]]
145 name = "rand_core"
227 name = "rand_core"
146 version = "0.3.1"
228 version = "0.3.1"
147 source = "registry+https://github.com/rust-lang/crates.io-index"
229 source = "registry+https://github.com/rust-lang/crates.io-index"
148 dependencies = [
230 dependencies = [
149 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
231 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
150 ]
232 ]
151
233
152 [[package]]
234 [[package]]
153 name = "rand_core"
235 name = "rand_core"
154 version = "0.4.0"
236 version = "0.4.2"
155 source = "registry+https://github.com/rust-lang/crates.io-index"
237 source = "registry+https://github.com/rust-lang/crates.io-index"
156
238
157 [[package]]
239 [[package]]
158 name = "rand_hc"
240 name = "rand_hc"
159 version = "0.1.0"
241 version = "0.1.0"
160 source = "registry+https://github.com/rust-lang/crates.io-index"
242 source = "registry+https://github.com/rust-lang/crates.io-index"
161 dependencies = [
243 dependencies = [
162 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
244 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
163 ]
245 ]
164
246
165 [[package]]
247 [[package]]
166 name = "rand_isaac"
248 name = "rand_isaac"
167 version = "0.1.1"
249 version = "0.1.1"
168 source = "registry+https://github.com/rust-lang/crates.io-index"
250 source = "registry+https://github.com/rust-lang/crates.io-index"
169 dependencies = [
251 dependencies = [
170 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
252 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
171 ]
253 ]
172
254
173 [[package]]
255 [[package]]
174 name = "rand_jitter"
256 name = "rand_jitter"
175 version = "0.1.2"
257 version = "0.1.4"
176 source = "registry+https://github.com/rust-lang/crates.io-index"
258 source = "registry+https://github.com/rust-lang/crates.io-index"
177 dependencies = [
259 dependencies = [
178 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
260 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
179 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
261 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
180 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
262 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
181 ]
263 ]
182
264
183 [[package]]
265 [[package]]
184 name = "rand_os"
266 name = "rand_os"
185 version = "0.1.2"
267 version = "0.1.3"
186 source = "registry+https://github.com/rust-lang/crates.io-index"
268 source = "registry+https://github.com/rust-lang/crates.io-index"
187 dependencies = [
269 dependencies = [
188 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
270 "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
189 "fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
271 "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
190 "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
272 "libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
191 "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
273 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
192 "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
274 "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
193 "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
275 "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
194 ]
276 ]
195
277
196 [[package]]
278 [[package]]
197 name = "rand_pcg"
279 name = "rand_pcg"
198 version = "0.1.1"
280 version = "0.1.2"
199 source = "registry+https://github.com/rust-lang/crates.io-index"
281 source = "registry+https://github.com/rust-lang/crates.io-index"
200 dependencies = [
282 dependencies = [
201 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
283 "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
202 "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
284 "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
203 ]
285 ]
204
286
205 [[package]]
287 [[package]]
206 name = "rand_xorshift"
288 name = "rand_xorshift"
207 version = "0.1.1"
289 version = "0.1.1"
208 source = "registry+https://github.com/rust-lang/crates.io-index"
290 source = "registry+https://github.com/rust-lang/crates.io-index"
209 dependencies = [
291 dependencies = [
210 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
292 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
211 ]
293 ]
212
294
213 [[package]]
295 [[package]]
296 name = "rayon"
297 version = "1.2.0"
298 source = "registry+https://github.com/rust-lang/crates.io-index"
299 dependencies = [
300 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
301 "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
302 "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
303 ]
304
305 [[package]]
306 name = "rayon-core"
307 version = "1.6.0"
308 source = "registry+https://github.com/rust-lang/crates.io-index"
309 dependencies = [
310 "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
311 "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
312 "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
313 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
314 "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
315 ]
316
317 [[package]]
214 name = "rdrand"
318 name = "rdrand"
215 version = "0.4.0"
319 version = "0.4.0"
216 source = "registry+https://github.com/rust-lang/crates.io-index"
320 source = "registry+https://github.com/rust-lang/crates.io-index"
217 dependencies = [
321 dependencies = [
218 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
322 "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
219 ]
323 ]
220
324
221 [[package]]
325 [[package]]
222 name = "regex"
326 name = "regex"
223 version = "1.1.0"
327 version = "1.3.1"
224 source = "registry+https://github.com/rust-lang/crates.io-index"
328 source = "registry+https://github.com/rust-lang/crates.io-index"
225 dependencies = [
329 dependencies = [
226 "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
330 "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
227 "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
331 "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
228 "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
332 "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
229 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
333 "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
230 "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
231 ]
334 ]
232
335
233 [[package]]
336 [[package]]
234 name = "regex-syntax"
337 name = "regex-syntax"
235 version = "0.6.4"
338 version = "0.6.12"
236 source = "registry+https://github.com/rust-lang/crates.io-index"
339 source = "registry+https://github.com/rust-lang/crates.io-index"
237 dependencies = [
238 "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
239 ]
240
340
241 [[package]]
341 [[package]]
242 name = "rustc_version"
342 name = "rustc_version"
243 version = "0.2.3"
343 version = "0.2.3"
244 source = "registry+https://github.com/rust-lang/crates.io-index"
344 source = "registry+https://github.com/rust-lang/crates.io-index"
245 dependencies = [
345 dependencies = [
246 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
346 "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
247 ]
347 ]
248
348
249 [[package]]
349 [[package]]
350 name = "scopeguard"
351 version = "1.0.0"
352 source = "registry+https://github.com/rust-lang/crates.io-index"
353
354 [[package]]
250 name = "semver"
355 name = "semver"
251 version = "0.9.0"
356 version = "0.9.0"
252 source = "registry+https://github.com/rust-lang/crates.io-index"
357 source = "registry+https://github.com/rust-lang/crates.io-index"
253 dependencies = [
358 dependencies = [
254 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
359 "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
255 ]
360 ]
256
361
257 [[package]]
362 [[package]]
258 name = "semver-parser"
363 name = "semver-parser"
259 version = "0.7.0"
364 version = "0.7.0"
260 source = "registry+https://github.com/rust-lang/crates.io-index"
365 source = "registry+https://github.com/rust-lang/crates.io-index"
261
366
262 [[package]]
367 [[package]]
263 name = "thread_local"
368 name = "thread_local"
264 version = "0.3.6"
369 version = "0.3.6"
265 source = "registry+https://github.com/rust-lang/crates.io-index"
370 source = "registry+https://github.com/rust-lang/crates.io-index"
266 dependencies = [
371 dependencies = [
267 "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
372 "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
268 ]
373 ]
269
374
270 [[package]]
375 [[package]]
271 name = "ucd-util"
272 version = "0.1.3"
273 source = "registry+https://github.com/rust-lang/crates.io-index"
274
275 [[package]]
276 name = "utf8-ranges"
277 version = "1.0.2"
278 source = "registry+https://github.com/rust-lang/crates.io-index"
279
280 [[package]]
281 name = "winapi"
376 name = "winapi"
282 version = "0.3.6"
377 version = "0.3.8"
283 source = "registry+https://github.com/rust-lang/crates.io-index"
378 source = "registry+https://github.com/rust-lang/crates.io-index"
284 dependencies = [
379 dependencies = [
285 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
380 "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
286 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
381 "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
287 ]
382 ]
288
383
289 [[package]]
384 [[package]]
290 name = "winapi-i686-pc-windows-gnu"
385 name = "winapi-i686-pc-windows-gnu"
291 version = "0.4.0"
386 version = "0.4.0"
292 source = "registry+https://github.com/rust-lang/crates.io-index"
387 source = "registry+https://github.com/rust-lang/crates.io-index"
293
388
294 [[package]]
389 [[package]]
295 name = "winapi-x86_64-pc-windows-gnu"
390 name = "winapi-x86_64-pc-windows-gnu"
296 version = "0.4.0"
391 version = "0.4.0"
297 source = "registry+https://github.com/rust-lang/crates.io-index"
392 source = "registry+https://github.com/rust-lang/crates.io-index"
298
393
299 [metadata]
394 [metadata]
300 "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e"
395 "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
301 "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
396 "checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
302 "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
397 "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
303 "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
398 "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
399 "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
400 "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
304 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
401 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
305 "checksum cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85532c648315aeb0829ad216a6a29aa3212cf9319bc7f6daf1404aa0bdd1485f"
402 "checksum cpython 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "85532c648315aeb0829ad216a6a29aa3212cf9319bc7f6daf1404aa0bdd1485f"
306 "checksum fuchsia-cprng 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "81f7f8eb465745ea9b02e2704612a9946a59fa40572086c6fd49d6ddcf30bf31"
403 "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
307 "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14"
404 "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
308 "checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74"
405 "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
309 "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39"
406 "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
310 "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
407 "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
408 "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
409 "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
410 "checksum libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)" = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c"
411 "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
412 "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
413 "checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
414 "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
415 "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
311 "checksum python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "372555e88a6bc8109eb641380240dc8d25a128fc48363ec9075664daadffdd5b"
416 "checksum python27-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "372555e88a6bc8109eb641380240dc8d25a128fc48363ec9075664daadffdd5b"
312 "checksum python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a8ebed3f1201fda179f3960609dbbc10cd8c75e9f2afcb03788278f367d8ea"
417 "checksum python3-sys 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f3a8ebed3f1201fda179f3960609dbbc10cd8c75e9f2afcb03788278f367d8ea"
313 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
418 "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
314 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
419 "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef"
315 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
420 "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
316 "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0"
421 "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc"
317 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
422 "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4"
318 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
423 "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08"
319 "checksum rand_jitter 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "080723c6145e37503a2224f801f252e14ac5531cb450f4502698542d188cb3c0"
424 "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
320 "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
425 "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
321 "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05"
426 "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44"
322 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
427 "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c"
428 "checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123"
429 "checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b"
323 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
430 "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2"
324 "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f"
431 "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd"
325 "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1"
432 "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
326 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
433 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
434 "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
327 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
435 "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
328 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
436 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
329 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
437 "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
330 "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86"
438 "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
331 "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
332 "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
333 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
439 "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
334 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
440 "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
@@ -1,17 +1,18 b''
1 [package]
1 [package]
2 name = "hg-core"
2 name = "hg-core"
3 version = "0.1.0"
3 version = "0.1.0"
4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
4 authors = ["Georges Racinet <gracinet@anybox.fr>"]
5 description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)"
5 description = "Mercurial pure Rust core library, with no assumption on Python bindings (FFI)"
6 edition = "2018"
6 edition = "2018"
7
7
8 [lib]
8 [lib]
9 name = "hg"
9 name = "hg"
10
10
11 [dependencies]
11 [dependencies]
12 byteorder = "1.3.1"
12 byteorder = "1.3.1"
13 lazy_static = "1.3.0"
13 lazy_static = "1.3.0"
14 memchr = "2.2.0"
14 memchr = "2.2.0"
15 rand = "0.6.5"
15 rand = "0.6.5"
16 rand_pcg = "0.1.1"
16 rand_pcg = "0.1.1"
17 regex = "1.1.0"
17 regex = "1.1.0"
18 rayon = "1.2.0"
@@ -1,76 +1,77 b''
1 // dirstate module
1 // dirstate module
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 use crate::{utils::hg_path::HgPathBuf, DirstateParseError};
8 use crate::{utils::hg_path::HgPathBuf, DirstateParseError};
9 use std::collections::hash_map;
9 use std::collections::hash_map;
10 use std::collections::HashMap;
10 use std::collections::HashMap;
11 use std::convert::TryFrom;
11 use std::convert::TryFrom;
12
12
13 pub mod dirs_multiset;
13 pub mod dirs_multiset;
14 pub mod dirstate_map;
14 pub mod dirstate_map;
15 pub mod parsers;
15 pub mod parsers;
16 pub mod status;
16
17
17 #[derive(Debug, PartialEq, Clone)]
18 #[derive(Debug, PartialEq, Clone)]
18 pub struct DirstateParents {
19 pub struct DirstateParents {
19 pub p1: [u8; 20],
20 pub p1: [u8; 20],
20 pub p2: [u8; 20],
21 pub p2: [u8; 20],
21 }
22 }
22
23
23 /// The C implementation uses all signed types. This will be an issue
24 /// The C implementation uses all signed types. This will be an issue
24 /// either when 4GB+ source files are commonplace or in 2038, whichever
25 /// either when 4GB+ source files are commonplace or in 2038, whichever
25 /// comes first.
26 /// comes first.
26 #[derive(Debug, PartialEq, Copy, Clone)]
27 #[derive(Debug, PartialEq, Copy, Clone)]
27 pub struct DirstateEntry {
28 pub struct DirstateEntry {
28 pub state: EntryState,
29 pub state: EntryState,
29 pub mode: i32,
30 pub mode: i32,
30 pub mtime: i32,
31 pub mtime: i32,
31 pub size: i32,
32 pub size: i32,
32 }
33 }
33
34
34 pub type StateMap = HashMap<HgPathBuf, DirstateEntry>;
35 pub type StateMap = HashMap<HgPathBuf, DirstateEntry>;
35 pub type StateMapIter<'a> = hash_map::Iter<'a, HgPathBuf, DirstateEntry>;
36 pub type StateMapIter<'a> = hash_map::Iter<'a, HgPathBuf, DirstateEntry>;
36 pub type CopyMap = HashMap<HgPathBuf, HgPathBuf>;
37 pub type CopyMap = HashMap<HgPathBuf, HgPathBuf>;
37 pub type CopyMapIter<'a> = hash_map::Iter<'a, HgPathBuf, HgPathBuf>;
38 pub type CopyMapIter<'a> = hash_map::Iter<'a, HgPathBuf, HgPathBuf>;
38
39
39 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
40 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
40 pub enum EntryState {
41 pub enum EntryState {
41 Normal,
42 Normal,
42 Added,
43 Added,
43 Removed,
44 Removed,
44 Merged,
45 Merged,
45 Unknown,
46 Unknown,
46 }
47 }
47
48
48 impl TryFrom<u8> for EntryState {
49 impl TryFrom<u8> for EntryState {
49 type Error = DirstateParseError;
50 type Error = DirstateParseError;
50
51
51 fn try_from(value: u8) -> Result<Self, Self::Error> {
52 fn try_from(value: u8) -> Result<Self, Self::Error> {
52 match value {
53 match value {
53 b'n' => Ok(EntryState::Normal),
54 b'n' => Ok(EntryState::Normal),
54 b'a' => Ok(EntryState::Added),
55 b'a' => Ok(EntryState::Added),
55 b'r' => Ok(EntryState::Removed),
56 b'r' => Ok(EntryState::Removed),
56 b'm' => Ok(EntryState::Merged),
57 b'm' => Ok(EntryState::Merged),
57 b'?' => Ok(EntryState::Unknown),
58 b'?' => Ok(EntryState::Unknown),
58 _ => Err(DirstateParseError::CorruptedEntry(format!(
59 _ => Err(DirstateParseError::CorruptedEntry(format!(
59 "Incorrect entry state {}",
60 "Incorrect entry state {}",
60 value
61 value
61 ))),
62 ))),
62 }
63 }
63 }
64 }
64 }
65 }
65
66
66 impl Into<u8> for EntryState {
67 impl Into<u8> for EntryState {
67 fn into(self) -> u8 {
68 fn into(self) -> u8 {
68 match self {
69 match self {
69 EntryState::Normal => b'n',
70 EntryState::Normal => b'n',
70 EntryState::Added => b'a',
71 EntryState::Added => b'a',
71 EntryState::Removed => b'r',
72 EntryState::Removed => b'r',
72 EntryState::Merged => b'm',
73 EntryState::Merged => b'm',
73 EntryState::Unknown => b'?',
74 EntryState::Unknown => b'?',
74 }
75 }
75 }
76 }
76 }
77 }
@@ -1,150 +1,151 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, DirsMultisetIter},
12 dirs_multiset::{DirsMultiset, DirsMultisetIter},
13 dirstate_map::DirstateMap,
13 dirstate_map::DirstateMap,
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
14 parsers::{pack_dirstate, parse_dirstate, PARENT_SIZE},
15 status::status,
15 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
16 CopyMap, CopyMapIter, DirstateEntry, DirstateParents, EntryState,
16 StateMap, StateMapIter,
17 StateMap, StateMapIter,
17 };
18 };
18 mod filepatterns;
19 mod filepatterns;
19 pub mod utils;
20 pub mod utils;
20
21
21 use crate::utils::hg_path::HgPathBuf;
22 use crate::utils::hg_path::HgPathBuf;
22 pub use filepatterns::{
23 pub use filepatterns::{
23 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
24 build_single_regex, read_pattern_file, PatternSyntax, PatternTuple,
24 };
25 };
25
26
26 /// Mercurial revision numbers
27 /// Mercurial revision numbers
27 ///
28 ///
28 /// As noted in revlog.c, revision numbers are actually encoded in
29 /// As noted in revlog.c, revision numbers are actually encoded in
29 /// 4 bytes, and are liberally converted to ints, whence the i32
30 /// 4 bytes, and are liberally converted to ints, whence the i32
30 pub type Revision = i32;
31 pub type Revision = i32;
31
32
32 /// Marker expressing the absence of a parent
33 /// Marker expressing the absence of a parent
33 ///
34 ///
34 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
35 /// Independently of the actual representation, `NULL_REVISION` is guaranteed
35 /// to be smaller that all existing revisions.
36 /// to be smaller that all existing revisions.
36 pub const NULL_REVISION: Revision = -1;
37 pub const NULL_REVISION: Revision = -1;
37
38
38 /// Same as `mercurial.node.wdirrev`
39 /// Same as `mercurial.node.wdirrev`
39 ///
40 ///
40 /// This is also equal to `i32::max_value()`, but it's better to spell
41 /// This is also equal to `i32::max_value()`, but it's better to spell
41 /// it out explicitely, same as in `mercurial.node`
42 /// it out explicitely, same as in `mercurial.node`
42 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
43 pub const WORKING_DIRECTORY_REVISION: Revision = 0x7fffffff;
43
44
44 /// The simplest expression of what we need of Mercurial DAGs.
45 /// The simplest expression of what we need of Mercurial DAGs.
45 pub trait Graph {
46 pub trait Graph {
46 /// Return the two parents of the given `Revision`.
47 /// Return the two parents of the given `Revision`.
47 ///
48 ///
48 /// Each of the parents can be independently `NULL_REVISION`
49 /// Each of the parents can be independently `NULL_REVISION`
49 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
50 fn parents(&self, rev: Revision) -> Result<[Revision; 2], GraphError>;
50 }
51 }
51
52
52 pub type LineNumber = usize;
53 pub type LineNumber = usize;
53
54
54 #[derive(Clone, Debug, PartialEq)]
55 #[derive(Clone, Debug, PartialEq)]
55 pub enum GraphError {
56 pub enum GraphError {
56 ParentOutOfRange(Revision),
57 ParentOutOfRange(Revision),
57 WorkingDirectoryUnsupported,
58 WorkingDirectoryUnsupported,
58 }
59 }
59
60
60 #[derive(Clone, Debug, PartialEq)]
61 #[derive(Clone, Debug, PartialEq)]
61 pub enum DirstateParseError {
62 pub enum DirstateParseError {
62 TooLittleData,
63 TooLittleData,
63 Overflow,
64 Overflow,
64 CorruptedEntry(String),
65 CorruptedEntry(String),
65 Damaged,
66 Damaged,
66 }
67 }
67
68
68 impl From<std::io::Error> for DirstateParseError {
69 impl From<std::io::Error> for DirstateParseError {
69 fn from(e: std::io::Error) -> Self {
70 fn from(e: std::io::Error) -> Self {
70 DirstateParseError::CorruptedEntry(e.to_string())
71 DirstateParseError::CorruptedEntry(e.to_string())
71 }
72 }
72 }
73 }
73
74
74 impl ToString for DirstateParseError {
75 impl ToString for DirstateParseError {
75 fn to_string(&self) -> String {
76 fn to_string(&self) -> String {
76 use crate::DirstateParseError::*;
77 use crate::DirstateParseError::*;
77 match self {
78 match self {
78 TooLittleData => "Too little data for dirstate.".to_string(),
79 TooLittleData => "Too little data for dirstate.".to_string(),
79 Overflow => "Overflow in dirstate.".to_string(),
80 Overflow => "Overflow in dirstate.".to_string(),
80 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
81 CorruptedEntry(e) => format!("Corrupted entry: {:?}.", e),
81 Damaged => "Dirstate appears to be damaged.".to_string(),
82 Damaged => "Dirstate appears to be damaged.".to_string(),
82 }
83 }
83 }
84 }
84 }
85 }
85
86
86 #[derive(Debug, PartialEq)]
87 #[derive(Debug, PartialEq)]
87 pub enum DirstatePackError {
88 pub enum DirstatePackError {
88 CorruptedEntry(String),
89 CorruptedEntry(String),
89 CorruptedParent,
90 CorruptedParent,
90 BadSize(usize, usize),
91 BadSize(usize, usize),
91 }
92 }
92
93
93 impl From<std::io::Error> for DirstatePackError {
94 impl From<std::io::Error> for DirstatePackError {
94 fn from(e: std::io::Error) -> Self {
95 fn from(e: std::io::Error) -> Self {
95 DirstatePackError::CorruptedEntry(e.to_string())
96 DirstatePackError::CorruptedEntry(e.to_string())
96 }
97 }
97 }
98 }
98 #[derive(Debug, PartialEq)]
99 #[derive(Debug, PartialEq)]
99 pub enum DirstateMapError {
100 pub enum DirstateMapError {
100 PathNotFound(HgPathBuf),
101 PathNotFound(HgPathBuf),
101 EmptyPath,
102 EmptyPath,
102 }
103 }
103
104
104 pub enum DirstateError {
105 pub enum DirstateError {
105 Parse(DirstateParseError),
106 Parse(DirstateParseError),
106 Pack(DirstatePackError),
107 Pack(DirstatePackError),
107 Map(DirstateMapError),
108 Map(DirstateMapError),
108 IO(std::io::Error),
109 IO(std::io::Error),
109 }
110 }
110
111
111 impl From<DirstateParseError> for DirstateError {
112 impl From<DirstateParseError> for DirstateError {
112 fn from(e: DirstateParseError) -> Self {
113 fn from(e: DirstateParseError) -> Self {
113 DirstateError::Parse(e)
114 DirstateError::Parse(e)
114 }
115 }
115 }
116 }
116
117
117 impl From<DirstatePackError> for DirstateError {
118 impl From<DirstatePackError> for DirstateError {
118 fn from(e: DirstatePackError) -> Self {
119 fn from(e: DirstatePackError) -> Self {
119 DirstateError::Pack(e)
120 DirstateError::Pack(e)
120 }
121 }
121 }
122 }
122
123
123 #[derive(Debug)]
124 #[derive(Debug)]
124 pub enum PatternError {
125 pub enum PatternError {
125 UnsupportedSyntax(String),
126 UnsupportedSyntax(String),
126 }
127 }
127
128
128 #[derive(Debug)]
129 #[derive(Debug)]
129 pub enum PatternFileError {
130 pub enum PatternFileError {
130 IO(std::io::Error),
131 IO(std::io::Error),
131 Pattern(PatternError, LineNumber),
132 Pattern(PatternError, LineNumber),
132 }
133 }
133
134
134 impl From<std::io::Error> for PatternFileError {
135 impl From<std::io::Error> for PatternFileError {
135 fn from(e: std::io::Error) -> Self {
136 fn from(e: std::io::Error) -> Self {
136 PatternFileError::IO(e)
137 PatternFileError::IO(e)
137 }
138 }
138 }
139 }
139
140
140 impl From<DirstateMapError> for DirstateError {
141 impl From<DirstateMapError> for DirstateError {
141 fn from(e: DirstateMapError) -> Self {
142 fn from(e: DirstateMapError) -> Self {
142 DirstateError::Map(e)
143 DirstateError::Map(e)
143 }
144 }
144 }
145 }
145
146
146 impl From<std::io::Error> for DirstateError {
147 impl From<std::io::Error> for DirstateError {
147 fn from(e: std::io::Error) -> Self {
148 fn from(e: std::io::Error) -> Self {
148 DirstateError::IO(e)
149 DirstateError::IO(e)
149 }
150 }
150 }
151 }
@@ -1,101 +1,128 b''
1 // files.rs
1 // files.rs
2 //
2 //
3 // Copyright 2019
3 // Copyright 2019
4 // Raphaël Gomès <rgomes@octobus.net>,
4 // Raphaël Gomès <rgomes@octobus.net>,
5 // Yuya Nishihara <yuya@tcha.org>
5 // Yuya Nishihara <yuya@tcha.org>
6 //
6 //
7 // This software may be used and distributed according to the terms of the
7 // This software may be used and distributed according to the terms of the
8 // GNU General Public License version 2 or any later version.
8 // GNU General Public License version 2 or any later version.
9
9
10 //! Functions for fiddling with files.
10 //! Functions for fiddling with files.
11
11
12 use crate::utils::hg_path::{HgPath, HgPathBuf};
12 use crate::utils::hg_path::{HgPath, HgPathBuf};
13 use std::iter::FusedIterator;
13 use std::iter::FusedIterator;
14
14
15 use std::fs::Metadata;
15 use std::path::Path;
16 use std::path::Path;
16
17
17 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path {
18 pub fn get_path_from_bytes(bytes: &[u8]) -> &Path {
18 let os_str;
19 let os_str;
19 #[cfg(unix)]
20 #[cfg(unix)]
20 {
21 {
21 use std::os::unix::ffi::OsStrExt;
22 use std::os::unix::ffi::OsStrExt;
22 os_str = std::ffi::OsStr::from_bytes(bytes);
23 os_str = std::ffi::OsStr::from_bytes(bytes);
23 }
24 }
24 // TODO Handle other platforms
25 // TODO Handle other platforms
25 // TODO: convert from WTF8 to Windows MBCS (ANSI encoding).
26 // TODO: convert from WTF8 to Windows MBCS (ANSI encoding).
26 // Perhaps, the return type would have to be Result<PathBuf>.
27 // Perhaps, the return type would have to be Result<PathBuf>.
27
28
28 Path::new(os_str)
29 Path::new(os_str)
29 }
30 }
30
31
31 /// An iterator over repository path yielding itself and its ancestors.
32 /// An iterator over repository path yielding itself and its ancestors.
32 #[derive(Copy, Clone, Debug)]
33 #[derive(Copy, Clone, Debug)]
33 pub struct Ancestors<'a> {
34 pub struct Ancestors<'a> {
34 next: Option<&'a HgPath>,
35 next: Option<&'a HgPath>,
35 }
36 }
36
37
37 impl<'a> Iterator for Ancestors<'a> {
38 impl<'a> Iterator for Ancestors<'a> {
38 type Item = &'a HgPath;
39 type Item = &'a HgPath;
39
40
40 fn next(&mut self) -> Option<Self::Item> {
41 fn next(&mut self) -> Option<Self::Item> {
41 let next = self.next;
42 let next = self.next;
42 self.next = match self.next {
43 self.next = match self.next {
43 Some(s) if s.is_empty() => None,
44 Some(s) if s.is_empty() => None,
44 Some(s) => {
45 Some(s) => {
45 let p = s.bytes().rposition(|c| *c == b'/').unwrap_or(0);
46 let p = s.bytes().rposition(|c| *c == b'/').unwrap_or(0);
46 Some(HgPath::new(&s.as_bytes()[..p]))
47 Some(HgPath::new(&s.as_bytes()[..p]))
47 }
48 }
48 None => None,
49 None => None,
49 };
50 };
50 next
51 next
51 }
52 }
52 }
53 }
53
54
54 impl<'a> FusedIterator for Ancestors<'a> {}
55 impl<'a> FusedIterator for Ancestors<'a> {}
55
56
56 /// Returns an iterator yielding ancestor directories of the given repository
57 /// Returns an iterator yielding ancestor directories of the given repository
57 /// path.
58 /// path.
58 ///
59 ///
59 /// The path is separated by '/', and must not start with '/'.
60 /// The path is separated by '/', and must not start with '/'.
60 ///
61 ///
61 /// The path itself isn't included unless it is b"" (meaning the root
62 /// The path itself isn't included unless it is b"" (meaning the root
62 /// directory.)
63 /// directory.)
63 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> {
64 pub fn find_dirs<'a>(path: &'a HgPath) -> Ancestors<'a> {
64 let mut dirs = Ancestors { next: Some(path) };
65 let mut dirs = Ancestors { next: Some(path) };
65 if !path.is_empty() {
66 if !path.is_empty() {
66 dirs.next(); // skip itself
67 dirs.next(); // skip itself
67 }
68 }
68 dirs
69 dirs
69 }
70 }
70
71
71 /// TODO more than ASCII?
72 /// TODO more than ASCII?
72 pub fn normalize_case(path: &HgPath) -> HgPathBuf {
73 pub fn normalize_case(path: &HgPath) -> HgPathBuf {
73 #[cfg(windows)] // NTFS compares via upper()
74 #[cfg(windows)] // NTFS compares via upper()
74 return path.to_ascii_uppercase();
75 return path.to_ascii_uppercase();
75 #[cfg(unix)]
76 #[cfg(unix)]
76 path.to_ascii_lowercase()
77 path.to_ascii_lowercase()
77 }
78 }
78
79
80 #[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
81 pub struct HgMetadata {
82 pub st_dev: u64,
83 pub st_mode: u32,
84 pub st_nlink: u64,
85 pub st_size: u64,
86 pub st_mtime: i64,
87 pub st_ctime: i64,
88 }
89
90 // TODO support other plaforms
91 #[cfg(unix)]
92 impl HgMetadata {
93 pub fn from_metadata(metadata: Metadata) -> Self {
94 use std::os::unix::fs::MetadataExt;
95 Self {
96 st_dev: metadata.dev(),
97 st_mode: metadata.mode(),
98 st_nlink: metadata.nlink(),
99 st_size: metadata.size(),
100 st_mtime: metadata.mtime(),
101 st_ctime: metadata.ctime(),
102 }
103 }
104 }
105
79 #[cfg(test)]
106 #[cfg(test)]
80 mod tests {
107 mod tests {
81 use super::*;
108 use super::*;
82
109
83 #[test]
110 #[test]
84 fn find_dirs_some() {
111 fn find_dirs_some() {
85 let mut dirs = super::find_dirs(HgPath::new(b"foo/bar/baz"));
112 let mut dirs = super::find_dirs(HgPath::new(b"foo/bar/baz"));
86 assert_eq!(dirs.next(), Some(HgPath::new(b"foo/bar")));
113 assert_eq!(dirs.next(), Some(HgPath::new(b"foo/bar")));
87 assert_eq!(dirs.next(), Some(HgPath::new(b"foo")));
114 assert_eq!(dirs.next(), Some(HgPath::new(b"foo")));
88 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
115 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
89 assert_eq!(dirs.next(), None);
116 assert_eq!(dirs.next(), None);
90 assert_eq!(dirs.next(), None);
117 assert_eq!(dirs.next(), None);
91 }
118 }
92
119
93 #[test]
120 #[test]
94 fn find_dirs_empty() {
121 fn find_dirs_empty() {
95 // looks weird, but mercurial.util.finddirs(b"") yields b""
122 // looks weird, but mercurial.util.finddirs(b"") yields b""
96 let mut dirs = super::find_dirs(HgPath::new(b""));
123 let mut dirs = super::find_dirs(HgPath::new(b""));
97 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
124 assert_eq!(dirs.next(), Some(HgPath::new(b"")));
98 assert_eq!(dirs.next(), None);
125 assert_eq!(dirs.next(), None);
99 assert_eq!(dirs.next(), None);
126 assert_eq!(dirs.next(), None);
100 }
127 }
101 }
128 }
General Comments 0
You need to be logged in to leave comments. Login now