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