1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

use super::common;
use crate::client::{Client, HglibError, Runner};
use crate::{runcommand, MkArg};

pub struct Arg<'a> {
    pub revrange: &'a [&'a str],
    pub path: &'a str,
    pub force: bool,
    pub newest: bool,
    pub bookmarks: bool,
    pub branch: &'a str,
    pub limit: Option<u32>,
    pub nomerges: bool,
    pub subrepos: bool,
}

impl<'a> Default for Arg<'a> {
    fn default() -> Self {
        Self {
            revrange: &[],
            path: "",
            force: false,
            newest: false,
            bookmarks: false,
            branch: "",
            limit: None,
            nomerges: false,
            subrepos: false,
        }
    }
}

impl<'a> Arg<'a> {
    fn run(&self, client: &mut Client) -> Result<(Vec<u8>, i32), HglibError> {
        runcommand!(
            client,
            "outgoing",
            &[self.path],
            "--template",
            common::CHANGESETS_TEMPLATE,
            "-r",
            self.revrange,
            "-f",
            self.force,
            "-n",
            self.newest,
            "-B",
            self.bookmarks,
            "-b",
            self.branch,
            "-l",
            self.limit,
            "-M",
            self.nomerges,
            "-S",
            self.subrepos
        )
    }
}

#[derive(Debug, PartialEq)]
pub struct Bookmark {
    pub bookmark: String,
    pub revision: String,
}

#[derive(Debug, PartialEq)]
pub enum Outgoing {
    Revisions(Vec<common::Revision>),
    Bookmarks(Vec<Bookmark>),
    Empty,
}

impl Client {
    pub fn outgoing(&mut self, x: Arg) -> Result<Outgoing, HglibError> {
        let data = match x.run(self) {
            Ok(ret) => ret.0,
            Err(e) => {
                if e.code == 1 {
                    return Ok(Outgoing::Empty);
                } else {
                    return Err(e);
                }
            }
        };

        let data = common::eatlines(&data, 2);
        if x.bookmarks {
            let mut res = Vec::new();
            let mut tmp: &[u8] = &[];
            let mut odd = false;
            for chunk in data
                .split(|c| *c == b' ' || *c == b'\n')
                .filter(|&c| !c.is_empty())
            {
                if odd {
                    res.push(Bookmark {
                        bookmark: String::from_utf8(tmp.to_vec())?,
                        revision: String::from_utf8(chunk.to_vec())?,
                    });
                    odd = false;
                } else {
                    tmp = chunk;
                    odd = true;
                }
            }
            Ok(Outgoing::Bookmarks(res))
        } else {
            Ok(Outgoing::Revisions(common::parserevs(data.to_vec())?))
        }
    }
}