Pass all tests successfully (for the moment)

This commit is contained in:
southerntofu 2022-01-07 19:30:06 +01:00
parent 70b0edaf89
commit 38d85f954a
2 changed files with 120 additions and 20 deletions

View File

@ -1,7 +1,8 @@
use std::env::{set_current_dir as cd, current_dir as pwd};
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::process::Command; use std::process::Command;
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Backend { pub enum Backend {
Git, Git,
Mercurial, Mercurial,
@ -55,13 +56,14 @@ impl Repo {
unreachable!("UNIMPLEMENTED!"); unreachable!("UNIMPLEMENTED!");
} }
Backend::Unknown(name) => { Backend::Unknown(name) => {
panic!("Uknown backend: {}. Cannot find ranch", name); // TODO: This should be a forgebuild error message
panic!("Uknown backend: {}. Cannot find branch", name);
} }
} }
} }
pub fn clone(&self) -> bool { pub fn clone(&self) -> bool {
match &self.backend { let success = match &self.backend {
Backend::Git => { Backend::Git => {
let output = Command::new("git") let output = Command::new("git")
.arg("clone") .arg("clone")
@ -76,14 +78,40 @@ impl Repo {
unreachable!("Unimplemented"); unreachable!("Unimplemented");
} }
Backend::Unknown(name) => { Backend::Unknown(name) => {
// TODO: This should be a forgebuild error message
eprintln!("Unknown DVCS: {}", name); eprintln!("Unknown DVCS: {}", name);
false false
} }
};
// If the clone was successful and subupdates is enabled,
// List submodules and check them for updates
if success && self.subupdates {
self.subupdate();
} }
return success
}
/// Checks for updates from submodules. If any update was found, download them and return true.
pub fn subupdate(&self) -> bool {
let mut found_subupdates = false;
for subpath in self.submodules() {
// Move into the submodule
cd(self.dest.join(subpath)).unwrap();
// Generate a Repo instance for the submodule but don't enable subupdates
// Just in case someone would trigger an infinite loop by accident
let subrepo = Repo::new(self.backend.clone(), "irrelevant", &pwd().expect("Failed to read pwd"), false);
if subrepo.update() {
found_subupdates = true;
}
// Move back into main repo
cd(&self.dest).unwrap();
}
found_subupdates
} }
pub fn checkout(&self, target: &str) -> bool { pub fn checkout(&self, target: &str) -> bool {
println!("CHECKOUT TO {}", target);
match &self.backend { match &self.backend {
Backend::Git => { Backend::Git => {
let status = Command::new("git") let status = Command::new("git")
@ -97,12 +125,51 @@ impl Repo {
unreachable!("UNIMPLEMENTED"); unreachable!("UNIMPLEMENTED");
} }
Backend::Unknown(name) => { Backend::Unknown(name) => {
// TODO: This should be a forgebuild error message
eprintln!("Unknown DVCS: {}", name); eprintln!("Unknown DVCS: {}", name);
false false
} }
} }
} }
/// Parse the list of submodules in the current repository
/// When there is no submodules (eg. no .gitmodules file), return an empty Vec
pub fn submodules(&self) -> Vec<PathBuf> {
match &self.backend {
Backend::Git => {
let cmd = Command::new("git")
.arg("config")
.arg("--file")
.arg(&format!("{}/.gitmodules", self.dest.to_str().unwrap()))
.arg("--get-regexp")
.arg("path")
.output()
.expect("WTF");
if cmd.status.success() {
// Command succeded, split by the first space character to find the path to the submodule
let out = std::string::String::from_utf8(cmd.stdout).expect("Wrong unicode");
let mut results = Vec::new();
for line in out.lines() {
results.push(PathBuf::from(line.split_once(" ").expect("Misformed .gitmodules").1));
}
results
} else {
// No submodules found (even if .gitmodules exist but is empty)
Vec::new()
}
},
Backend::Mercurial => {
unimplemented!("Soon");
},
Backend::Unknown(name) => {
// TODO: This should be a forgebuild error message
eprintln!("Unknown DVCS:{}!", name);
Vec::new()
}
}
}
/// Check for updates on the main repository
pub fn has_updates(&self) -> bool { pub fn has_updates(&self) -> bool {
match &self.backend { match &self.backend {
Backend::Git => { Backend::Git => {
@ -116,6 +183,7 @@ impl Repo {
.success() .success()
{ {
// FAILED, no internet?? // FAILED, no internet??
// TODO: This should be a forgebuild error message
eprintln!("Fetching updates failed"); eprintln!("Fetching updates failed");
return false; return false;
} }
@ -123,7 +191,7 @@ impl Repo {
if Command::new("git") if Command::new("git")
.arg("diff") .arg("diff")
.arg("--quiet") .arg("--quiet")
.arg(format!("remotes/origin/{}", &branch)) .arg(&format!("remotes/origin/{}", &branch))
.status() .status()
.expect("WTF") .expect("WTF")
.success() .success()
@ -133,31 +201,57 @@ impl Repo {
} }
// Updates // Updates
return true; return true;
} },
Backend::Mercurial => { Backend::Mercurial => {
unreachable!("unimplemented"); unimplemented!();
} },
Backend::Unknown(name) => { Backend::Unknown(name) => {
// TODO: This should be a forgebuild error message
eprintln!("Unknown DVCS:{}!", name); eprintln!("Unknown DVCS:{}!", name);
false false
} }
} }
} }
/*
/// Runs an update on the repository in dest. Returns true /// Checks if the repository has updates, if so download them
/// when an update was performed, false otherwise /// Returns true if updates have been applied, false otherwise
pub fn update(&self, dest: &str) -> bool { /// Also applies submodules updates if self.subupdates is true
match self { pub fn update(&self) -> bool {
match &self.backend {
Backend::Git => { Backend::Git => {
// First try to run submodules updates
let had_subupdates = if self.subupdates { self.subupdate() } else { false };
}, // Now run main repo updates
if self.has_updates() {
if Command::new("git")
.arg("pull")
.arg("--ff-only")
.arg("origin")
.arg(self.branch())
.status()
.expect("WTF")
.success()
{
// Main updates succeeded
return true;
} else {
// Main updates failed, return true if there were some submodule updates
return had_subupdates;
}
}
// No main updates
return had_subupdates;
}
Backend::Mercurial => { Backend::Mercurial => {
unreachable!("unimplemented");
}, }
Backend::Unknown(name) => { Backend::Unknown(name) => {
eprintln!("Unknown DVCS: {}", name); // TODO: This should be a forgebuild error message
eprintln!("Unknown DVCS:{}!", name);
false false
} }
} }
}*/ }
} }

View File

@ -64,10 +64,14 @@ impl Task {
let dest = source_dir_from_basedir(&basedir, &name); let dest = source_dir_from_basedir(&basedir, &name);
let cloned = source.clone().map_or(false, |_| dest.is_dir()); let cloned = source.clone().map_or(false, |_| dest.is_dir());
let subupdates = read_extension(path, "subupdates").is_some(); let subupdates = read_extension(path, "subupdates").is_some();
let checkout = read_extension(path, "checkout");
// Copy the global context so we have a more local scope // Copy the global context so we have a more local scope
let mut context = context.clone(); let mut context = context.clone();
context.insert("$i18n_task".to_string(), name.clone()); context.insert("$i18n_task".to_string(), name.clone());
if let Some(branch) = &checkout {
context.insert("$i18n_branch".to_string(), branch.to_string());
}
if let Some(source_url) = &source { if let Some(source_url) = &source {
context.insert("$i18n_source".to_string(), source_url.clone()); context.insert("$i18n_source".to_string(), source_url.clone());
} }
@ -86,7 +90,7 @@ impl Task {
}), }),
source, source,
config: HashMap::new(), config: HashMap::new(),
branch: read_extension(path, "checkout"), branch: checkout,
hosts: read_extension(path, "hosts").map_or(Vec::new(), |c| { hosts: read_extension(path, "hosts").map_or(Vec::new(), |c| {
c.split("\n").map(|line| line.to_string()).collect() c.split("\n").map(|line| line.to_string()).collect()
}), }),
@ -99,6 +103,8 @@ impl Task {
pub fn checkout(&self) { pub fn checkout(&self) {
if let Some(branch) = &self.branch { if let Some(branch) = &self.branch {
if let Some(repo) = &self.repo { if let Some(repo) = &self.repo {
self.info("to_branch");
self.debug("checkout");
repo.checkout(branch); repo.checkout(branch);
} }
} }
@ -120,7 +126,7 @@ impl Task {
pub fn update_and_run(&self, force: &bool) { pub fn update_and_run(&self, force: &bool) {
if let Some(repo) = &self.repo { if let Some(repo) = &self.repo {
if repo.has_updates() { if repo.update() {
self.run(); self.run();
} else if *force { } else if *force {
self.debug("forcing"); self.debug("forcing");