Skip to content

Commit 72bf82a

Browse files
committed
properly show stderr output, cargo fmt
1 parent 99f8f88 commit 72bf82a

File tree

6 files changed

+155
-65
lines changed

6 files changed

+155
-65
lines changed

src/backends/distrobox/distrobox.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use serde::{Deserialize, Deserializer};
44
use std::{
55
cell::LazyCell,
66
collections::BTreeMap,
7-
87
ffi::OsString,
98
io,
109
os::unix::ffi::OsStringExt,
@@ -659,22 +658,29 @@ impl Distrobox {
659658

660659
async fn host_applications_path(&self) -> Result<PathBuf, Error> {
661660
// Resolve XDG_DATA_HOME via runner (works in Flatpak via map_flatpak_spawn_host)
662-
let xdg_data_home_opt = match crate::fakers::resolve_host_env_via_runner(&self.cmd_runner, "XDG_DATA_HOME").await {
663-
Ok(Some(s)) if !s.trim().is_empty() => Some(Path::new(s.trim()).to_path_buf()),
664-
Ok(_) => None,
665-
Err(e) => {
666-
tracing::warn!("failed to resolve XDG_DATA_HOME via CommandRunner: {e:?}");
667-
None
668-
}
669-
};
661+
let xdg_data_home_opt =
662+
match crate::fakers::resolve_host_env_via_runner(&self.cmd_runner, "XDG_DATA_HOME")
663+
.await
664+
{
665+
Ok(Some(s)) if !s.trim().is_empty() => Some(Path::new(s.trim()).to_path_buf()),
666+
Ok(_) => None,
667+
Err(e) => {
668+
tracing::warn!("failed to resolve XDG_DATA_HOME via CommandRunner: {e:?}");
669+
None
670+
}
671+
};
670672

671673
let apps_base = if let Some(p) = xdg_data_home_opt {
672674
p
673675
} else {
674676
// Fallback to HOME
675677
match crate::fakers::resolve_host_env_via_runner(&self.cmd_runner, "HOME").await {
676678
Ok(Some(s)) if !s.trim().is_empty() => Path::new(s.trim()).join(".local/share"),
677-
Ok(_) => return Err(Error::ResolveHostPath("XDG_DATA_HOME and HOME are not set on the host".into())),
679+
Ok(_) => {
680+
return Err(Error::ResolveHostPath(
681+
"XDG_DATA_HOME and HOME are not set on the host".into(),
682+
));
683+
}
678684
Err(e) => {
679685
tracing::warn!("failed to resolve HOME via CommandRunner: {e:?}");
680686
return Err(Error::ResolveHostPath("failed to resolve host HOME".into()));
@@ -714,14 +720,15 @@ impl Distrobox {
714720
debug!(desktop_files = format_args!("{desktop_files:#?}"));
715721

716722
// Resolve host HOME via CommandRunner so this works inside Flatpak as well
717-
let host_home_opt = match crate::fakers::resolve_host_env_via_runner(&self.cmd_runner, "HOME").await {
718-
Ok(Some(s)) => Some(PathBuf::from(s)),
719-
Ok(None) => None,
720-
Err(e) => {
721-
tracing::warn!("failed to resolve host HOME via CommandRunner: {e:?}");
722-
None
723-
}
724-
};
723+
let host_home_opt =
724+
match crate::fakers::resolve_host_env_via_runner(&self.cmd_runner, "HOME").await {
725+
Ok(Some(s)) => Some(PathBuf::from(s)),
726+
Ok(None) => None,
727+
Err(e) => {
728+
tracing::warn!("failed to resolve host HOME via CommandRunner: {e:?}");
729+
None
730+
}
731+
};
725732

726733
Ok(desktop_files
727734
.into_map(host_home_opt)

src/dialogs/create_distrobox_dialog.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -166,16 +166,18 @@ mod imp {
166166
let subtitle: String = obj.imp().image_row.property("subtitle");
167167
let default_sub = gettext("Select an image...");
168168

169-
let initial_search_repo: &str = split_repo_tag_digest(
170-
if subtitle == default_sub {
169+
let initial_search_repo: &str =
170+
split_repo_tag_digest(if subtitle == default_sub {
171171
""
172172
} else {
173173
&subtitle
174-
},
175-
).0;
174+
})
175+
.0;
176176
// A repo is docker.io/library/xyz by default, we only want to search by 'xyz'
177-
let initial_search = initial_search_repo.rsplit('/').next().unwrap_or(initial_search_repo);
178-
177+
let initial_search = initial_search_repo
178+
.rsplit('/')
179+
.next()
180+
.unwrap_or(initial_search_repo);
179181

180182
let picker = obj.build_image_picker_view(Some(initial_search));
181183
obj.imp().navigation_view.push(&picker);
@@ -186,7 +188,7 @@ mod imp {
186188
let home_row = self.obj().build_file_row(
187189
&gettext("Select Home Directory"),
188190
FileRowSelection::Folder,
189-
None, // No filter for folders
191+
None, // No filter for folders
190192
move |path| {
191193
obj.set_home_folder(Some(path.display().to_string()));
192194
},
@@ -225,7 +227,7 @@ mod imp {
225227

226228
let create_btn = gtk::Button::with_label(&gettext("Create"));
227229
create_btn.set_halign(gtk::Align::Center);
228-
create_btn.set_sensitive(false); // Initially disabled until name is valid
230+
create_btn.set_sensitive(false); // Initially disabled until name is valid
229231

230232
let obj = self.obj();
231233
create_btn.connect_clicked(clone!(
@@ -296,12 +298,22 @@ mod imp {
296298
imp.image_row.set_subtitle(&gettext("Select an image..."));
297299
}
298300
} else {
299-
let candidates = imp.images_model.snapshot().into_iter().filter_map(|item| {
300-
item.downcast::<gtk::StringObject>().ok().map(|sobj| sobj.string().to_string())
301-
}).collect::<Vec<_>>();
302-
301+
let candidates = imp
302+
.images_model
303+
.snapshot()
304+
.into_iter()
305+
.filter_map(|item| {
306+
item.downcast::<gtk::StringObject>()
307+
.ok()
308+
.map(|sobj| sobj.string().to_string())
309+
})
310+
.collect::<Vec<_>>();
311+
303312
let (_filter, suggested_opt) =
304-
crate::dialogs::create_distrobox_helpers::derive_image_prefill(&text, Some(&candidates));
313+
crate::dialogs::create_distrobox_helpers::derive_image_prefill(
314+
&text,
315+
Some(&candidates),
316+
);
305317
if let Some(suggested) = suggested_opt {
306318
// set subtitle as tentative prefill (do not overwrite confirmed selection)
307319
if imp.selected_image.borrow().is_empty() {
@@ -385,7 +397,6 @@ mod imp {
385397
url_row.set_text("https://example.com/container.ini");
386398
url_row.set_show_apply_button(true);
387399

388-
389400
url_group.add(&url_row);
390401
url_page.append(&url_group);
391402

@@ -574,7 +585,7 @@ impl CreateDistroboxDialog {
574585
row.add_suffix(&file_icon);
575586

576587
let title = title.to_owned();
577-
let filter = filter.cloned(); // Clone the Option<&FileFilter> to Option<FileFilter>
588+
let filter = filter.cloned(); // Clone the Option<&FileFilter> to Option<FileFilter>
578589
let dialog_cb = clone!(
579590
#[weak(rename_to=this)]
580591
self,
@@ -961,11 +972,11 @@ impl CreateDistroboxDialog {
961972
// CRITICAL: Use self.root_store().command_runner() for Flatpak compatibility
962973
let command_runner = self.root_store().command_runner();
963974
let mut cmd = Command::new("curl");
964-
cmd.arg("-s"); // Silent
965-
cmd.arg("-f"); // Fail on HTTP errors
966-
cmd.arg("-I"); // HEAD request only
975+
cmd.arg("-s"); // Silent
976+
cmd.arg("-f"); // Fail on HTTP errors
977+
cmd.arg("-I"); // HEAD request only
967978
cmd.arg("--connect-timeout");
968-
cmd.arg("5"); // 5 second connection timeout
979+
cmd.arg("5"); // 5 second connection timeout
969980
cmd.arg(url);
970981

971982
match command_runner.output(cmd).await {

src/dialogs/create_distrobox_helpers.rs

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ use std::sync::LazyLock;
44
use regex::Regex;
55

66
// Matches tags that are numeric-only (e.g. "1.2.3" or "1_2-3")
7-
static VERSION_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"^(?:\d+(?:[._-]\d+)*)$").unwrap());
7+
static VERSION_RE: LazyLock<Regex> =
8+
LazyLock::new(|| Regex::new(r"^(?:\d+(?:[._-]\d+)*)$").unwrap());
89
// Capture a numeric version inside a tag (e.g. "v1.2" -> captures "1.2")
9-
static VER_CAPTURE_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(r"(?P<ver>\d+(?:[._-]\d+)*)").unwrap());
10+
static VER_CAPTURE_RE: LazyLock<Regex> =
11+
LazyLock::new(|| Regex::new(r"(?P<ver>\d+(?:[._-]\d+)*)").unwrap());
1012

1113
// Compare two numeric-version vectors treating missing components as zeros.
1214
fn compare_version_vec(a: &[u64], b: &[u64]) -> std::cmp::Ordering {
@@ -48,7 +50,10 @@ pub fn split_repo_tag_digest(s: &str) -> (&str, Option<&str>, Option<&str>) {
4850
(s, None, None)
4951
}
5052

51-
pub fn derive_image_prefill(container_name: &str, candidates: Option<&[String]>) -> (String, Option<String>) {
53+
pub fn derive_image_prefill(
54+
container_name: &str,
55+
candidates: Option<&[String]>,
56+
) -> (String, Option<String>) {
5257
// Basic normalization: trim, lowercase, replace spaces with '-', keep ascii alnum, '.', '_', '-', '/',
5358
// but preserve registry port patterns like ':5000' when immediately before '/' or end of component.
5459
let s = container_name.trim().to_lowercase();
@@ -130,15 +135,17 @@ pub fn derive_image_prefill(container_name: &str, candidates: Option<&[String]>)
130135
}
131136

132137
// Trim leading/trailing '-' '.' '/'
133-
let filter = norm.trim_matches(|c| c == '-' || c == '.' || c == '/').to_string();
138+
let filter = norm
139+
.trim_matches(|c| c == '-' || c == '.' || c == '/')
140+
.to_string();
134141
if filter.is_empty() {
135142
return (filter, None);
136143
}
137144

138145
// If candidates are provided, try to pick the best matching image tag
139146
if let Some(cands) = candidates {
140147
// collect matching candidates where repo ends with filter or equals it
141-
let matching: Vec<&String> = cands
148+
let matching: Vec<&String> = cands
142149
.iter()
143150
.filter(|img| {
144151
let s = img.as_str();
@@ -220,11 +227,26 @@ mod tests {
220227

221228
#[test]
222229
fn split_repo_tag_digest_examples() {
223-
assert_eq!(split_repo_tag_digest("repo:1.2.3"), ("repo", Some("1.2.3"), None));
224-
assert_eq!(split_repo_tag_digest("repo@sha256:abcdef"), ("repo", None, Some("sha256:abcdef")));
225-
assert_eq!(split_repo_tag_digest("host:5000/repo:1.0"), ("host:5000/repo", Some("1.0"), None));
226-
assert_eq!(split_repo_tag_digest("host:5000/repo@sha256:abc"), ("host:5000/repo", None, Some("sha256:abc")));
227-
assert_eq!(split_repo_tag_digest("repo:tag@sha256:abc"), ("repo", None, Some("sha256:abc")));
230+
assert_eq!(
231+
split_repo_tag_digest("repo:1.2.3"),
232+
("repo", Some("1.2.3"), None)
233+
);
234+
assert_eq!(
235+
split_repo_tag_digest("repo@sha256:abcdef"),
236+
("repo", None, Some("sha256:abcdef"))
237+
);
238+
assert_eq!(
239+
split_repo_tag_digest("host:5000/repo:1.0"),
240+
("host:5000/repo", Some("1.0"), None)
241+
);
242+
assert_eq!(
243+
split_repo_tag_digest("host:5000/repo@sha256:abc"),
244+
("host:5000/repo", None, Some("sha256:abc"))
245+
);
246+
assert_eq!(
247+
split_repo_tag_digest("repo:tag@sha256:abc"),
248+
("repo", None, Some("sha256:abc"))
249+
);
228250
}
229251

230252
#[test]
@@ -272,7 +294,10 @@ mod tests {
272294

273295
#[test]
274296
fn candidates_none_matching_returns_none() {
275-
let cands = vec!["other/repo:1.0".to_string(), "another/repo:latest".to_string()];
297+
let cands = vec![
298+
"other/repo:1.0".to_string(),
299+
"another/repo:latest".to_string(),
300+
];
276301
let (f, s) = derive_image_prefill("doesnotexist", Some(&cands));
277302
assert_eq!(f, "doesnotexist");
278303
assert!(s.is_none());
@@ -281,11 +306,20 @@ mod tests {
281306
#[test]
282307
fn split_repo_tag_digest_more_cases() {
283308
// triple combo: repo:tag@sha256: -> digest should win, tag discarded
284-
assert_eq!(split_repo_tag_digest("repo:tag@sha256:abc"), ("repo", None, Some("sha256:abc")));
309+
assert_eq!(
310+
split_repo_tag_digest("repo:tag@sha256:abc"),
311+
("repo", None, Some("sha256:abc"))
312+
);
285313
// host with port, tag and digest -> digest wins and repo includes host:port/repo
286-
assert_eq!(split_repo_tag_digest("example.com:5000/repo:1.0@sha256:abc"), ("example.com:5000/repo", None, Some("sha256:abc")));
314+
assert_eq!(
315+
split_repo_tag_digest("example.com:5000/repo:1.0@sha256:abc"),
316+
("example.com:5000/repo", None, Some("sha256:abc"))
317+
);
287318
// plain repo no tag/digest
288-
assert_eq!(split_repo_tag_digest("plainrepo"), ("plainrepo", None, None));
319+
assert_eq!(
320+
split_repo_tag_digest("plainrepo"),
321+
("plainrepo", None, None)
322+
);
289323
}
290324

291325
#[test]
@@ -313,8 +347,14 @@ mod tests {
313347

314348
#[test]
315349
fn ipv6_and_bracketed_host_handling() {
316-
assert_eq!(split_repo_tag_digest("[::1]:5000/repo:1.0"), ("[::1]:5000/repo", Some("1.0"), None));
317-
assert_eq!(split_repo_tag_digest("[::1]:5000/repo@sha256:abc"), ("[::1]:5000/repo", None, Some("sha256:abc")));
350+
assert_eq!(
351+
split_repo_tag_digest("[::1]:5000/repo:1.0"),
352+
("[::1]:5000/repo", Some("1.0"), None)
353+
);
354+
assert_eq!(
355+
split_repo_tag_digest("[::1]:5000/repo@sha256:abc"),
356+
("[::1]:5000/repo", None, Some("sha256:abc"))
357+
);
318358
}
319359

320360
#[test]

0 commit comments

Comments
 (0)