##// END OF EJS Templates
copies-rust: move is_ancestor caching within the rust code...
marmoute -
r46586:8b99c473 default
parent child Browse files
Show More
@@ -259,7 +259,7 b' def _changesetforwardcopies(a, b, match)'
259 259 children = {}
260 260
261 261 cl = repo.changelog
262 isancestor = cached_is_ancestor(cl.isancestorrev)
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 b' 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 b' 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 b' 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 b' pub fn combine_changeset_copies('
168 205 _ => unreachable!(),
169 206 };
170 207 let merged_copies =
171 merge_copies_dict(minor, major, &changes, is_ancestor);
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 b' 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 b' 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 b' 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 b' 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