cargo/util/
vcs.rs

1use crate::util::paths;
2use crate::util::{process, CargoResult};
3use std::path::Path;
4
5// Check if we are in an existing repo. We define that to be true if either:
6//
7// 1. We are in a git repo and the path to the new package is not an ignored
8//    path in that repo.
9// 2. We are in an HG repo.
10pub fn existing_vcs_repo(path: &Path, cwd: &Path) -> bool {
11    fn in_git_repo(path: &Path, cwd: &Path) -> bool {
12        if let Ok(repo) = GitRepo::discover(path, cwd) {
13            // Don't check if the working directory itself is ignored.
14            if repo.workdir().map_or(false, |workdir| workdir == path) {
15                true
16            } else {
17                !repo.is_path_ignored(path).unwrap_or(false)
18            }
19        } else {
20            false
21        }
22    }
23
24    in_git_repo(path, cwd) || HgRepo::discover(path, cwd).is_ok()
25}
26
27pub struct HgRepo;
28pub struct GitRepo;
29pub struct PijulRepo;
30pub struct FossilRepo;
31
32impl GitRepo {
33    pub fn init(path: &Path, _: &Path) -> CargoResult<GitRepo> {
34        git2::Repository::init(path)?;
35        Ok(GitRepo)
36    }
37    pub fn discover(path: &Path, _: &Path) -> Result<git2::Repository, git2::Error> {
38        git2::Repository::discover(path)
39    }
40}
41
42impl HgRepo {
43    pub fn init(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {
44        process("hg").cwd(cwd).arg("init").arg(path).exec()?;
45        Ok(HgRepo)
46    }
47    pub fn discover(path: &Path, cwd: &Path) -> CargoResult<HgRepo> {
48        process("hg")
49            .cwd(cwd)
50            .arg("--cwd")
51            .arg(path)
52            .arg("root")
53            .exec_with_output()?;
54        Ok(HgRepo)
55    }
56}
57
58impl PijulRepo {
59    pub fn init(path: &Path, cwd: &Path) -> CargoResult<PijulRepo> {
60        process("pijul").cwd(cwd).arg("init").arg(path).exec()?;
61        Ok(PijulRepo)
62    }
63}
64
65impl FossilRepo {
66    pub fn init(path: &Path, cwd: &Path) -> CargoResult<FossilRepo> {
67        // fossil doesn't create the directory so we'll do that first
68        paths::create_dir_all(path)?;
69
70        // set up the paths we'll use
71        let db_fname = ".fossil";
72        let mut db_path = path.to_owned();
73        db_path.push(db_fname);
74
75        // then create the fossil DB in that location
76        process("fossil")
77            .cwd(cwd)
78            .arg("init")
79            .arg(&db_path)
80            .exec()?;
81
82        // open it in that new directory
83        process("fossil")
84            .cwd(&path)
85            .arg("open")
86            .arg(db_fname)
87            .exec()?;
88
89        // set `target` as ignoreable and cleanable
90        process("fossil")
91            .cwd(cwd)
92            .arg("settings")
93            .arg("ignore-glob")
94            .arg("target");
95        process("fossil")
96            .cwd(cwd)
97            .arg("settings")
98            .arg("clean-glob")
99            .arg("target");
100        Ok(FossilRepo)
101    }
102}