Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mercury/src/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

use std::{fmt::Display, io};

use bincode::{Encode, Decode};
use colored::Colorize;
use serde::{Deserialize, Serialize};
use sha1::Digest;
Expand All @@ -28,6 +29,7 @@ use crate::internal::object::types::ObjectType;
///
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default, Deserialize, Serialize,
Encode, Decode
)]
pub struct SHA1(pub [u8; 20]);

Expand Down
2 changes: 2 additions & 0 deletions mercury/src/internal/object/blob.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ use crate::internal::object::ObjectTrait;

/// **The Blob Object**
#[derive(Eq, Debug, Clone)]
#[non_exhaustive]
pub struct Blob {
pub id: SHA1,
pub data: Vec<u8>,
Expand Down Expand Up @@ -113,4 +114,5 @@ mod tests {
"5dd01c177f5d7d1be5346a5bc18a569a7410c2ef"
);
}

}
18 changes: 14 additions & 4 deletions mercury/src/internal/object/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::hash::SHA1;
use crate::internal::object::signature::Signature;
use crate::internal::object::ObjectTrait;
use crate::internal::object::ObjectType;
use bincode::{Decode, Encode};
use bstr::ByteSlice;
use callisto::git_commit;
use callisto::mega_commit;
Expand All @@ -35,7 +36,7 @@ use serde::Serialize;
/// history of a repository with a single commit object at its root.
/// - The author and committer fields contain the name, email address, timestamp and timezone.
/// - The message field contains the commit message, which maybe include signed or DCO.
#[derive(Eq, Debug, Clone, Serialize, Deserialize)]
#[derive(Eq, Debug, Clone, Serialize, Deserialize, Decode, Encode)]
#[non_exhaustive]
pub struct Commit {
pub id: SHA1,
Expand Down Expand Up @@ -119,6 +120,8 @@ impl Commit {
Commit::new(author, committer, tree_id, parent_commit_ids, message)
}

/// Formats the commit message by extracting the first line of the message.
/// If the message contains a PGP signature, it will return the first line after the signature.
pub fn format_message(&self) -> String {
let mut has_signature = false;
for line in self.message.lines() {
Expand Down Expand Up @@ -148,21 +151,26 @@ impl ObjectTrait for Commit {
// Find the tree id and remove it from the data
let tree_end = commit.find_byte(0x0a).unwrap();
let tree_id: SHA1 = SHA1::from_str(
String::from_utf8(commit[5..tree_end].to_owned())
String::from_utf8(commit[5..tree_end].to_owned()) // 5 is the length of "tree "
.unwrap()
.as_str(),
)
.unwrap();
let binding = commit[tree_end + 1..].to_vec();
let binding = commit[tree_end + 1..].to_vec(); // Move past the tree id
commit = &binding;

// Find the parent commit ids and remove them from the data
let author_begin = commit.find("author").unwrap();
// Find all parent commit ids
// The parent commit ids are all the lines that start with "parent "
// We can use find_iter to find all occurrences of "parent "
// and then extract the SHA1 hashes from them.
let parent_commit_ids: Vec<SHA1> = commit[..author_begin]
.find_iter("parent")
.map(|parent| {
let parent_end = commit[parent..].find_byte(0x0a).unwrap();
SHA1::from_str(
// 7 is the length of "parent "
String::from_utf8(commit[parent + 7..parent + parent_end].to_owned())
.unwrap()
.as_str(),
Expand All @@ -174,8 +182,10 @@ impl ObjectTrait for Commit {
commit = &binding;

// Find the author and committer and remove them from the data
// 0x0a is the newline character
let author =
Signature::from_data(commit[..commit.find_byte(0x0a).unwrap()].to_vec()).unwrap();
Signature::from_data(commit[..commit.find_byte(0x0a).unwrap()].to_vec()).unwrap();

let binding = commit[commit.find_byte(0x0a).unwrap() + 1..].to_vec();
commit = &binding;
let committer =
Expand Down
5 changes: 3 additions & 2 deletions mercury/src/internal/object/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//!
use std::{fmt::Display, str::FromStr};

use bincode::{Decode, Encode};
use bstr::ByteSlice;
use chrono::Offset;
use serde::{Deserialize, Serialize};
Expand All @@ -30,7 +31,7 @@ use crate::errors::GitError;
/// ```
///
/// So, we design a `SignatureType` enum to indicate the signature type.
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Decode, Encode)]
pub enum SignatureType {
Author,
Committer,
Expand Down Expand Up @@ -75,7 +76,7 @@ impl SignatureType {
}
}

#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize)]
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize,Decode,Encode)]
pub struct Signature {
pub signature_type: SignatureType,
pub name: String,
Expand Down
3 changes: 2 additions & 1 deletion mercury/src/internal/object/tag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ use crate::internal::object::ObjectType;

/// The tag object is used to Annotated tag
#[derive(Eq, Debug, Clone)]
#[non_exhaustive]
pub struct Tag {
pub id: SHA1,
pub object_hash: SHA1,
Expand Down Expand Up @@ -123,7 +124,7 @@ impl ObjectTrait for Tag {
let tagger = Signature::from_data(tagger_data).unwrap();
data = &data[data.find_byte(0x0a).unwrap() + 1..];

let message = unsafe {
let message = unsafe { // There may be non-UTF-8 characters, so we use `to_str_unchecked` for conversion.
data[data.find_byte(0x0a).unwrap()..]
.to_vec()
.to_str_unchecked()
Expand Down
8 changes: 5 additions & 3 deletions mercury/src/internal/object/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use crate::errors::GitError;
use crate::hash::SHA1;
use crate::internal::object::ObjectTrait;
use crate::internal::object::ObjectType;
use bincode::{Encode, Decode};
use colored::Colorize;
use encoding_rs::GBK;
use serde::Deserialize;
Expand All @@ -28,7 +29,7 @@ use std::fmt::Display;
/// that entry. The mode is a three-digit octal number that encodes both the permissions and the
/// type of the object. The first digit specifies the object type, and the remaining two digits
/// specify the file mode or permissions.
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize, Hash)]
#[derive(PartialEq, Eq, Debug, Clone, Copy, Serialize, Deserialize, Hash, Encode, Decode)]
pub enum TreeItemMode {
Blob,
BlobExecutable,
Expand Down Expand Up @@ -129,7 +130,7 @@ impl TreeItemMode {
/// 100644 hello-world\0<blob object ID>
/// 040000 data\0<tree object ID>
/// ```
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Hash)]
#[derive(PartialEq, Eq, Debug, Clone, Serialize, Deserialize, Hash, Encode, Decode)]
pub struct TreeItem {
pub mode: TreeItemMode,
pub id: SHA1,
Expand Down Expand Up @@ -220,7 +221,8 @@ impl TreeItem {

/// A tree object is a Git object that represents a directory. It contains a list of entries, one
/// for each file or directory in the tree.
#[derive(Eq, Debug, Clone, Serialize, Deserialize)]
#[derive(Eq, Debug, Clone, Serialize, Deserialize, Encode, Decode)]
#[non_exhaustive]
pub struct Tree {
pub id: SHA1,
pub tree_items: Vec<TreeItem>,
Expand Down
2 changes: 1 addition & 1 deletion mercury/src/internal/pack/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ impl Caches {
let hash_str = hash._to_string();
path.push(&hash_str[..2]); // use first 2 chars as the directory
self.path_prefixes[hash.as_ref()[0] as usize].call_once(|| {
// 检查目录是否存在,只有在不存在时才创建
// Check if the directory exists, if not, create it
if !path.exists() {
fs::create_dir_all(&path).unwrap();
}
Expand Down
2 changes: 2 additions & 0 deletions mercury/src/internal/pack/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ impl PackEncoder {
return self.inner_encode(entry_rx, true).await;
}

/// Delta selection heuristics are based on:
/// https://github.com/git/git/blob/master/Documentation/technical/pack-heuristics.adoc
async fn inner_encode(
&mut self,
mut entry_rx: mpsc::Receiver<Entry>,
Expand Down
7 changes: 2 additions & 5 deletions scorpio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,8 @@ reqwest = { version = "0.12.7", features = ["json","blocking"] }
serde = { version = "1.0.210", features = ["derive"] }
fuse-backend-rs = { version = "0.12.0", features = ["fusedev","async-io"]}
tokio = { version = "1.40.0", features = ["full"] }
vm-memory = { version = "0.15.0", features = ["backend-mmap", "backend-bitmap"] }
axum = { version = "0.7.7",features=["macros"]}
axum = { version = "0.8.4",features=["macros"]}
rfuse3 = { version = "0.0.2" ,features = ["tokio-runtime","unprivileged"]}
futures-util = { version = "0.3.30", features = ["sink"] }
syn = { version = "2.0.98", features = ["full", "extra-traits"] }
clap = { version = "4.0", features = ["derive"] }

Expand All @@ -30,11 +28,10 @@ once_cell = "1.19.0"
arc-swap = "1.7.1"
env_logger = "0.11.5"
sled = "0.34.7"
bincode = "1.3.3"
bincode = { workspace = true , features = ["serde"] }
async-recursion = "1.1.1"
bytes = "1.7.2"
futures = "0.3.31"
vmm-sys-util = "0.11"
quote = "1.0.38"
proc-macro2 = "1.0.93"
uuid = "1.14.0"
Expand Down
22 changes: 14 additions & 8 deletions scorpio/src/dicfuse/tree_store.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::util::{config, GPath};
use bincode::{Decode, Encode};
use rfuse3::raw::reply::ReplyEntry;
use rfuse3::FileType;
use serde::{Deserialize, Serialize};
Expand All @@ -14,7 +15,7 @@ pub struct TreeStorage {
db: Db,
}

#[derive(Serialize, Deserialize, Clone)]
#[derive(Serialize, Deserialize, Clone,Encode,Decode)]
pub struct StorageItem {
inode: u64,
parent: u64,
Expand Down Expand Up @@ -80,12 +81,12 @@ impl TreeStorage {
children: Vec::new(),
hash: item.hash,
};

let config = bincode::config::standard();
// Insert an item into db and update the parent item's children list.
self.db
.insert(
inode.to_be_bytes(),
bincode::serialize(&storage_item).map_err(Error::other)?,
bincode::encode_to_vec(&storage_item,config).map_err(Error::other)?,
)
.map_err(Error::other)?;

Expand All @@ -97,7 +98,7 @@ impl TreeStorage {
self.db
.insert(
parent.to_be_bytes(),
bincode::serialize(&parent_item).map_err(Error::other)?,
bincode::encode_to_vec(&parent_item,config).map_err(Error::other)?,
)
.map_err(Error::other)?;
}
Expand All @@ -122,10 +123,12 @@ impl TreeStorage {
if storage_item.parent != 0 {
let mut parent_item: StorageItem = self.get_storage_item(storage_item.parent)?;
parent_item.children.retain(|&x| x != inode);
let config = bincode::config::standard();

self.db
.insert(
storage_item.parent.to_be_bytes(),
bincode::serialize(&parent_item).map_err(Error::other)?,
bincode::encode_to_vec(&parent_item, config).map_err(Error::other)?,
)
.map_err(Error::other)?;
}
Expand All @@ -140,10 +143,11 @@ impl TreeStorage {
pub fn append_child(&self, parent: u64, inode: u64) -> io::Result<()> {
let mut st = self.get_storage_item(parent)?;
st.children.push(inode);
let config = bincode::config::standard();
self.db
.insert(
parent.to_be_bytes(),
bincode::serialize(&st).map_err(Error::other)?,
bincode::encode_to_vec(&st, config).map_err(Error::other)?,
)
.map_err(Error::other)?;
Ok(())
Expand All @@ -163,7 +167,8 @@ impl TreeStorage {
pub fn get_storage_item(&self, inode: u64) -> io::Result<StorageItem> {
match self.db.get(inode.to_be_bytes())? {
Some(value) => {
let item: StorageItem = bincode::deserialize(&value).map_err(Error::other)?;
let config = bincode::config::standard();
let (item ,_) = bincode::decode_from_slice(&value,config).map_err(Error::other)?;
Ok(item)
}
None => Err(Error::new(ErrorKind::NotFound, "Item not found")),
Expand All @@ -184,10 +189,11 @@ impl TreeStorage {
pub fn update_item_hash(&self, inode: u64, hash: String) -> io::Result<()> {
let mut item = self.get_storage_item(inode)?;
item.hash = hash;
let config = bincode::config::standard();
self.db
.insert(
inode.to_be_bytes(),
bincode::serialize(&item).map_err(Error::other)?,
bincode::encode_to_vec(&item,config).map_err(Error::other)?,
)
.map_err(Error::other)?;
Ok(())
Expand Down
8 changes: 3 additions & 5 deletions scorpio/src/manager/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,7 @@ fn build_new_tree_map(
Err(_) => {
#[cfg(debug_assertions)]
color_info!("New Tree: \x1b[1;32m{}\x1b[0m", parent_path.display());
Tree {
id: SHA1::default(),
tree_items: Vec::new(),
}
Tree::from_tree_items(vec![]).unwrap()
}
};
// Update the new TreeItem
Expand Down Expand Up @@ -277,10 +274,11 @@ pub fn commit_core(
// overwrite operation, we can update it
// with confidence.
let mut batch = sled::Batch::default();
let config = bincode::config::standard();
for (path, tree) in hashmap.iter() {
batch.insert(
path.to_string_lossy().into_owned().as_str(),
bincode::serialize(tree).unwrap(),
bincode::encode_to_vec(tree,config).unwrap(),
);
}
new_tree_db.apply_batch(batch)?;
Expand Down
Loading
Loading