diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 211 |
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); } } } |
