Files
kagami/src/config.rs
2026-01-19 10:16:00 +09:00

200 lines
5.8 KiB
Rust

use anyhow::Context;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Config {
pub source_hosts: HashMap<String, SourceHostConfig>,
pub sources: HashMap<String, SourceConfig>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SourceHostConfig {
#[serde(rename = "type")]
pub _type: SourceHostType,
pub host: Option<String>,
pub token_file: Option<PathBuf>,
pub token: Option<String>,
}
impl SourceHostConfig {
pub fn get_token(&self) -> anyhow::Result<Option<String>> {
if let Some(ref t) = self.token {
return Ok(Some(t.clone()));
}
if let Some(ref p) = self.token_file {
let s = std::fs::read_to_string(p).context("failed to read token file")?;
return Ok(Some(s.trim().to_string()));
}
Ok(None)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum SourceHostType {
Github,
Gitlab,
Gitea,
Forgejo,
Git,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
#[serde(rename_all = "kebab-case")]
pub enum SourceConfig {
User {
/// Which source host to use (as defined in source_hosts)
/// You can also specify either of the following built-in source hosts:
///
/// - "github" for GitHub at github.com
/// - "gitlab" for GitLab at gitlab.com
/// - "gitea" for Gitea at gitea.com
/// - "codeberg" for Forgejo at codeberg.org
source_host: String,
/// The user name
name: String,
/// Filters applied when selecting repositories
#[serde(default)]
repository_filters: RepositoryFilterConfig,
/// Whether to clone the selected repositories
#[serde(default)]
clone: bool,
/// Filters applied when cloning repositories
#[serde(default)]
clone_filters: CloneFilterConfig,
/// Whether to export issues for the selected repositories
#[serde(default)]
export_issues: bool,
/// Filters applied when exporting issues
#[serde(default)]
issue_filters: IssueFilterConfig,
},
Organization {
/// Which source host to use (as defined in source_hosts)
/// You can also specify either of the following built-in source hosts:
///
/// - "github" for GitHub at github.com
/// - "gitlab" for GitLab at gitlab.com
/// - "gitea" for Gitea at gitea.com
/// - "codeberg" for Forgejo at codeberg.org
source_host: String,
/// The organization name
name: String,
/// Whether to recurse into the organization's groups/subgroups (if supported)
#[serde(default)]
recurse_groups: bool,
/// Filters applied when selecting repositories
#[serde(default)]
repository_filters: RepositoryFilterConfig,
/// Whether to clone the selected repositories
#[serde(default)]
clone: bool,
/// Filters applied when cloning repositories
#[serde(default)]
clone_filters: CloneFilterConfig,
/// Whether to export issues for the selected repositories
#[serde(default)]
export_issues: bool,
/// Filters applied when exporting issues
#[serde(default)]
issue_filters: IssueFilterConfig,
},
UserStars {
/// Which source host to use (as defined in source_hosts)
/// You can also specify either of the following built-in source hosts:
///
/// - "github" for GitHub at github.com
/// - "gitlab" for GitLab at gitlab.com
/// - "gitea" for Gitea at gitea.com
/// - "codeberg" for Forgejo at codeberg.org
source_host: String,
/// The username whose stars to fetch
name: String,
/// Filters applied when selecting repositories
#[serde(default)]
repository_filters: RepositoryFilterConfig,
/// Whether to clone the selected repositories
#[serde(default)]
clone: bool,
/// Filters applied when cloning repositories
#[serde(default)]
clone_filters: CloneFilterConfig,
/// Whether to export issues for the selected repositories
#[serde(default)]
export_issues: bool,
/// Filters applied when exporting issues
#[serde(default)]
issue_filters: IssueFilterConfig,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RepositoryFilterConfig {
pub filter_regex: Vec<RegexFilter>,
pub include_forks: bool,
pub include_archived: bool,
pub min_stars: Option<u32>,
pub max_stars: Option<u32>,
pub include_public: bool,
pub include_internal: bool,
pub include_private: bool,
}
impl Default for RepositoryFilterConfig {
fn default() -> Self {
Self {
filter_regex: Vec::new(),
include_forks: true,
include_archived: true,
min_stars: None,
max_stars: None,
include_public: true,
include_internal: true,
include_private: true,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum RegexFilter {
Include(String),
Exclude(String),
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct IssueFilterConfig {
// - Filter by label(s)
// - Filter by assignee(s)
// - Filter by milestone(s)
// - Filter by state (open, closed, all)
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct CloneFilterConfig {
// - Use native API if available
// - Which branches to get
// - Which tags to get
// - Get LFS objects
// - Get Releases
// - Get Pull Requests
}