hglib/commands/
bookmarks.rs1use crate::client::{Client, HglibError, Runner};
6use crate::runcommand;
7
8pub struct Arg {}
9
10impl Default for Arg {
11 fn default() -> Self {
12 Self {}
13 }
14}
15
16impl Arg {
17 fn run(&self, client: &mut Client) -> Result<(Vec<u8>, i32), HglibError> {
18 runcommand!(client, "bookmarks", &[""])
19 }
20}
21
22#[derive(Debug, PartialEq)]
23pub struct Bookmark {
24 pub name: String,
25 pub rev: u64,
26 pub node: String,
27}
28
29#[derive(Debug, PartialEq)]
30pub struct Bookmarks {
31 pub bookmarks: Vec<Bookmark>,
32 pub current: Option<usize>,
33}
34
35impl Client {
36 pub fn bookmarks(&mut self, x: Arg) -> Result<Bookmarks, HglibError> {
37 let (data, _) = x.run(self)?;
38 let empty = b"no bookmarks set";
39 let mut bookmarks = Vec::new();
40 let mut current = None;
41
42 if data.starts_with(empty)
43 && data[empty.len()..]
44 .iter()
45 .all(|x| *x == b' ' || *x == b'\n')
46 {
47 return Ok(Bookmarks { bookmarks, current });
48 }
49
50 for line in data.split(|x| *x == b'\n').filter(|x| x.len() >= 3) {
51 let start = unsafe { line.get_unchecked(..3) };
52 if start.iter().any(|x| *x == b'*') {
53 current = Some(bookmarks.len());
54 }
55 let line = unsafe { line.get_unchecked(3..) };
56 let mut iter = line.split(|x| *x == b' ').filter(|x| !x.is_empty());
57 let name = String::from_utf8(iter.next().unwrap().to_vec())?;
58 let rev_node = iter.next().unwrap();
59 let iter = &mut rev_node.iter();
60 let rev = iter
61 .take_while(|x| **x != b':')
62 .fold(0, |r, x| r * 10 + u64::from(*x - b'0'));
63 let node = iter.as_slice();
64 let node = String::from_utf8(node.to_vec())?;
65 bookmarks.push(Bookmark { name, rev, node });
66 }
67
68 Ok(Bookmarks { bookmarks, current })
69 }
70}