Mercurial > public > mercurial-scm > hg
annotate rust/hg-core/src/operations/annotate.rs @ 52770:7b4548a075ab
rust: refactor conversions from GraphError
This is in preparation for adding a new kind of GraphError.
author | Mitchell Kember <mkember@janestreet.com> |
---|---|
date | Fri, 07 Feb 2025 16:03:35 -0500 |
parents | 6183949219b2 |
children | 874c64e041b5 |
rev | line source |
---|---|
52767
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
1 use crate::{ |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
2 bdiff::{self, Lines}, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
3 errors::HgError, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
4 repo::Repo, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
5 revlog::{ |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
6 changelog::Changelog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
7 filelog::{Filelog, FilelogRevisionData}, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
8 manifest::Manifestlog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
9 }, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
10 utils::{ |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
11 self, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
12 hg_path::{HgPath, HgPathBuf}, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
13 }, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
14 AncestorsIterator, FastHashMap, Graph, GraphError, Node, Revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
15 NULL_REVISION, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
16 }; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
17 use itertools::Itertools as _; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
18 use rayon::prelude::*; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
19 use self_cell::self_cell; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
20 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
21 /// Options for [`annotate`]. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
22 #[derive(Copy, Clone)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
23 pub struct AnnotateOptions { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
24 pub treat_binary_as_text: bool, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
25 pub follow_copies: bool, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
26 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
27 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
28 /// The final result of annotating a file. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
29 pub enum AnnotateOutput { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
30 /// An annotated text file. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
31 Text(ChangesetAnnotatedFile), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
32 /// The file cannot be annotated because it is binary. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
33 Binary, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
34 /// The file was not found in the repository. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
35 NotFound, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
36 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
37 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
38 /// A file with user-facing changeset annotations for each line. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
39 pub struct ChangesetAnnotatedFile { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
40 // The lines of the file, including original line endings. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
41 pub lines: Vec<Vec<u8>>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
42 // List of annotations corresponding to `lines`. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
43 pub annotations: Vec<ChangesetAnnotation>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
44 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
45 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
46 /// A user-facing changeset annotation for one line. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
47 pub struct ChangesetAnnotation { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
48 /// The file path as it was at `revision`. This can be different from the |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
49 /// file's current path if it was copied or renamed in the past. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
50 pub path: HgPathBuf, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
51 /// The changelog revision that introduced the line. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
52 pub revision: Revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
53 /// The one-based line number in the original file. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
54 pub line_number: u32, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
55 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
56 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
57 self_cell!( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
58 /// A wrapper around [`Lines`] that owns the file text. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
59 struct OwnedLines { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
60 owner: Vec<u8>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
61 #[covariant] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
62 dependent: Lines, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
63 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
64 ); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
65 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
66 impl OwnedLines { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
67 fn split(data: Vec<u8>) -> Result<Self, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
68 Self::try_new(data, |data| bdiff::split_lines(data)) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
69 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
70 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
71 fn get(&self) -> &Lines { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
72 self.borrow_dependent() |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
73 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
74 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
75 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
76 /// A file with filelog annotations for each line. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
77 struct AnnotatedFile { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
78 lines: OwnedLines, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
79 annotations: Vec<Annotation>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
80 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
81 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
82 /// A filelog annotation for one line. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
83 #[derive(Copy, Clone)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
84 struct Annotation { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
85 /// The file revision that introduced the line. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
86 id: FileId, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
87 /// The one-based line number in the original file. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
88 line_number: u32, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
89 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
90 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
91 /// Helper for keeping track of multiple filelogs. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
92 #[derive(Default)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
93 struct FilelogSet { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
94 /// List of filelogs. The first one is for the root file being blamed. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
95 /// Others are added only when following copies/renames. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
96 items: Vec<FilelogSetItem>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
97 /// Mapping of paths to indexes in `items`. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
98 path_to_index: FastHashMap<HgPathBuf, FilelogIndex>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
99 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
100 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
101 struct FilelogSetItem { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
102 path: HgPathBuf, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
103 filelog: Filelog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
104 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
105 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
106 /// Identifies a filelog in a FilelogSet. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
107 type FilelogIndex = u32; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
108 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
109 /// Identifies a file revision in a FilelogSet. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
110 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
111 struct FileId { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
112 index: FilelogIndex, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
113 revision: Revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
114 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
115 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
116 impl FilelogSet { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
117 /// Returns filelog item at the given index. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
118 fn get(&self, index: FilelogIndex) -> &FilelogSetItem { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
119 &self.items[index as usize] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
120 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
121 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
122 /// Opens a filelog by path and returns its index. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
123 fn open( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
124 &mut self, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
125 repo: &Repo, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
126 path: &HgPath, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
127 ) -> Result<FilelogIndex, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
128 if let Some(&index) = self.path_to_index.get(path) { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
129 return Ok(index); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
130 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
131 let index = self.items.len() as FilelogIndex; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
132 self.items.push(FilelogSetItem { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
133 filelog: repo.filelog(path)?, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
134 path: path.into(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
135 }); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
136 self.path_to_index.insert(path.into(), index); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
137 Ok(index) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
138 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
139 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
140 /// Opens a new filelog by path and returns the id for the given file node. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
141 fn open_at_node( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
142 &mut self, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
143 repo: &Repo, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
144 path: &HgPath, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
145 node: Node, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
146 ) -> Result<FileId, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
147 let index = self.open(repo, path)?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
148 let revision = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
149 self.get(index).filelog.revlog.rev_from_node(node.into())?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
150 Ok(FileId { index, revision }) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
151 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
152 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
153 /// Reads the contents of a file by id. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
154 fn read(&self, id: FileId) -> Result<FilelogRevisionData, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
155 self.get(id.index).filelog.entry(id.revision)?.data() |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
156 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
157 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
158 /// Returns the parents of a file. If `follow_copies` is true, it treats |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
159 /// the copy source as a parent. In that case, also returns the file data |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
160 /// (since it has to read the file to extract the copy metadata). |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
161 fn parents( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
162 &mut self, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
163 repo: &Repo, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
164 id: FileId, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
165 follow_copies: bool, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
166 ) -> Result<(Vec<FileId>, Option<Vec<u8>>), HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
167 let filelog = &self.get(id.index).filelog; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
168 let revisions = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
169 filelog.parents(id.revision).map_err(from_graph_error)?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
170 let mut parents = Vec::with_capacity(2); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
171 let mut file_data = None; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
172 if revisions[0] != NULL_REVISION { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
173 parents.push(FileId { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
174 index: id.index, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
175 revision: revisions[0], |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
176 }); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
177 } else if follow_copies { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
178 // A null p1 indicates there might be copy metadata. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
179 // Check for it, and if present use it as the parent. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
180 let data = filelog.entry(id.revision)?.data()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
181 let meta = data.metadata()?.parse()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
182 // If copy or copyrev occurs without the other, ignore it. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
183 // This matches filerevisioncopied in storageutil.py. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
184 if let (Some(copy), Some(copyrev)) = (meta.copy, meta.copyrev) { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
185 parents.push(self.open_at_node(repo, copy, copyrev)?); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
186 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
187 file_data = Some(data.into_file_data()?); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
188 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
189 if revisions[1] != NULL_REVISION { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
190 parents.push(FileId { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
191 index: id.index, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
192 revision: revisions[1], |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
193 }); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
194 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
195 Ok((parents, file_data)) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
196 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
197 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
198 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
199 /// Per [`FileId`] information used in the [`annotate`] algorithm. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
200 #[derive(Default)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
201 struct FileInfo { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
202 /// Parents of this revision (via p1 and p2 or copy metadata). |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
203 parents: Option<Vec<FileId>>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
204 /// Current state for annotating the file. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
205 file: AnnotatedFileState, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
206 /// Remaining number of times `file` is needed before we can drop it. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
207 needed: usize, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
208 /// Current state for converting to a changelog revision. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
209 revision: ChangelogRevisionState, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
210 /// The value of `revision` from a descendant. If the linkrev needs |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
211 /// adjustment, we can start iterating the changelog here. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
212 descendant: Option<Revision>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
213 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
214 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
215 /// State enum for reading a file and annotating it. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
216 #[derive(Default)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
217 enum AnnotatedFileState { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
218 #[default] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
219 None, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
220 Read(OwnedLines), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
221 Annotated(AnnotatedFile), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
222 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
223 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
224 /// State enum for converting a filelog revision to a changelog revision, but |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
225 /// only if needed (because it will appear in the final output). |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
226 #[derive(Default)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
227 enum ChangelogRevisionState { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
228 #[default] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
229 NotNeeded, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
230 Needed, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
231 Done(Revision), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
232 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
233 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
234 /// A collection of [`FileInfo`], forming a graph via [`FileInfo::parents`]. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
235 #[derive(Default)] |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
236 struct FileGraph(FastHashMap<FileId, FileInfo>); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
237 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
238 impl FileGraph { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
239 fn get_or_insert_default(&mut self, id: FileId) -> &mut FileInfo { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
240 self.0.entry(id).or_default() |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
241 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
242 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
243 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
244 impl std::ops::Index<FileId> for FileGraph { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
245 type Output = FileInfo; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
246 fn index(&self, id: FileId) -> &Self::Output { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
247 self.0.get(&id).expect("the graph should be populated") |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
248 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
249 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
250 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
251 impl std::ops::IndexMut<FileId> for FileGraph { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
252 fn index_mut(&mut self, id: FileId) -> &mut Self::Output { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
253 self.0.get_mut(&id).expect("the graph should be populated") |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
254 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
255 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
256 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
257 /// Annotates each line of a file with changeset information. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
258 pub fn annotate( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
259 repo: &Repo, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
260 path: &HgPath, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
261 changelog_revision: Revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
262 options: AnnotateOptions, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
263 ) -> Result<AnnotateOutput, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
264 // Step 1: Load the base file and check if it's binary. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
265 let changelog = repo.changelog()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
266 let manifestlog = repo.manifestlog()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
267 let mut fls = FilelogSet::default(); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
268 let base_id = { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
269 let changelog_data = changelog.entry(changelog_revision)?.data()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
270 let manifest = manifestlog |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
271 .data_for_node(changelog_data.manifest_node()?.into())?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
272 let Some(entry) = manifest.find_by_path(path)? else { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
273 return Ok(AnnotateOutput::NotFound); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
274 }; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
275 fls.open_at_node(repo, path, entry.node_id()?)? |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
276 }; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
277 let base_file_data = fls.read(base_id)?.into_file_data()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
278 if !options.treat_binary_as_text |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
279 && utils::files::is_binary(&base_file_data) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
280 { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
281 return Ok(AnnotateOutput::Binary); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
282 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
283 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
284 // Step 2: DFS to build the graph. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
285 let mut graph = FileGraph::default(); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
286 let mut visit = vec![base_id]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
287 while let Some(id) = visit.pop() { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
288 let info = graph.get_or_insert_default(id); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
289 if info.parents.is_some() { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
290 continue; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
291 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
292 let (parents, file_data) = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
293 fls.parents(repo, id, options.follow_copies)?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
294 info.parents = Some(parents.clone()); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
295 if let Some(data) = file_data { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
296 info.file = AnnotatedFileState::Read(OwnedLines::split(data)?); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
297 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
298 for id in parents { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
299 let info = graph.get_or_insert_default(id); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
300 info.needed += 1; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
301 if info.parents.is_none() { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
302 visit.push(id); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
303 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
304 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
305 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
306 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
307 // Step 3: Read files and split lines in parallel. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
308 graph[base_id].file = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
309 AnnotatedFileState::Read(OwnedLines::split(base_file_data)?); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
310 graph.0.par_iter_mut().try_for_each( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
311 |(&id, info)| -> Result<(), HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
312 if let AnnotatedFileState::None = info.file { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
313 let lines = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
314 OwnedLines::split(fls.read(id)?.into_file_data()?)?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
315 info.file = AnnotatedFileState::Read(lines); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
316 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
317 Ok(()) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
318 }, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
319 )?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
320 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
321 // Step 4: DFS to do the actual annotate algorithm. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
322 // While we're at it, save the topological order. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
323 let mut topological_order = vec![]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
324 visit.push(base_id); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
325 while let Some(&id) = visit.last() { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
326 let info = &mut graph[id]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
327 if let AnnotatedFileState::Annotated(_) = info.file { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
328 visit.pop(); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
329 continue; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
330 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
331 let visit_len = visit.len(); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
332 let parents = info.parents.clone().expect("parents set in step 2"); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
333 for &id in &parents { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
334 match graph[id].file { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
335 AnnotatedFileState::Annotated(_) => {} |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
336 _ => visit.push(id), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
337 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
338 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
339 if visit.len() != visit_len { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
340 continue; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
341 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
342 visit.pop(); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
343 topological_order.push(id); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
344 let lines = match std::mem::take(&mut graph[id].file) { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
345 AnnotatedFileState::Read(lines) => lines, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
346 _ => unreachable!(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
347 }; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
348 let mut parent_files = Vec::with_capacity(2); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
349 for &id in &parents { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
350 match graph[id].file { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
351 AnnotatedFileState::Annotated(ref file) => { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
352 parent_files.push(file) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
353 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
354 _ => unreachable!(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
355 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
356 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
357 graph[id].file = AnnotatedFileState::Annotated(annotate_pair( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
358 id, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
359 lines, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
360 parent_files, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
361 )?); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
362 for &id in &parents { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
363 let info = &mut graph[id]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
364 info.needed -= 1; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
365 if info.needed == 0 { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
366 info.file = AnnotatedFileState::None; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
367 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
368 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
369 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
370 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
371 // Step 5: Map filelog revisions to changelog revisions. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
372 let base_info = &mut graph[base_id]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
373 base_info.descendant = Some(changelog_revision); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
374 let AnnotatedFileState::Annotated(AnnotatedFile { lines, annotations }) = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
375 std::mem::take(&mut base_info.file) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
376 else { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
377 panic!("the base file should have been annotated in step 4") |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
378 }; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
379 // Only convert revisions that actually appear in the final output. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
380 for &Annotation { id, .. } in &annotations { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
381 graph[id].revision = ChangelogRevisionState::Needed; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
382 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
383 // Use the same object for all ancestor checks, since it internally |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
384 // builds a hash set of seen revisions. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
385 let mut ancestors = ancestor_iter(&changelog, changelog_revision, None); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
386 // Iterate in reverse topological order so that we visits nodes after their |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
387 // children, that way we can propagate `descendant` correctly. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
388 for &id in topological_order.iter().rev() { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
389 let info = &mut graph[id]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
390 let descendant = |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
391 info.descendant.expect("descendant set by prior iteration"); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
392 let propagate = match info.revision { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
393 ChangelogRevisionState::NotNeeded => descendant, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
394 ChangelogRevisionState::Needed => { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
395 let revision = adjust_link_revision( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
396 &changelog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
397 &manifestlog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
398 &fls, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
399 &mut ancestors, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
400 descendant, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
401 id, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
402 )?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
403 info.revision = ChangelogRevisionState::Done(revision); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
404 revision |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
405 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
406 ChangelogRevisionState::Done(_) => unreachable!(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
407 }; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
408 for id in info.parents.clone().expect("parents set in step 2") { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
409 let descendant = &mut graph[id].descendant; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
410 // If the parent had other descendants, choose the smallest one |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
411 // because we want to skip over as much as possible. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
412 *descendant = Some(descendant.unwrap_or(propagate).min(propagate)); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
413 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
414 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
415 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
416 // Step 6: Convert to `ChangesetAnnotatedFile`. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
417 let mut changeset_annotations = Vec::with_capacity(annotations.len()); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
418 for Annotation { id, line_number } in annotations { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
419 changeset_annotations.push(ChangesetAnnotation { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
420 path: fls.get(id.index).path.clone(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
421 revision: match graph[id].revision { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
422 ChangelogRevisionState::Done(revision) => revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
423 _ => unreachable!(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
424 }, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
425 line_number, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
426 }); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
427 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
428 Ok(AnnotateOutput::Text(ChangesetAnnotatedFile { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
429 lines: lines.get().iter().map(ToOwned::to_owned).collect(), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
430 annotations: changeset_annotations, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
431 })) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
432 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
433 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
434 /// Annotates a file by diffing against its parents, attributing changed lines |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
435 /// to `id`, and copying ids from the parent results for unchanged lines. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
436 /// If there are two parents and a line is unchanged in both diffs, p2 wins. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
437 fn annotate_pair( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
438 id: FileId, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
439 lines: OwnedLines, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
440 parents: Vec<&AnnotatedFile>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
441 ) -> Result<AnnotatedFile, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
442 let len = lines.get().len(); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
443 let mut annotations = Vec::with_capacity(len); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
444 for line_number in 1..(len + 1) as u32 { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
445 annotations.push(Annotation { id, line_number }); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
446 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
447 for parent in parents { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
448 for bdiff::Hunk { a1, a2, b1, b2 } in |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
449 bdiff::diff(parent.lines.get(), lines.get())?.iter() |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
450 { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
451 for (a, b) in (a1..a2).zip(b1..b2) { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
452 annotations[b as usize] = parent.annotations[a as usize]; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
453 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
454 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
455 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
456 Ok(AnnotatedFile { lines, annotations }) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
457 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
458 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
459 /// Creates an iterator over the ancestors of `base_revision` (inclusive), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
460 /// stopping at `stop_revision` if provided. Panics if `base_revision` is null. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
461 fn ancestor_iter( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
462 changelog: &Changelog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
463 base_revision: Revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
464 stop_revision: Option<Revision>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
465 ) -> AncestorsIterator<&Changelog> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
466 AncestorsIterator::new( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
467 changelog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
468 [base_revision], |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
469 stop_revision.unwrap_or(NULL_REVISION), |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
470 true, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
471 ) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
472 .expect("base_revision should not be null") |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
473 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
474 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
475 /// If the linkrev of `id` is in `ancestors`, returns it. Otherwise, finds and |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
476 /// returns the first ancestor of `descendant` that introduced `id`. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
477 fn adjust_link_revision( |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
478 changelog: &Changelog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
479 manifestlog: &Manifestlog, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
480 fls: &FilelogSet, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
481 ancestors: &mut AncestorsIterator<&Changelog>, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
482 descendant: Revision, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
483 id: FileId, |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
484 ) -> Result<Revision, HgError> { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
485 let FilelogSetItem { filelog, path } = fls.get(id.index); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
486 let linkrev = filelog |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
487 .revlog |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
488 .link_revision(id.revision, &changelog.revlog)?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
489 if ancestors.contains(linkrev).map_err(from_graph_error)? { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
490 return Ok(linkrev); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
491 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
492 let file_node = *filelog.revlog.node_from_rev(id.revision); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
493 for ancestor in ancestor_iter(changelog, descendant, Some(linkrev)) { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
494 let ancestor = ancestor.map_err(from_graph_error)?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
495 let data = changelog.entry(ancestor)?.data()?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
496 if data.files().contains(&path.as_ref()) { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
497 let manifest_rev = manifestlog |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
498 .revlog |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
499 .rev_from_node(data.manifest_node()?.into())?; |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
500 if let Some(entry) = manifestlog |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
501 .inexact_data_delta_parents(manifest_rev)? |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
502 .find_by_path(path)? |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
503 { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
504 if entry.node_id()? == file_node { |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
505 return Ok(ancestor); |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
506 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
507 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
508 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
509 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
510 // In theory this should be unreachable. But in case it happens, return the |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
511 // linkrev. This matches _adjustlinkrev in context.py. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
512 Ok(linkrev) |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
513 } |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
514 |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
515 /// Converts a [`GraphError`] to an [`HgError`]. |
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
516 fn from_graph_error(err: GraphError) -> HgError { |
52770
7b4548a075ab
rust: refactor conversions from GraphError
Mitchell Kember <mkember@janestreet.com>
parents:
52767
diff
changeset
|
517 HgError::corrupted(err.to_string()) |
52767
6183949219b2
rhg: implement rhg annotate
Mitchell Kember <mkember@janestreet.com>
parents:
diff
changeset
|
518 } |