refactor, new functions

This commit is contained in:
Luca Bilke 2024-06-04 13:17:09 +02:00
parent 4611d251d5
commit b2461d0cc8
No known key found for this signature in database
GPG Key ID: C9E851809C1A5BDE
7 changed files with 181 additions and 80 deletions

39
Cargo.lock generated
View File

@ -17,6 +17,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "atomic-waker" name = "atomic-waker"
version = "1.1.2" version = "1.1.2"
@ -466,6 +475,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"confy", "confy",
"git2", "git2",
"regex",
"reqwest", "reqwest",
"serde", "serde",
"serde_json", "serde_json",
@ -736,6 +746,35 @@ dependencies = [
"thiserror", "thiserror",
] ]
[[package]]
name = "regex"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.4" version = "0.12.4"

View File

@ -3,16 +3,15 @@ name = "klados"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies]
git2 = "0.18.3"
regex = "1.10.4"
serde_json = "1.0.117"
[dependencies.reqwest] [dependencies.reqwest]
version = "0.12.4" version = "0.12.4"
features = ["json", "blocking"] features = ["json", "blocking"]
[dependencies.git2]
version = "0.18.3"
[dependencies.serde_json]
version = "1.0.117"
[dependencies.serde] [dependencies.serde]
version = "1.0.203" version = "1.0.203"
features = ["derive"] features = ["derive"]

View File

@ -2,8 +2,8 @@
- [X] Define config schema - [X] Define config schema
- [X] Parse config - [X] Parse config
- [ ] Discover local repositories in $KLADOS_DIR
- [X] Discover remote repositories - [X] Discover remote repositories
- [X] Discover local repositories
- [ ] Clone remote repositories - [ ] Clone remote repositories
- [ ] List unclean local repositories - [ ] List unclean local repositories
- [ ] Pull clean local repositories - [ ] Pull clean local repositories

View File

@ -1,34 +0,0 @@
use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct Config {
blacklist: Option<Vec<String>>,
lookups: Option<Vec<Lookup>>,
map: Option<Vec<Map>>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Lookup {
name: String,
url: String,
field: String,
interpolate: Option<Vec<String>>,
token_cmd: Option<String>,
block_unmatched: Option<bool>,
auth_header: Option<String>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Map {
patterns: Option<Vec<String>>,
url: Option<String>,
directory: Option<String>,
rename: Option<Vec<Rename>>,
ignore: Option<bool>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Rename {
replace: String,
with: String,
}

134
src/lib.rs Normal file
View File

@ -0,0 +1,134 @@
use git2::Repository;
use regex::Regex;
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::{env, fs, path::PathBuf};
#[derive(Debug, Default, Deserialize, Serialize)]
pub struct Config {
pub root_dir: String,
blacklist: Option<Vec<String>>,
lookups: Option<Vec<Lookup>>,
map: Vec<Map>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Lookup {
name: String,
url: String,
field: String,
interpolate: Option<Vec<String>>,
token_cmd: Option<String>,
block_unmatched: Option<bool>,
auth_header: Option<String>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Map {
patterns: Option<Vec<String>>,
url: Option<String>,
directory: Option<PathBuf>,
rename: Option<Vec<Rename>>,
ignore: Option<bool>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Rename {
replace: String,
with: String,
}
impl Config {
pub fn setup(self: &mut Config) {
self.root_dir = expand_env_vars(&self.root_dir);
}
pub fn list_target_dirs(self: &Config) -> Vec<PathBuf> {
self.map
.iter()
.filter_map(|map| {
map.directory
.as_ref()
.map(|path| PathBuf::from(self.root_dir.clone()).join(path))
})
.collect()
}
pub fn get_target_dir(self: &Config, repo_url: &str) -> Option<&PathBuf> {
for map in &self.map {
if let Some(patterns) = &map.patterns {
for pattern in patterns {
if repo_url.contains(pattern) {
return map.directory.as_ref();
}
}
}
}
None
}
}
pub fn get_remote_urls(
endpoint: &str,
auth_header: &str,
field: &str,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let handle = reqwest::blocking::Client::new();
let mut headers = HeaderMap::new();
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
headers.insert(
"Authorization",
HeaderValue::from_str(auth_header).expect("Malformed auth header"),
);
let res = handle
.get(endpoint)
.headers(headers)
.send()
.expect("Request to API Failed")
.json::<Value>()
.expect("Malformed JSON Response from API");
let urls = res
.as_array()
.unwrap_or(&Vec::new())
.iter()
.filter_map(|obj| obj[field].as_str())
.map(|url| url.to_string())
.collect();
Ok(urls)
}
pub fn get_existing_repos(directories: &Vec<PathBuf>) -> Option<Vec<Repository>> {
let mut repos: Vec<Repository> = Vec::new();
for dir in directories {
let entries = match fs::read_dir(dir) {
Ok(entries) => entries
.filter_map(|entry| entry.ok())
.map(|entry| entry.path())
.filter_map(|path| Repository::open(path).ok())
.collect::<Vec<Repository>>(),
Err(_) => continue,
};
repos.extend(entries)
}
Some(repos)
}
fn expand_env_vars(input: &str) -> String {
let re = Regex::new(r"\$\{?[a-zA-Z_][a-zA-Z0-9_]*(\}|\b)").unwrap();
re.replace_all(input, |captures: &regex::Captures| {
let var = captures
.get(0)
.unwrap()
.as_str()
.trim_start_matches('$')
.trim_matches(|c| c == '{' || c == '}');
env::var(var).unwrap()
})
.to_string()
}

View File

@ -1,6 +1,4 @@
pub mod config;
pub mod remote;
fn main() { fn main() {
let cfg: config::Config = confy::load("klados", "config").unwrap(); let mut cfg: klados::Config = confy::load("klados", "config").unwrap();
cfg.setup();
} }

View File

@ -1,35 +0,0 @@
use reqwest::header::{HeaderMap, HeaderValue, CONTENT_TYPE};
use serde_json::Value;
pub fn get_remote_urls(
endpoint: &str,
auth_header: &str,
field: &str,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
let handle = reqwest::blocking::Client::new();
let mut headers = HeaderMap::new();
headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
headers.insert(
"Authorization",
HeaderValue::from_str(auth_header).expect("Malformed auth header"),
);
let res = handle
.get(endpoint)
.headers(headers)
.send()
.expect("Request to API Failed")
.json::<Value>()
.expect("Malformed JSON Response from API");
let urls = res
.as_array()
.unwrap_or(&Vec::new())
.iter()
.filter_map(|obj| obj[field].as_str())
.map(|url| url.to_string())
.collect();
Ok(urls)
}