rhq_core/
repository.rs

1//! defines functions/types related to local repository access.
2
3use std::ffi::OsStr;
4use std::fmt::Display;
5use std::path::{Path, PathBuf};
6
7use remote::Remote;
8use util::{self, process};
9use vcs::Vcs;
10
11
12/// local repository
13#[derive(Clone, Debug, Serialize, Deserialize)]
14pub struct Repository {
15    /// name of repository
16    name: String,
17    /// (canonicalized) absolute path of the repository
18    path: PathBuf,
19    /// used version control system
20    vcs: Vcs,
21    /// information of remote repository
22    #[serde(skip_serializing_if = "Option::is_none")]
23    remote: Option<Remote>,
24}
25
26impl Repository {
27    /// Make an instance of `Repository` from local path.
28    pub fn new<P: AsRef<Path>, R: Into<Option<Remote>>>(path: P, vcs: Vcs, remote: R) -> ::Result<Self> {
29        let path = util::canonicalize_pretty(path)?;
30        let name = path.file_name()
31            .map(|s| s.to_string_lossy().into_owned())
32            .ok_or("cannot determine repository name")?;
33        Ok(Repository {
34            name,
35            path,
36            vcs,
37            remote: remote.into(),
38        })
39    }
40
41    /// Check existence of repository and drop if not exists.
42    pub fn refresh(self) -> Option<Self> {
43        match self.vcs.get_remote_url(&self.path) {
44            Ok(url) => Self::new(self.path, self.vcs, url.map(Remote::new)).ok(),
45            _ => None,
46        }
47    }
48
49    pub fn is_same_local(&self, other: &Self) -> bool {
50        self.path.as_path() == other.path.as_path()
51    }
52
53    pub fn is_contained<P: AsRef<Path>>(&self, path: P) -> bool {
54        self.path.starts_with(path)
55    }
56
57    /// Run command into the repository.
58    pub fn run_command<I, S>(&self, command: &str, args: I) -> ::Result<bool>
59    where
60        I: IntoIterator<Item = S>,
61        S: AsRef<OsStr> + Display,
62    {
63        let output = process::inherit(command)
64            .args(args)
65            .current_dir(&self.path)
66            .output()?;
67        Ok(output.status.success())
68    }
69
70    pub fn name(&self) -> &str {
71        &self.name
72    }
73
74    pub fn path_string(&self) -> String {
75        format!("{}", self.path.display())
76    }
77
78    pub fn remote(&self) -> Option<&Remote> {
79        self.remote.as_ref()
80    }
81}