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