hglib/commands/
annotate.rs1use crate::client::{Client, HglibError, Runner};
6use crate::{runcommand, MkArg};
7
8pub struct Arg<'a> {
9 pub files: &'a [&'a str],
10 pub revrange: &'a str,
11 pub nofollow: bool,
12 pub text: bool,
13 pub user: bool,
14 pub file: bool,
15 pub date: bool,
16 pub number: bool,
17 pub changeset: bool,
18 pub line: bool,
19 pub verbose: bool,
20 pub include: &'a [&'a str],
21 pub exclude: &'a [&'a str],
22}
23
24impl<'a> Default for Arg<'a> {
25 fn default() -> Self {
26 Self {
27 files: &[],
28 revrange: "",
29 nofollow: false,
30 text: false,
31 user: false,
32 file: false,
33 date: false,
34 number: false,
35 changeset: false,
36 line: false,
37 verbose: false,
38 include: &[],
39 exclude: &[],
40 }
41 }
42}
43
44impl<'a> Arg<'a> {
45 fn run(&self, client: &mut Client) -> Result<(Vec<u8>, i32), HglibError> {
46 runcommand!(
47 client,
48 "annotate",
49 self.files,
50 "-r",
51 self.revrange,
52 "--no-follow",
53 self.nofollow,
54 "-a",
55 self.text,
56 "-u",
57 self.user,
58 "-f",
59 self.file,
60 "-d",
61 self.date,
62 "-n",
63 self.number,
64 "-c",
65 self.changeset,
66 "-l",
67 self.line,
68 "-v",
69 self.verbose,
70 "-I",
71 self.include,
72 "-X",
73 self.exclude
74 )
75 }
76}
77
78#[derive(Debug, PartialEq)]
79pub struct Line<'a> {
80 pub info: &'a str,
81 pub content: &'a [u8],
82}
83
84pub struct Lines {
85 buf: Vec<u8>,
86 pos: usize,
87}
88
89impl Lines {
90 fn new(buf: Vec<u8>) -> Lines {
91 Lines { buf, pos: 0 }
92 }
93
94 pub fn next_line(&mut self) -> Result<Option<Line>, HglibError> {
95 if self.pos >= self.buf.len() {
96 return Ok(None);
97 }
98
99 let mut info_end = 0;
100 let mut info = "";
101 for (n, c) in self.buf[self.pos..].iter().enumerate() {
102 if *c == b':' {
103 if info_end == 0 {
104 if let Some(c) = self.buf.get(self.pos + n + 1) {
105 if *c == b' ' {
106 info_end = self.pos + n;
107 let _info = unsafe { self.buf.get_unchecked(self.pos..info_end) };
108 info = std::str::from_utf8(_info)?;
109 }
110 }
111 }
112 } else if *c == b'\n' {
113 self.pos += n + 1;
114 let content = unsafe { self.buf.get_unchecked(info_end + 2..self.pos - 1) };
115 return Ok(Some(Line { info, content }));
116 }
117 }
118 Ok(None)
119 }
120}
121
122impl Client {
123 pub fn annotate(&mut self, x: Arg) -> Result<Lines, HglibError> {
124 let (data, _) = x.run(self)?;
125 Ok(Lines::new(data))
126 }
127}