Skip to content

Commit bf8de1f

Browse files
committed
imp(core): add sync_cache function
1 parent f597912 commit bf8de1f

7 files changed

Lines changed: 128 additions & 84 deletions

File tree

cli/src/lib.rs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,10 @@ enum CodeownersSubcommand {
129129
/// Output format: text|json|bincode
130130
#[arg(long, value_name = "FORMAT", default_value = "text", value_parser = parse_output_format)]
131131
format: OutputFormat,
132+
133+
/// Custom cache file location
134+
#[arg(long, value_name = "FILE", default_value = ".codeowners.cache")]
135+
cache_file: Option<PathBuf>,
132136
},
133137

134138
#[clap(
@@ -143,6 +147,10 @@ enum CodeownersSubcommand {
143147
/// Output format: text|json|bincode
144148
#[arg(long, value_name = "FORMAT", default_value = "text", value_parser = parse_output_format)]
145149
format: OutputFormat,
150+
151+
/// Custom cache file location
152+
#[arg(long, value_name = "FILE", default_value = ".codeowners.cache")]
153+
cache_file: Option<PathBuf>,
146154
},
147155
#[clap(
148156
name = "list-tags",
@@ -156,6 +164,10 @@ enum CodeownersSubcommand {
156164
/// Output format: text|json|bincode
157165
#[arg(long, value_name = "FORMAT", default_value = "text", value_parser = parse_output_format)]
158166
format: OutputFormat,
167+
168+
/// Custom cache file location
169+
#[arg(long, value_name = "FILE", default_value = ".codeowners.cache")]
170+
cache_file: Option<PathBuf>,
159171
},
160172
}
161173

@@ -208,19 +220,25 @@ pub(crate) fn codeowners(subcommand: &CodeownersSubcommand) -> Result<()> {
208220
owners,
209221
unowned,
210222
format,
223+
cache_file,
211224
} => commands::codeowners_list_files(
212225
path.as_deref(),
213226
tags.as_deref(),
214227
owners.as_deref(),
215228
*unowned,
216229
format,
230+
cache_file.as_deref(),
217231
),
218-
CodeownersSubcommand::ListOwners { path, format } => {
219-
commands::codeowners_list_owners(path.as_deref(), format)
220-
}
221-
CodeownersSubcommand::ListTags { path, format } => {
222-
commands::codeowners_list_tags(path.as_deref(), format)
223-
}
232+
CodeownersSubcommand::ListOwners {
233+
path,
234+
format,
235+
cache_file,
236+
} => commands::codeowners_list_owners(path.as_deref(), format, cache_file.as_deref()),
237+
CodeownersSubcommand::ListTags {
238+
path,
239+
format,
240+
cache_file,
241+
} => commands::codeowners_list_tags(path.as_deref(), format, cache_file.as_deref()),
224242
}
225243
}
226244

core/src/cache.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,29 @@ pub fn load_cache(path: &Path) -> Result<CodeownersCache> {
125125
}
126126
}
127127
}
128+
129+
pub fn sync_cache(
130+
repo: &std::path::Path, cache_file: Option<&std::path::Path>,
131+
) -> Result<CodeownersCache> {
132+
let config_cache_file = utils::app_config::AppConfig::fetch()?.cache_file.clone();
133+
134+
let cache_file: &std::path::Path = match cache_file {
135+
Some(file) => file.into(),
136+
None => std::path::Path::new(&config_cache_file),
137+
};
138+
139+
// Verify that the cache file exists
140+
if !repo.join(cache_file).exists() {
141+
// parse the codeowners files and build the cache
142+
return parse_repo(&repo, &cache_file);
143+
}
144+
145+
// Load the cache from the specified file
146+
load_cache(&repo.join(cache_file)).map_err(|e| {
147+
utils::error::Error::new(&format!(
148+
"Failed to load cache from {}: {}",
149+
cache_file.display(),
150+
e
151+
))
152+
})
153+
}

core/src/commands.rs

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use std::io::{self, Write};
22

3-
use crate::cache::{build_cache, load_cache, store_cache};
3+
use crate::cache::{build_cache, load_cache, store_cache, sync_cache};
44
use crate::common::find_files;
5-
use crate::types::{CacheEncoding, CodeownersEntry, OutputFormat};
5+
use crate::parse::parse_repo;
6+
use crate::types::{CacheEncoding, CodeownersCache, CodeownersEntry, OutputFormat};
67

78
use utils::app_config::AppConfig;
89
use utils::error::Result;
@@ -21,10 +22,18 @@ pub fn codeowners_parse(
2122
) -> Result<()> {
2223
println!("Parsing CODEOWNERS files at {}", path.display());
2324

24-
let codeowners_files = crate::common::find_codeowners_files(path)?;
25+
let cache_file = match cache_file {
26+
Some(file) => path.join(file),
27+
None => {
28+
let config = utils::app_config::AppConfig::fetch()?;
29+
path.join(config.cache_file)
30+
}
31+
};
2532

26-
//dbg!(&codeowners_files);
33+
// Collect all CODEOWNERS files in the specified path
34+
let codeowners_files = crate::common::find_codeowners_files(path)?;
2735

36+
// Parse each CODEOWNERS file and collect entries
2837
let parsed_codeowners: Vec<CodeownersEntry> = codeowners_files
2938
.iter()
3039
.filter_map(|file| {
@@ -34,18 +43,17 @@ pub fn codeowners_parse(
3443
.flatten()
3544
.collect();
3645

37-
//dbg!(&parsed_codeowners);
38-
46+
// Collect all files in the specified path
3947
let files = find_files(path)?;
4048

41-
//dbg!(&files);
49+
// Build the cache from the parsed CODEOWNERS entries and the files
4250
let cache = build_cache(parsed_codeowners, files)?;
4351

44-
store_cache(&cache, cache_file.unwrap(), encoding)?;
45-
46-
let cache = load_cache(cache_file.unwrap())?;
52+
// Store the cache in the specified file
53+
store_cache(&cache, &cache_file, encoding)?;
4754

48-
dbg!(cache);
55+
// Test the cache by loading it back
56+
let _cache = load_cache(&cache_file)?;
4957

5058
println!("CODEOWNERS parsing completed successfully");
5159

@@ -54,33 +62,14 @@ pub fn codeowners_parse(
5462

5563
/// Find and list files with their owners based on filter criteria
5664
pub fn codeowners_list_files(
57-
path: Option<&std::path::Path>, tags: Option<&str>, owners: Option<&str>, unowned: bool,
58-
format: &OutputFormat,
65+
repo: Option<&std::path::Path>, tags: Option<&str>, owners: Option<&str>, unowned: bool,
66+
format: &OutputFormat, cache_file: Option<&std::path::Path>,
5967
) -> Result<()> {
60-
let path_str = path.map_or(".".into(), |p| p.display().to_string());
61-
info!("Listing files in {}", path_str);
62-
info!("Tags filter: {:?}", tags);
63-
info!("Owners filter: {:?}", owners);
64-
info!("Unowned only: {}", unowned);
65-
info!("Output format: {}", format);
66-
67-
// Determine the cache file path based on repository path
68-
let repo_path = path.unwrap_or_else(|| std::path::Path::new("."));
69-
//let config = utils::app_config::AppConfig::fetch()?;
70-
// let cache_dir = config
71-
// .cache_dir
72-
// .unwrap_or_else(|| repo_path.join(".codeowners.cache"));
73-
let cache_file = repo_path.join(".codeowners.cache");
74-
75-
if !cache_file.exists() {
76-
return Err(utils::error::Error::new(&format!(
77-
"Cache file not found at {}. Please run 'codeowners parse' first.",
78-
cache_file.display()
79-
)));
80-
}
68+
// Repository path
69+
let repo = repo.unwrap_or_else(|| std::path::Path::new("."));
8170

8271
// Load the cache
83-
let cache = load_cache(&cache_file)?;
72+
let cache = sync_cache(repo, cache_file)?;
8473

8574
// Filter files based on criteria
8675
let filtered_files = cache
@@ -179,23 +168,14 @@ pub fn codeowners_list_files(
179168
}
180169

181170
/// Display aggregated owner statistics and associations
182-
pub fn codeowners_list_owners(path: Option<&std::path::Path>, format: &OutputFormat) -> Result<()> {
183-
info!("Listing owners");
184-
info!("Output format: {}", format);
185-
186-
// Determine the cache file path based on repository path
187-
let repo_path = path.unwrap_or_else(|| std::path::Path::new("."));
188-
let cache_file = repo_path.join(".codeowners.cache");
189-
190-
if !cache_file.exists() {
191-
return Err(utils::error::Error::new(&format!(
192-
"Cache file not found at {}. Please run 'codeowners parse' first.",
193-
cache_file.display()
194-
)));
195-
}
171+
pub fn codeowners_list_owners(
172+
repo: Option<&std::path::Path>, format: &OutputFormat, cache_file: Option<&std::path::Path>,
173+
) -> Result<()> {
174+
// Repository path
175+
let repo = repo.unwrap_or_else(|| std::path::Path::new("."));
196176

197177
// Load the cache
198-
let cache = load_cache(&cache_file)?;
178+
let cache = sync_cache(repo, cache_file)?;
199179

200180
// Process the owners from the cache
201181
match format {
@@ -267,23 +247,14 @@ pub fn codeowners_list_owners(path: Option<&std::path::Path>, format: &OutputFor
267247
}
268248

269249
/// Audit and analyze tag usage across CODEOWNERS files
270-
pub fn codeowners_list_tags(path: Option<&std::path::Path>, format: &OutputFormat) -> Result<()> {
271-
info!("Listing tags");
272-
info!("Output format: {}", format);
273-
274-
// Determine the cache file path based on repository path
275-
let repo_path = path.unwrap_or_else(|| std::path::Path::new("."));
276-
let cache_file = repo_path.join(".codeowners.cache");
277-
278-
if !cache_file.exists() {
279-
return Err(utils::error::Error::new(&format!(
280-
"Cache file not found at {}. Please run 'codeowners parse' first.",
281-
cache_file.display()
282-
)));
283-
}
250+
pub fn codeowners_list_tags(
251+
repo: Option<&std::path::Path>, format: &OutputFormat, cache_file: Option<&std::path::Path>,
252+
) -> Result<()> {
253+
// Repository path
254+
let repo = repo.unwrap_or_else(|| std::path::Path::new("."));
284255

285256
// Load the cache
286-
let cache = load_cache(&cache_file)?;
257+
let cache = sync_cache(repo, cache_file)?;
287258

288259
// Process the tags from the cache
289260
match format {

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate log;
44
pub mod cache;
55
pub mod commands;
66
pub mod common;
7+
pub mod parse;
78
pub mod types;
89

910
use utils::error::Result;

core/src/parse.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
use utils::error::Result;
2+
3+
use crate::{
4+
cache::{build_cache, store_cache},
5+
common::{find_codeowners_files, find_files, parse_codeowners},
6+
types::{CacheEncoding, CodeownersCache, CodeownersEntry},
7+
};
8+
9+
pub fn parse_repo(repo: &std::path::Path, cache_file: &std::path::Path) -> Result<CodeownersCache> {
10+
println!("Parsing CODEOWNERS files at {}", repo.display());
11+
12+
// Collect all CODEOWNERS files in the specified path
13+
let codeowners_files = find_codeowners_files(repo)?;
14+
15+
// Parse each CODEOWNERS file and collect entries
16+
let parsed_codeowners: Vec<CodeownersEntry> = codeowners_files
17+
.iter()
18+
.filter_map(|file| {
19+
let parsed = parse_codeowners(file).ok()?;
20+
Some(parsed)
21+
})
22+
.flatten()
23+
.collect();
24+
25+
// Collect all files in the specified path
26+
let files = find_files(repo)?;
27+
28+
// Build the cache from the parsed CODEOWNERS entries and the files
29+
let cache = build_cache(parsed_codeowners, files)?;
30+
31+
// Store the cache in the specified file
32+
store_cache(&cache, &repo.join(cache_file), CacheEncoding::Bincode)?;
33+
34+
println!("CODEOWNERS parsing completed successfully");
35+
36+
Ok(cache)
37+
}

src/resources/default_config.toml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
debug = false
22
log_level = "info"
3-
4-
[database]
5-
url = "custom database url"
6-
variable = "custom variable"
3+
cache_file = ".codeowners.cache"

utils/src/app_config.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,11 @@ lazy_static! {
1414
pub static ref BUILDER: RwLock<ConfigBuilder<DefaultState>> = RwLock::new(Config::builder());
1515
}
1616

17-
#[derive(Debug, Serialize, Deserialize)]
18-
pub struct Database {
19-
pub url: String,
20-
pub variable: String,
21-
}
22-
2317
#[derive(Debug, Serialize, Deserialize)]
2418
pub struct AppConfig {
2519
pub debug: bool,
2620
pub log_level: LogLevel,
27-
pub database: Database,
21+
pub cache_file: String,
2822
}
2923

3024
impl AppConfig {
@@ -44,7 +38,7 @@ impl AppConfig {
4438
}
4539

4640
// Merge settings with env variables
47-
builder = builder.add_source(Environment::with_prefix("APP")); // TODO: Merge settings with Clap Settings Arguments
41+
builder = builder.add_source(Environment::with_prefix("CODEINPUT")); // TODO: Merge settings with Clap Settings Arguments
4842

4943
// Save Config to RwLoc
5044
{
@@ -126,7 +120,7 @@ impl TryFrom<Config> for AppConfig {
126120
Ok(AppConfig {
127121
debug: config.get_bool("debug")?,
128122
log_level: config.get::<LogLevel>("log_level")?,
129-
database: config.get::<Database>("database")?,
123+
cache_file: config.get::<String>("cache_file")?,
130124
})
131125
}
132126
}

0 commit comments

Comments
 (0)