diff options
Diffstat (limited to 'pkgs/by-name/ba/back/src/config/mod.rs')
-rw-r--r-- | pkgs/by-name/ba/back/src/config/mod.rs | 110 |
1 files changed, 98 insertions, 12 deletions
diff --git a/pkgs/by-name/ba/back/src/config/mod.rs b/pkgs/by-name/ba/back/src/config/mod.rs index 7351ad8..1161ce3 100644 --- a/pkgs/by-name/ba/back/src/config/mod.rs +++ b/pkgs/by-name/ba/back/src/config/mod.rs @@ -18,21 +18,97 @@ use gix::ThreadSafeRepository; use serde::Deserialize; use url::Url; -use crate::error::{self, Error}; +use crate::{ + error::{self, Error}, + git_bug::dag::is_git_bug, +}; pub struct BackConfig { - // NOTE(@bpeetz): We do not need to html escape this, as the value must be a valid url. As such - // `<tags>` of all kinds _should_ be invalid. <2024-12-26> + /// The url to the source code of back. This is needed, because back is licensed under the + /// AGPL. pub source_code_repository_url: Url, - pub repository: ThreadSafeRepository, + + /// A list of the repositories known to back. + /// This list is constructed from the `scan_path` and the `project_list` file. + pub repositories: BackRepositories, + + /// The root url this instance of back is hosted on. + /// For example: + /// `issues.foss-syndicate.org` pub root: Url, } +pub struct BackRepositories { + repositories: Vec<BackRepository>, + + /// The path that is the common parent of all the repositories. + scan_path: PathBuf, +} + +impl BackRepositories { + pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter { + self.into_iter() + } +} + +impl<'a> IntoIterator for &'a BackRepositories { + type Item = <&'a Vec<BackRepository> as IntoIterator>::Item; + + type IntoIter = <&'a Vec<BackRepository> as IntoIterator>::IntoIter; + + 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 fn scan_path(&self) -> &Path { + &self.scan_path + } +} + +pub struct BackRepository { + repo_path: PathBuf, +} + +impl BackRepository { + pub fn open(&self, scan_path: &Path) -> Result<ThreadSafeRepository, error::Error> { + let repo = ThreadSafeRepository::open(scan_path.join(&self.repo_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 + } +} + #[derive(Deserialize)] struct RawBackConfig { source_code_repository_url: Url, - repository_path: PathBuf, root_url: Url, + project_list: PathBuf, + scan_path: PathBuf, } impl BackConfig { @@ -56,16 +132,26 @@ impl TryFrom<RawBackConfig> for BackConfig { type Error = error::Error; fn try_from(value: RawBackConfig) -> Result<Self, Self::Error> { - let repository = { - ThreadSafeRepository::open(&value.repository_path).map_err(|err| Error::RepoOpen { - repository_path: value.repository_path, - error: Box::new(err), - }) - }?; + let repositories = fs::read_to_string(&value.project_list) + .map_err(|err| error::Error::ProjectListRead { + error: err, + file: value.project_list, + })? + .lines() + .try_fold(vec![], |mut acc, path| { + acc.push(BackRepository { + repo_path: PathBuf::from(path), + }); + + Ok::<_, Self::Error>(acc) + })?; Ok(Self { - repository, source_code_repository_url: value.source_code_repository_url, + repositories: BackRepositories { + repositories, + scan_path: value.scan_path, + }, root: value.root_url, }) } |