Skip to content

Commit

Permalink
feat: implement handle_cmd and git storage - filesystem
Browse files Browse the repository at this point in the history
  • Loading branch information
forfd8960 committed Aug 24, 2024
1 parent cd04e46 commit a164cc5
Show file tree
Hide file tree
Showing 16 changed files with 164 additions and 8 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ version = "0.1.0"
edition = "2021"

[dependencies]
anyhow = "1.0.86"
clap = { version = "4.5.16", features = ["derive"] }
26 changes: 26 additions & 0 deletions src/command/handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use crate::repo::Repository;

use super::GitSubCommand;

pub fn handle_command(cmd: &GitSubCommand) -> anyhow::Result<()> {
match cmd {
GitSubCommand::Init(opts) => {
println!("init repo optiond: {:?}", opts);
let repo = Repository::new(".");
repo.init()?;
}
GitSubCommand::Add(opts) => {
todo!()
}
GitSubCommand::Commit(opts) => {
todo!()
}
GitSubCommand::Log(opts) => {
todo!()
}
GitSubCommand::Branch(opts) => {
todo!()
}
}
Ok(())
}
17 changes: 11 additions & 6 deletions src/command/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use clap::{Parser, Subcommand};

pub mod handler;

#[derive(Debug, Parser)]
#[command(name="simple-git", version="0.0.1", about, long_about = None)]
pub struct SimpleGit {
Expand All @@ -20,7 +22,10 @@ pub enum GitSubCommand {
Commit(CommitOpts),
#[command(name = "log", about = "show commit logs")]
Log(LogOpts),
#[command(name = "branch", about = "git-branch - List, create, or delete branches")]
#[command(
name = "branch",
about = "git-branch - List, create, or delete branches"
)]
Branch(BranchOpts),
}

Expand All @@ -32,18 +37,18 @@ pub struct InitOpts {

/// Specify the given object <format> (hash algorithm) for the repository. The valid values are sha1 and (if enabled) sha256. sha1 is the default.
#[arg(long = "object-format", default_value = "sha1")]
pub object_format: String,
pub object_format: Option<String>,

#[arg(long = "ref-format", default_value = "files")]
pub ref_format: String,
pub ref_format: Option<String>,

/// Specify the directory from which templates will be used.
#[arg(long = "template")]
pub template: String,
pub template: Option<String>,

/// Use <branch-name> for the initial branch in the newly created repository. If not specified, fall back to the default name.
#[arg(short, long = "initial-branch")]
pub branch: String,
pub branch: Option<String>,
}

#[derive(Debug, Parser)]
Expand Down Expand Up @@ -132,7 +137,7 @@ pub struct BranchOpts {
pub delete: String,

/// Move/rename a branch, together with its config and reflog.
#[arg(short='m', long="move")]
#[arg(short = 'm', long = "move")]
pub move_branch: String,

/// Copy a branch, together with its config and reflog.
Expand Down
5 changes: 5 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
pub mod command;
pub mod objects;
pub mod plumbing;
pub mod repo;
pub mod storage;
pub mod worktree;
7 changes: 5 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use anyhow::Result;
use clap::Parser;
use git_rs::command::SimpleGit;
use git_rs::command::{handler::handle_command, SimpleGit};

fn main() {
fn main() -> Result<()> {
let cmd = SimpleGit::parse();
println!("{:?}", cmd);
handle_command(&cmd.command)?;
Ok(())
}
2 changes: 2 additions & 0 deletions src/objects/blob.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[derive(Debug)]
pub struct Blob {}
2 changes: 2 additions & 0 deletions src/objects/commit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[derive(Debug)]
pub struct Commit {}
3 changes: 3 additions & 0 deletions src/objects/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod blob;
pub mod tree;
pub mod commit;
2 changes: 2 additions & 0 deletions src/objects/tree.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#[derive(Debug)]
pub struct Tree {}
3 changes: 3 additions & 0 deletions src/plumbing/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub const HEAD: &'static str = "HEAD";
pub const MASTER: &'static str = "refs/heads/master";
pub const MAIN: &'static str = "refs/heads/main";
18 changes: 18 additions & 0 deletions src/repo/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use crate::storage::{filesystem::FileSystem, Store};

pub struct Repository {
storer: FileSystem,
}

impl Repository {
pub fn new(path: &str) -> Self {
Repository {
storer: FileSystem::new(path),
}
}

pub fn init(&self) -> anyhow::Result<()> {
self.storer.init_dot_git()?;
Ok(())
}
}
69 changes: 69 additions & 0 deletions src/storage/filesystem.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
use std::fs;
use std::io::Write;
use std::path::Path;

use crate::plumbing;

use super::Store;

// The file operations git will perforam.
pub struct FileSystem {
pub root: String,
}

impl FileSystem {
pub fn new(path: &str) -> Self {
FileSystem {
root: path.to_string(),
}
}
}

impl Store for FileSystem {
fn init_dot_git(&self) -> anyhow::Result<()> {
let full_path = format!("{}/{}", self.root, ".git");
if !Path::new(&full_path).exists() {
fs::create_dir(full_path.clone())?;
}

// create the directories
let dirs = ["objects", "refs", "hooks", "info"];
for dir in dirs {
let sub_dir = format!("{}/{}", full_path, dir);
if !Path::new(&sub_dir).exists() {
fs::create_dir(sub_dir.clone())?;
match dir {
"objects" => {
fs::create_dir(format!("{}/{}", sub_dir, "info"))?;
fs::create_dir(format!("{}/{}", sub_dir, "pack"))?;
}
"refs" => {
fs::create_dir(format!("{}/{}", sub_dir, "heads"))?;
fs::create_dir(format!("{}/{}", sub_dir, "tags"))?;
}
"info" => {
fs::create_dir(format!("{}/{}", sub_dir, "exclude"))?;
}
_ => {}
}
}
}

// create the files
let files = [plumbing::HEAD, "config", "description"];
for file in files {
let sub_file = format!("{}/{}", full_path, file);
let _ = fs::File::create(sub_file)?;
}

let main_ref_path = format!("{}/{}", full_path, plumbing::HEAD);
Self::set_head(&main_ref_path, "ref: refs/heads/master")?;
Ok(())
}

fn set_head(file: &str, ref_content: &str) -> anyhow::Result<()> {
let mut ref_f = fs::File::open(file)?;
let _ = ref_f.write_all(ref_content.as_bytes())?;
Ok(())
}
}
7 changes: 7 additions & 0 deletions src/storage/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod filesystem;

use anyhow::Result;
pub trait Store {
fn init_dot_git(&self) -> Result<()>;
fn set_head(file: &str, ref_content: &str) -> Result<()>;
}
Empty file added src/worktree/index.rs
Empty file.
3 changes: 3 additions & 0 deletions src/worktree/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod index;

pub struct Worktree {}

0 comments on commit a164cc5

Please sign in to comment.