mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00

* Collapse the nested cargotest::support module into the cargotest module (merge the mod.rs's) * Rename the cargotest module to support * Nest the top-level hamcrest module into support
165 lines
4.5 KiB
Rust
165 lines
4.5 KiB
Rust
use std::fs::{self, File};
|
|
use std::io::prelude::*;
|
|
use std::path::{Path, PathBuf};
|
|
|
|
use cargo::util::ProcessError;
|
|
use git2;
|
|
use url::Url;
|
|
|
|
use support::{project, Project, ProjectBuilder, path2url};
|
|
|
|
#[must_use]
|
|
pub struct RepoBuilder {
|
|
repo: git2::Repository,
|
|
files: Vec<PathBuf>,
|
|
}
|
|
|
|
pub struct Repository(git2::Repository);
|
|
|
|
pub fn repo(p: &Path) -> RepoBuilder {
|
|
RepoBuilder::init(p)
|
|
}
|
|
|
|
impl RepoBuilder {
|
|
pub fn init(p: &Path) -> RepoBuilder {
|
|
t!(fs::create_dir_all(p.parent().unwrap()));
|
|
let repo = t!(git2::Repository::init(p));
|
|
{
|
|
let mut config = t!(repo.config());
|
|
t!(config.set_str("user.name", "name"));
|
|
t!(config.set_str("user.email", "email"));
|
|
}
|
|
RepoBuilder {
|
|
repo,
|
|
files: Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn file(self, path: &str, contents: &str) -> RepoBuilder {
|
|
let mut me = self.nocommit_file(path, contents);
|
|
me.files.push(PathBuf::from(path));
|
|
me
|
|
}
|
|
|
|
pub fn nocommit_file(self, path: &str, contents: &str) -> RepoBuilder {
|
|
let dst = self.repo.workdir().unwrap().join(path);
|
|
t!(fs::create_dir_all(dst.parent().unwrap()));
|
|
t!(t!(File::create(&dst)).write_all(contents.as_bytes()));
|
|
self
|
|
}
|
|
|
|
pub fn build(self) -> Repository {
|
|
{
|
|
let mut index = t!(self.repo.index());
|
|
for file in self.files.iter() {
|
|
t!(index.add_path(file));
|
|
}
|
|
t!(index.write());
|
|
let id = t!(index.write_tree());
|
|
let tree = t!(self.repo.find_tree(id));
|
|
let sig = t!(self.repo.signature());
|
|
t!(self.repo
|
|
.commit(Some("HEAD"), &sig, &sig, "Initial commit", &tree, &[]));
|
|
}
|
|
let RepoBuilder { repo, .. } = self;
|
|
Repository(repo)
|
|
}
|
|
}
|
|
|
|
impl Repository {
|
|
pub fn root(&self) -> &Path {
|
|
self.0.workdir().unwrap()
|
|
}
|
|
|
|
pub fn url(&self) -> Url {
|
|
path2url(self.0.workdir().unwrap().to_path_buf())
|
|
}
|
|
}
|
|
|
|
pub fn new<F>(name: &str, callback: F) -> Result<Project, ProcessError>
|
|
where
|
|
F: FnOnce(ProjectBuilder) -> ProjectBuilder,
|
|
{
|
|
let mut git_project = project().at(name);
|
|
git_project = callback(git_project);
|
|
let git_project = git_project.build();
|
|
|
|
let repo = t!(git2::Repository::init(&git_project.root()));
|
|
let mut cfg = t!(repo.config());
|
|
t!(cfg.set_str("user.email", "foo@bar.com"));
|
|
t!(cfg.set_str("user.name", "Foo Bar"));
|
|
drop(cfg);
|
|
add(&repo);
|
|
commit(&repo);
|
|
Ok(git_project)
|
|
}
|
|
|
|
pub fn add(repo: &git2::Repository) {
|
|
// FIXME(libgit2/libgit2#2514): apparently add_all will add all submodules
|
|
// as well, and then fail b/c they're a directory. As a stopgap, we just
|
|
// ignore all submodules.
|
|
let mut s = t!(repo.submodules());
|
|
for submodule in s.iter_mut() {
|
|
t!(submodule.add_to_index(false));
|
|
}
|
|
let mut index = t!(repo.index());
|
|
t!(index.add_all(
|
|
["*"].iter(),
|
|
git2::IndexAddOption::DEFAULT,
|
|
Some(
|
|
&mut (|a, _b| if s.iter().any(|s| a.starts_with(s.path())) {
|
|
1
|
|
} else {
|
|
0
|
|
})
|
|
)
|
|
));
|
|
t!(index.write());
|
|
}
|
|
|
|
pub fn add_submodule<'a>(
|
|
repo: &'a git2::Repository,
|
|
url: &str,
|
|
path: &Path,
|
|
) -> git2::Submodule<'a> {
|
|
let path = path.to_str().unwrap().replace(r"\", "/");
|
|
let mut s = t!(repo.submodule(url, Path::new(&path), false));
|
|
let subrepo = t!(s.open());
|
|
t!(subrepo.remote_add_fetch("origin", "refs/heads/*:refs/heads/*"));
|
|
let mut origin = t!(subrepo.find_remote("origin"));
|
|
t!(origin.fetch(&[], None, None));
|
|
t!(subrepo.checkout_head(None));
|
|
t!(s.add_finalize());
|
|
return s;
|
|
}
|
|
|
|
pub fn commit(repo: &git2::Repository) -> git2::Oid {
|
|
let tree_id = t!(t!(repo.index()).write_tree());
|
|
let sig = t!(repo.signature());
|
|
let mut parents = Vec::new();
|
|
match repo.head().ok().map(|h| h.target().unwrap()) {
|
|
Some(parent) => parents.push(t!(repo.find_commit(parent))),
|
|
None => {}
|
|
}
|
|
let parents = parents.iter().collect::<Vec<_>>();
|
|
t!(repo.commit(
|
|
Some("HEAD"),
|
|
&sig,
|
|
&sig,
|
|
"test",
|
|
&t!(repo.find_tree(tree_id)),
|
|
&parents
|
|
))
|
|
}
|
|
|
|
pub fn tag(repo: &git2::Repository, name: &str) {
|
|
let head = repo.head().unwrap().target().unwrap();
|
|
t!(repo.tag(
|
|
name,
|
|
&t!(repo.find_object(head, None)),
|
|
&t!(repo.signature()),
|
|
"make a new tag",
|
|
false
|
|
));
|
|
}
|