aboutsummaryrefslogtreecommitdiffstats
path: root/src/config
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-05-12 12:39:10 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-05-12 12:39:10 +0200
commit1e4dff1995833538f436b381bc0450a7c0080bad (patch)
tree2dc620ac9ea683cbee412b8d5818b3992462677c /src/config
downloadback-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')
-rw-r--r--src/config/mod.rs137
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,
+ })
+ }
+}