commit ccd06709150b08234b4d77d24fc402599b6e6a8c
parent b4b4c67b1766a18b72b35af0d94dbc50e31fc4e8
Author: Stefan Koch <programming@stefan-koch.name>
Date: Sun, 15 Sep 2019 15:25:00 +0200
allow to pass the branch to be checked out and built
Diffstat:
6 files changed, 114 insertions(+), 25 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -33,12 +33,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "cinderella"
version = "0.1.0"
dependencies = [
+ "getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
"git2 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
+name = "getopts"
+version = "0.2.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
name = "getrandom"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -251,6 +260,11 @@ dependencies = [
]
[[package]]
+name = "unicode-width"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
name = "url"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -276,6 +290,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
"checksum cc 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "b548a4ee81fccb95919d4e22cfea83c7693ebfd78f0495493178db20b3139da7"
"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
+"checksum getopts 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872"
"checksum git2 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "327d698f86a7ebdfeb86a4238ccdb004828939d3a3555b6ead679541d14e36c0"
"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9"
@@ -302,6 +317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum toml 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7aabe75941d914b72bf3e5d3932ed92ce0664d49d8432305a8b547c37227724"
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426"
+"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61"
"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95"
"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7"
diff --git a/Cargo.toml b/Cargo.toml
@@ -5,6 +5,7 @@ authors = ["Stefan Koch <programming@stefan-koch.name>"]
edition = "2018"
[dependencies]
+getopts = "0.2"
git2 = { version = "0.10.0", features = ["vendored-openssl"] }
rand = "0.7.0"
toml = { version = "0.5", features = ["preserve_order"] }
diff --git a/src/lib.rs b/src/lib.rs
@@ -9,35 +9,55 @@ mod pipeline;
mod execution;
use crate::vcs::CodeSource;
+use crate::vcs::WorkingCopy;
-fn random_dir() -> String {
- rand::thread_rng()
+pub struct RepoPointer {
+ pub repo_url: String,
+ pub branch: Option<String>,
+}
+
+fn random_dir(base_path: &str) -> PathBuf {
+ let mut tempdir = PathBuf::from(base_path);
+
+ let random_dirname = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(10)
- .collect::<String>()
+ .collect::<String>();
+ tempdir.push(random_dirname);
+
+ tempdir
}
-pub fn run(repo_url: &str) {
- let repo = vcs::Git {
- src: String::from(repo_url),
+fn cinderella_file(folder: &PathBuf) -> PathBuf {
+ let mut cinderella_file = folder.clone();
+ cinderella_file.push(".cinderella.toml");
+
+ cinderella_file
+}
+
+pub fn run(repo_ptr: &RepoPointer) {
+ let repo = vcs::GitSource {
+ src: String::from(&repo_ptr.repo_url),
};
// generate a temp unique work dir
- let mut tempdir = PathBuf::from("/tmp/cinderella");
- tempdir.push(random_dir());
-
+ let tempdir = random_dir("/tmp/cinderella");
let workdir = repo.fetch(&tempdir).expect("could not clone repo");
println!("Workdir is at {:?}", workdir.path);
+ // checkout the branch if a branch was provided
+ if let Some(branch) = &repo_ptr.branch {
+ println!("Switching to branch {}", branch);
+ workdir.checkout_branch(&branch);
+ }
+
// Switch to the exported work dir so that all commands
// are executed there
assert!(env::set_current_dir(&workdir.path).is_ok());
- let mut cinderella_file = workdir.path.clone();
- cinderella_file.push(".cinderella.toml");
-
- if let Some(pipelines) = pipeline::load_pipeline(".cinderella.toml") {
+ let cinderella_file = cinderella_file(&workdir.path);
+ if let Some(pipelines) = pipeline::load_pipeline(&cinderella_file) {
execution::execute(&pipelines);
} else {
println!("No Cinderella configuration found");
diff --git a/src/main.rs b/src/main.rs
@@ -1,11 +1,36 @@
use std::env;
+use getopts::Options;
+use cinderella::RepoPointer;
+
+fn print_usage(program: &str, opts: Options) {
+ let brief = format!("Usage: {} REPO_URL [options]", program);
+ print!("{}", opts.usage(&brief));
+}
+
fn main() {
let args: Vec<String> = env::args().collect();
+ let program = args[0].clone();
+
+ let mut opts = Options::new();
+ opts.optopt("b", "branch", "set the branch to checkout", "BRANCH");
- if args.len() > 1 {
- cinderella::run(&args[1])
+ let matches = match opts.parse(&args[1..]) {
+ Ok(m) => { m },
+ Err(f) => { panic!(f.to_string()) },
+ };
+
+ let repository_url = if !matches.free.is_empty() {
+ matches.free[0].clone()
} else {
- println!("Please specify the URL to a git repository");
- }
+ print_usage(&program, opts);
+ return;
+ };
+
+ let repo = RepoPointer {
+ repo_url: repository_url,
+ branch: matches.opt_str("b"),
+ };
+
+ cinderella::run(&repo)
}
diff --git a/src/pipeline.rs b/src/pipeline.rs
@@ -1,4 +1,5 @@
use std::fs;
+use std::path::PathBuf;
use toml::Value;
#[derive(Debug)]
@@ -7,7 +8,7 @@ pub struct Pipeline {
pub commands: Vec<String>,
}
-pub fn load_pipeline(path: &str) -> Option<Vec<Pipeline>> {
+pub fn load_pipeline(path: &PathBuf) -> Option<Vec<Pipeline>> {
if let Ok(contents) = fs::read_to_string(path) {
let data = contents.parse::<Value>().unwrap();
diff --git a/src/vcs.rs b/src/vcs.rs
@@ -5,30 +5,56 @@ use std::path::{Path, PathBuf};
use git2::Repository;
pub trait CodeSource {
- fn fetch(&self, target: &Path) -> Result<WorkDir, Box<dyn Error>>;
+ // TODO: Returned working copy here should be dynamic
+ fn fetch(&self, target: &Path) -> Result<GitWorkingCopy, Box<dyn Error>>;
}
-pub struct Git {
+pub trait WorkingCopy {
+ fn checkout_branch(&self, branch: &str);
+}
+
+pub struct GitSource {
pub src: String,
}
-pub struct WorkDir {
+pub struct GitWorkingCopy {
pub path: PathBuf,
+ repo: Repository,
}
-impl CodeSource for Git {
- fn fetch(&self, target: &Path) -> Result<WorkDir, Box<dyn Error>> {
+impl CodeSource for GitSource {
+ fn fetch(&self, target: &Path) -> Result<GitWorkingCopy, Box<dyn Error>> {
let repo = Repository::clone(&self.src, target)?;
+
let path = repo.workdir()
.expect("Newly cloned repo is expected to have a workdir");
- Ok(WorkDir {
+ Ok(GitWorkingCopy {
path: path.to_path_buf(),
+ repo: repo,
})
}
}
-impl Drop for WorkDir {
+impl WorkingCopy for GitWorkingCopy {
+ fn checkout_branch(&self, branch_name: &str) {
+ let revname = format!("refs/remotes/origin/{}", branch_name);
+ self.checkout_rev(&revname);
+ }
+}
+
+impl GitWorkingCopy {
+ fn checkout_rev(&self, rev: &str) {
+ let obj = self.repo.revparse_single(rev).unwrap();
+
+ self.repo.checkout_tree(
+ &obj,
+ None
+ );
+ }
+}
+
+impl Drop for GitWorkingCopy {
fn drop(&mut self) {
// TODO: Only write this error to a log file, but do not panic
fs::remove_dir_all(&self.path)