diff options
| author | Bernhard Guillon <Bernhard.Guillon@begu.org> | 2025-09-22 16:00:28 +0200 |
|---|---|---|
| committer | Bernhard Guillon <Bernhard.Guillon@begu.org> | 2025-09-22 16:00:28 +0200 |
| commit | fce9ead9c50e00fb1315cd2c1df79a9fe79ddf13 (patch) | |
| tree | 1b0c924da8f216722c3cd2e31054b68e72816aed | |
| parent | 1bbbc6659120f79468ac0d60df42aae633926c3c (diff) | |
| download | future-me-fce9ead9c50e00fb1315cd2c1df79a9fe79ddf13.tar.gz future-me-fce9ead9c50e00fb1315cd2c1df79a9fe79ddf13.zip | |
future-me: move git stuff into it's own library
| -rw-r--r-- | Cargo.toml | 9 | ||||
| -rw-r--r-- | src/bin/main.rs (renamed from src/main.rs) | 266 | ||||
| -rw-r--r-- | src/git.rs | 231 |
3 files changed, 244 insertions, 262 deletions
@@ -3,6 +3,15 @@ name = "future-me" version = "0.1.0" edition = "2024" +[lib] +name = "git" +path = "src/git.rs" + +[[bin]] +name = "future-me" +path = "src/bin/main.rs" + + [dependencies] chrono = "0.4.42" serde = { version = "1.0.145", features = ["derive"] } diff --git a/src/main.rs b/src/bin/main.rs index c64f6fe..0812f49 100644 --- a/src/main.rs +++ b/src/bin/main.rs @@ -5,7 +5,7 @@ // I follow the copy all and fix it later approach. To make // rust a nice prototyping languague. If you don't like that // approach you do yours and I do mine ^^ - +use git::GitError; use serde::{Deserialize, Serialize}; use std::time::{SystemTime, UNIX_EPOCH}; use std::{ @@ -16,13 +16,14 @@ use std::{ process::Stdio, }; use std::fs; -use std::fmt; -use std::num::ParseIntError; use std::io::Write; use std::collections::HashMap; use chrono::{Utc, TimeZone}; use std::env::args; +// TODO +use git::*; + #[derive(Serialize, Deserialize, Debug, Default, Clone)] struct BugReport { timestamp: String, @@ -69,29 +70,7 @@ fn new_bug() -> String { serde_json::to_string(&report).unwrap() } -#[derive(Debug)] -enum GitError { - GitLog(String), - Parse(ParseIntError), - UnknownRef, -} -impl fmt::Display for GitError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - GitError::GitLog(s) => write!(f, "{}", s), - GitError::Parse(s) => write!(f, "{}", s), - GitError::UnknownRef => write!(f, "Unknown reference"), - } - } -} - -impl From<ParseIntError> for GitError { - fn from(err: ParseIntError) -> GitError { - GitError::Parse(err) - } -} -impl std::error::Error for GitError {} #[derive(Debug, Default, Clone)] struct GitLog{ @@ -217,44 +196,6 @@ fn show() { } } - -//create-new-bug() { -// readonly bug="$1" -// last_ref=$(git show-ref refs/notes/devtools/future-me | cut -d ' ' -f 1) -// echo $last_ref -// if [ -n "$last_ref" ] -// then -// git read-tree $last_ref -// else -// git read-tree --empty -// fi -// -// object_id=$(echo "$1" | git hash-object -w --stdin) -// echo $object_id -// file_path=${object_id:0:2}/${object_id:2} -// git update-index --add --cacheinfo 100644 $object_id $file_path -// tree_id=$(git write-tree) -// files_to_unstage=$(git update-index --refresh | cut -d ' ' -f 1 | cut -d ':' -f 1) -// git update-index --remove $files_to_unstage -// if [ -n "$last_ref" ] -// then -// add_parent="$last_ref" -// commit_id=$(echo 'future-me: created a new bug for you' | git commit-tree $tree_id -p $add_parent) -// else -// commit_id=$(echo 'future-me: created a new bug for you' | git commit-tree $tree_id) -// fi -// git update-ref refs/notes/devtools/future-me $commit_id -//} -// -// new) -// echo create new bug "$payload" #"${*:2}" -// check-git-status -// last_tree="$(git --no-pager log -1 --format="%H" | tr --delete '\n')" -// echo $last_tree -// create-new-bug "$payload" -// git read-tree "$last_tree" -// ;; - fn hash_to_path(hash: &str) -> String { format!("{}/{}", &hash[..2], &hash[2..]) } @@ -319,205 +260,6 @@ fn create_new_bug() { println!("hello new bug"); } -fn get_files_to_unstage() -> String { - let cmd = Command::new("git") - .arg("update-index") - .arg("--refresh") - .output() - .expect("Error with update-index"); - match cmd.status.code() { - Some(1) => (), - Some(0) => (), - Some(s) => panic!("Fixme status code: {}",s), - None => panic!("Fixme git update-index"), - } - let lines = String::from_utf8_lossy(&cmd.stdout).to_string(); - let mut files = String::default(); - for line in lines.lines() { - files = files + " " +line.split(":").next().unwrap(); - } - files[1..].to_string() -} - -fn unstage_object(path: &str) { - let cmd = Command::new("git") - .arg("update-index") - .arg("--remove") - .arg(path) - .output() - .expect("Error with update-index"); - if !cmd.status.success() { - panic!("FIXME unstage_object failed"); - } -} - -fn update_ref(object: &str) { - let cmd = Command::new("git") - .arg("update-ref") - .arg("refs/notes/devtools/future-me") - .arg(object) - .output() - .expect("Error with update-index"); - if !cmd.status.success() { - panic!("FIXME: update ref failed"); - } -} - -fn stage_object(hash: &str, path: &str) { - // with git update-index --add --cacheinfo 100644 hash dd/fffff - let cmd = Command::new("git") - .arg("update-index") - .arg("--add") - .arg("--cacheinfo") - .arg("100644") - .arg(hash) - .arg(path) - .output() - .expect("Error with update-index"); - if !cmd.status.success() { - panic!("FIXME"); - } -} - -fn create_object(object: String) -> Result<String, GitError> { - - // create an git object with git hash-object -w --stdin - let mut files = Command::new("git") - .arg("hash-object") - .arg("-w") - .arg("--stdin") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Error with git hash-ojbect"); - - let mut stdin = files.stdin.take().expect("Failed to open stdin"); - std::thread::spawn(move || { - stdin.write_all(object.as_bytes()).expect("Failed to write to stdin"); - }); - - let output = files.wait_with_output().expect("Failed to write to stdout"); - let lines = String::from_utf8_lossy(&output.stdout).to_string(); - Ok(lines.split_whitespace().next().unwrap().to_string()) -} - -fn commit(object: String, parent: Option<String>) -> Result<String, GitError> { - // commit_id=$(echo 'future-me: created a new bug for you' | git commit-tree $tree_id) - let mut files = match parent { - Some(parent) => - Command::new("git") - .arg("commit-tree") - .arg(object) - .arg("-p") - .arg(parent) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Error with git commit-tree"), - None => - Command::new("git") - .arg("commit-tree") - .arg(object) - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Error with git commit-tree"), - }; - - let mut stdin = files.stdin.take().expect("Failed to open stdin"); - std::thread::spawn(move || { - stdin.write_all("future-me: created a new bug for you".as_bytes()).expect("Failed to write to stdin"); - }); - - let output = files.wait_with_output().expect("Failed to write to stdout"); - let lines = String::from_utf8_lossy(&output.stdout).to_string(); - Ok(lines.split_whitespace().next().unwrap().to_string()) -} - -fn get_last_ref() -> Result<String, GitError> { - let cmd = Command::new("git") - .arg("show-ref") - .arg("refs/notes/devtools/future-me") - .output() - .expect("Error with git show-ref"); - if !cmd.status.success() { - //return GitError::GitLog(String::from_utf8_lossy(&cmd.stderr).to_string()); - GitError::GitLog(String::from_utf8_lossy(&cmd.stderr).to_string()); - } - let lines = String::from_utf8_lossy(&cmd.stdout); - - match lines.split_whitespace().next() { - Some(line) => Ok(line.to_string()), - None => Err(GitError::UnknownRef), - } -} - -fn get_current_tree() -> Result<String, GitError>{ - let cmd = Command::new("git") - .arg("log") - .arg("-1") - .arg("--format=%H") - .output() - .expect("Error with git log"); - if !cmd.status.success() { - GitError::GitLog(String::from_utf8_lossy(&cmd.stderr).to_string()); - } - let lines = String::from_utf8_lossy(&cmd.stdout); - Ok(lines.trim().to_string()) -} - -fn write_tree() -> String { - let cmd = Command::new("git") - .arg("write-tree") - .output() - .expect("Error with git write-tree"); - if !cmd.status.success() { - panic!("{}", String::from_utf8_lossy(&cmd.stderr)); - } - let lines = String::from_utf8_lossy(&cmd.stdout); - lines.trim().to_string() -} - -fn create_new_tree() { - let cmd = Command::new("git") - .arg("read-tree") - .arg("--empty") - .output() - .expect("Error with git read-tree"); - if !cmd.status.success() { - panic!("{}", String::from_utf8_lossy(&cmd.stderr)); - } -} - -fn read_tree(tree: &str) { - let cmd = Command::new("git") - .arg("read-tree") - .arg(tree) - .output() - .expect("Error with git read-tree"); - if !cmd.status.success() { - panic!("{}", String::from_utf8_lossy(&cmd.stderr)); - } -} - -fn check_status() { - let logs = Command::new("git") - .arg("status") - .arg("--porcelain") - .output() - .expect("Error with git status"); - if !logs.status.success() { - GitError::GitLog(String::from_utf8_lossy(&logs.stderr).to_string()); - } - let lines = String::from_utf8_lossy(&logs.stdout); - for line in lines.lines() { - println!("{}", line); - if line.starts_with(['M', 'A']) { - panic!("You first need to clean you git staging status to use future-me"); - } - } -} - fn print_usage() { println!("usage: future-me <command>\n"); println!("commands:"); diff --git a/src/git.rs b/src/git.rs new file mode 100644 index 0000000..728b247 --- /dev/null +++ b/src/git.rs @@ -0,0 +1,231 @@ +use std::num::ParseIntError; +use std::fmt; +use std::process::Command; +use std::io::Write; +use std::process::Stdio; + +#[derive(Debug)] +pub enum GitError { + GitLog(String), + Parse(ParseIntError), + UnknownRef, +} +impl fmt::Display for GitError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + GitError::GitLog(s) => write!(f, "{}", s), + GitError::Parse(s) => write!(f, "{}", s), + GitError::UnknownRef => write!(f, "Unknown reference"), + } + } +} +impl From<ParseIntError> for GitError { + fn from(err: ParseIntError) -> GitError { + GitError::Parse(err) + } +} +impl std::error::Error for GitError {} + +////// TODO +pub fn get_files_to_unstage() -> String { + let cmd = Command::new("git") + .arg("update-index") + .arg("--refresh") + .output() + .expect("Error with update-index"); + match cmd.status.code() { + Some(1) => (), + Some(0) => (), + Some(s) => panic!("Fixme status code: {}",s), + None => panic!("Fixme git update-index"), + } + let lines = String::from_utf8_lossy(&cmd.stdout).to_string(); + let mut files = String::default(); + for line in lines.lines() { + files = files + " " +line.split(":").next().unwrap(); + } + files[1..].to_string() +} + +pub fn unstage_object(path: &str) { + let cmd = Command::new("git") + .arg("update-index") + .arg("--remove") + .arg(path) + .output() + .expect("Error with update-index"); + if !cmd.status.success() { + panic!("FIXME unstage_object failed"); + } +} + +pub fn update_ref(object: &str) { + let cmd = Command::new("git") + .arg("update-ref") + .arg("refs/notes/devtools/future-me") + .arg(object) + .output() + .expect("Error with update-index"); + if !cmd.status.success() { + panic!("FIXME: update ref failed"); + } +} + +pub fn stage_object(hash: &str, path: &str) { + // with git update-index --add --cacheinfo 100644 hash dd/fffff + let cmd = Command::new("git") + .arg("update-index") + .arg("--add") + .arg("--cacheinfo") + .arg("100644") + .arg(hash) + .arg(path) + .output() + .expect("Error with update-index"); + if !cmd.status.success() { + panic!("FIXME"); + } +} + +pub fn create_object(object: String) -> Result<String, GitError> { + + // create an git object with git hash-object -w --stdin + let mut files = Command::new("git") + .arg("hash-object") + .arg("-w") + .arg("--stdin") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Error with git hash-ojbect"); + + let mut stdin = files.stdin.take().expect("Failed to open stdin"); + std::thread::spawn(move || { + stdin.write_all(object.as_bytes()).expect("Failed to write to stdin"); + }); + + let output = files.wait_with_output().expect("Failed to write to stdout"); + let lines = String::from_utf8_lossy(&output.stdout).to_string(); + Ok(lines.split_whitespace().next().unwrap().to_string()) +} + +pub fn commit(object: String, parent: Option<String>) -> Result<String, GitError> { + // commit_id=$(echo 'future-me: created a new bug for you' | git commit-tree $tree_id) + let mut files = match parent { + Some(parent) => + Command::new("git") + .arg("commit-tree") + .arg(object) + .arg("-p") + .arg(parent) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Error with git commit-tree"), + None => + Command::new("git") + .arg("commit-tree") + .arg(object) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Error with git commit-tree"), + }; + + let mut stdin = files.stdin.take().expect("Failed to open stdin"); + std::thread::spawn(move || { + stdin.write_all("future-me: created a new bug for you".as_bytes()).expect("Failed to write to stdin"); + }); + + let output = files.wait_with_output().expect("Failed to write to stdout"); + let lines = String::from_utf8_lossy(&output.stdout).to_string(); + Ok(lines.split_whitespace().next().unwrap().to_string()) +} + +pub fn get_last_ref() -> Result<String, GitError> { + let cmd = Command::new("git") + .arg("show-ref") + .arg("refs/notes/devtools/future-me") + .output() + .expect("Error with git show-ref"); + if !cmd.status.success() { + //return GitError::GitLog(String::from_utf8_lossy(&cmd.stderr).to_string()); + GitError::GitLog(String::from_utf8_lossy(&cmd.stderr).to_string()); + } + let lines = String::from_utf8_lossy(&cmd.stdout); + + match lines.split_whitespace().next() { + Some(line) => Ok(line.to_string()), + None => Err(GitError::UnknownRef), + } +} + +pub fn get_current_tree() -> Result<String, GitError>{ + let cmd = Command::new("git") + .arg("log") + .arg("-1") + .arg("--format=%H") + .output() + .expect("Error with git log"); + if !cmd.status.success() { + GitError::GitLog(String::from_utf8_lossy(&cmd.stderr).to_string()); + } + let lines = String::from_utf8_lossy(&cmd.stdout); + Ok(lines.trim().to_string()) +} + +pub fn write_tree() -> String { + let cmd = Command::new("git") + .arg("write-tree") + .output() + .expect("Error with git write-tree"); + if !cmd.status.success() { + panic!("{}", String::from_utf8_lossy(&cmd.stderr)); + } + let lines = String::from_utf8_lossy(&cmd.stdout); + lines.trim().to_string() +} + +pub fn create_new_tree() { + let cmd = Command::new("git") + .arg("read-tree") + .arg("--empty") + .output() + .expect("Error with git read-tree"); + if !cmd.status.success() { + panic!("{}", String::from_utf8_lossy(&cmd.stderr)); + } +} + +pub fn read_tree(tree: &str) { + let cmd = Command::new("git") + .arg("read-tree") + .arg(tree) + .output() + .expect("Error with git read-tree"); + if !cmd.status.success() { + panic!("{}", String::from_utf8_lossy(&cmd.stderr)); + } +} + +pub fn check_status() { + let logs = Command::new("git") + .arg("status") + .arg("--porcelain") + .output() + .expect("Error with git status"); + if !logs.status.success() { + GitError::GitLog(String::from_utf8_lossy(&logs.stderr).to_string()); + } + let lines = String::from_utf8_lossy(&logs.stdout); + for line in lines.lines() { + println!("{}", line); + if line.starts_with(['M', 'A']) { + panic!("You first need to clean you git staging status to use future-me"); + } + } +} + +pub fn hello() { + println!("hello from git"); +} |
