aboutsummaryrefslogtreecommitdiffstats
path: root/src/git.rs
diff options
context:
space:
mode:
authorBernhard Guillon <Bernhard.Guillon@begu.org>2025-09-22 16:00:28 +0200
committerBernhard Guillon <Bernhard.Guillon@begu.org>2025-09-22 16:00:28 +0200
commitfce9ead9c50e00fb1315cd2c1df79a9fe79ddf13 (patch)
tree1b0c924da8f216722c3cd2e31054b68e72816aed /src/git.rs
parent1bbbc6659120f79468ac0d60df42aae633926c3c (diff)
downloadfuture-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.rs231
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");
+}