Create basic config file structure
This commit is contained in:
29
Cargo.lock
generated
29
Cargo.lock
generated
@@ -2560,6 +2560,8 @@ dependencies = [
|
||||
"regex",
|
||||
"reqwest 0.13.1",
|
||||
"sd-notify",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tracing-journald",
|
||||
@@ -3326,6 +3328,8 @@ dependencies = [
|
||||
"rustls",
|
||||
"rustls-pki-types",
|
||||
"rustls-platform-verifier",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sync_wrapper",
|
||||
"tokio",
|
||||
"tokio-rustls",
|
||||
@@ -3652,14 +3656,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.143"
|
||||
version = "1.0.149"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4046,9 +4051,21 @@ dependencies = [
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-native-tls"
|
||||
version = "0.3.1"
|
||||
@@ -4893,3 +4910,9 @@ dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.100",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea"
|
||||
|
||||
@@ -13,8 +13,10 @@ gitlab = "0.1807.0"
|
||||
gix = "0.70.0"
|
||||
octocrab = "0.49.5"
|
||||
regex = "1.12.2"
|
||||
reqwest = "0.13.1"
|
||||
reqwest = { version = "0.13.1", features = ["json"] }
|
||||
sd-notify = "0.4.5"
|
||||
tokio = { version = "1.49.0", features = ["rt-multi-thread"] }
|
||||
serde = "1.0.228"
|
||||
serde_json = "1.0.149"
|
||||
tokio = { version = "1.49.0", features = ["macros", "rt-multi-thread"] }
|
||||
tracing = "0.1.41"
|
||||
tracing-journald = "0.3.1"
|
||||
|
||||
29
example-config.json
Normal file
29
example-config.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"source_hosts": {
|
||||
"pvv-git": {
|
||||
"type": "gitea",
|
||||
"host": "git.pvv.ntnu.no",
|
||||
"token": null
|
||||
}
|
||||
},
|
||||
"sources": {
|
||||
"oysteikt-repos": {
|
||||
"type": "user",
|
||||
"source_host": "pvv-git",
|
||||
"name": "oysteikt",
|
||||
"clone": true
|
||||
},
|
||||
"drift-repos": {
|
||||
"type": "organization",
|
||||
"source_host": "pvv-git",
|
||||
"name": "drift",
|
||||
"clone": true
|
||||
},
|
||||
"oysteikt-stars": {
|
||||
"type": "user-stars",
|
||||
"source_host": "pvv-git",
|
||||
"name": "oysteikt",
|
||||
"clone": true
|
||||
}
|
||||
}
|
||||
}
|
||||
196
src/config.rs
196
src/config.rs
@@ -1 +1,197 @@
|
||||
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>,
|
||||
}
|
||||
|
||||
#[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)]
|
||||
pub struct IssueFilterConfig {
|
||||
// - Filter by label(s)
|
||||
// - Filter by assignee(s)
|
||||
// - Filter by milestone(s)
|
||||
// - Filter by state (open, closed, all)
|
||||
}
|
||||
|
||||
impl Default for IssueFilterConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct CloneFilterConfig {
|
||||
// - Use native API if available
|
||||
// - Which branches to get
|
||||
// - Which tags to get
|
||||
// - Get LFS objects
|
||||
// - Get Releases
|
||||
// - Get Pull Requests
|
||||
}
|
||||
|
||||
impl Default for CloneFilterConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
40
src/main.rs
40
src/main.rs
@@ -1,28 +1,33 @@
|
||||
pub mod config;
|
||||
pub mod sources;
|
||||
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Context;
|
||||
use clap::{CommandFactory, Parser};
|
||||
use clap_complete::{Shell, generate};
|
||||
|
||||
use config::Config;
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about)]
|
||||
struct Args {
|
||||
#[command(subcommand)]
|
||||
command: Command,
|
||||
|
||||
#[arg(short, long)]
|
||||
/// Path to the configuration file.
|
||||
#[arg(short, long, global = true, default_value = "./config.json")]
|
||||
config: PathBuf,
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug, Clone)]
|
||||
enum Command {
|
||||
/// Mirror repositories as specified in the config
|
||||
Rror,
|
||||
// Rror,
|
||||
|
||||
/// Create a linktree of the latest backups of the repositories, for use with cgit et al.
|
||||
Linktree,
|
||||
// Linktree,
|
||||
|
||||
/// Validate the configuration provided configuration file
|
||||
ValidateConfig,
|
||||
@@ -38,20 +43,23 @@ struct GenerateCompletionArgs {
|
||||
shell: Shell,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let args = Args::parse();
|
||||
|
||||
match args.command {
|
||||
Command::GenerateCompletions(args) => {
|
||||
generate(
|
||||
args.shell,
|
||||
&mut Args::command(),
|
||||
"kagami",
|
||||
&mut std::io::stdout(),
|
||||
);
|
||||
}
|
||||
_ => {
|
||||
unimplemented!()
|
||||
}
|
||||
if let Command::GenerateCompletions(args) = args.command {
|
||||
generate(
|
||||
args.shell,
|
||||
&mut Args::command(),
|
||||
"kagami",
|
||||
&mut std::io::stdout(),
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let raw_config = fs::read_to_string(&args.config).context("failed to read config file")?;
|
||||
let _config: Config =
|
||||
serde_json::from_str(&raw_config).context("failed to parse config file")?;
|
||||
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user