aboutsummaryrefslogtreecommitdiffstats
path: root/src/git.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/git.rs')
-rw-r--r--src/git.rs86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/git.rs b/src/git.rs
index 728b247..b974375 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -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");
}