From 197950c3b2cb164807072ae018b5dacdf864ff08 Mon Sep 17 00:00:00 2001 From: realaravinth Date: Wed, 16 Feb 2022 20:23:04 +0530 Subject: [PATCH] feat: accommodate binary file content SUMMARY Binary content is essential to store images. ContentType enum accommodates both utf-8 and and non utf-8 encodings. Data::write_file and Data::read_file are modified to handle ContentType enum --- src/api/v1/gists.rs | 7 +-- src/data/api/v1/gists.rs | 111 +++++++++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 42 deletions(-) diff --git a/src/api/v1/gists.rs b/src/api/v1/gists.rs index ac972f6..c5204bd 100644 --- a/src/api/v1/gists.rs +++ b/src/api/v1/gists.rs @@ -74,6 +74,7 @@ async fn new( #[cfg(test)] mod tests { use super::*; + use crate::data::api::v1::gists::ContentType; use crate::tests::*; #[actix_rt::test] @@ -97,15 +98,15 @@ mod tests { let files = [ File { filename: "foo".into(), - content: "foobar".into(), + content: ContentType::Text("foobar".into()), }, File { filename: "bar".into(), - content: "foobar".into(), + content: ContentType::Text("foobar".into()), }, File { filename: "foo bar".into(), - content: "foobar".into(), + content: ContentType::Text("foobar".into()), }, ]; diff --git a/src/data/api/v1/gists.rs b/src/data/api/v1/gists.rs index 6d237f9..eb4e48f 100644 --- a/src/data/api/v1/gists.rs +++ b/src/data/api/v1/gists.rs @@ -39,7 +39,7 @@ pub struct CreateGist<'a> { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct File { pub filename: String, - pub content: String, + pub content: ContentType, } pub enum GistID<'a> { @@ -47,6 +47,38 @@ pub enum GistID<'a> { ID(&'a str), } +#[derive(Serialize, PartialEq, Clone, Debug, Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum ContentType { + Binary(Vec), + Text(String), +} + +impl ContentType { + pub fn as_bytes(&self) -> &[u8] { + match self { + Self::Text(text) => text.as_bytes(), + Self::Binary(bin) => bin.as_ref(), + } + } + + pub fn from_blob(blob: &git2::Blob) -> Self { + if blob.is_binary() { + Self::Binary(blob.content().to_vec()) + } else { + Self::Text(String::from_utf8_lossy(blob.content()).to_string()) + } + } +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +#[serde(rename_all = "lowercase")] +pub enum FileType { + /// Contains file content + File(ContentType), + Dir, +} + impl Data { pub async fn new_gist( &self, @@ -167,13 +199,13 @@ impl Data { _db: &T, gist_id: &str, path: &str, - ) -> ServiceResult> { + ) -> ServiceResult { let repo = git2::Repository::open(self.get_repository_path(gist_id)).unwrap(); let head = repo.head().unwrap(); let tree = head.peel_to_tree().unwrap(); let entry = tree.get_path(Path::new(path)).unwrap(); let blob = repo.find_blob(entry.id()).unwrap(); - Ok(blob.content().to_vec()) + Ok(ContentType::from_blob(&blob)) } } @@ -208,7 +240,7 @@ pub mod tests { .read_file(db, &gist_id, &escape_spaces(&file.filename)) .await .unwrap(); - assert_eq!(String::from_utf8_lossy(&content), file.content); + assert_eq!(content, file.content); } } } @@ -229,43 +261,44 @@ pub mod tests { let _ = data.register_and_signin(db, NAME, EMAIL, PASSWORD).await; - for i in 0..2 { - let create_gist_msg = CreateGist { - owner: NAME, - description: None, - visibility: &GistVisibility::Public, - }; - let mut gist = data.new_gist(db, &create_gist_msg).await.unwrap(); - assert!(gist.repository.is_empty().unwrap()); - data.gist_created_test_helper(db, &gist.id, NAME).await; + let create_gist_msg = CreateGist { + owner: NAME, + description: None, + visibility: &GistVisibility::Public, + }; + let mut gist = data.new_gist(db, &create_gist_msg).await.unwrap(); + assert!(gist.repository.is_empty().unwrap()); + data.gist_created_test_helper(db, &gist.id, NAME).await; - // save files - let files = [ - File { - filename: "foo".into(), - content: "foobar".into(), - }, - File { - filename: "bar".into(), - content: "foobar".into(), - }, - File { - filename: "foo bar".into(), - content: "foobar".into(), - }, - ]; + // save files + let files = [ + File { + filename: "foo".into(), + content: ContentType::Text("foobar".into()), + }, + File { + filename: "bar".into(), + content: ContentType::Text("foobar".into()), + }, + File { + filename: "foo bar".into(), + content: ContentType::Text("foobar".into()), + }, + ]; - if i == 0 { - data.write_file(db, GistID::Repository(&mut gist.repository), &files) - .await - .unwrap(); - } else { - data.write_file(db, GistID::ID(&gist.id), &files) - .await - .unwrap(); - } - data.gist_files_written_helper(db, &gist.id, &files).await; - } + data.write_file(db, GistID::Repository(&mut gist.repository), &files) + .await + .unwrap(); + data.gist_files_written_helper(db, &gist.id, &files).await; + let files2 = [File { + filename: "notfirstcommit".into(), + content: ContentType::Text("foobar".into()), + }]; + + data.write_file(db, GistID::ID(&gist.id), &files2) + .await + .unwrap(); + data.gist_files_written_helper(db, &gist.id, &files2).await; } } }