mirror of
https://github.com/outbackdingo/hyprcosmic.git
synced 2026-08-25 07:10:09 +00:00
rustfmt, no behaviour change
rustfmt and clippy were installed all along; I had wrongly recorded them as missing and never ran either. This is the mechanical half -- files rustfmt reformatted and nothing else touched, committed separately so the real fixes in the next commit are readable.
This commit is contained in:
+33
-8
@@ -92,7 +92,12 @@ fn parse_modifiers(raw: &str, span: Span) -> Result<Vec<&'static str>, BindError
|
||||
));
|
||||
}
|
||||
|
||||
found.sort_by_key(|m| MODIFIER_ORDER.iter().position(|o| o == m).unwrap_or(usize::MAX));
|
||||
found.sort_by_key(|m| {
|
||||
MODIFIER_ORDER
|
||||
.iter()
|
||||
.position(|o| o == m)
|
||||
.unwrap_or(usize::MAX)
|
||||
});
|
||||
Ok(found)
|
||||
}
|
||||
|
||||
@@ -179,7 +184,10 @@ fn workspace_index(arg: &str, span: Span, dispatcher: &str) -> Result<u8, BindEr
|
||||
arg.trim().parse::<u8>().map_err(|_| {
|
||||
err(
|
||||
span,
|
||||
format!("`{dispatcher}` needs a workspace number, got `{}`", arg.trim()),
|
||||
format!(
|
||||
"`{dispatcher}` needs a workspace number, got `{}`",
|
||||
arg.trim()
|
||||
),
|
||||
Some("COSMIC addresses workspaces 1-255 by index"),
|
||||
)
|
||||
})
|
||||
@@ -342,19 +350,33 @@ mod tests {
|
||||
// COSMIC's defaults bind bare Super to the launcher this way.
|
||||
let b = bind("SUPER, , exec, rofi -show drun");
|
||||
assert_eq!(b.key, None);
|
||||
assert_eq!(render(&[b]), "{\n (modifiers: [Super]): Spawn(\"rofi -show drun\"),\n}\n");
|
||||
assert_eq!(
|
||||
render(&[b]),
|
||||
"{\n (modifiers: [Super]): Spawn(\"rofi -show drun\"),\n}\n"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keys_normalise_to_xkb_spelling() {
|
||||
assert_eq!(bind("SUPER, Q, killactive").key.as_deref(), Some("q"));
|
||||
assert_eq!(bind("SUPER, Return, killactive").key.as_deref(), Some("Return"));
|
||||
assert_eq!(bind("SUPER, enter, killactive").key.as_deref(), Some("Return"));
|
||||
assert_eq!(
|
||||
bind("SUPER, Return, killactive").key.as_deref(),
|
||||
Some("Return")
|
||||
);
|
||||
assert_eq!(
|
||||
bind("SUPER, enter, killactive").key.as_deref(),
|
||||
Some("Return")
|
||||
);
|
||||
assert_eq!(bind("SUPER, f5, killactive").key.as_deref(), Some("F5"));
|
||||
assert_eq!(bind("SUPER, slash, killactive").key.as_deref(), Some("slash"));
|
||||
assert_eq!(
|
||||
bind("SUPER, slash, killactive").key.as_deref(),
|
||||
Some("slash")
|
||||
);
|
||||
// Unknown names pass through so exact keysyms stay usable.
|
||||
assert_eq!(
|
||||
bind("SUPER, XF86AudioRaiseVolume, killactive").key.as_deref(),
|
||||
bind("SUPER, XF86AudioRaiseVolume, killactive")
|
||||
.key
|
||||
.as_deref(),
|
||||
Some("XF86AudioRaiseVolume")
|
||||
);
|
||||
}
|
||||
@@ -381,7 +403,10 @@ mod tests {
|
||||
assert_eq!(bind("SUPER, Q, killactive").action, "Close");
|
||||
assert_eq!(bind("SUPER, F, fullscreen").action, "Fullscreen");
|
||||
assert_eq!(bind("SUPER, left, movefocus, l").action, "Focus(Left)");
|
||||
assert_eq!(bind("SUPER SHIFT, left, movewindow, l").action, "Move(Left)");
|
||||
assert_eq!(
|
||||
bind("SUPER SHIFT, left, movewindow, l").action,
|
||||
"Move(Left)"
|
||||
);
|
||||
assert_eq!(bind("SUPER, 1, workspace, 1").action, "Workspace(1)");
|
||||
assert_eq!(
|
||||
bind("SUPER SHIFT, 1, movetoworkspace, 1").action,
|
||||
|
||||
+58
-19
@@ -72,9 +72,15 @@ impl CornerRadii {
|
||||
pub enum EmitError {
|
||||
Io(io::Error),
|
||||
/// A projected target whose composite shape this emitter cannot rebuild.
|
||||
UnsupportedComposite { key: String, detail: String },
|
||||
UnsupportedComposite {
|
||||
key: String,
|
||||
detail: String,
|
||||
},
|
||||
/// An existing file could not be parsed, so read-modify-write is unsafe.
|
||||
Unreadable { path: PathBuf, detail: String },
|
||||
Unreadable {
|
||||
path: PathBuf,
|
||||
detail: String,
|
||||
},
|
||||
NoConfigDirectory,
|
||||
}
|
||||
|
||||
@@ -293,10 +299,12 @@ fn composite(
|
||||
// default (0, 8) — theme.rs:939.
|
||||
"gaps" => {
|
||||
let (mut outer, mut inner) = match previous {
|
||||
Some(text) => ron::from_str::<(u32, u32)>(text).map_err(|e| EmitError::Unreadable {
|
||||
path: path.to_path_buf(),
|
||||
detail: e.to_string(),
|
||||
})?,
|
||||
Some(text) => {
|
||||
ron::from_str::<(u32, u32)>(text).map_err(|e| EmitError::Unreadable {
|
||||
path: path.to_path_buf(),
|
||||
detail: e.to_string(),
|
||||
})?
|
||||
}
|
||||
None => (0, 8),
|
||||
};
|
||||
|
||||
@@ -398,7 +406,10 @@ mod tests {
|
||||
let e = Emitter::with_root(tmp.path());
|
||||
e.apply(&planned).unwrap();
|
||||
|
||||
assert_eq!(read(tmp.path(), "com.system76.CosmicComp", "autotile"), "true");
|
||||
assert_eq!(
|
||||
read(tmp.path(), "com.system76.CosmicComp", "autotile"),
|
||||
"true"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -411,7 +422,10 @@ mod tests {
|
||||
|
||||
let root = tmp.path();
|
||||
assert_eq!(read(root, "com.system76.CosmicComp", "autotile"), "true");
|
||||
assert_eq!(read(root, "com.system76.CosmicComp", "edge_snap_threshold"), "12");
|
||||
assert_eq!(
|
||||
read(root, "com.system76.CosmicComp", "edge_snap_threshold"),
|
||||
"12"
|
||||
);
|
||||
assert_eq!(
|
||||
read(root, "com.system76.CosmicTk", "icon_theme"),
|
||||
"\"Tela-circle-dracula\""
|
||||
@@ -423,7 +437,8 @@ mod tests {
|
||||
#[test]
|
||||
fn both_gaps_reach_disk_in_one_tuple() {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let planned = plan_for("general {\n gaps_in = 3\n gaps_out = 8\n}\n", tmp.path()).unwrap();
|
||||
let planned =
|
||||
plan_for("general {\n gaps_in = 3\n gaps_out = 8\n}\n", tmp.path()).unwrap();
|
||||
Emitter::with_root(tmp.path()).apply(&planned).unwrap();
|
||||
|
||||
// (outer, inner) — theme.rs:895
|
||||
@@ -480,10 +495,16 @@ mod tests {
|
||||
|
||||
let b = "com.system76.CosmicTheme.Dark.Builder";
|
||||
// Option<Srgb>: three components, no alpha.
|
||||
assert_eq!(read(tmp.path(), b, "accent"), "Some((red: 1.0, green: 0.0, blue: 0.0))");
|
||||
assert_eq!(
|
||||
read(tmp.path(), b, "accent"),
|
||||
"Some((red: 1.0, green: 0.0, blue: 0.0))"
|
||||
);
|
||||
// Option<Srgba>: four.
|
||||
let bg = read(tmp.path(), b, "bg_color");
|
||||
assert!(bg.starts_with("Some((red: 0.0, green: 1.0, blue: 0.0, alpha: "), "{bg}");
|
||||
assert!(
|
||||
bg.starts_with("Some((red: 0.0, green: 1.0, blue: 0.0, alpha: "),
|
||||
"{bg}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -492,7 +513,11 @@ mod tests {
|
||||
let planned = plan_for("decoration {\n rounding = 10\n}\n", tmp.path()).unwrap();
|
||||
Emitter::with_root(tmp.path()).apply(&planned).unwrap();
|
||||
|
||||
let text = read(tmp.path(), "com.system76.CosmicTheme.Dark.Builder", "corner_radii");
|
||||
let text = read(
|
||||
tmp.path(),
|
||||
"com.system76.CosmicTheme.Dark.Builder",
|
||||
"corner_radii",
|
||||
);
|
||||
let radii: CornerRadii = ron::from_str(&text).expect("round-trips as CornerRadii");
|
||||
assert_eq!(radii.radius_m, [10.0; 4]);
|
||||
}
|
||||
@@ -504,7 +529,11 @@ mod tests {
|
||||
let planned = plan_for("decoration {\n rounding = 10\n}\n", tmp.path()).unwrap();
|
||||
Emitter::with_root(tmp.path()).apply(&planned).unwrap();
|
||||
|
||||
let text = read(tmp.path(), "com.system76.CosmicTheme.Dark.Builder", "corner_radii");
|
||||
let text = read(
|
||||
tmp.path(),
|
||||
"com.system76.CosmicTheme.Dark.Builder",
|
||||
"corner_radii",
|
||||
);
|
||||
let radii: CornerRadii = ron::from_str(&text).unwrap();
|
||||
let d = CornerRadii::default();
|
||||
assert_eq!(radii.radius_0, d.radius_0);
|
||||
@@ -544,10 +573,13 @@ mod tests {
|
||||
};
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let e = Emitter::with_root(tmp.path());
|
||||
let res = e.plan(&Resolved { writes: vec![write] });
|
||||
assert!(
|
||||
matches!(res.unwrap_err()[0], EmitError::UnsupportedComposite { .. }),
|
||||
);
|
||||
let res = e.plan(&Resolved {
|
||||
writes: vec![write],
|
||||
});
|
||||
assert!(matches!(
|
||||
res.unwrap_err()[0],
|
||||
EmitError::UnsupportedComposite { .. }
|
||||
),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -561,7 +593,11 @@ mod tests {
|
||||
fs::write(dir.join("gaps"), "not ron at all").unwrap();
|
||||
|
||||
let errs = plan_for("general {\n gaps_in = 3\n}\n", tmp.path()).unwrap_err();
|
||||
assert!(matches!(errs[0], EmitError::Unreadable { .. }), "{:?}", errs[0]);
|
||||
assert!(
|
||||
matches!(errs[0], EmitError::Unreadable { .. }),
|
||||
"{:?}",
|
||||
errs[0]
|
||||
);
|
||||
}
|
||||
|
||||
/// Planning must not touch disk — that is what makes emission transactional.
|
||||
@@ -613,7 +649,10 @@ mod tests {
|
||||
.map(|e| e.file_name().to_string_lossy().to_string())
|
||||
.filter(|n| n.starts_with(".atomicwrite"))
|
||||
.collect();
|
||||
assert!(leftovers.is_empty(), "temp files left behind: {leftovers:?}");
|
||||
assert!(
|
||||
leftovers.is_empty(),
|
||||
"temp files left behind: {leftovers:?}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+38
-13
@@ -70,7 +70,8 @@ fn strip_hyde_header(src: &str) -> &str {
|
||||
let Some(first) = lines.next() else {
|
||||
return src;
|
||||
};
|
||||
let is_destination_header = !first.contains('=') && (first.contains("|>") || first.contains('|'));
|
||||
let is_destination_header =
|
||||
!first.contains('=') && (first.contains("|>") || first.contains('|'));
|
||||
if is_destination_header {
|
||||
// Preserve line numbering by keeping the newline count intact: callers
|
||||
// report spans against the stripped text, so re-add a blank line.
|
||||
@@ -105,7 +106,12 @@ fn is_gradient(value: &str) -> bool {
|
||||
|
||||
/// Flatten to dotted keys, keeping variables separate — HyDE carries
|
||||
/// `$GTK_THEME` / `$ICON_THEME` as variables rather than config keys.
|
||||
fn walk(items: &[Item], prefix: &str, out: &mut Vec<(String, String, Span)>, vars: &mut Vec<(String, String, Span)>) {
|
||||
fn walk(
|
||||
items: &[Item],
|
||||
prefix: &str,
|
||||
out: &mut Vec<(String, String, Span)>,
|
||||
vars: &mut Vec<(String, String, Span)>,
|
||||
) {
|
||||
for item in items {
|
||||
match item {
|
||||
Item::Section { name, items } => {
|
||||
@@ -150,7 +156,11 @@ pub fn import_hypr_theme(src: &str, theme_name: &str) -> Result<Import, ParseErr
|
||||
match name.as_str() {
|
||||
"ICON_THEME" => theme.push(("icon_theme".into(), value.clone())),
|
||||
"COLOR_SCHEME" => {
|
||||
let mode = if value.contains("light") { "light" } else { "dark" };
|
||||
let mode = if value.contains("light") {
|
||||
"light"
|
||||
} else {
|
||||
"dark"
|
||||
};
|
||||
theme.push(("mode".into(), mode.into()));
|
||||
}
|
||||
"GTK_THEME" => notes.push(Note {
|
||||
@@ -208,14 +218,16 @@ pub fn import_hypr_theme(src: &str, theme_name: &str) -> Result<Import, ParseErr
|
||||
"general.layout" => notes.push(note(Reason::NoEquivalent(
|
||||
"cosmic-comp uses a BSP tiler; dwindle/master are not available",
|
||||
))),
|
||||
"general.resize_on_border" => notes.push(note(Reason::NoEquivalent(
|
||||
"no equivalent setting",
|
||||
))),
|
||||
"general.resize_on_border" => {
|
||||
notes.push(note(Reason::NoEquivalent("no equivalent setting")))
|
||||
}
|
||||
|
||||
k if k.starts_with("decoration.blur") => notes.push(note(
|
||||
Reason::NeedsCompositorPatch("COSMIC blur is client-requested via \
|
||||
ext-background-effect; rule-driven blur is spec Phase 2"),
|
||||
)),
|
||||
k if k.starts_with("decoration.blur") => {
|
||||
notes.push(note(Reason::NeedsCompositorPatch(
|
||||
"COSMIC blur is client-requested via \
|
||||
ext-background-effect; rule-driven blur is spec Phase 2",
|
||||
)))
|
||||
}
|
||||
k if k.starts_with("decoration.shadow") => notes.push(note(
|
||||
Reason::NeedsCompositorPatch("shadow.frag exists but is not configurable yet"),
|
||||
)),
|
||||
@@ -300,7 +312,12 @@ pub fn render_report(import: &Import) -> String {
|
||||
if !lossy.is_empty() {
|
||||
out.push_str("Translated with loss:\n");
|
||||
for n in &lossy {
|
||||
out.push_str(&format!(" {} = {}\n {}\n", n.key, n.value, n.reason.describe()));
|
||||
out.push_str(&format!(
|
||||
" {} = {}\n {}\n",
|
||||
n.key,
|
||||
n.value,
|
||||
n.reason.describe()
|
||||
));
|
||||
}
|
||||
}
|
||||
if !dropped.is_empty() {
|
||||
@@ -309,7 +326,12 @@ pub fn render_report(import: &Import) -> String {
|
||||
}
|
||||
out.push_str("Not translated:\n");
|
||||
for n in &dropped {
|
||||
out.push_str(&format!(" {} = {}\n {}\n", n.key, n.value, n.reason.describe()));
|
||||
out.push_str(&format!(
|
||||
" {} = {}\n {}\n",
|
||||
n.key,
|
||||
n.value,
|
||||
n.reason.describe()
|
||||
));
|
||||
}
|
||||
}
|
||||
out
|
||||
@@ -431,7 +453,10 @@ layerrule = blur,waybar
|
||||
"group.col.border_active",
|
||||
"layerrule",
|
||||
] {
|
||||
assert!(keys.contains(&expected), "`{expected}` missing from {keys:?}");
|
||||
assert!(
|
||||
keys.contains(&expected),
|
||||
"`{expected}` missing from {keys:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-3
@@ -25,7 +25,10 @@ pub use resolve::{resolve, Diagnostic, Resolved, Value, Write, WriteKind};
|
||||
|
||||
/// Render a diagnostic against source text, cargo-style.
|
||||
pub fn render_diagnostic(source: &str, span: Span, message: &str, help: Option<&str>) -> String {
|
||||
let line = source.lines().nth(span.line.saturating_sub(1)).unwrap_or("");
|
||||
let line = source
|
||||
.lines()
|
||||
.nth(span.line.saturating_sub(1))
|
||||
.unwrap_or("");
|
||||
let gutter = span.line.to_string().len();
|
||||
let pad = " ".repeat(gutter);
|
||||
let caret = " ".repeat(span.col.saturating_sub(1)) + &"^".repeat(span.len.max(1));
|
||||
@@ -72,7 +75,11 @@ theme {
|
||||
// gaps fold per builder; accent fans out to both; autotile is direct.
|
||||
let gaps: Vec<_> = r.writes.iter().filter(|w| w.target.key == "gaps").collect();
|
||||
assert_eq!(gaps.len(), 2);
|
||||
let accent: Vec<_> = r.writes.iter().filter(|w| w.target.key == "accent").collect();
|
||||
let accent: Vec<_> = r
|
||||
.writes
|
||||
.iter()
|
||||
.filter(|w| w.target.key == "accent")
|
||||
.collect();
|
||||
assert_eq!(accent.len(), 2);
|
||||
}
|
||||
|
||||
@@ -81,7 +88,12 @@ theme {
|
||||
let src = "general {\n gaps_inn = 8\n}\n";
|
||||
let ast = parse(src).unwrap();
|
||||
let diags = resolve(&ast).unwrap_err();
|
||||
let out = render_diagnostic(src, diags[0].span, &diags[0].message, diags[0].help.as_deref());
|
||||
let out = render_diagnostic(
|
||||
src,
|
||||
diags[0].span,
|
||||
&diags[0].message,
|
||||
diags[0].help.as_deref(),
|
||||
);
|
||||
|
||||
assert!(out.contains("unknown key"), "{out}");
|
||||
assert!(out.contains("cosmic.conf:2:5"), "{out}");
|
||||
|
||||
@@ -300,7 +300,10 @@ mod tests {
|
||||
_ => None,
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(binds, vec!["SUPER, Return, spawn, kitty", "SUPER, Q, close"]);
|
||||
assert_eq!(
|
||||
binds,
|
||||
vec!["SUPER, Return, spawn, kitty", "SUPER, Q, close"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -332,7 +335,11 @@ mod tests {
|
||||
#[test]
|
||||
fn rejects_line_without_equals() {
|
||||
let err = parse("this is not valid\n").unwrap_err();
|
||||
assert!(err.message.contains("expected `key = value`"), "{}", err.message);
|
||||
assert!(
|
||||
err.message.contains("expected `key = value`"),
|
||||
"{}",
|
||||
err.message
|
||||
);
|
||||
assert_eq!(err.span.line, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,8 +114,16 @@ macro_rules! both_themes {
|
||||
macro_rules! both_themes_direct {
|
||||
($key:literal) => {
|
||||
&[
|
||||
Target::Direct { component: DARK_BUILDER, version: 1, key: $key },
|
||||
Target::Direct { component: LIGHT_BUILDER, version: 1, key: $key },
|
||||
Target::Direct {
|
||||
component: DARK_BUILDER,
|
||||
version: 1,
|
||||
key: $key,
|
||||
},
|
||||
Target::Direct {
|
||||
component: LIGHT_BUILDER,
|
||||
version: 1,
|
||||
key: $key,
|
||||
},
|
||||
]
|
||||
};
|
||||
}
|
||||
@@ -126,14 +134,20 @@ pub const REGISTRY: &[Entry] = &[
|
||||
conf: "general.gaps_in",
|
||||
targets: both_themes!("gaps", &[GAPS_INNER_IDX]),
|
||||
ty: Ty::U32,
|
||||
validate: Some(Range { min: 0.0, max: 128.0 }),
|
||||
validate: Some(Range {
|
||||
min: 0.0,
|
||||
max: 128.0,
|
||||
}),
|
||||
doc: "Gap between adjacent tiled windows, in px",
|
||||
},
|
||||
Entry {
|
||||
conf: "general.gaps_out",
|
||||
targets: both_themes!("gaps", &[GAPS_OUTER_IDX]),
|
||||
ty: Ty::U32,
|
||||
validate: Some(Range { min: 0.0, max: 256.0 }),
|
||||
validate: Some(Range {
|
||||
min: 0.0,
|
||||
max: 256.0,
|
||||
}),
|
||||
doc: "Gap between tiled windows and the screen edge, in px",
|
||||
},
|
||||
Entry {
|
||||
@@ -177,7 +191,10 @@ pub const REGISTRY: &[Entry] = &[
|
||||
key: "focus_follows_cursor_delay",
|
||||
}],
|
||||
ty: Ty::U32,
|
||||
validate: Some(Range { min: 0.0, max: 5000.0 }),
|
||||
validate: Some(Range {
|
||||
min: 0.0,
|
||||
max: 5000.0,
|
||||
}),
|
||||
doc: "Delay in ms before focus follows the cursor",
|
||||
},
|
||||
Entry {
|
||||
@@ -199,7 +216,10 @@ pub const REGISTRY: &[Entry] = &[
|
||||
key: "edge_snap_threshold",
|
||||
}],
|
||||
ty: Ty::U32,
|
||||
validate: Some(Range { min: 0.0, max: 256.0 }),
|
||||
validate: Some(Range {
|
||||
min: 0.0,
|
||||
max: 256.0,
|
||||
}),
|
||||
doc: "Distance in px at which windows snap to output edges",
|
||||
},
|
||||
// ---- decoration ------------------------------------------------------
|
||||
@@ -207,7 +227,10 @@ pub const REGISTRY: &[Entry] = &[
|
||||
conf: "decoration.rounding",
|
||||
targets: both_themes!("corner_radii", &["radius_m"]),
|
||||
ty: Ty::F32,
|
||||
validate: Some(Range { min: 0.0, max: 64.0 }),
|
||||
validate: Some(Range {
|
||||
min: 0.0,
|
||||
max: 64.0,
|
||||
}),
|
||||
doc: "Window corner radius in px (maps to the theme's radius_m)",
|
||||
},
|
||||
// ---- theme -----------------------------------------------------------
|
||||
|
||||
@@ -65,13 +65,19 @@ fn write_raw_link(header: &mut tar::Header, target: &str) {
|
||||
}
|
||||
|
||||
/// A theme directory just complete enough for `plan` to consider the archive.
|
||||
fn theme_with_archive(entries: &[(&str, tar::EntryType, &[u8], Option<&str>)]) -> (TempDir, PathBuf, PathBuf) {
|
||||
fn theme_with_archive(
|
||||
entries: &[(&str, tar::EntryType, &[u8], Option<&str>)],
|
||||
) -> (TempDir, PathBuf, PathBuf) {
|
||||
let tmp = TempDir::new().unwrap();
|
||||
let theme_dir = tmp.path().join("Configs/.config/hyde/themes/Evil");
|
||||
let source_dir = tmp.path().join("Source");
|
||||
fs::create_dir_all(&theme_dir).unwrap();
|
||||
fs::create_dir_all(&source_dir).unwrap();
|
||||
fs::write(theme_dir.join("hypr.theme"), "general {\n gaps_in = 3\n}\n").unwrap();
|
||||
fs::write(
|
||||
theme_dir.join("hypr.theme"),
|
||||
"general {\n gaps_in = 3\n}\n",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
hostile_tarball(&source_dir.join("Gtk_Evil.tar.gz"), entries);
|
||||
(tmp, theme_dir, source_dir)
|
||||
|
||||
Reference in New Issue
Block a user