mirror of https://github.com/realaravinth/gitpad
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 enummaster
parent
06830bfd2c
commit
197950c3b2
|
@ -74,6 +74,7 @@ async fn new(
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::data::api::v1::gists::ContentType;
|
||||||
use crate::tests::*;
|
use crate::tests::*;
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
|
@ -97,15 +98,15 @@ mod tests {
|
||||||
let files = [
|
let files = [
|
||||||
File {
|
File {
|
||||||
filename: "foo".into(),
|
filename: "foo".into(),
|
||||||
content: "foobar".into(),
|
content: ContentType::Text("foobar".into()),
|
||||||
},
|
},
|
||||||
File {
|
File {
|
||||||
filename: "bar".into(),
|
filename: "bar".into(),
|
||||||
content: "foobar".into(),
|
content: ContentType::Text("foobar".into()),
|
||||||
},
|
},
|
||||||
File {
|
File {
|
||||||
filename: "foo bar".into(),
|
filename: "foo bar".into(),
|
||||||
content: "foobar".into(),
|
content: ContentType::Text("foobar".into()),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub struct CreateGist<'a> {
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct File {
|
pub struct File {
|
||||||
pub filename: String,
|
pub filename: String,
|
||||||
pub content: String,
|
pub content: ContentType,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum GistID<'a> {
|
pub enum GistID<'a> {
|
||||||
|
@ -47,6 +47,38 @@ pub enum GistID<'a> {
|
||||||
ID(&'a str),
|
ID(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, PartialEq, Clone, Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum ContentType {
|
||||||
|
Binary(Vec<u8>),
|
||||||
|
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 {
|
impl Data {
|
||||||
pub async fn new_gist<T: GistDatabase>(
|
pub async fn new_gist<T: GistDatabase>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -167,13 +199,13 @@ impl Data {
|
||||||
_db: &T,
|
_db: &T,
|
||||||
gist_id: &str,
|
gist_id: &str,
|
||||||
path: &str,
|
path: &str,
|
||||||
) -> ServiceResult<Vec<u8>> {
|
) -> ServiceResult<ContentType> {
|
||||||
let repo = git2::Repository::open(self.get_repository_path(gist_id)).unwrap();
|
let repo = git2::Repository::open(self.get_repository_path(gist_id)).unwrap();
|
||||||
let head = repo.head().unwrap();
|
let head = repo.head().unwrap();
|
||||||
let tree = head.peel_to_tree().unwrap();
|
let tree = head.peel_to_tree().unwrap();
|
||||||
let entry = tree.get_path(Path::new(path)).unwrap();
|
let entry = tree.get_path(Path::new(path)).unwrap();
|
||||||
let blob = repo.find_blob(entry.id()).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))
|
.read_file(db, &gist_id, &escape_spaces(&file.filename))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.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;
|
let _ = data.register_and_signin(db, NAME, EMAIL, PASSWORD).await;
|
||||||
|
|
||||||
for i in 0..2 {
|
let create_gist_msg = CreateGist {
|
||||||
let create_gist_msg = CreateGist {
|
owner: NAME,
|
||||||
owner: NAME,
|
description: None,
|
||||||
description: None,
|
visibility: &GistVisibility::Public,
|
||||||
visibility: &GistVisibility::Public,
|
};
|
||||||
};
|
let mut gist = data.new_gist(db, &create_gist_msg).await.unwrap();
|
||||||
let mut gist = data.new_gist(db, &create_gist_msg).await.unwrap();
|
assert!(gist.repository.is_empty().unwrap());
|
||||||
assert!(gist.repository.is_empty().unwrap());
|
data.gist_created_test_helper(db, &gist.id, NAME).await;
|
||||||
data.gist_created_test_helper(db, &gist.id, NAME).await;
|
|
||||||
|
|
||||||
// save files
|
// save files
|
||||||
let files = [
|
let files = [
|
||||||
File {
|
File {
|
||||||
filename: "foo".into(),
|
filename: "foo".into(),
|
||||||
content: "foobar".into(),
|
content: ContentType::Text("foobar".into()),
|
||||||
},
|
},
|
||||||
File {
|
File {
|
||||||
filename: "bar".into(),
|
filename: "bar".into(),
|
||||||
content: "foobar".into(),
|
content: ContentType::Text("foobar".into()),
|
||||||
},
|
},
|
||||||
File {
|
File {
|
||||||
filename: "foo bar".into(),
|
filename: "foo bar".into(),
|
||||||
content: "foobar".into(),
|
content: ContentType::Text("foobar".into()),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
if i == 0 {
|
data.write_file(db, GistID::Repository(&mut gist.repository), &files)
|
||||||
data.write_file(db, GistID::Repository(&mut gist.repository), &files)
|
.await
|
||||||
.await
|
.unwrap();
|
||||||
.unwrap();
|
data.gist_files_written_helper(db, &gist.id, &files).await;
|
||||||
} else {
|
let files2 = [File {
|
||||||
data.write_file(db, GistID::ID(&gist.id), &files)
|
filename: "notfirstcommit".into(),
|
||||||
.await
|
content: ContentType::Text("foobar".into()),
|
||||||
.unwrap();
|
}];
|
||||||
}
|
|
||||||
data.gist_files_written_helper(db, &gist.id, &files).await;
|
data.write_file(db, GistID::ID(&gist.id), &files2)
|
||||||
}
|
.await
|
||||||
|
.unwrap();
|
||||||
|
data.gist_files_written_helper(db, &gist.id, &files2).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue