More rust I guess...

This commit is contained in:
Graham Christensen 2017-11-05 11:26:55 -05:00
parent 1fb5e7d6b9
commit 64efc98ee2
No known key found for this signature in database
GPG key ID: ACA1C1D120C83D5C
3 changed files with 158 additions and 63 deletions

View file

@ -1,9 +1,11 @@
use std::path::{Path,PathBuf}; use std::path::{Path,PathBuf};
use md5; use md5;
use std::fs; use std::fs;
use std::io::Error; use std::io::{Error,ErrorKind};
use ofborg::clone; use ofborg::clone;
use ofborg::clone::GitClonable; use ofborg::clone::GitClonable;
use std::ffi::OsStr;
use std::process::Command;
pub struct CachedCloner { pub struct CachedCloner {
root: PathBuf root: PathBuf
@ -20,6 +22,13 @@ pub struct CachedProject {
clone_url: String clone_url: String
} }
pub struct CachedProjectCo {
root: PathBuf,
id: String,
clone_url: String,
local_reference: PathBuf,
}
impl CachedCloner { impl CachedCloner {
pub fn project(&self, name: String, clone_url: String) -> CachedProject { pub fn project(&self, name: String, clone_url: String) -> CachedProject {
// <root>/repo/<hash>/clone // <root>/repo/<hash>/clone
@ -39,28 +48,111 @@ impl CachedCloner {
} }
impl CachedProject { impl CachedProject {
pub fn checkout_ref(&self, pub fn clone_for(&self, use_category: String, id: String) -> Result<CachedProjectCo, Error> {
name: String, self.prefetch_cache()?;
git_ref: String,
) -> Result<String, Error> {
let repo_cache_path = self.prefetch_cache()?;
// let build_dir = self.build_dir(); let mut new_root = self.root.clone();
new_root.push(use_category);
return Ok(repo_cache_path.to_str().unwrap().to_string()) return Ok(CachedProjectCo{
root: new_root,
id: id,
clone_url: self.clone_from().clone(),
local_reference: self.clone_to().clone(),
})
} }
fn prefetch_cache(&self) -> Result<PathBuf, Error> { fn prefetch_cache(&self) -> Result<PathBuf, Error> {
fs::create_dir_all(&self.root)?; fs::create_dir_all(&self.root)?;
self.clone_repo()?; self.clone_repo()?;
self.fetch_repo()?;
return Ok(self.clone_to()); return Ok(self.clone_to());
} }
} }
impl clone::GitClonable for CachedProject { impl CachedProjectCo {
pub fn checkout_ref(&self, git_ref: &OsStr) -> Result<String, Error> {
self.clone_repo()?;
self.fetch_repo()?;
self.clean()?;
self.checkout(git_ref)?;
// let build_dir = self.build_dir();
return Ok(self.clone_to().to_str().unwrap().to_string())
}
pub fn fetch_pr(&self, pr_id: i64) -> Result<(),Error> {
let mut lock = self.lock()?;
let result = Command::new("git")
.arg("fetch")
.arg("origin")
.arg(format!("+refs/pull/{}/head:pr", pr_id))
.current_dir(self.clone_to())
.status()?;
lock.unlock();
if result.success() {
return Ok(())
} else {
return Err(Error::new(ErrorKind::Other, "Failed to fetch PR"));
}
}
pub fn merge_commit(&self, commit: &OsStr) -> Result<(), Error> {
let mut lock = self.lock()?;
let result = Command::new("git")
.arg("merge")
.arg("--no-gpg-sign")
.arg("-m")
.arg("Automatic merge for GrahamCOfBorg")
.arg(commit)
.current_dir(self.clone_to())
.status()?;
lock.unlock();
if result.success() {
return Ok(())
} else {
return Err(Error::new(ErrorKind::Other, "Failed to merge"));
}
}
}
impl clone::GitClonable for CachedProjectCo {
fn clone_from(&self) -> String {
return self.clone_url.clone()
}
fn clone_to(&self) -> PathBuf {
let mut clone_path = self.root.clone();
clone_path.push(&self.id);
return clone_path
}
fn lock_path(&self) -> PathBuf {
let mut lock_path = self.root.clone();
lock_path.push(format!("{}.lock", self.id));
return lock_path
}
fn extra_clone_args(&self) -> Vec<&OsStr> {
let local_ref = self.local_reference.as_ref();
return vec![
OsStr::new("--shared"),
OsStr::new("--reference-if-able"),
local_ref,
]
}
}
impl clone::GitClonable for CachedProject {
fn clone_from(&self) -> String { fn clone_from(&self) -> String {
return self.clone_url.clone() return self.clone_url.clone()
} }
@ -73,55 +165,13 @@ impl clone::GitClonable for CachedProject {
fn lock_path(&self) -> PathBuf { fn lock_path(&self) -> PathBuf {
let mut clone_path = self.root.clone(); let mut clone_path = self.root.clone();
clone_path.set_file_name("clone.lock"); clone_path.push("clone.lock");
return clone_path return clone_path
} }
fn extra_clone_args(&self) -> Vec<String> { fn extra_clone_args(&self) -> Vec<&OsStr> {
return vec!() return vec![
OsStr::new("--bare"),
]
} }
} }
/*
fn try_clone_repo(&self) -> Result<(), Error> {
let result = Command::new("git")
.arg("clone")
.arg("--bare")
.arg(&self.clone_url)
.arg(&self.clone_path())
.status()?;
if result.success() {
return Ok(())
} else {
return Err(Error::new(ErrorKind::Other, "Failed to clone"));
}
}
fn try_fetch(&self) -> Result<(), Error> {
let result = Command::new("git")
.arg("fetch")
.arg("origin")
.current_dir(self.clone_path())
.status()?;
if result.success() {
return Ok(())
} else {
return Err(Error::new(ErrorKind::Other, "Failed to fetch"));
}
}
}
impl locks::Lockable for CachedProject {
fn lock_path(&self) -> PathBuf {
let mut clone_path = self.root.clone();
clone_path.set_file_name("clone.lock");
return clone_path
}
}
*/

View file

@ -3,7 +3,7 @@ use fs2::FileExt;
use std::fs; use std::fs;
use std::io::{Error,ErrorKind}; use std::io::{Error,ErrorKind};
use std::process::Command; use std::process::Command;
use std::ffi::OsStr;
pub struct Lock { pub struct Lock {
lock: Option<fs::File> lock: Option<fs::File>
@ -15,15 +15,15 @@ impl Lock {
} }
} }
pub trait GitClonable { pub trait GitClonable {
fn clone_from(&self) -> String; fn clone_from(&self) -> String;
fn clone_to(&self) -> PathBuf; fn clone_to(&self) -> PathBuf;
fn extra_clone_args(&self) -> Vec<String>; fn extra_clone_args(&self) -> Vec<&OsStr>;
fn lock_path(&self) -> PathBuf; fn lock_path(&self) -> PathBuf;
fn lock(&self) -> Result<Lock, Error> { fn lock(&self) -> Result<Lock, Error> {
println!("Locking {:?}", self.lock_path());
let lock = fs::File::create(self.lock_path())?; let lock = fs::File::create(self.lock_path())?;
lock.lock_exclusive()?; lock.lock_exclusive()?;
return Ok(Lock{ return Ok(Lock{
@ -60,7 +60,6 @@ pub trait GitClonable {
let result = Command::new("git") let result = Command::new("git")
.arg("fetch") .arg("fetch")
.arg("origin") .arg("origin")
.args(self.extra_clone_args())
.current_dir(self.clone_to()) .current_dir(self.clone_to())
.status()?; .status()?;
@ -72,4 +71,48 @@ pub trait GitClonable {
return Err(Error::new(ErrorKind::Other, "Failed to fetch")); return Err(Error::new(ErrorKind::Other, "Failed to fetch"));
} }
} }
fn clean(&self) -> Result<(), Error> {
let mut lock = self.lock()?;
Command::new("git")
.arg("am")
.arg("--abort")
.current_dir(self.clone_to())
.status()?;
Command::new("git")
.arg("merge")
.arg("--abort")
.current_dir(self.clone_to())
.status()?;
Command::new("git")
.arg("reset")
.arg("--hard")
.current_dir(self.clone_to())
.status()?;
lock.unlock();
return Ok(())
}
fn checkout(&self, git_ref: &OsStr) -> Result<(), Error> {
let mut lock = self.lock()?;
let result = Command::new("git")
.arg("checkout")
.arg(git_ref)
.current_dir(self.clone_to())
.status()?;
lock.unlock();
if result.success() {
return Ok(())
} else {
return Err(Error::new(ErrorKind::Other, "Failed to checkout"));
}
}
} }

View file

@ -18,10 +18,12 @@ fn main() {
let project = cloner.project("NixOS/nixpkgs".to_string(), let project = cloner.project("NixOS/nixpkgs".to_string(),
"https://github.com/nixos/nixpkgs.git".to_string() "https://github.com/nixos/nixpkgs.git".to_string()
); );
let co = project.clone_for("builder".to_string(),
"1234".to_string()).unwrap();
let refpath = project.checkout_ref("builder-1234".to_string(), let refpath = co.checkout_ref("origin/master".as_ref());
"origin/master".to_string() co.fetch_pr(31228).unwrap();
); co.merge_commit("7214d0f6f7a6467205761f87973140727154e1b3".as_ref()).unwrap();
match refpath { match refpath {
Ok(path) => { Ok(path) => {