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 /src/git.rs | |
| parent | 1bbbc6659120f79468ac0d60df42aae633926c3c (diff) | |
| download | future-me-fce9ead9c50e00fb1315cd2c1df79a9fe79ddf13.tar.gz future-me-fce9ead9c50e00fb1315cd2c1df79a9fe79ddf13.zip | |
future-me: move git stuff into it's own library
Diffstat (limited to 'src/git.rs')
| -rw-r--r-- | src/git.rs | 231 |
1 files changed, 231 insertions, 0 deletions
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"); +} |
