Show More
@@ -259,7 +259,7 def _changesetforwardcopies(a, b, match) | |||
|
259 | 259 | children = {} |
|
260 | 260 | |
|
261 | 261 | cl = repo.changelog |
|
262 |
isancestor = |
|
|
262 | isancestor = cl.isancestorrev | |
|
263 | 263 | missingrevs = cl.findmissingrevs(common=[a.rev()], heads=[b.rev()]) |
|
264 | 264 | mrset = set(missingrevs) |
|
265 | 265 | roots = set() |
@@ -321,6 +321,8 def _combine_changeset_copies( | |||
|
321 | 321 | list(revs), children, targetrev, revinfo, isancestor |
|
322 | 322 | ) |
|
323 | 323 | |
|
324 | isancestor = cached_is_ancestor(isancestor) | |
|
325 | ||
|
324 | 326 | all_copies = {} |
|
325 | 327 | for r in revs: |
|
326 | 328 | copies = all_copies.pop(r, None) |
@@ -64,6 +64,42 impl ChangedFiles { | |||
|
64 | 64 | } |
|
65 | 65 | } |
|
66 | 66 | |
|
67 | /// A struct responsible for answering "is X ancestors of Y" quickly | |
|
68 | /// | |
|
69 | /// The structure will delegate ancestors call to a callback, and cache the | |
|
70 | /// result. | |
|
71 | #[derive(Debug)] | |
|
72 | struct AncestorOracle<'a, A: Fn(Revision, Revision) -> bool> { | |
|
73 | inner: &'a A, | |
|
74 | pairs: HashMap<(Revision, Revision), bool>, | |
|
75 | } | |
|
76 | ||
|
77 | impl<'a, A: Fn(Revision, Revision) -> bool> AncestorOracle<'a, A> { | |
|
78 | fn new(func: &'a A) -> Self { | |
|
79 | Self { | |
|
80 | inner: func, | |
|
81 | pairs: HashMap::default(), | |
|
82 | } | |
|
83 | } | |
|
84 | ||
|
85 | /// returns `true` if `anc` is an ancestors of `desc`, `false` otherwise | |
|
86 | fn is_ancestor(&mut self, anc: Revision, desc: Revision) -> bool { | |
|
87 | if anc > desc { | |
|
88 | false | |
|
89 | } else if anc == desc { | |
|
90 | true | |
|
91 | } else { | |
|
92 | if let Some(b) = self.pairs.get(&(anc, desc)) { | |
|
93 | *b | |
|
94 | } else { | |
|
95 | let b = (self.inner)(anc, desc); | |
|
96 | self.pairs.insert((anc, desc), b); | |
|
97 | b | |
|
98 | } | |
|
99 | } | |
|
100 | } | |
|
101 | } | |
|
102 | ||
|
67 | 103 | /// Same as mercurial.copies._combine_changeset_copies, but in Rust. |
|
68 | 104 | /// |
|
69 | 105 | /// Arguments are: |
@@ -77,14 +113,15 impl ChangedFiles { | |||
|
77 | 113 | /// * ChangedFiles |
|
78 | 114 | /// isancestors(low_rev, high_rev): callback to check if a revision is an |
|
79 | 115 | /// ancestor of another |
|
80 | pub fn combine_changeset_copies( | |
|
116 | pub fn combine_changeset_copies<A: Fn(Revision, Revision) -> bool>( | |
|
81 | 117 | revs: Vec<Revision>, |
|
82 | 118 | children: HashMap<Revision, Vec<Revision>>, |
|
83 | 119 | target_rev: Revision, |
|
84 | 120 | rev_info: &impl Fn(Revision) -> RevInfo, |
|
85 | is_ancestor: &impl Fn(Revision, Revision) -> bool, | |
|
121 | is_ancestor: &A, | |
|
86 | 122 | ) -> PathCopies { |
|
87 | 123 | let mut all_copies = HashMap::new(); |
|
124 | let mut oracle = AncestorOracle::new(is_ancestor); | |
|
88 | 125 | |
|
89 | 126 | for rev in revs { |
|
90 | 127 | // Retrieve data computed in a previous iteration |
@@ -168,7 +205,7 pub fn combine_changeset_copies( | |||
|
168 | 205 | _ => unreachable!(), |
|
169 | 206 | }; |
|
170 | 207 | let merged_copies = |
|
171 |
merge_copies_dict(minor, major, &changes, |
|
|
208 | merge_copies_dict(minor, major, &changes, &mut oracle); | |
|
172 | 209 | all_copies.insert(child, merged_copies); |
|
173 | 210 | } |
|
174 | 211 | }; |
@@ -194,11 +231,11 pub fn combine_changeset_copies( | |||
|
194 | 231 | /// In case of conflict, value from "major" will be picked, unless in some |
|
195 | 232 | /// cases. See inline documentation for details. |
|
196 | 233 | #[allow(clippy::if_same_then_else)] |
|
197 | fn merge_copies_dict( | |
|
234 | fn merge_copies_dict<A: Fn(Revision, Revision) -> bool>( | |
|
198 | 235 | minor: TimeStampedPathCopies, |
|
199 | 236 | major: TimeStampedPathCopies, |
|
200 | 237 | changes: &ChangedFiles, |
|
201 | is_ancestor: &impl Fn(Revision, Revision) -> bool, | |
|
238 | oracle: &mut AncestorOracle<A>, | |
|
202 | 239 | ) -> TimeStampedPathCopies { |
|
203 | 240 | if minor.is_empty() { |
|
204 | 241 | return major; |
@@ -244,7 +281,8 fn merge_copies_dict( | |||
|
244 | 281 | // If the two entry are identical, no need to do |
|
245 | 282 | // anything (but diff should not have yield them) |
|
246 | 283 | unreachable!(); |
|
247 |
} else if is_ancestor(src_major.rev, src_minor.rev) |
|
|
284 | } else if oracle.is_ancestor(src_major.rev, src_minor.rev) | |
|
285 | { | |
|
248 | 286 | pick_minor(); |
|
249 | 287 | } else { |
|
250 | 288 | pick_major(); |
@@ -271,7 +309,7 fn merge_copies_dict( | |||
|
271 | 309 | // each side might conflict. The major side will win such |
|
272 | 310 | // conflict. |
|
273 | 311 | pick_major(); |
|
274 | } else if is_ancestor(src_major.rev, src_minor.rev) { | |
|
312 | } else if oracle.is_ancestor(src_major.rev, src_minor.rev) { | |
|
275 | 313 | // If the minor side is strictly newer than the major side, |
|
276 | 314 | // it should be kept. |
|
277 | 315 | pick_minor(); |
@@ -279,7 +317,7 fn merge_copies_dict( | |||
|
279 | 317 | // without any special case, the "major" value win other |
|
280 | 318 | // the "minor" one. |
|
281 | 319 | pick_major(); |
|
282 | } else if is_ancestor(src_minor.rev, src_major.rev) { | |
|
320 | } else if oracle.is_ancestor(src_minor.rev, src_major.rev) { | |
|
283 | 321 | // the "major" rev is a direct ancestors of "minor", any |
|
284 | 322 | // different value should overwrite |
|
285 | 323 | pick_major(); |
General Comments 0
You need to be logged in to leave comments.
Login now