aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Guillon <Bernhard.Guillon@begu.org>2025-09-22 13:43:24 +0200
committerBernhard Guillon <Bernhard.Guillon@begu.org>2025-09-22 13:43:24 +0200
commit1bbbc6659120f79468ac0d60df42aae633926c3c (patch)
tree8910f12270eb0bd88751d789a8e81713f0341f17
parent52608100d24d2574b37d6a62cdadcdbbfe5fe51c (diff)
downloadfuture-me-1bbbc6659120f79468ac0d60df42aae633926c3c.tar.gz
future-me-1bbbc6659120f79468ac0d60df42aae633926c3c.zip
future-me: fix show command
-rw-r--r--src/main.rs211
1 files changed, 195 insertions, 16 deletions
diff --git a/src/main.rs b/src/main.rs
index 19c63a2..c64f6fe 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -33,7 +33,7 @@ struct BugReport {
version: String
}
-fn new_bug() {
+fn new_bug() -> String {
let editor = var("EDITOR").unwrap();
let mut file_path = temp_dir(); // TODO: figgure out how to get .git dir in a save manner
file_path.push("NEW_BUG_REPORT");
@@ -66,20 +66,21 @@ fn new_bug() {
tags: None,
version: "v1".to_owned(),
};
- let j = serde_json::to_string(&report).unwrap();
- print!("{}", j);
+ serde_json::to_string(&report).unwrap()
}
#[derive(Debug)]
enum GitError {
GitLog(String),
- Parse(ParseIntError)
+ 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"),
}
}
}
@@ -122,6 +123,7 @@ fn collect_reachable_objects() -> Result<(Vec<GitLog>, String), GitError> {
.expect("Error with git log");
if !logs.status.success() {
GitError::GitLog(String::from_utf8_lossy(&logs.stderr).to_string());
+ //return GitError::GitLog(String::from_utf8_lossy(&logs.stderr).to_string());
}
let lines = String::from_utf8_lossy(&logs.stdout);
let mut git_log = GitLog::default();
@@ -163,6 +165,8 @@ fn show() {
// in the desired format.
// For a short log we don't need to do all this extra work ^^
let (logs, blobs) = collect_reachable_objects().unwrap();
+ //println!("logs {:?}", logs);
+ //println!("blobs {:?}", blobs);
let mut files = Command::new("git")
.arg("cat-file")
.arg("--batch")
@@ -182,17 +186,24 @@ fn show() {
let mut bug_report: BugReport = BugReport::default();
let mut hash: String = String::default();
for (i, object) in objects.lines().enumerate() {
- match i%3 {
+ //println!("object |{}|", object);
+ match i%2 {
0 => hash = object.split(" ").next().unwrap().to_string(),
- 1 => bug_report = serde_json::from_str(&object).unwrap(),
- 2 => (),
+ 1 => {
+ //println!("|{:?}|", object);
+ bug_report = serde_json::from_str(&object).unwrap(); map.insert(hash.clone(), bug_report.clone());
+ //println!("INSERT")
+ },
+ //2 => (),
_ => todo!(),
}
- if i>=1 && i%3 ==1 {
- map.insert(hash.clone(), bug_report.clone());
- }
+// if i>=1 && i%3 ==1 {
+// println!("insert bug report");
+// map.insert(hash.clone(), bug_report.clone());
+// }
}
for log in logs {
+ //println!("{:?}", log);
let entry = map[&log.blob_object].clone();
let datetime = Utc.timestamp_opt(log.timestamp as i64, 0).unwrap();
// TODO: do we really need to be able to convert times? Or should we just
@@ -244,6 +255,9 @@ fn show() {
// git read-tree "$last_tree"
// ;;
+fn hash_to_path(hash: &str) -> String {
+ format!("{}/{}", &hash[..2], &hash[2..])
+}
fn create_new_bug() {
// first of all check if there is anything staged as we mess with the trees and staging area
@@ -280,9 +294,146 @@ fn create_new_bug() {
// git update-ref refs/notes/devtools/future-me $commit_id
//
// switch back to what ever was the working tree we got from get_current_tree
+
+
+ check_status();
+ let save_current_tree = get_current_tree().unwrap();
+ let future_me_ref = match get_last_ref() {
+ Ok(hash) => {read_tree(&hash); Some(hash)},
+ Err(GitError::UnknownRef) => {create_new_tree(); None},
+ Err(_) => panic!("fixme"),
+ };
+ let bug_report = new_bug();
+ let bug_object = create_object(bug_report.clone()).unwrap();
+ let path = hash_to_path(&bug_object);
+ stage_object(&bug_object, &path);
+ let tree_object = write_tree();
+ let commit_object = match future_me_ref {
+ Some(parent) => commit(tree_object, Some(parent)).unwrap(),
+ None => commit(tree_object, None).unwrap(),
+ };
+ let files_to_unstage = get_files_to_unstage();
+ unstage_object(&files_to_unstage);
+ update_ref(&commit_object);
+ read_tree(&save_current_tree);
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")
@@ -290,11 +441,15 @@ fn get_last_ref() -> Result<String, GitError> {
.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);
- // TODO: generate GitError
- Ok(lines.split_whitespace().next().unwrap().to_string())
+
+ match lines.split_whitespace().next() {
+ Some(line) => Ok(line.to_string()),
+ None => Err(GitError::UnknownRef),
+ }
}
fn get_current_tree() -> Result<String, GitError>{
@@ -311,6 +466,29 @@ fn get_current_tree() -> Result<String, GitError>{
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")
@@ -372,11 +550,12 @@ fn process_args() -> Cmd {
fn main() {
match process_args() {
Cmd::Show => show(),
- Cmd::New => new_bug(),
+ Cmd::New => create_new_bug(),
Cmd::Check=> {
- let tree = get_current_tree().unwrap();
- println!("{}", get_last_ref().unwrap());
- read_tree(&tree);
+ println!("{}", get_files_to_unstage());
+ //let tree = get_current_tree().unwrap();
+ //println!("{}", get_last_ref().unwrap());
+ //read_tree(&tree);
}
}
}