feat: added fast subcommand

As described in preceding commits.

Also added documentation changes that I forgot to add before amending to
previous commit :(

Signed-off-by: Christina Sørensen <christina@cafkafk.com>
This commit is contained in:
Christina Sørensen 2023-07-01 14:57:41 +02:00
parent a52cc15f8e
commit be0cbc8849
Signed by: cafkafk
GPG key ID: CDDC792F655251ED
3 changed files with 112 additions and 13 deletions

View file

@ -77,6 +77,10 @@ pub enum Commands {
#[command(visible_alias = "q")] #[command(visible_alias = "q")]
Quick { msg: Option<String> }, Quick { msg: Option<String> },
/// Do fast pull-commit-push with msg for commit, skipping repo on failure
#[command(visible_alias = "f")]
Fast { msg: Option<String> },
/// Clone all repositories /// Clone all repositories
#[command(visible_alias = "c")] #[command(visible_alias = "c")]
Clone { msg: Option<String> }, Clone { msg: Option<String> },

View file

@ -81,6 +81,22 @@ pub struct GitRepo {
pub flags: Vec<RepoFlags>, pub flags: Vec<RepoFlags>,
} }
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
/// Represents a single operation on a repository
struct SeriesItem<'series> {
/// The string to be displayed to the user
operation: &'series str,
/// The closure representing the actual operation
closure: Box<dyn Fn(&GitRepo) -> (bool)>,
}
////////////////////////////////////
////////////////////////////////////
////////////////////////////////////
fn handle_file_exists(selff: &Links, tx_path: &Path, rx_path: &Path) { fn handle_file_exists(selff: &Links, tx_path: &Path, rx_path: &Path) {
match rx_path.read_link() { match rx_path.read_link() {
Ok(file) if file.canonicalize().unwrap() == tx_path.canonicalize().unwrap() => { Ok(file) if file.canonicalize().unwrap() == tx_path.canonicalize().unwrap() => {
@ -102,8 +118,8 @@ fn handle_file_exists(selff: &Links, tx_path: &Path, rx_path: &Path) {
} }
impl Links { impl Links {
/// Creates a link from a file /// Creates the link from the link struct
fn link(&self) { pub fn link(&self) {
let tx_path: &Path = std::path::Path::new(&self.tx); let tx_path: &Path = std::path::Path::new(&self.tx);
let rx_path: &Path = std::path::Path::new(&self.rx); let rx_path: &Path = std::path::Path::new(&self.rx);
match rx_path.try_exists() { match rx_path.try_exists() {
@ -216,7 +232,9 @@ impl GitRepo {
false false
} }
} }
/// Removes repository /// Removes a repository (not implemented)
///
/// Kept here as a reminder that we probably shouldn't do this
fn remove(&self) -> Result<(), std::io::Error> { fn remove(&self) -> Result<(), std::io::Error> {
// https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html // https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html
unimplemented!("This seems to easy to missuse/exploit"); unimplemented!("This seems to easy to missuse/exploit");
@ -224,14 +242,9 @@ impl GitRepo {
} }
} }
struct SeriesItem<'series> {
operation: &'series str,
closure: Box<dyn Fn(&GitRepo) -> (bool)>,
}
impl Config { impl Config {
/* GIT RELATED */ /* GIT RELATED */
/// Reads the configuration toml from a path. /// Loads the configuration toml from a path in to the Config struct.
pub fn new(path: &String) -> Self { pub fn new(path: &String) -> Self {
debug!("initializing new Config struct"); debug!("initializing new Config struct");
let yaml = fs::read_to_string(path).unwrap_or_else(|_| { let yaml = fs::read_to_string(path).unwrap_or_else(|_| {
@ -245,6 +258,9 @@ impl Config {
) )
}) })
} }
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
/// Runs associated function on all repos in config /// Runs associated function on all repos in config
/// ///
/// TODO: need to be made over a generic repo type /// TODO: need to be made over a generic repo type
@ -286,8 +302,6 @@ impl Config {
/// ///
/// TODO: need to be made over a generic repo type /// TODO: need to be made over a generic repo type
/// ///
/// NOTE: currently unused
///
/// # Current Problem /// # Current Problem
/// ///
/// The goal of this function is that it should run some function on all /// The goal of this function is that it should run some function on all
@ -343,6 +357,55 @@ impl Config {
} }
} }
} }
/// Runs associated function on all repos in config
///
/// Unlike `series_on_all`, this does not stop if it encounters an error
///
/// # Usage
///
/// Here is an example of how an associated method could use this function.
///
/// ```
/// let series: Vec<SeriesItem> = vec![
/// SeriesItem {
/// operation: "pull",
/// closure: Box::new(move |repo: &GitRepo| repo.pull()),
/// },
/// SeriesItem {
/// operation: "add",
/// closure: Box::new(move |repo: &GitRepo| repo.add_all()),
/// },
/// SeriesItem {
/// operation: "commit",
/// closure: Box::new(move |repo: &GitRepo| repo.commit()),
/// },
/// SeriesItem {
/// operation: "push",
/// closure: Box::new(move |repo: &GitRepo| repo.push()),
/// },
/// ];
/// self.all_on_all(series);
/// ```
pub fn all_on_all(&self, closures: Vec<SeriesItem>) {
for (_, category) in self.categories.iter() {
for (_, repo) in category.repos.iter() {
for instruction in closures.iter() {
let f = &instruction.closure;
let op = instruction.operation;
let mut sp =
Spinner::new(Spinners::Dots10, format!("{}: {}", repo.name, op).into());
if f(repo) {
sp.stop_and_persist("", format!("{}: {}", repo.name, op).into());
} else {
sp.stop_and_persist("", format!("{}: {}", repo.name, op).into());
}
}
}
}
}
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
/// Tries to pull all repositories, skips if fail. /// Tries to pull all repositories, skips if fail.
pub fn pull_all(&self) { pub fn pull_all(&self) {
debug!("exectuting pull_all"); debug!("exectuting pull_all");
@ -370,6 +433,8 @@ impl Config {
} }
/// Tries to pull, add all, commit with msg "quick commit", and push all /// Tries to pull, add all, commit with msg "quick commit", and push all
/// repositories, skips if fail. /// repositories, skips if fail.
///
/// FIXME currently msg isn't used
pub fn quick(&self, msg: &String) { pub fn quick(&self, msg: &String) {
debug!("exectuting quick"); debug!("exectuting quick");
let series: Vec<SeriesItem> = vec![ let series: Vec<SeriesItem> = vec![
@ -390,10 +455,37 @@ impl Config {
closure: Box::new(move |repo: &GitRepo| repo.push()), closure: Box::new(move |repo: &GitRepo| repo.push()),
}, },
]; ];
self.all_on_all(series);
}
/// Tries to pull, add all, commit with msg "quick commit", and push all
/// repositories, skips if fail.
///
/// FIXME currently msg isn't used
pub fn fast(&self, msg: &String) {
debug!("exectuting fast");
let series: Vec<SeriesItem> = vec![
SeriesItem {
operation: "pull",
closure: Box::new(move |repo: &GitRepo| repo.pull()),
},
SeriesItem {
operation: "add",
closure: Box::new(move |repo: &GitRepo| repo.add_all()),
},
SeriesItem {
operation: "commit",
closure: Box::new(move |repo: &GitRepo| repo.commit()),
}, // FIXME doesn't take msg
SeriesItem {
operation: "push",
closure: Box::new(move |repo: &GitRepo| repo.push()),
},
];
self.series_on_all(series); self.series_on_all(series);
} }
//////////////////////////////////////////////////////////////
/* LINK RELATED */ //////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
/// Tries to link all repositories, skips if fail. /// Tries to link all repositories, skips if fail.
pub fn link_all(&self) { pub fn link_all(&self) {
debug!("exectuting link_all"); debug!("exectuting link_all");

View file

@ -70,6 +70,9 @@ fn main() {
Some(Commands::Quick { msg }) => { Some(Commands::Quick { msg }) => {
config.quick(msg.as_ref().get_or_insert(&"gg: quick commit".to_string())); config.quick(msg.as_ref().get_or_insert(&"gg: quick commit".to_string()));
} }
Some(Commands::Fast { msg }) => {
config.fast(msg.as_ref().get_or_insert(&"gg: fast commit".to_string()));
}
Some(Commands::Clone { msg: _ }) => { Some(Commands::Clone { msg: _ }) => {
config.clone_all(); config.clone_all();
} }