mirror of
https://github.com/storytold/craft-launcher.git
synced 2026-11-02 18:07:04 +00:00
feat(linux): handle installing and updating Arch packages (.pkg.tar.zst) via settings
This commit is contained in:
@@ -44,7 +44,8 @@ fn unquote(v: &str) -> &str {
|
||||
}
|
||||
|
||||
/// The distro's own package format: `.deb` for the Debian family, `.rpm` for the Fedora, Red Hat
|
||||
/// and SUSE families, `None` for anything else (Arch, unknown distros), which gets AppImages.
|
||||
/// and SUSE families, `.pkg.tar.zst` for the Arch Linux family, `None` for anything else
|
||||
/// (unknown distros), which gets AppImages.
|
||||
pub fn native_package(os: &OsRelease) -> Option<PackageKind> {
|
||||
std::iter::once(&os.id).chain(&os.id_like).find_map(|id| family(id))
|
||||
}
|
||||
@@ -54,6 +55,7 @@ fn family(id: &str) -> Option<PackageKind> {
|
||||
"debian" | "ubuntu" => Some(PackageKind::Deb),
|
||||
"fedora" | "rhel" | "centos" | "suse" | "sles" => Some(PackageKind::Rpm),
|
||||
_ if id.starts_with("opensuse") => Some(PackageKind::Rpm),
|
||||
"arch" | "manjaro" | "endeavouros" | "garuda" | "cachyos" | "artix" => Some(PackageKind::ArchPkg),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -99,7 +101,7 @@ ID_LIKE=debian
|
||||
assert_eq!(native(TUMBLEWEED), Some(PackageKind::Rpm));
|
||||
assert_eq!(native(UBUNTU), Some(PackageKind::Deb));
|
||||
assert_eq!(native(MINT), Some(PackageKind::Deb));
|
||||
assert_eq!(native(ARCH), None);
|
||||
assert_eq!(native(ARCH), Some(PackageKind::ArchPkg));
|
||||
assert_eq!(native(UNKNOWN), None);
|
||||
assert_eq!(native(""), None);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ pub enum PackageKind {
|
||||
AppImage,
|
||||
Deb,
|
||||
Rpm,
|
||||
/// Arch Linux package (`.pkg.tar.zst`).
|
||||
ArchPkg,
|
||||
Flatpak,
|
||||
/// Linux or FreeBSD tarball (`bin/<app>`, `share/…`).
|
||||
TarGz,
|
||||
@@ -74,6 +76,7 @@ impl PackageKind {
|
||||
Self::AppImage => "AppImage",
|
||||
Self::Deb => "Debian package (.deb)",
|
||||
Self::Rpm => "RPM package (.rpm)",
|
||||
Self::ArchPkg => "Arch package (.pkg.tar.zst)",
|
||||
Self::Flatpak => "Flatpak bundle",
|
||||
Self::TarGz => "Tarball (.tar.gz)",
|
||||
}
|
||||
@@ -87,6 +90,7 @@ impl PackageKind {
|
||||
Self::AppImage => ".AppImage",
|
||||
Self::Deb => ".deb",
|
||||
Self::Rpm => ".rpm",
|
||||
Self::ArchPkg => ".pkg.tar.zst",
|
||||
Self::Flatpak => ".flatpak",
|
||||
Self::TarGz => ".tar.gz",
|
||||
}
|
||||
@@ -171,7 +175,7 @@ impl Platform {
|
||||
match self.os {
|
||||
Os::Windows => &[PackageKind::Msi, PackageKind::PortableZip],
|
||||
Os::MacOs => &[PackageKind::Dmg],
|
||||
Os::Linux => &[PackageKind::AppImage, PackageKind::Deb, PackageKind::Rpm, PackageKind::Flatpak, PackageKind::TarGz],
|
||||
Os::Linux => &[PackageKind::AppImage, PackageKind::Deb, PackageKind::Rpm, PackageKind::ArchPkg, PackageKind::Flatpak, PackageKind::TarGz],
|
||||
Os::FreeBsd => &[PackageKind::TarGz],
|
||||
}
|
||||
}
|
||||
@@ -189,7 +193,7 @@ pub struct AssetName {
|
||||
/// Reads `<stem>-<version>-<os>-<arch>[-portable].<ext>`; `None` for checksums, zsync files, CLI
|
||||
/// and web bundles, or anything else.
|
||||
pub fn parse_asset_name(name: &str, stems: &[&str]) -> Option<AssetName> {
|
||||
const KINDS: [PackageKind; 8] = [
|
||||
const KINDS: [PackageKind; 9] = [
|
||||
PackageKind::PortableZip,
|
||||
PackageKind::TarGz,
|
||||
PackageKind::Msi,
|
||||
@@ -197,6 +201,7 @@ pub fn parse_asset_name(name: &str, stems: &[&str]) -> Option<AssetName> {
|
||||
PackageKind::AppImage,
|
||||
PackageKind::Deb,
|
||||
PackageKind::Rpm,
|
||||
PackageKind::ArchPkg,
|
||||
PackageKind::Flatpak,
|
||||
];
|
||||
let (kind, base) = KINDS.iter().find_map(|k| name.strip_suffix(k.suffix()).map(|b| (*k, b)))?;
|
||||
@@ -362,6 +367,8 @@ mod tests {
|
||||
"photocraft-0.5.0-linux-x86_64.deb",
|
||||
"photocraft-0.5.0-linux-aarch64.rpm",
|
||||
"photocraft-0.5.0-linux-x86_64.rpm",
|
||||
"photocraft-0.5.0-linux-aarch64.pkg.tar.zst",
|
||||
"photocraft-0.5.0-linux-x86_64.pkg.tar.zst",
|
||||
"photocraft-0.5.0-linux-aarch64.flatpak",
|
||||
"photocraft-0.5.0-linux-x86_64.flatpak",
|
||||
"photocraft-0.5.0-linux-aarch64.tar.gz",
|
||||
@@ -371,7 +378,7 @@ mod tests {
|
||||
let p_x64 = Platform { os: Os::Linux, arch: Arch::X64 };
|
||||
let p_arm64 = Platform { os: Os::Linux, arch: Arch::Arm64 };
|
||||
|
||||
for kind in [PackageKind::AppImage, PackageKind::Deb, PackageKind::Rpm, PackageKind::Flatpak, PackageKind::TarGz] {
|
||||
for kind in [PackageKind::AppImage, PackageKind::Deb, PackageKind::Rpm, PackageKind::ArchPkg, PackageKind::Flatpak, PackageKind::TarGz] {
|
||||
let pick_x64 = pick_asset(&multi_arch_release, &["photocraft"], p_x64, &[kind]).map(|(a, _)| a.name.clone());
|
||||
assert!(pick_x64.as_deref().unwrap().contains("linux-x86_64"), "Expected x86_64 asset for {kind:?}, got {pick_x64:?}");
|
||||
|
||||
@@ -384,10 +391,11 @@ mod tests {
|
||||
"photocraft-0.5.0-linux-aarch64.AppImage",
|
||||
"photocraft-0.5.0-linux-aarch64.deb",
|
||||
"photocraft-0.5.0-linux-aarch64.rpm",
|
||||
"photocraft-0.5.0-linux-aarch64.pkg.tar.zst",
|
||||
"photocraft-0.5.0-linux-aarch64.flatpak",
|
||||
"photocraft-0.5.0-linux-aarch64.tar.gz",
|
||||
]);
|
||||
for kind in [PackageKind::AppImage, PackageKind::Deb, PackageKind::Rpm, PackageKind::Flatpak, PackageKind::TarGz] {
|
||||
for kind in [PackageKind::AppImage, PackageKind::Deb, PackageKind::Rpm, PackageKind::ArchPkg, PackageKind::Flatpak, PackageKind::TarGz] {
|
||||
assert_eq!(pick_asset(&arm_only_release, &["photocraft"], p_x64, &[kind]), None, "x86_64 must never match an aarch64 asset for {kind:?}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,7 +117,9 @@ pub fn install_at(
|
||||
.map(Some)
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
PackageKind::Deb | PackageKind::Rpm | PackageKind::Flatpak => linux::install_package(kind, &file, job.stop, &mut *job.phase).map(|_| None),
|
||||
PackageKind::Deb | PackageKind::Rpm | PackageKind::ArchPkg | PackageKind::Flatpak => {
|
||||
linux::install_package(kind, &file, job.stop, &mut *job.phase).map(|_| None)
|
||||
}
|
||||
#[cfg(target_os = "linux")]
|
||||
PackageKind::AppImage => {
|
||||
linux::install_appimage(&file, &asset.name, destination.as_deref(), previous, job.replace).map(|(path, replaced)| {
|
||||
@@ -253,6 +255,7 @@ fn record(version: &str, kind: PackageKind, path: PathBuf, files: Vec<PathBuf>,
|
||||
/// stays a `.deb` update), else the user's choice, else the best this system supports.
|
||||
pub fn choose_kinds(existing: Option<&Installed>, record: Option<&Record>, preferred: &[PackageKind]) -> Vec<PackageKind> {
|
||||
let available = available_kinds();
|
||||
let can_pacman = which("pacman").is_some();
|
||||
if let Some(inst) = existing {
|
||||
let kind = match inst.source {
|
||||
InstallSource::Launcher => record.map(|r| r.kind),
|
||||
@@ -260,18 +263,17 @@ pub fn choose_kinds(existing: Option<&Installed>, record: Option<&Record>, prefe
|
||||
InstallSource::Msi => Some(PackageKind::Msi),
|
||||
InstallSource::Deb => Some(PackageKind::Deb),
|
||||
InstallSource::Rpm => Some(PackageKind::Rpm),
|
||||
// Arch/AUR installs are owned by pacman and updated by the user's AUR helper (see
|
||||
// `managed_elsewhere`); the launcher opens and removes them but never replaces them.
|
||||
InstallSource::Pacman => None,
|
||||
InstallSource::Pacman => Some(PackageKind::ArchPkg),
|
||||
InstallSource::Flatpak => Some(PackageKind::Flatpak),
|
||||
InstallSource::AppImage => Some(PackageKind::AppImage),
|
||||
InstallSource::Binary => Some(PackageKind::TarGz),
|
||||
};
|
||||
if let Some(k) = kind.filter(|k| available.contains(k)) {
|
||||
if let Some(k) = kind.filter(|k| available.contains(k) || (*k == PackageKind::ArchPkg && can_pacman)) {
|
||||
return vec![k];
|
||||
}
|
||||
}
|
||||
let mut kinds: Vec<PackageKind> = preferred.iter().copied().filter(|k| available.contains(k)).collect();
|
||||
let mut kinds: Vec<PackageKind> =
|
||||
preferred.iter().copied().filter(|k| available.contains(k) || (*k == PackageKind::ArchPkg && can_pacman)).collect();
|
||||
for k in available {
|
||||
if !kinds.contains(&k) {
|
||||
kinds.push(k);
|
||||
@@ -340,12 +342,16 @@ pub fn managed_elsewhere(app: &CraftApp, installed: &Installed, uninstall: bool)
|
||||
match installed.source {
|
||||
InstallSource::Pacman if !uninstall => {
|
||||
let pkg = installed.package.clone().unwrap_or_else(|| app.id.to_string());
|
||||
let helper = ["paru", "yay"].into_iter().find(|h| which(h).is_some());
|
||||
let cmd = match helper {
|
||||
Some(h) => format!("{h} -S {pkg}"),
|
||||
None => format!("your AUR helper (for example: yay -S {pkg})"),
|
||||
};
|
||||
Some(format!("{} was installed from the AUR ({pkg}). Update it with {cmd}", app.name))
|
||||
if pkg.ends_with("-git") || which("pacman").is_none() {
|
||||
let helper = ["paru", "yay"].into_iter().find(|h| which(h).is_some());
|
||||
let cmd = match helper {
|
||||
Some(h) => format!("{h} -S {pkg}"),
|
||||
None => format!("your AUR helper (for example: yay -S {pkg})"),
|
||||
};
|
||||
Some(format!("{} was installed from the AUR ({pkg}). Update it with {cmd}", app.name))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
InstallSource::Binary => Some(format!("{} was installed outside the launcher. Update or remove it the way it was installed.", app.name)),
|
||||
_ => None,
|
||||
@@ -670,6 +676,7 @@ pub(crate) mod linux {
|
||||
PackageKind::Rpm if which("dnf").is_some() => Some(&["dnf", "install", "-y"]),
|
||||
PackageKind::Rpm if which("zypper").is_some() => Some(&["zypper", "--non-interactive", "install", "--allow-unsigned-rpm"]),
|
||||
PackageKind::Rpm => Some(&["rpm", "-U", "--replacepkgs"]),
|
||||
PackageKind::ArchPkg => Some(&["pacman", "-U", "--noconfirm"]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -689,8 +696,9 @@ pub(crate) mod linux {
|
||||
/// AppImage cannot mount there and a distro package needs root, so both are dead ends.
|
||||
/// - Running as an AppImage: prefers AppImage.
|
||||
/// - Otherwise (system install): prefers the distro's own package format (`.deb` on the
|
||||
/// Debian family, `.rpm` on the Fedora, Red Hat and SUSE families, read from `os-release`
|
||||
/// rather than from whichever tools are on `PATH`), then Flatpak if available, then AppImage.
|
||||
/// Debian family, `.rpm` on the Fedora, Red Hat and SUSE families, `.pkg.tar.zst` on Arch,
|
||||
/// read from `os-release` rather than from whichever tools are on `PATH`), then Flatpak if
|
||||
/// available, then AppImage.
|
||||
pub fn available_kinds() -> Vec<PackageKind> {
|
||||
let flatpak = process::is_flatpak_available();
|
||||
let is_flatpak = process::in_sandbox();
|
||||
@@ -702,7 +710,8 @@ pub(crate) mod linux {
|
||||
let root = root && !immutable_ostree();
|
||||
let can_deb = root && native == Some(PackageKind::Deb) && which("apt-get").is_some() && which("dpkg").is_some();
|
||||
let can_rpm = root && native == Some(PackageKind::Rpm) && which("rpm").is_some();
|
||||
order_available_kinds(is_flatpak, is_appimage, flatpak, can_deb, can_rpm)
|
||||
let can_arch = root && native == Some(PackageKind::ArchPkg) && which("pacman").is_some();
|
||||
order_available_kinds(is_flatpak, is_appimage, flatpak, can_deb, can_rpm, can_arch)
|
||||
}
|
||||
|
||||
pub(crate) fn order_available_kinds(
|
||||
@@ -711,6 +720,7 @@ pub(crate) mod linux {
|
||||
flatpak_available: bool,
|
||||
can_deb: bool,
|
||||
can_rpm: bool,
|
||||
can_arch: bool,
|
||||
) -> Vec<PackageKind> {
|
||||
let mut kinds = Vec::new();
|
||||
if is_flatpak && flatpak_available {
|
||||
@@ -727,6 +737,9 @@ pub(crate) mod linux {
|
||||
if can_rpm {
|
||||
kinds.push(PackageKind::Rpm);
|
||||
}
|
||||
if can_arch {
|
||||
kinds.push(PackageKind::ArchPkg);
|
||||
}
|
||||
|
||||
if flatpak_available && !kinds.contains(&PackageKind::Flatpak) {
|
||||
kinds.push(PackageKind::Flatpak);
|
||||
@@ -746,6 +759,9 @@ pub(crate) mod linux {
|
||||
if kind == PackageKind::Deb && which("apt-get").is_none() {
|
||||
return Err("this system has no apt-get to install a Debian package with".into());
|
||||
}
|
||||
if kind == PackageKind::ArchPkg && which("pacman").is_none() {
|
||||
return Err("this system has no pacman to install an Arch package with".into());
|
||||
}
|
||||
install_package_via(&SYSTEM, kind, file, stop, phase)
|
||||
}
|
||||
|
||||
@@ -2105,39 +2121,42 @@ mod tests {
|
||||
use super::linux::order_available_kinds;
|
||||
|
||||
// Flatpak launcher defaults to Flatpak if available
|
||||
let kinds = order_available_kinds(true, false, true, true, false);
|
||||
let kinds = order_available_kinds(true, false, true, true, false, false);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::Flatpak));
|
||||
assert!(kinds.contains(&PackageKind::Deb));
|
||||
assert!(kinds.contains(&PackageKind::AppImage));
|
||||
|
||||
// AppImage launcher defaults to AppImage
|
||||
let kinds = order_available_kinds(false, true, true, true, false);
|
||||
let kinds = order_available_kinds(false, true, true, true, false, false);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::AppImage));
|
||||
assert!(kinds.contains(&PackageKind::Deb));
|
||||
assert!(kinds.contains(&PackageKind::Flatpak));
|
||||
|
||||
// Base Linux launcher defaults to native package format (deb or rpm) if available
|
||||
let kinds = order_available_kinds(false, false, true, true, false);
|
||||
// Base Linux launcher defaults to native package format (deb, rpm, or arch) if available
|
||||
let kinds = order_available_kinds(false, false, true, true, false, false);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::Deb));
|
||||
|
||||
let kinds = order_available_kinds(false, false, true, false, true);
|
||||
let kinds = order_available_kinds(false, false, true, false, true, false);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::Rpm));
|
||||
|
||||
let kinds = order_available_kinds(false, false, true, false, false, true);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::ArchPkg));
|
||||
|
||||
// Base Linux launcher without root/distro packaging falls back to Flatpak then AppImage
|
||||
let kinds = order_available_kinds(false, false, true, false, false);
|
||||
let kinds = order_available_kinds(false, false, true, false, false, false);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::Flatpak));
|
||||
assert_eq!(kinds.get(1), Some(&PackageKind::AppImage));
|
||||
|
||||
// The tarball runs inside the sandbox, so it is only offered there: with a usable host
|
||||
// Flatpak it stays an alternative, without one it is the default (an AppImage cannot
|
||||
// mount in a sandbox, and a distro package needs root).
|
||||
let kinds = order_available_kinds(true, false, true, false, false);
|
||||
let kinds = order_available_kinds(true, false, true, false, false, false);
|
||||
assert_eq!(kinds.first(), Some(&PackageKind::Flatpak));
|
||||
assert_eq!(kinds.get(1), Some(&PackageKind::TarGz));
|
||||
let kinds = order_available_kinds(true, false, false, false, false);
|
||||
let kinds = order_available_kinds(true, false, false, false, false, false);
|
||||
assert_eq!(kinds, [PackageKind::TarGz, PackageKind::AppImage]);
|
||||
for (appimage, flatpak) in [(true, true), (false, false), (false, true)] {
|
||||
assert!(!order_available_kinds(false, appimage, flatpak, true, true).contains(&PackageKind::TarGz));
|
||||
assert!(!order_available_kinds(false, appimage, flatpak, true, true, false).contains(&PackageKind::TarGz));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +151,9 @@ fn detect(exe: &Path) -> Option<Install> {
|
||||
if process::capture("rpm", &["-q", LAUNCHER.id], t).is_some() {
|
||||
return Some(Install::Package(PackageKind::Rpm, exe.to_path_buf()));
|
||||
}
|
||||
if process::capture("pacman", &["-Q", LAUNCHER.id], t).is_some() || process::capture("pacman", &["-Q", &LAUNCHER.bundle_id()], t).is_some() {
|
||||
return Some(Install::Package(PackageKind::ArchPkg, exe.to_path_buf()));
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
@@ -568,6 +571,7 @@ mod tests {
|
||||
"artcraft-launcher-0.2.0-linux-x86_64.AppImage",
|
||||
"artcraft-launcher-0.2.0-linux-x86_64.deb",
|
||||
"artcraft-launcher-0.2.0-linux-x86_64.flatpak",
|
||||
"artcraft-launcher-0.2.0-linux-x86_64.pkg.tar.zst",
|
||||
"artcraft-launcher-web-0.2.0.zip",
|
||||
];
|
||||
let release = Release {
|
||||
@@ -585,6 +589,7 @@ mod tests {
|
||||
assert_eq!(pick(Os::Linux, Install::AppImage(PathBuf::new()).kind()).as_deref(), Some(names[3]));
|
||||
assert_eq!(pick(Os::Linux, Install::Package(PackageKind::Deb, PathBuf::new()).kind()).as_deref(), Some(names[4]));
|
||||
assert_eq!(pick(Os::Linux, Install::Flatpak.kind()).as_deref(), Some(names[5]));
|
||||
assert_eq!(pick(Os::Linux, Install::Package(PackageKind::ArchPkg, PathBuf::new()).kind()).as_deref(), Some(names[6]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -421,7 +421,7 @@ impl LauncherUi {
|
||||
if !is_flatpak && !is_appimage {
|
||||
ui.selectable_value(&mut choice, None, tl!("System package (recommended)"));
|
||||
}
|
||||
for k in [PackageKind::Deb, PackageKind::Rpm, PackageKind::Flatpak, PackageKind::AppImage] {
|
||||
for k in [PackageKind::Deb, PackageKind::Rpm, PackageKind::ArchPkg, PackageKind::Flatpak, PackageKind::AppImage] {
|
||||
ui.selectable_value(&mut choice, Some(k), crate::i18n::t(k.label()));
|
||||
}
|
||||
// The tarball is unpacked and run inside the launcher's own sandbox, so it
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
Disk image (.dmg) Obraz disku (.dmg)
|
||||
Debian package (.deb) Balíček Debian (.deb)
|
||||
RPM package (.rpm) Balíček RPM (.rpm)
|
||||
Arch package (.pkg.tar.zst) Balíček Arch (.pkg.tar.zst)
|
||||
Flatpak bundle Balíček Flatpak
|
||||
Tarball (.tar.gz) Archiv tar (.tar.gz)
|
||||
photocraft Image editing Úpravy obrázků
|
||||
|
||||
|
@@ -155,6 +155,7 @@
|
||||
Disk image (.dmg) Disk-Image (.dmg)
|
||||
Debian package (.deb) Debian-Paket (.deb)
|
||||
RPM package (.rpm) RPM-Paket (.rpm)
|
||||
Arch package (.pkg.tar.zst) Arch-Paket (.pkg.tar.zst)
|
||||
Flatpak bundle Flatpak-Bundle
|
||||
Tarball (.tar.gz) Tar-Archiv (.tar.gz)
|
||||
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 11 and column 16.
|
@@ -152,6 +152,7 @@
|
||||
Disk image (.dmg) Imagen de disco (.dmg)
|
||||
Debian package (.deb) Paquete Debian (.deb)
|
||||
RPM package (.rpm) Paquete RPM (.rpm)
|
||||
Arch package (.pkg.tar.zst) Paquete Arch (.pkg.tar.zst)
|
||||
Flatpak bundle Paquete Flatpak
|
||||
Tarball (.tar.gz) Archivo tar (.tar.gz)
|
||||
photocraft Image editing Edición de imágenes
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 48.
|
@@ -153,6 +153,7 @@
|
||||
Disk image (.dmg) Image disque (.dmg)
|
||||
Debian package (.deb) Paquet Debian (.deb)
|
||||
RPM package (.rpm) Paquet RPM (.rpm)
|
||||
Arch package (.pkg.tar.zst) Paquet Arch (.pkg.tar.zst)
|
||||
Flatpak bundle Paquet Flatpak
|
||||
Tarball (.tar.gz) Archive (.tar.gz)
|
||||
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 50.
|
@@ -155,6 +155,7 @@
|
||||
Disk image (.dmg) Lemezkép (.dmg)
|
||||
Debian package (.deb) Debian-csomag (.deb)
|
||||
RPM package (.rpm) RPM-csomag (.rpm)
|
||||
Arch package (.pkg.tar.zst) Arch-csomag (.pkg.tar.zst)
|
||||
Flatpak bundle Flatpak-csomag
|
||||
Tarball (.tar.gz) Tömörített archívum (.tar.gz)
|
||||
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 11 and column 16.
|
@@ -157,6 +157,7 @@
|
||||
Disk image (.dmg) ディスクイメージ (.dmg)
|
||||
Debian package (.deb) Debian パッケージ (.deb)
|
||||
RPM package (.rpm) RPM パッケージ (.rpm)
|
||||
Arch package (.pkg.tar.zst) Arch パッケージ (.pkg.tar.zst)
|
||||
Flatpak bundle Flatpak バンドル
|
||||
Tarball (.tar.gz) tarball (.tar.gz)
|
||||
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 14 and column 44.
|
@@ -156,6 +156,7 @@
|
||||
Disk image (.dmg) Obraz dysku (.dmg)
|
||||
Debian package (.deb) Pakiet Debiana (.deb)
|
||||
RPM package (.rpm) Pakiet RPM (.rpm)
|
||||
Arch package (.pkg.tar.zst) Pakiet Arch (.pkg.tar.zst)
|
||||
Flatpak bundle Pakiet Flatpak
|
||||
Tarball (.tar.gz) Archiwum (.tar.gz)
|
||||
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 11 and column 15.
|
@@ -143,6 +143,7 @@
|
||||
Disk image (.dmg) Imagem de disco (.dmg)
|
||||
Debian package (.deb) Pacote Debian (.deb)
|
||||
RPM package (.rpm) Pacote RPM (.rpm)
|
||||
Arch package (.pkg.tar.zst) Pacote Arch (.pkg.tar.zst)
|
||||
Flatpak bundle Pacote Flatpak
|
||||
Tarball (.tar.gz) Arquivo (.tar.gz)
|
||||
|
||||
|
||||
|
@@ -153,6 +153,7 @@
|
||||
Disk image (.dmg) Образ диска (.dmg)
|
||||
Debian package (.deb) Пакет Debian (.deb)
|
||||
RPM package (.rpm) Пакет RPM (.rpm)
|
||||
Arch package (.pkg.tar.zst) Пакет Arch (.pkg.tar.zst)
|
||||
Flatpak bundle Пакет Flatpak
|
||||
Tarball (.tar.gz) Архив (.tar.gz)
|
||||
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 13 and column 44.
|
@@ -515,8 +515,16 @@ fn message_templates_match_real_messages() {
|
||||
#[test]
|
||||
fn complete_catalogs_translate_package_formats() {
|
||||
use artcraft_launcher_core::PackageKind;
|
||||
let kinds =
|
||||
[PackageKind::Msi, PackageKind::PortableZip, PackageKind::Dmg, PackageKind::Deb, PackageKind::Rpm, PackageKind::Flatpak, PackageKind::TarGz];
|
||||
let kinds = [
|
||||
PackageKind::Msi,
|
||||
PackageKind::PortableZip,
|
||||
PackageKind::Dmg,
|
||||
PackageKind::Deb,
|
||||
PackageKind::Rpm,
|
||||
PackageKind::ArchPkg,
|
||||
PackageKind::Flatpak,
|
||||
PackageKind::TarGz,
|
||||
];
|
||||
for lang in Lang::all().filter(|l| l.complete_menus()) {
|
||||
for kind in kinds {
|
||||
assert!(super::has(lang, kind.label()), "{}: {}", lang.code(), kind.label());
|
||||
|
||||
@@ -288,6 +288,7 @@ figcraft Interface design and prototyping 界面设计与原型制作
|
||||
Disk image (.dmg) 磁盘映像 (.dmg)
|
||||
Debian package (.deb) Debian 软件包 (.deb)
|
||||
RPM package (.rpm) RPM 软件包 (.rpm)
|
||||
Arch package (.pkg.tar.zst) Arch 软件包 (.pkg.tar.zst)
|
||||
Flatpak bundle Flatpak 包
|
||||
Tarball (.tar.gz) 压缩包 (.tar.gz)
|
||||
App details 应用详情
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 4 and column 3.
|
Reference in New Issue
Block a user