Compare commits

...

10 Commits

Author SHA1 Message Date
breadone
aaff62cbc6
rollback makefile change
add ip addr command
2024-08-12 23:35:29 +12:00
breadone
8d6f07bc26
update makefile 2024-08-12 23:31:41 +12:00
breadone
11374bf8f6
changed git delete to git rm 2024-07-30 11:43:29 +12:00
breadone
f0f02a2b60
Changed some formatting 2024-07-30 11:41:47 +12:00
breadone
e27053a4cc
make update finally works 2024-07-30 11:27:27 +12:00
breadone
d5b9431547
Added sys subcommand
Add restart subsubcommand
2024-07-30 11:18:54 +12:00
breadone
5068420359
update verison 2024-07-28 19:01:56 +12:00
breadone
07fce376c8
version 2 release! 2024-07-28 18:23:56 +12:00
breadone
bfdd939fc1
updated addremoterepo! 2024-07-28 18:14:57 +12:00
breadone
a514ff72d2
Updated initrepo 2024-07-28 18:12:42 +12:00
6 changed files with 183 additions and 72 deletions

2
Cargo.lock generated
View File

@ -100,7 +100,7 @@ checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
name = "bp"
version = "0.1.0"
version = "2.2.0"
dependencies = [
"clap",
"inquire",

View File

@ -1,6 +1,6 @@
[package]
name = "bp"
version = "0.1.0"
version = "2.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -1,4 +1,4 @@
UNAME := $(shell uname)
build:
@cargo build
@ -11,6 +11,11 @@ clean:
release: clean
@cargo build --release
update: release
@sudo cp target/release/bp /usr/bin
@echo "Copied release file to /usr/bin"
update: release
ifeq ($(UNAME), Darwin)
cp target/release/bp ~/bin/
endif
ifeq ($(UNAME), Linux)
sudo cp target/release/bp /usr/bin
endif

View File

@ -1,6 +1,6 @@
use clap::Subcommand;
use openssh::{Session, KnownHosts};
use inquire::{Select, InquireError};
use inquire::{Text, Select, Confirm, InquireError};
use core::str;
use std::process::Command;
@ -10,24 +10,24 @@ pub enum GitCommand {
Init {
#[arg()]
/// Name of the repo
name: String
name: Option<String>
},
/// List all repositories in breadpi.
Ls,
/// Delete the specified repository in breadpi.
Delete {
Rm {
#[arg()]
/// Name of the repo
name: String
name: Option<String>
},
/// Add remote to the git repo in the current directory
Add {
#[arg()]
/// Name of the repo
name: String
name: Option<String>
},
/// Clone a repo from the remote
@ -44,64 +44,25 @@ pub async fn handle_git(cmd: &GitCommand) {
.expect("Could not connect to git@breadpi");
match cmd {
GitCommand::Init { name } => {
let init = session.command("git")
.arg("init")
.arg("--bare")
.arg("store/".to_owned() + name + ".git")
.output().await.unwrap();
GitCommand::Init { name } => { init_repo(name, &session).await; }
eprintln!(
"{}",
String::from_utf8(init.stdout).expect("Failed to init git repo.")
);
GitCommand::Rm { name } => { rm_repo(name, &session).await; }
print!("Would you like to add the remote to the repo in this directory? (Y/n): ");
}
GitCommand::Add { name } => { add_remote_to_repo(name, &session).await; }
GitCommand::Delete { name } => {
let rm = session.command("rm")
.arg("-r")
.arg("-f")
.arg("store/".to_owned() + name + ".git")
.output().await.unwrap();
eprintln!(
"{}",
String::from_utf8(rm.stdout).expect("Failed to rm repo.")
);
}
GitCommand::Clone { name } => { clone_repo(name, &session).await; }
GitCommand::Ls => {
let ls = list_repos(&session).await.join("\n");
let ls = list_repos(&session).await.join("\n") + "\n";
print!("{ls}");
}
GitCommand::Add { name } => { add_remote_to_repo(name.to_string()); }
GitCommand::Clone { name } => { clone_repo(name, &session).await; }
}
let _ = session.close().await;
}
fn add_remote_to_repo(name: String) {
let cmd = Command::new("git")
.arg("remote")
.arg("add")
.arg("origin")
.arg("git@breadpi:/home/git/store/".to_owned() + &name + ".git")
.output().expect("Could not add remote");
eprintln!(
"{}",
String::from_utf8(cmd.stdout).expect("Failed to add git remote.")
);
println!("Added remote origin git@breadpi:/home/git/store/{name}.git");
}
async fn list_repos(session: &Session) -> Vec<String> {
let buf = session.command("ls")
.arg("store/")
@ -118,29 +79,102 @@ async fn list_repos(session: &Session) -> Vec<String> {
// split string into array
let list: Vec<String> = s.split("\n").map(str::to_string).collect();
let repos: Vec<String> = list.iter().map(|x| {
// remove the trailing .git from each item
let mut repos: Vec<String> = list.iter().map(|x| {
let mut chars = x.chars();
for _ in 0..4 { chars.next_back(); }
return chars.as_str().to_string();
} ).collect();
}).collect();
repos.truncate(repos.len() - 1);
return repos;
}
async fn clone_repo(name: &Option<String>, session: &Session) {
let mut unwrapped_name: String = "".to_string();
async fn choose_repo_from_list(session: &Session) -> String {
let list = list_repos(session).await;
let repos = list.iter().map(|s| s as &str).collect();
let repo: Result<&str, InquireError> = Select::new("Choose a repo: ", repos).prompt();
match repo {
Ok(s) => return s.to_string(),
Err(e) => panic!("{e}")
}
}
async fn add_remote_to_repo(name: &Option<String>, session: &Session) {
let unwrapped_name: String;
// check if name is null and present list if so
if name.is_none() {
let list = list_repos(session).await;
let repos = list.iter().map(|s| s as &str).collect();
unwrapped_name = choose_repo_from_list(session).await;
} else {
unwrapped_name = name.clone().unwrap();
}
let repo: Result<&str, InquireError> = Select::new("Choose a repo: ", repos).prompt();
let cmd = Command::new("git")
.arg("remote")
.arg("add")
.arg("origin")
.arg("git@breadpi:/home/git/store/".to_owned() + &unwrapped_name + ".git")
.output().expect("Could not add remote");
eprintln!(
"{}",
String::from_utf8(cmd.stdout).expect("Failed to add git remote.")
);
match repo {
Ok(s) => unwrapped_name = s.to_string(),
Err(_) => println!("error!")
println!("Added remote origin git@breadpi:/home/git/store/{unwrapped_name}.git");
}
async fn init_repo(name: &Option<String>, session: &Session) {
let unwrapped_name: String;
// check if name is null and present list if so
if name.is_none() {
let text = Text::new("Enter the repo name: ").prompt();
match text {
Ok(s) => unwrapped_name = s,
Err(e) => panic!("{e}")
}
} else {
unwrapped_name = name.clone().unwrap();
}
let init = session.command("git")
.arg("init")
.arg("--bare")
.arg("store/".to_owned() + &unwrapped_name + ".git")
.output().await.unwrap();
eprintln!(
"{}",
String::from_utf8(init.stdout).expect("Failed to init git repo.")
);
let add_repo = Confirm::new("Would you like to add the remote to the repo in this directory?").prompt();
if add_repo.is_ok_and(|choice| choice) {
add_remote_to_repo(&Some(unwrapped_name), session).await
}
// match add_repo {
// Ok(true) => add_remote_to_repo(&Some(unwrapped_name), session).await,
// Ok(false) => { return 0; },
// Err(e) => panic!("{e}")
// }
}
async fn clone_repo(name: &Option<String>, session: &Session) {
let unwrapped_name: String;
// check if name is null and present list if so
if name.is_none() {
unwrapped_name = choose_repo_from_list(session).await;
} else {
unwrapped_name = name.clone().unwrap();
}
@ -157,3 +191,25 @@ async fn clone_repo(name: &Option<String>, session: &Session) {
println!("Cloned repo git@breadpi:/home/git/store/{unwrapped_name} to {unwrapped_name}.");
}
async fn rm_repo(name: &Option<String>, session: &Session) {
let unwrapped_name: String;
// check if name is null and present list if so
if name.is_none() {
unwrapped_name = choose_repo_from_list(session).await;
} else {
unwrapped_name = name.clone().unwrap();
}
let rm = session.command("rm")
.arg("-r")
.arg("-f")
.arg("store/".to_owned() + &unwrapped_name + ".git")
.output().await.unwrap();
eprintln!(
"{}",
String::from_utf8(rm.stdout).expect("Failed to rm repo.")
);
}

View File

@ -1,25 +1,31 @@
mod git;
mod sys;
use sys::{SysCommand, handle_sys};
use tokio;
use clap::{Parser, Subcommand};
use crate::git::{handle_git, GitCommand};
const VERSION: &str = "2.0b1";
#[derive(Subcommand)]
enum Command {
/// Various commands for creating and adding git repos to breadpi.
Git {
#[command(subcommand)]
git_command: GitCommand
},
Sys {
#[command(subcommand)]
sys_command: SysCommand
}
}
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Command
command: Command,
}
#[tokio::main]
@ -27,8 +33,7 @@ async fn main() {
let cli = Cli::parse();
match &cli.command {
Command::Git { git_command } => {
handle_git(&git_command).await;
}
Command::Git { git_command } => { handle_git(&git_command).await; },
Command::Sys { sys_command } => { handle_sys(&sys_command).await; }
}
}

45
src/sys.rs Normal file
View File

@ -0,0 +1,45 @@
use clap::Subcommand;
use openssh::{Session, KnownHosts};
use core::str;
#[derive(Subcommand)]
pub enum SysCommand {
/// Reboot breadpi.
Reboot,
/// Returns the local IP address of breadpi.
Ip
}
pub async fn handle_sys(cmd: &SysCommand) {
let session = Session::connect("bread@breadpi", KnownHosts::Strict)
.await
.expect("Could not connect to breadpi");
match cmd {
SysCommand::Reboot => { sys_reboot(&session).await; },
SysCommand::Ip => { ip_addr(&session).await; }
}
let _ = session.close();
}
async fn sys_reboot(session: &Session) {
let cmd = session.command("sudo")
.arg("systemctl")
.arg("reboot")
.output().await.unwrap();
if !cmd.status.success() {
println!("Error rebooting! Try again, possibly directly through ssh...");
println!("Error: {:?}", String::from_utf8(cmd.stderr));
}
}
async fn ip_addr(session: &Session) {
let cmd = session.command("hostname")
.arg("-I")
.raw_arg("| grep -o '^[0-9.]*'")
.output().await.unwrap();
println!("{}", String::from_utf8(cmd.stdout).expect("nuh uh"));
}