diff options
| author | Bernhard Guillon <Bernhard.Guillon@begu.org> | 2025-09-22 16:53:13 +0200 |
|---|---|---|
| committer | Bernhard Guillon <Bernhard.Guillon@begu.org> | 2025-09-22 16:53:13 +0200 |
| commit | f3299cac648c5719bf180bd8770d1135522ed02a (patch) | |
| tree | e65eb947846be7245b453cf603417120a4a2613d | |
| parent | fce9ead9c50e00fb1315cd2c1df79a9fe79ddf13 (diff) | |
| download | future-me-f3299cac648c5719bf180bd8770d1135522ed02a.tar.gz future-me-f3299cac648c5719bf180bd8770d1135522ed02a.zip | |
future-me: split more git functions into git
| -rw-r--r-- | src/bin/main.rs | 109 | ||||
| -rw-r--r-- | src/git.rs | 86 |
2 files changed, 88 insertions, 107 deletions
diff --git a/src/bin/main.rs b/src/bin/main.rs index 0812f49..79242a7 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -5,7 +5,6 @@ // 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::{ @@ -13,16 +12,15 @@ use std::{ fs::File, io::Read, process::Command, - process::Stdio, }; use std::fs; -use std::io::Write; use std::collections::HashMap; use chrono::{Utc, TimeZone}; use std::env::args; // TODO use git::*; +use git::GitError; #[derive(Serialize, Deserialize, Debug, Default, Clone)] struct BugReport { @@ -70,119 +68,25 @@ fn new_bug() -> String { serde_json::to_string(&report).unwrap() } - - -#[derive(Debug, Default, Clone)] -struct GitLog{ - timestamp: u64, - hash: String, - author_name: String, - author_email: String, - blob_object: String, -} - -fn collect_reachable_objects() -> Result<(Vec<GitLog>, String), GitError> { - // TODO: until we have the need for archiving old stuff to archive - // we can guarantee that all objects collected exist and are - // unchanged. As soon as we support archives we might need to - // change this approach a bit. - - // As we use the first two chars of a git hash as directory name and - // the other part as file name we are able to regenerate the hash - // from the changed file path. Git log can provide the file path - // as well as all other needed information. - let mut git_logs: Vec<GitLog> = Vec::new(); - let mut blobs = String::default(); - let logs = Command::new("git") - .arg("log") - .arg("--pretty=format:%H#%an#%ae#%at") - .arg("--name-only") - .arg("refs/notes/devtools/future-me") - .output() - .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(); - for (i, line) in lines.lines().enumerate() { - match i%3 { - 0 => { - let parts = line.split("#"); - for (i, part) in parts.enumerate() { - match i%4 { - 0 => git_log.hash=part.to_string(), - 1 => git_log.author_name = part.to_string(), - 2 => git_log.author_email = part.to_string(), - 3 => git_log.timestamp = part.parse::<u64>()?, - _ => todo!(), // TODO: why we need this? - } - } - }, - 1 => { - git_log.blob_object = line.replace("/", ""); - if blobs.len() > 0 { - blobs = blobs + "\n" + &git_log.blob_object; - } - else { - blobs = blobs + &git_log.blob_object; - } - }, - 2 => (), // commit seperator - _ => todo!(), // TODO: why we need this? - } - if i>=1 && i%3 ==1 { - git_logs.push(git_log.clone()); - } - } - return Ok((git_logs, blobs)); -} - fn show() { // TODO: split this function to collect the reports and to show them // 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") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Error with git cat-files --batch"); - - let mut stdin = files.stdin.take().expect("Failed to open stdin"); - std::thread::spawn(move || { - stdin.write_all(blobs.as_bytes()).expect("Failed to write to stdin"); - }); - - let output = files.wait_with_output().expect("Failed to write to stdout"); - let objects = String::from_utf8_lossy(&output.stdout); + let objects = cat_files(blobs).unwrap(); let mut map: HashMap<String, BugReport> = HashMap::new(); let mut bug_report: BugReport = BugReport::default(); let mut hash: String = String::default(); for (i, object) in objects.lines().enumerate() { - //println!("object |{}|", object); match i%2 { 0 => hash = object.split(" ").next().unwrap().to_string(), 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 { -// 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 @@ -257,7 +161,6 @@ fn create_new_bug() { unstage_object(&files_to_unstage); update_ref(&commit_object); read_tree(&save_current_tree); - println!("hello new bug"); } fn print_usage() { @@ -271,7 +174,6 @@ fn print_usage() { enum Cmd{ Show, New, - Check, } fn process_args() -> Cmd { @@ -284,7 +186,6 @@ fn process_args() -> Cmd { match unwraped.as_str() { "show" => Cmd::Show, "new" => Cmd::New, - "check" => Cmd::Check, _ => {print_usage(); todo!()}, } } @@ -293,11 +194,5 @@ fn main() { match process_args() { Cmd::Show => show(), Cmd::New => create_new_bug(), - Cmd::Check=> { - println!("{}", get_files_to_unstage()); - //let tree = get_current_tree().unwrap(); - //println!("{}", get_last_ref().unwrap()); - //read_tree(&tree); - } } } @@ -226,6 +226,92 @@ pub fn check_status() { } } +#[derive(Debug, Default, Clone)] +pub struct GitLog{ + pub timestamp: u64, + pub hash: String, + pub author_name: String, + pub author_email: String, + pub blob_object: String, +} + +pub fn collect_reachable_objects() -> Result<(Vec<GitLog>, String), GitError> { + // TODO: until we have the need for archiving old stuff to archive + // we can guarantee that all objects collected exist and are + // unchanged. As soon as we support archives we might need to + // change this approach a bit. + + // As we use the first two chars of a git hash as directory name and + // the other part as file name we are able to regenerate the hash + // from the changed file path. Git log can provide the file path + // as well as all other needed information. + let mut git_logs: Vec<GitLog> = Vec::new(); + let mut blobs = String::default(); + let logs = Command::new("git") + .arg("log") + .arg("--pretty=format:%H#%an#%ae#%at") + .arg("--name-only") + .arg("refs/notes/devtools/future-me") + .output() + .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(); + for (i, line) in lines.lines().enumerate() { + match i%3 { + 0 => { + let parts = line.split("#"); + for (i, part) in parts.enumerate() { + match i%4 { + 0 => git_log.hash=part.to_string(), + 1 => git_log.author_name = part.to_string(), + 2 => git_log.author_email = part.to_string(), + 3 => git_log.timestamp = part.parse::<u64>()?, + _ => todo!(), // TODO: why we need this? + } + } + }, + 1 => { + git_log.blob_object = line.replace("/", ""); + if blobs.len() > 0 { + blobs = blobs + "\n" + &git_log.blob_object; + } + else { + blobs = blobs + &git_log.blob_object; + } + }, + 2 => (), // commit seperator + _ => todo!(), // TODO: why we need this? + } + if i>=1 && i%3 ==1 { + git_logs.push(git_log.clone()); + } + } + return Ok((git_logs, blobs)); +} + +pub fn cat_files(blobs: String) -> Result<String, GitError> { + let mut files = Command::new("git") + .arg("cat-file") + .arg("--batch") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Error with git cat-files --batch"); + let mut stdin = files.stdin.take().expect("Failed to open stdin"); + std::thread::spawn(move || { + stdin.write_all(blobs.as_bytes()).expect("Failed to write to stdin"); + }); + let output = files.wait_with_output().expect("Failed to write to stdout"); + let objects = String::from_utf8_lossy(&output.stdout); + Ok(objects.to_string()) +} + + + pub fn hello() { println!("hello from git"); } |
