Skip to content

Instantly share code, notes, and snippets.

@RandyMcMillan
Forked from rust-play/playground.rs
Last active July 15, 2025 16:48
Show Gist options
  • Save RandyMcMillan/db4b8b3f80ecb6f9d3a1cb3179867c1f to your computer and use it in GitHub Desktop.
Save RandyMcMillan/db4b8b3f80ecb6f9d3a1cb3179867c1f to your computer and use it in GitHub Desktop.
git_vfs.rs
use std::collections::HashMap;
use std::io::{self, Read, Write};
#[derive(Debug, PartialEq)]
enum GitVfsError {
NotFound,
AlreadyExists,
InvalidOperation,
}
type GitVfsResult<T> = Result<T, GitVfsError>;
struct GitVfs {
objects: HashMap<String, Vec<u8>>, // Stores git objects (blobs, trees, commits)
refs: HashMap<String, String>, // Stores references (branches, tags)
head: Option<String>, // Stores the current HEAD reference
}
impl GitVfs {
fn new() -> Self {
GitVfs {
objects: HashMap::new(),
refs: HashMap::new(),
head: None,
}
}
fn create_object(&mut self, hash: &str, data: &[u8]) -> GitVfsResult<()> {
if self.objects.contains_key(hash) {
return Err(GitVfsError::AlreadyExists);
}
self.objects.insert(hash.to_string(), data.to_vec());
Ok(())
}
fn get_object(&self, hash: &str) -> GitVfsResult<Vec<u8>> {
match self.objects.get(hash) {
Some(data) => Ok(data.clone()),
None => Err(GitVfsError::NotFound),
}
}
fn create_ref(&mut self, ref_name: &str, hash: &str) -> GitVfsResult<()> {
self.refs.insert(ref_name.to_string(), hash.to_string());
Ok(())
}
fn get_ref(&self, ref_name: &str) -> GitVfsResult<String> {
match self.refs.get(ref_name) {
Some(hash) => Ok(hash.clone()),
None => Err(GitVfsError::NotFound),
}
}
fn update_ref(&mut self, ref_name: &str, hash: &str) -> GitVfsResult<()> {
if !self.refs.contains_key(ref_name) {
return Err(GitVfsError::NotFound);
}
self.refs.insert(ref_name.to_string(), hash.to_string());
Ok(())
}
fn set_head(&mut self, ref_name: &str) -> GitVfsResult<()> {
if !self.refs.contains_key(ref_name) {
return Err(GitVfsError::NotFound);
}
self.head = Some(ref_name.to_string());
Ok(())
}
fn get_head(&self) -> GitVfsResult<String> {
match &self.head {
Some(head_ref) => Ok(head_ref.clone()),
None => Err(GitVfsError::NotFound),
}
}
//Simulates creating a blob object.
fn create_blob(&mut self, data: &[u8]) -> GitVfsResult<String> {
//In a real git this would be a real hash function, but for simplicity
//we use a string representation of the data length.
let hash = format!("{}", data.len());
self.create_object(&hash, data)?;
Ok(hash)
}
}
fn main() {
let mut git_vfs = GitVfs::new();
let blob_data = b"Hello, git virtual world!";
let blob_hash = git_vfs
.create_blob(blob_data)
.expect("Failed to create blob");
let blob_content = git_vfs.get_object(&blob_hash).expect("Failed to get blob");
println!("Blob content: {}", String::from_utf8_lossy(&blob_content));
git_vfs
.create_ref("refs/heads/main", &blob_hash)
.expect("Failed to create ref");
git_vfs
.set_head("refs/heads/main")
.expect("failed to set head");
let head_ref = git_vfs.get_head().expect("failed to get head");
println!("HEAD: {}", head_ref);
let main_ref_hash = git_vfs
.get_ref("refs/heads/main")
.expect("failed to get ref");
println!("Main ref hash: {}", main_ref_hash);
git_vfs
.update_ref("refs/heads/main", "new_hash")
.expect("failed to update ref");
let main_ref_hash = git_vfs
.get_ref("refs/heads/main")
.expect("failed to get ref");
println!("Updated Main ref hash: {}", main_ref_hash);
}
/*
Key Improvements and Git Concepts:
Object Storage:
Uses objects: HashMap<String, Vec<u8>> to store Git objects (blobs, trees, commits).
Objects are addressed by their SHA-1 hashes (simplified here).
References (Refs):
Uses refs: HashMap<String, String> to store references like branches (refs/heads/main), tags (refs/tags/v1.0), and other refs.
Each ref points to a commit hash.
HEAD:
Uses head: Option<String> to track the current branch or commit.
HEAD points to the currently checked-out branch.
Blob Creation:
The create_blob function simulates creating a blob object.
In a real Git, this would involve hashing the content with SHA-1.
For simplicity, the provided code uses the length of the data as the hash.
Ref Operations:
create_ref, get_ref, and update_ref functions manage references.
HEAD Operations:
set_head and get_head functions manage the HEAD reference.
Error Handling:
Uses GitVfsError for Git-specific errors.
Simplified Hashing:
The example avoids real SHA-1 hashing for simplicity. In a real Git implementation, you'd use a hashing library.
How to Use:
Create Objects: Use create_blob to create blob objects (representing file content).
Create Refs: Use create_ref to create branches or tags.
Set HEAD: Use set_head to switch branches.
Get Objects and Refs: Use get_object and get_ref to retrieve data.
Update Refs: use update_ref to move branches to new commit hashes.
This example provides a basic, in-memory simulation of a Git repository's core data structures. For a real Git implementation, you'd need to handle more complex object types (trees, commits), implement proper SHA-1 hashing, and manage a persistent storage mechanism.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment