summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJustin Wernick <justin@worthe-it.co.za>2023-08-11 22:04:19 +0200
committerJustin Wernick <justin@worthe-it.co.za>2023-08-15 21:40:35 +0200
commit64da82c661b2a28c7a258bd30c0084633d0e1896 (patch)
treee631e496b70f10d8414a3d1962797aa6354de918 /src
parent2203a06532979e8c4772dcb134c109e1f308031a (diff)
Create group directories if they don't already exist
- With the correct ownership - With the correct permissions Fix #5
Diffstat (limited to 'src')
-rw-r--r--src/git.rs53
-rw-r--r--src/lib.rs2
-rw-r--r--src/user_info.rs9
3 files changed, 49 insertions, 15 deletions
diff --git a/src/git.rs b/src/git.rs
index 9fa3e78..ea55f2c 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -1,11 +1,12 @@
use crate::{
parser::{GitReceivePackArgs, GitUploadPackArgs},
- user_info::{get_user_groups, get_username},
+ user_info::{get_gid, get_user_groups, get_username},
ShackleError,
};
use git2::{ErrorCode, Repository, RepositoryInitMode, RepositoryInitOptions};
use std::{
fs,
+ os::unix::fs::PermissionsExt,
path::{Path, PathBuf},
process::Command,
};
@@ -75,24 +76,48 @@ pub fn init(
description: &Option<String>,
branch: &str,
) -> Result<GitInitResult, ShackleError> {
+ if let Some(group) = &group {
+ if !verify_user_is_in_group(group) {
+ return Err(ShackleError::InvalidGroup);
+ }
+ }
+
+ let git_prefix = git_dir_prefix();
+ let collection_dir = match group {
+ Some(group) => group_git_dir(group),
+ None => personal_git_dir()?,
+ };
+ let path = collection_dir.join(repo_name).with_extension("git");
+
+ if !git_prefix.is_dir() {
+ fs::create_dir(&git_prefix)?;
+ }
+
+ if !collection_dir.is_dir() {
+ fs::create_dir(&collection_dir)?;
+
+ if let Some(group) = group {
+ let gid = get_gid(&group).expect("User is in group but no group ID?");
+ nix::unistd::chown(&collection_dir, None, Some(gid))?;
+ }
+
+ let mut perms = collection_dir.metadata()?.permissions();
+ perms.set_mode(match group {
+ Some(_) => 0o2770,
+ None => 0o700,
+ });
+ fs::set_permissions(&collection_dir, perms)?;
+ }
+
let mut init_opts = RepositoryInitOptions::new();
init_opts
.bare(true)
- .mkdir(true)
+ .mkdir(false)
.no_reinit(true)
.initial_head(branch);
-
- let path = match group {
- Some(group) => {
- if !verify_user_is_in_group(group) {
- return Err(ShackleError::InvalidGroup);
- }
-
- init_opts.mode(RepositoryInitMode::SHARED_GROUP);
- group_git_dir(group).join(repo_name).with_extension("git")
- }
- None => personal_git_dir()?.join(repo_name).with_extension("git"),
- };
+ if group.is_some() {
+ init_opts.mode(RepositoryInitMode::SHARED_GROUP);
+ }
Repository::init_opts(&path, &init_opts)?;
if let Some(description) = description {
diff --git a/src/lib.rs b/src/lib.rs
index 163e41b..62c050a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -97,6 +97,8 @@ pub enum ShackleError {
#[error(transparent)]
IoError(#[from] io::Error),
#[error(transparent)]
+ NixError(#[from] nix::errno::Errno),
+ #[error(transparent)]
GitError(#[from] git2::Error),
#[error(transparent)]
ReadlineError(#[from] ReadlineError),
diff --git a/src/user_info.rs b/src/user_info.rs
index 7a42db9..a352adb 100644
--- a/src/user_info.rs
+++ b/src/user_info.rs
@@ -1,4 +1,4 @@
-use nix::unistd::{getgroups, getuid, Group, User};
+use nix::unistd::{getgroups, getuid, Gid, Group, User};
pub fn get_username() -> Option<String> {
let uid = getuid();
@@ -13,6 +13,13 @@ pub fn get_user_groups() -> Vec<String> {
.collect()
}
+pub fn get_gid(group_name: &str) -> Option<Gid> {
+ nix::unistd::Group::from_name(&group_name)
+ .ok()
+ .flatten()
+ .map(|group| group.gid)
+}
+
#[cfg(test)]
mod test {
use super::*;