diff options
Diffstat (limited to 'src/git.rs')
-rw-r--r-- | src/git.rs | 38 |
1 files changed, 32 insertions, 6 deletions
@@ -3,19 +3,42 @@ use crate::{ ShackleError, }; use git2::{Repository, RepositoryInitOptions}; -use std::{path::PathBuf, process::Command}; +use std::{ + path::{Path, PathBuf}, + process::Command, +}; use user_info::get_username; pub struct GitInitResult { pub path: PathBuf, } -pub fn init(repo_name: &str) -> Result<GitInitResult, ShackleError> { +fn personal_git_dir() -> Result<PathBuf, ShackleError> { let username = get_username().ok_or(ShackleError::UserReadError)?; - let mut path = PathBuf::from("git"); - path.push(username); - path.push(repo_name); - path.set_extension("git"); + Ok(Path::new("git").join(username)) +} + +fn is_valid_personal_git_repo(path: &PathBuf) -> Result<bool, ShackleError> { + let valid_dir = personal_git_dir()?.canonicalize()?; + let canonical_path = path.canonicalize()?; + let relative_path = match canonical_path.strip_prefix(&valid_dir) { + Ok(relative_path) => relative_path, + Err(_) => { + return Ok(false); + } + }; + + if relative_path.parent() != Some(Path::new("")) + || relative_path.extension().map(|ext| ext == "git") != Some(true) + { + return Ok(false); + } + + Ok(true) +} + +pub fn init(repo_name: &str) -> Result<GitInitResult, ShackleError> { + let path = personal_git_dir()?.join(repo_name).with_extension("git"); Repository::init_opts( &path, @@ -29,6 +52,9 @@ pub fn init(repo_name: &str) -> Result<GitInitResult, ShackleError> { pub fn upload_pack(upload_pack_args: &GitUploadPackArgs) -> Result<(), ShackleError> { let mut command = Command::new("git-upload-pack"); + if !is_valid_personal_git_repo(&upload_pack_args.directory)? { + return Err(ShackleError::InvalidDirectory); + } if upload_pack_args.strict { command.arg("strict"); |