diff options
author | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-05-12 12:39:10 +0200 |
---|---|---|
committer | Benedikt Peetz <benedikt.peetz@b-peetz.de> | 2025-05-12 12:39:10 +0200 |
commit | 1e4dff1995833538f436b381bc0450a7c0080bad (patch) | |
tree | 2dc620ac9ea683cbee412b8d5818b3992462677c /src/config/mod.rs | |
download | back-1e4dff1995833538f436b381bc0450a7c0080bad.zip |
chore: Initial commit
Based on the version that was previously in `vhack.eu/nixos-server/pkgs/by-name/ba/back`.
Diffstat (limited to 'src/config/mod.rs')
-rw-r--r-- | src/config/mod.rs | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/config/mod.rs b/src/config/mod.rs new file mode 100644 index 0000000..6c90fce --- /dev/null +++ b/src/config/mod.rs @@ -0,0 +1,137 @@ +// Back - An extremely simple git bug visualization system. Inspired by TVL's +// panettone. +// +// Copyright (C) 2024 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de> +// SPDX-License-Identifier: AGPL-3.0-or-later +// +// This file is part of Back. +// +// You should have received a copy of the License along with this program. +// If not, see <https://www.gnu.org/licenses/agpl.txt>. + +use std::{ + fs, + path::{Path, PathBuf}, +}; + +use gix::ThreadSafeRepository; +use serde::Deserialize; +use url::Url; + +use crate::{ + error::{self, Error}, + git_bug::dag::is_git_bug, +}; + +#[derive(Deserialize)] +pub struct BackConfig { + /// The url to the source code of back. This is needed, because back is licensed under the + /// AGPL. + pub source_code_repository_url: Url, + + /// The root url this instance of back is hosted on. + /// For example: + /// `issues.foss-syndicate.org` + pub root_url: Url, + + project_list: PathBuf, + + /// The path that is the common parent of all the repositories. + pub scan_path: PathBuf, +} + +pub struct BackRepositories { + repositories: Vec<BackRepository>, +} + +impl BackRepositories { + pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { + self.into_iter() + } +} + +impl<'a> IntoIterator for &'a BackRepositories { + type IntoIter = <&'a Vec<BackRepository> as IntoIterator>::IntoIter; + type Item = <&'a Vec<BackRepository> as IntoIterator>::Item; + + fn into_iter(self) -> Self::IntoIter { + self.repositories.iter() + } +} + +impl BackRepositories { + /// Try to get the repository at path `path`. + /// If no repository was registered/found at `path`, returns an error. + pub fn get(&self, path: &Path) -> Result<&BackRepository, error::Error> { + self.repositories + .iter() + .find(|p| p.repo_path == path) + .ok_or(error::Error::RepoFind { + repository_path: path.to_owned(), + }) + } +} + +pub struct BackRepository { + repo_path: PathBuf, +} + +impl BackRepository { + pub fn open(&self, scan_path: &Path) -> Result<ThreadSafeRepository, error::Error> { + let path = { + let base = scan_path.join(&self.repo_path); + if base.is_dir() { + base + } else { + PathBuf::from(base.display().to_string() + ".git") + } + }; + let repo = ThreadSafeRepository::open(path).map_err(|err| Error::RepoOpen { + repository_path: self.repo_path.to_owned(), + error: Box::new(err), + })?; + if is_git_bug(&repo.to_thread_local())? { + Ok(repo) + } else { + Err(error::Error::NotGitBug { + path: self.repo_path.clone(), + }) + } + } + + pub fn path(&self) -> &Path { + &self.repo_path + } +} + +impl BackConfig { + pub fn repositories(&self) -> error::Result<BackRepositories> { + let repositories = fs::read_to_string(&self.project_list) + .map_err(|err| error::Error::ProjectListRead { + error: err, + file: self.project_list.to_owned(), + })? + .lines() + .try_fold(vec![], |mut acc, path| { + acc.push(BackRepository { + repo_path: PathBuf::from(path), + }); + + Ok::<_, error::Error>(acc) + })?; + Ok(BackRepositories { repositories }) + } + + pub fn from_config_file(path: &Path) -> error::Result<Self> { + let value = fs::read_to_string(path).map_err(|err| Error::ConfigRead { + file: path.to_owned(), + error: err, + })?; + + serde_json::from_str(&value).map_err(|err| Error::ConfigParse { + file: path.to_owned(), + error: err, + }) + } +} |