aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBernhard Guillon <Bernhard.Guillon@begu.org>2025-09-17 19:42:01 +0200
committerBernhard Guillon <Bernhard.Guillon@begu.org>2025-09-17 19:42:01 +0200
commit5c9246f5331fe579cd686a987ae83e46f0cc868b (patch)
tree05e6cd42fc8bed15bcfde53497a4e066987d2c0c
parent99f8dcce0276dbc7df2689e8f8b101ab31b4746d (diff)
downloadfuture-me-5c9246f5331fe579cd686a987ae83e46f0cc868b.tar.gz
future-me-5c9246f5331fe579cd686a987ae83e46f0cc868b.zip
future-me: Traverse all logs to be able to print the full log
This is how it looks now :) ------------------------------------------------------------------------- 65e8eaa new Bernhard Guillon Hello second bug 2025-09-16 19:44:28 This is the second bug yey - looks nice ------------------------------------------------------------------------- 79708a9 new Bernhard Guillon Hello world 2025-09-16 19:43:17 this is my first bug report
-rw-r--r--Cargo.lock254
-rw-r--r--Cargo.toml1
-rw-r--r--src/main.rs184
3 files changed, 395 insertions, 44 deletions
diff --git a/Cargo.lock b/Cargo.lock
index f7be8a3..3de7ead 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,26 +3,150 @@
version = 4
[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
+[[package]]
+name = "cc"
+version = "1.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+
+[[package]]
+name = "chrono"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d"
+
+[[package]]
name = "future-me"
version = "0.1.0"
dependencies = [
+ "chrono",
"serde",
"serde_json",
]
[[package]]
+name = "iana-time-zone"
+version = "0.1.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
name = "itoa"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
+name = "js-sys"
+version = "0.3.80"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "852f13bec5eba4ba9afbeb93fd7c13fe56147f055939ae21c43a29a0ecb2702e"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.175"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
+
+[[package]]
+name = "log"
+version = "0.4.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+
+[[package]]
name = "memchr"
version = "2.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
+[[package]]
name = "proc-macro2"
version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -41,6 +165,12 @@ dependencies = [
]
[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
name = "ryu"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -90,6 +220,12 @@ dependencies = [
]
[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
name = "syn"
version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -105,3 +241,121 @@ name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ab10a69fbd0a177f5f649ad4d8d3305499c42bab9aef2f7ff592d0ec8f833819"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0bb702423545a6007bbc368fde243ba47ca275e549c8a28617f56f6ba53b1d1c"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc65f4f411d91494355917b605e1480033152658d71f722a90647f56a70c88a0"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffc003a991398a8ee604a401e194b6b3a39677b3173d6e74495eb51b82e99a32"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.103"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "293c37f4efa430ca14db3721dfbe48d8c33308096bd44d80ebaa775ab71ba1cf"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.62.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57fe7168f7de578d2d8a05b07fd61870d2e73b4020e9f49aa00da8471723497c"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-link"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
+
+[[package]]
+name = "windows-result"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
+dependencies = [
+ "windows-link",
+]
diff --git a/Cargo.toml b/Cargo.toml
index ab405c3..97d761a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,5 +4,6 @@ version = "0.1.0"
edition = "2024"
[dependencies]
+chrono = "0.4.42"
serde = { version = "1.0.145", features = ["derive"] }
serde_json = "1.0.145"
diff --git a/src/main.rs b/src/main.rs
index a25a5f7..e070af3 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,15 +1,28 @@
+// SPDX MIT Bernhard Guillon 2025
+//
+// As this project is currently in research please just ignore
+// all clones and memory copies ^^ As on all my rust projects
+// 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 serde::{Deserialize, Serialize};
-//use serde_json::Result;
use std::time::{SystemTime, UNIX_EPOCH};
use std::{
env::{temp_dir, var},
fs::File,
io::Read,
process::Command,
+ process::Stdio,
};
use std::fs;
+use std::fmt;
+use std::num::ParseIntError;
+use std::io::Write;
+use std::collections::HashMap;
+use chrono::{NaiveDateTime, Utc, TimeZone};
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Default, Clone)]
struct BugReport {
timestamp: String,
status: String,
@@ -56,57 +69,140 @@ fn new_bug() {
print!("{}", j);
}
-fn show() {
- let reports = get_reports();
- for report in reports {
- //println!("{:?}", report);
- println!("=================================================================");
- println!("{} | {}", report.status, report.title);
- println!("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
- for l in report.description {
- println!("{}", l);
+#[derive(Debug)]
+enum GitError {
+ GitLog(String),
+ Parse(ParseIntError)
+}
+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),
}
}
}
-fn get_reports() -> Vec<BugReport> {
- let mut ret: Vec<BugReport> = Vec::new();
- let output = Command::new("git")
- .arg("ls-tree")
- .arg("--full-tree")
- .arg("-r")
+impl From<ParseIntError> for GitError {
+ fn from(err: ParseIntError) -> GitError {
+ GitError::Parse(err)
+ }
+}
+
+impl std::error::Error for GitError {}
+
+#[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 ls-tree");
- //println!("{}", output.status);
- if output.status.success() {
- let lines = String::from_utf8_lossy(&output.stdout);
- for line in lines.lines() {
- if let Some(after_blob) = line.split_once("blob ") {
- if let Some((hash, _)) = after_blob.1.split_once('\t') {
- let blob = Command::new("git")
- .arg("cat-file")
- .arg("-p")
- .arg(hash)
- .output()
- .expect("Error with git cat-file");
- if blob.status.success() {
- let lines = String::from_utf8_lossy(&blob.stdout);
- // TODO: error handling
- let bug_report: BugReport = serde_json::from_str(&lines).unwrap();
- ret.push(bug_report);
- }
- else {
- println!("{}", String::from_utf8_lossy(&blob.stderr));
- }
- }
- }
+ .expect("Error with git log");
+ if !logs.status.success() {
+ 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();
+ 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 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() {
+ match i%3 {
+ 0 => hash = object.split(" ").next().unwrap().to_string(),
+ 1 => bug_report = serde_json::from_str(&object).unwrap(),
+ 2 => (),
+ _ => todo!(),
+ }
+ if i>=1 && i%3 ==1 {
+ map.insert(hash.clone(), bug_report.clone());
}
}
- else {
- println!("{}", String::from_utf8_lossy(&output.stderr));
+ for log in logs {
+ 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
+ // collect the git time with the possibilites git gives us?
+ // I don't like the chrono dependency :/
+ println!("-------------------------------------------------------------------------");
+ println!{"{} {} {} {}\t{}", &log.hash[0..7], entry.status, log.author_name, entry.title, datetime.format("%Y-%m-%d %H:%M:%S")};
+ for line in entry.description {
+ println!("{}", line);
+ }
}
- ret
}
fn main() {