Skip to content
This repository was archived by the owner on Jan 21, 2026. It is now read-only.

Commit 99d9595

Browse files
committed
add glob support
1 parent 4357d40 commit 99d9595

File tree

7 files changed

+43
-13
lines changed

7 files changed

+43
-13
lines changed

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ binary = ["clap", "indicatif"]
2121
[dependencies]
2222
bzip2 = "0.5.2"
2323
clap = { version = "4.5.35", features = ["cargo", "derive"], optional = true }
24+
fast-glob = "0.4.5"
2425
flate2 = "1.1.1"
2526
futures = "0.3.31"
2627
indicatif = { version = "0.17.11", optional = true }

src/bin/soar-dl/cli.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,11 @@ pub struct Args {
3131

3232
/// Regex to select the asset.
3333
#[arg(required = false, short = 'r', long = "regex")]
34-
pub regex_patterns: Option<Vec<String>>,
34+
pub regexes: Option<Vec<String>>,
35+
36+
/// Glob to select the asset.
37+
#[arg(required = false, short = 'g', long = "glob")]
38+
pub globs: Option<Vec<String>>,
3539

3640
/// Check if the asset contains given string
3741
#[arg(required = false, short, long = "match")]

src/bin/soar-dl/download_manager.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ impl DownloadManager {
3737
let _ = self.handle_direct_downloads().await;
3838
}
3939

40-
fn create_regex(&self) -> Vec<Regex> {
40+
fn create_regexes(&self) -> Vec<Regex> {
4141
self.args
42-
.regex_patterns
42+
.regexes
4343
.clone()
4444
.map(|patterns| {
4545
patterns
@@ -53,12 +53,13 @@ impl DownloadManager {
5353
}
5454

5555
fn create_platform_options(&self, tag: Option<String>) -> PlatformDownloadOptions {
56-
let asset_regexes = self.create_regex();
56+
let regexes = self.create_regexes();
5757
PlatformDownloadOptions {
5858
output_path: self.args.output.clone(),
5959
progress_callback: Some(self.progress_callback.clone()),
6060
tag,
61-
regex_patterns: asset_regexes,
61+
regexes,
62+
globs: self.args.globs.clone().unwrap_or_default(),
6263
match_keywords: self.args.match_keywords.clone().unwrap_or_default(),
6364
exclude_keywords: self.args.exclude_keywords.clone().unwrap_or_default(),
6465
exact_case: false,
@@ -129,14 +130,15 @@ impl DownloadManager {
129130
}
130131

131132
async fn handle_oci_download(&self, reference: &str) -> Result<(), PlatformError> {
132-
let regex_patterns = self.create_regex();
133+
let regexes = self.create_regexes();
133134
let options = OciDownloadOptions {
134135
url: reference.to_string(),
135136
concurrency: self.args.concurrency.clone(),
136137
output_path: self.args.output.clone(),
137138
progress_callback: Some(self.progress_callback.clone()),
138139
api: self.args.ghcr_api.clone(),
139-
regex_patterns,
140+
regexes,
141+
globs: self.args.globs.clone().unwrap_or_default(),
140142
match_keywords: self.args.match_keywords.clone().unwrap_or_default(),
141143
exclude_keywords: self.args.exclude_keywords.clone().unwrap_or_default(),
142144
exact_case: self.args.exact_case,

src/downloader.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ pub struct OciDownloadOptions {
5757
pub output_path: Option<String>,
5858
pub progress_callback: Option<Arc<dyn Fn(DownloadState) + Send + Sync + 'static>>,
5959
pub api: Option<String>,
60-
pub regex_patterns: Vec<Regex>,
60+
pub regexes: Vec<Regex>,
61+
pub globs: Vec<String>,
6162
pub match_keywords: Vec<String>,
6263
pub exclude_keywords: Vec<String>,
6364
pub exact_case: bool,
@@ -289,7 +290,8 @@ impl OciDownloader {
289290

290291
matches_pattern(
291292
&title,
292-
options.regex_patterns.as_slice(),
293+
options.regexes.as_slice(),
294+
options.globs.as_slice(),
293295
options.match_keywords.as_slice(),
294296
options.exclude_keywords.as_slice(),
295297
options.exact_case,

src/platform.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ pub struct PlatformDownloadOptions {
120120
pub output_path: Option<String>,
121121
pub progress_callback: Option<Arc<dyn Fn(DownloadState) + Send + Sync + 'static>>,
122122
pub tag: Option<String>,
123-
pub regex_patterns: Vec<Regex>,
123+
pub regexes: Vec<Regex>,
124+
pub globs: Vec<String>,
124125
pub match_keywords: Vec<String>,
125126
pub exclude_keywords: Vec<String>,
126127
pub exact_case: bool,
@@ -254,7 +255,8 @@ impl<P: ReleasePlatform> ReleaseHandler<'_, P> {
254255
let name = asset.name();
255256
matches_pattern(
256257
name,
257-
options.regex_patterns.as_slice(),
258+
options.regexes.as_slice(),
259+
options.globs.as_slice(),
258260
options.match_keywords.as_slice(),
259261
options.exclude_keywords.as_slice(),
260262
options.exact_case,

src/utils.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::{
33
path::{Path, PathBuf},
44
};
55

6+
use fast_glob::glob_match;
67
use regex::Regex;
78
use reqwest::StatusCode;
89
use tokio::{
@@ -59,12 +60,14 @@ pub fn should_fallback(status: StatusCode) -> bool {
5960

6061
pub fn matches_pattern(
6162
name: &str,
62-
regex_patterns: &[Regex],
63+
regexes: &[Regex],
64+
globs: &[String],
6365
match_keywords: &[String],
6466
exclude_keywords: &[String],
6567
exact_case: bool,
6668
) -> bool {
67-
regex_patterns.iter().all(|regex| regex.is_match(name))
69+
regexes.iter().all(|regex| regex.is_match(name))
70+
&& globs.iter().all(|glob| glob_match(glob, name))
6871
&& match_keywords.iter().all(|keyword| {
6972
keyword
7073
.split(',')

0 commit comments

Comments
 (0)