Skip to content

Commit

Permalink
feat: cargo format
Browse files Browse the repository at this point in the history
  • Loading branch information
derdilla committed Jul 4, 2024
1 parent 4688694 commit 3d8b84f
Show file tree
Hide file tree
Showing 4 changed files with 130 additions and 63 deletions.
2 changes: 1 addition & 1 deletion rust/vcs/src/git/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pub mod objects;
pub mod repo;
pub mod repo;
102 changes: 70 additions & 32 deletions rust/vcs/src/git/objects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@ pub struct GitBlob {

impl BinSerializable for GitBlob {
fn deserialize(data: Vec<u8>) -> Self {
Self {
data
}
Self { data }
}

fn serialize(self) -> Vec<u8> {
Expand All @@ -64,48 +62,53 @@ pub struct GitCommit {
impl GitCommit {
/// Reference to a tree object.
pub fn get_tree(&self) -> Option<String> {
self.kvlm
.iter().filter(|(k,_)| k == "tree")
.map(|(_k,v)| v.trim_matches(|e| e == '\n').to_string())
.next()
self.kvlm
.iter()
.filter(|(k, _)| k == "tree")
.map(|(_k, v)| v.trim_matches(|e| e == '\n').to_string())
.next()
}
/// References to commits this commit is based on.
///
/// - merge commits may have multiple
/// - the first commit may have none
pub fn get_parents(&self) -> Vec<String> {
self.kvlm
.iter().filter(|(k,_)| k == "parent")
.iter()
.filter(|(k, _)| k == "parent")
.map(|(_k, v)| v.trim_matches(|e| e == '\n').to_string())
.collect::<Vec<String>>()
}
/// Like: `Scott Chacon <[email protected]> 1243040974 -0700`
pub fn get_author(&self) -> Option<String> {
self.kvlm
.iter().filter(|(k,_)| k == "author")
.map(|(_k,v)| v.trim_matches(|e| e == '\n').to_string())
.iter()
.filter(|(k, _)| k == "author")
.map(|(_k, v)| v.trim_matches(|e| e == '\n').to_string())
.next()
}
pub fn get_commiter(&self) -> Option<String> {
self.kvlm
.iter().filter(|(k,_)| k == "committer")
.map(|(_k,v)| v.trim_matches(|e| e == '\n').to_string())
.iter()
.filter(|(k, _)| k == "committer")
.map(|(_k, v)| v.trim_matches(|e| e == '\n').to_string())
.next()
}
/// PGP signature of the object.
pub fn get_gpgsig(&self) -> Option<String> {
self.kvlm
.iter().filter(|(k,_)| k == "gpgsig")
.map(|(_k,v)| v.trim_matches(|e| e == '\n').to_string())
.iter()
.filter(|(k, _)| k == "gpgsig")
.map(|(_k, v)| v.trim_matches(|e| e == '\n').to_string())
.next()
}
pub fn get_message(&self) -> Option<String> {
self.kvlm
.iter().filter(|(k,_)| k == "__message__")
.map(|(_k,v)| v.trim_matches(|e| e == '\n').to_string())
.iter()
.filter(|(k, _)| k == "__message__")
.map(|(_k, v)| v.trim_matches(|e| e == '\n').to_string())
.next()
}

}

impl BinSerializable for GitCommit {
Expand Down Expand Up @@ -159,7 +162,6 @@ fn kvlm_parse(mut raw: Bytes<&[u8]>) -> Vec<(String, String)> {
}
in_message_block = true;
value = String::new();

} else {
// New value: save old kv and start new
if let Some(last_key) = key {
Expand All @@ -174,7 +176,6 @@ fn kvlm_parse(mut raw: Bytes<&[u8]>) -> Vec<(String, String)> {
value = v.to_string();
} // non conformant lines are ignored as comments
}

}

if in_message_block {
Expand All @@ -185,7 +186,8 @@ fn kvlm_parse(mut raw: Bytes<&[u8]>) -> Vec<(String, String)> {
kv_entries
}

fn kvlm_serialize(kvlm: Vec<(String, String)>) -> Vec<u8> { // TODO: test
fn kvlm_serialize(kvlm: Vec<(String, String)>) -> Vec<u8> {
// TODO: test
let mut out = String::new();
for (k, v) in kvlm {
if k == "__message__" {
Expand All @@ -202,7 +204,7 @@ fn kvlm_serialize(kvlm: Vec<(String, String)>) -> Vec<u8> { // TODO: test
mod tests {
use std::io::Read;

use crate::git::objects::{BinSerializable, GitCommit, kvlm_parse};
use crate::git::objects::{kvlm_parse, BinSerializable, GitCommit};

const SAMPLE_COMMIT: &str = "tree 29ff16c9c14e2652b22f8b78bb08a5a07930c147
parent 206941306e8a8af65b66eaaaea388a7ae24d49a0
Expand Down Expand Up @@ -230,17 +232,31 @@ Create first draft";
let parsed = kvlm_parse(SAMPLE_COMMIT.as_bytes().bytes());
// TODO: verify \n is wanted
assert_eq!(parsed.get(0).unwrap().0, "tree");
assert_eq!(parsed.get(0).unwrap().1, "29ff16c9c14e2652b22f8b78bb08a5a07930c147\n");
assert_eq!(
parsed.get(0).unwrap().1,
"29ff16c9c14e2652b22f8b78bb08a5a07930c147\n"
);
assert_eq!(parsed.get(1).unwrap().0, "parent");
assert_eq!(parsed.get(1).unwrap().1, "206941306e8a8af65b66eaaaea388a7ae24d49a0\n");
assert_eq!(
parsed.get(1).unwrap().1,
"206941306e8a8af65b66eaaaea388a7ae24d49a0\n"
);
assert_eq!(parsed.get(2).unwrap().0, "author");
assert_eq!(parsed.get(2).unwrap().1, "Thibault Polge <[email protected]> 1527025023 +0200\n");
assert_eq!(
parsed.get(2).unwrap().1,
"Thibault Polge <[email protected]> 1527025023 +0200\n"
);
assert_eq!(parsed.get(3).unwrap().0, "committer");
assert_eq!(parsed.get(3).unwrap().1, "Thibault Polge <[email protected]> 1527025044 +0200\n");
assert_eq!(
parsed.get(3).unwrap().1,
"Thibault Polge <[email protected]> 1527025044 +0200\n"
);
assert_eq!(parsed.get(4).unwrap().0, "gpgsig");
let v4 = parsed.get(4).unwrap().1.clone();
assert!(v4.clone().contains("-----BEGIN PGP SIGNATURE-----"));
assert!(v4.clone().contains("iQIzBAABCAAdFiEExwXquOM8bWb4Q2zVGxM2FxoLkGQFAlsEjZQACgkQGxM2FxoL"));
assert!(v4
.clone()
.contains("iQIzBAABCAAdFiEExwXquOM8bWb4Q2zVGxM2FxoLkGQFAlsEjZQACgkQGxM2FxoL"));
assert!(v4.contains("-----END PGP SIGNATURE-----"));
assert_eq!(parsed.get(5).unwrap().0, "__message__");
assert_eq!(parsed.get(5).unwrap().1, "Create first draft");
Expand All @@ -249,11 +265,33 @@ Create first draft";
#[test]
fn git_commit_deserialize() {
let commit = GitCommit::deserialize(SAMPLE_COMMIT.as_bytes().to_vec());
assert_eq!(commit.get_tree(), Some(String::from("29ff16c9c14e2652b22f8b78bb08a5a07930c147")));
assert_eq!(commit.get_parents().iter().next().unwrap().clone(), String::from("206941306e8a8af65b66eaaaea388a7ae24d49a0"));
assert_eq!(commit.get_author(), Some(String::from("Thibault Polge <[email protected]> 1527025023 +0200")));
assert_eq!(commit.get_commiter(), Some(String::from("Thibault Polge <[email protected]> 1527025044 +0200")));
assert!(commit.get_gpgsig().unwrap().contains("iQIzBAABCAAdFiEExwXquOM8bWb4Q2zVGxM2FxoLkGQFAlsEjZQACgkQGxM2FxoL"));
assert_eq!(commit.get_message(), Some(String::from("Create first draft")));
assert_eq!(
commit.get_tree(),
Some(String::from("29ff16c9c14e2652b22f8b78bb08a5a07930c147"))
);
assert_eq!(
commit.get_parents().iter().next().unwrap().clone(),
String::from("206941306e8a8af65b66eaaaea388a7ae24d49a0")
);
assert_eq!(
commit.get_author(),
Some(String::from(
"Thibault Polge <[email protected]> 1527025023 +0200"
))
);
assert_eq!(
commit.get_commiter(),
Some(String::from(
"Thibault Polge <[email protected]> 1527025044 +0200"
))
);
assert!(commit
.get_gpgsig()
.unwrap()
.contains("iQIzBAABCAAdFiEExwXquOM8bWb4Q2zVGxM2FxoLkGQFAlsEjZQACgkQGxM2FxoL"));
assert_eq!(
commit.get_message(),
Some(String::from("Create first draft"))
);
}
}
76 changes: 53 additions & 23 deletions rust/vcs/src/git/repo.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::git::objects::{BinSerializable, GitBlob, GitCommit, GitObject, GitObjectType};
use iniconf::{IniFile, IniFileOpenError};
use log::warn;
use sha1::{Digest, Sha1};
use std::fs;
use std::io::Read;
use std::path::{Path, PathBuf};
use log::warn;
use sha1::{Sha1, Digest};
use crate::git::objects::{GitBlob, GitObject, BinSerializable, GitObjectType, GitCommit};

pub struct Repository {
/// Where the files meant to be in version control live.
Expand Down Expand Up @@ -32,7 +32,8 @@ impl Repository {
if instance.git_dir.is_dir() || force {
let path = instance.git_dir.join("config");
if path.is_file() || force {
instance.config = RepoConfig::read(path).expect("IO is possible as per check above");
instance.config =
RepoConfig::read(path).expect("IO is possible as per check above");
if instance.config.repository_format_version <= 0 || force {
Ok(instance)
} else {
Expand All @@ -41,7 +42,6 @@ impl Repository {
supported: 0,
})
}

} else {
Err(RepositoryLoadError::ConfigurationFileMissing)
}
Expand Down Expand Up @@ -76,7 +76,11 @@ impl Repository {
repo.repo_path(vec!["refs", "heads"], Some(true), Some(false))?;

let desc = repo.repo_path(vec!["description"], Some(false), Some(true))?;
fs::write(desc, "Unnamed repository; edit this file 'description' to name the repository.\n").ok()?;
fs::write(
desc,
"Unnamed repository; edit this file 'description' to name the repository.\n",
)
.ok()?;

let head = repo.repo_path(vec!["HEAD"], Some(false), Some(true))?;
fs::write(head, "ref: refs/heads/master\n").ok()?;
Expand All @@ -93,7 +97,12 @@ impl Repository {
/// If [mkdir] is true directories specified in the path will be created.
/// If [has_file] is true no directory will be created for the last item in
/// [path_list]. [mkdir] and [has_file] default to false.
fn repo_path<P: AsRef<Path>>(&self, path_list: Vec<P>, mkdir: Option<bool>, has_file: Option<bool>) -> Option<PathBuf> {
fn repo_path<P: AsRef<Path>>(
&self,
path_list: Vec<P>,
mkdir: Option<bool>,
has_file: Option<bool>,
) -> Option<PathBuf> {
if path_list.is_empty() {
panic!("repo_path needs a path to join")
}
Expand All @@ -113,7 +122,10 @@ impl Repository {
}
if mkdir {
if res_path.exists() && !res_path.is_dir() {
panic!("Tried to create dir where there already was a file: {:?}", &res_path);
panic!(
"Tried to create dir where there already was a file: {:?}",
&res_path
);
}
if fs::create_dir_all(&res_path).is_err() {
warn!("Failed to create {:?}", &res_path);
Expand All @@ -122,7 +134,11 @@ impl Repository {

if res_path.exists() {
if has_file {
res_path = res_path.join(path_list.last().expect("repo_path won't accept empty paths."))
res_path = res_path.join(
path_list
.last()
.expect("repo_path won't accept empty paths."),
)
}
Some(res_path)
} else {
Expand All @@ -137,7 +153,11 @@ impl Repository {
/// Load a git object by hash.
pub fn object_read(&self, sha: String) -> Option<GitObject> {
// let sha: String = sha.iter().map(|byte| format!("{:x}", byte)).collect();
let path = self.repo_path(vec!["objects", &sha[0..2], &sha[2..sha.len()]], None, Some(true));
let path = self.repo_path(
vec!["objects", &sha[0..2], &sha[2..sha.len()]],
None,
Some(true),
);
if path.as_ref().is_some_and(|p| p.is_file()) {
if let Ok(data) = fs::read(path.unwrap()) {
let data = flate2::read::ZlibDecoder::new(&data[..]);
Expand All @@ -157,7 +177,9 @@ impl Repository {
}
obj_len.push(char::from(byte));
}
let obj_len = obj_len.parse::<u64>().expect("GitObject doesn't contain size");
let obj_len = obj_len
.parse::<u64>()
.expect("GitObject doesn't contain size");

let remaining_bits: Vec<u8> = data.map(|e| e.unwrap()).collect();
assert_eq!(obj_len as usize, remaining_bits.len());
Expand All @@ -171,7 +193,6 @@ impl Repository {
};
return Some(obj);
}

}
None
}
Expand All @@ -184,8 +205,11 @@ impl Repository {
let sha = hasher.finalize();
let sha: String = sha.iter().map(|byte| format!("{:x}", byte)).collect();


let path = self.repo_path(vec!["objects", &sha[..2], &sha[2..]], Some(true), Some(true));
let path = self.repo_path(
vec!["objects", &sha[..2], &sha[2..]],
Some(true),
Some(true),
);
if let Some(path) = path {
if !path.exists() {
fs::write(path, obj).unwrap();
Expand Down Expand Up @@ -249,7 +273,7 @@ impl RepoConfig {
fs::create_dir_all(path.parent().unwrap()).ok()?;
}
if !(path.is_dir() || path.is_symlink()) {
let x =IniFile::open(path.clone());
let x = IniFile::open(path.clone());
println!("{:#?}", &x);
match x {
Ok(file) => {
Expand All @@ -258,11 +282,12 @@ impl RepoConfig {
let bare = file.get::<bool>("core", "bare");
Some(Self {
file,
repository_format_version: version.unwrap_or(Self::default().repository_format_version),
repository_format_version: version
.unwrap_or(Self::default().repository_format_version),
file_mode: mode.unwrap_or(Self::default().file_mode),
bare: bare.unwrap_or(Self::default().bare),
})
},
}
Err(IniFileOpenError::FormatError) => {
warn!("Overriding repo config as it is badly formatted");
if fs::remove_file(&path).is_ok() {
Expand All @@ -277,7 +302,7 @@ impl RepoConfig {
} else {
None
}
},
}
Err(IniFileOpenError::IOError) => {
warn!("Couldn't open ini file: IOError");
None
Expand All @@ -287,13 +312,18 @@ impl RepoConfig {
warn!("Tried to read config from directory or symlink.");
None
}

}

fn write(&mut self) -> Option<()> {
self.file.set_str("core", "repositoryformatversion", format!("{}", self.repository_format_version).as_str());
self.file.set_str("core", "filemode", format!("{}", self.file_mode).as_str());
self.file.set_str("core", "bare", format!("{}", self.bare).as_str());
self.file.set_str(
"core",
"repositoryformatversion",
format!("{}", self.repository_format_version).as_str(),
);
self.file
.set_str("core", "filemode", format!("{}", self.file_mode).as_str());
self.file
.set_str("core", "bare", format!("{}", self.bare).as_str());

self.file.write().ok()
}
Expand All @@ -307,4 +337,4 @@ impl Default for RepoConfig {
bare: false,
}
}
}
}
Loading

0 comments on commit 3d8b84f

Please sign in to comment.