Skip to content

Commit 630bb8f

Browse files
committed
Fix multi-desktop file extraction logic for sharun based AppImages
1 parent a82befc commit 630bb8f

2 files changed

Lines changed: 69 additions & 53 deletions

File tree

‎meson.build‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
project('app-manager', ['vala', 'c'],
2-
version: '3.6.4',
2+
version: '3.6.5',
33
meson_version: '>=0.64.0'
44
)
55

‎src/core/app_image_assets.vala‎

Lines changed: 68 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -201,92 +201,108 @@ namespace AppManager.Core {
201201
}
202202

203203
/**
204-
* Extract all .desktop files from usr/share/applications/ inside the AppImage.
204+
* Extract all .desktop files from the AppImage's applications directory.
205+
* Standard AppImages keep these under usr/share/applications/; sharun-packed
206+
* AppImages (e.g. anylinux Visual Studio Code) drop the usr prefix and use
207+
* share/applications/. Both layouts are searched, deduplicated by filename.
205208
* Returns an array of paths to extracted files (empty if none present).
206209
* Used by issue #106 multi-desktop-entry support (e.g. WPS Office components).
207210
*/
208211
public static string[] extract_extra_desktop_entries(string appimage_path, string temp_root) throws Error {
209212
var extra_root = Path.build_filename(temp_root, "extra_desktop");
210213
DirUtils.create_with_parents(extra_root, 0755);
211214

212-
if (!extract_entry(appimage_path, extra_root, "usr/share/applications/*.desktop")) {
213-
return new string[0];
214-
}
215-
216-
var apps_dir = Path.build_filename(extra_root, "usr", "share", "applications");
217-
if (!FileUtils.test(apps_dir, FileTest.IS_DIR)) {
218-
return new string[0];
219-
}
215+
string[] apps_dir_variants = { "usr/share/applications", "share/applications" };
220216

221217
var results = new ArrayList();
222-
try {
223-
var dir = Dir.open(apps_dir);
224-
string? name;
225-
while ((name = dir.read_name()) != null) {
226-
if (!name.has_suffix(".desktop")) continue;
227-
var path = Path.build_filename(apps_dir, name);
228-
if (FileUtils.test(path, FileTest.IS_DIR)) continue;
229-
230-
var file = File.new_for_path(path);
231-
var type = file.query_file_type(FileQueryInfoFlags.NONE);
232-
if (type == FileType.SYMBOLIC_LINK) {
233-
try {
234-
results.add(resolve_symlink(path, appimage_path, extra_root));
235-
} catch (Error e) {
236-
debug("Skipping unresolvable extra desktop symlink %s: %s", path, e.message);
218+
var seen = new HashSet(); // dedup by basename across both layouts
219+
foreach (var rel_dir in apps_dir_variants) {
220+
if (!extract_entry(appimage_path, extra_root, rel_dir + "/*.desktop")) {
221+
continue;
222+
}
223+
224+
var apps_dir = Path.build_filename(extra_root, rel_dir);
225+
if (!FileUtils.test(apps_dir, FileTest.IS_DIR)) {
226+
continue;
227+
}
228+
229+
try {
230+
var dir = Dir.open(apps_dir);
231+
string? name;
232+
while ((name = dir.read_name()) != null) {
233+
if (!name.has_suffix(".desktop")) continue;
234+
if (seen.contains(name)) continue;
235+
var path = Path.build_filename(apps_dir, name);
236+
if (FileUtils.test(path, FileTest.IS_DIR)) continue;
237+
238+
var file = File.new_for_path(path);
239+
var type = file.query_file_type(FileQueryInfoFlags.NONE);
240+
if (type == FileType.SYMBOLIC_LINK) {
241+
try {
242+
results.add(resolve_symlink(path, appimage_path, extra_root));
243+
seen.add(name);
244+
} catch (Error e) {
245+
debug("Skipping unresolvable extra desktop symlink %s: %s", path, e.message);
246+
}
247+
} else {
248+
results.add(path);
249+
seen.add(name);
237250
}
238-
} else {
239-
results.add(path);
240251
}
252+
} catch (Error e) {
253+
debug("Failed to list extra desktop entries in %s: %s", apps_dir, e.message);
241254
}
242-
} catch (Error e) {
243-
debug("Failed to list extra desktop entries in %s: %s", apps_dir, e.message);
244255
}
245256

246257
return results.to_array();
247258
}
248259

249260
/**
250261
* Look up a named icon inside the AppImage's icon themes.
251-
* Tries usr/share/icons/hicolor//apps/.{png,svg} (largest size first),
252-
* then usr/share/pixmaps/.{png,svg}. Returns the extracted file path or null.
262+
* Tries /icons/hicolor//apps/.{png,svg} (largest size first),
263+
* then /pixmaps/.{png,svg}, where is usr/share (standard
264+
* layout) or share (sharun-packed layout). Returns the extracted file path or null.
253265
*/
254266
public static string? extract_named_icon(string appimage_path, string temp_root, string icon_name) {
255267
if (icon_name.strip() == "") return null;
256268

257269
var icon_root = Path.build_filename(temp_root, "named_icons", icon_name);
258270
DirUtils.create_with_parents(icon_root, 0755);
259271

260-
// Try hicolor PNGs at all sizes; pick the largest available
272+
string[] share_roots = { "usr/share", "share" };
261273
string[] sizes = { "512x512", "256x256", "192x192", "128x128", "96x96", "64x64", "48x48", "32x32", "24x24", "16x16" };
262-
foreach (var size in sizes) {
263-
var pattern = "usr/share/icons/hicolor/%s/apps/%s.png".printf(size, icon_name);
264-
if (extract_entry(appimage_path, icon_root, pattern)) {
265-
var path = Path.build_filename(icon_root, "usr", "share", "icons", "hicolor", size, "apps", "%s.png".printf(icon_name));
266-
if (FileUtils.test(path, FileTest.IS_REGULAR)) {
267-
return path;
268-
}
269-
}
270-
}
271274

272-
// Try hicolor scalable SVG
273-
var svg_pattern = "usr/share/icons/hicolor/scalable/apps/%s.svg".printf(icon_name);
274-
if (extract_entry(appimage_path, icon_root, svg_pattern)) {
275-
var path = Path.build_filename(icon_root, "usr", "share", "icons", "hicolor", "scalable", "apps", "%s.svg".printf(icon_name));
276-
if (FileUtils.test(path, FileTest.IS_REGULAR)) {
277-
return path;
275+
foreach (var share_root in share_roots) {
276+
// Try hicolor PNGs at all sizes; pick the largest available
277+
foreach (var size in sizes) {
278+
var rel = "%s/icons/hicolor/%s/apps/%s.png".printf(share_root, size, icon_name);
279+
if (extract_entry(appimage_path, icon_root, rel)) {
280+
var path = Path.build_filename(icon_root, rel);
281+
if (FileUtils.test(path, FileTest.IS_REGULAR)) {
282+
return path;
283+
}
284+
}
278285
}
279-
}
280286

281-
// Try pixmaps PNG then SVG
282-
foreach (var ext in new string[] { "png", "svg" }) {
283-
var pattern = "usr/share/pixmaps/%s.%s".printf(icon_name, ext);
284-
if (extract_entry(appimage_path, icon_root, pattern)) {
285-
var path = Path.build_filename(icon_root, "usr", "share", "pixmaps", "%s.%s".printf(icon_name, ext));
287+
// Try hicolor scalable SVG
288+
var svg_rel = "%s/icons/hicolor/scalable/apps/%s.svg".printf(share_root, icon_name);
289+
if (extract_entry(appimage_path, icon_root, svg_rel)) {
290+
var path = Path.build_filename(icon_root, svg_rel);
286291
if (FileUtils.test(path, FileTest.IS_REGULAR)) {
287292
return path;
288293
}
289294
}
295+
296+
// Try pixmaps PNG then SVG
297+
foreach (var ext in new string[] { "png", "svg" }) {
298+
var rel = "%s/pixmaps/%s.%s".printf(share_root, icon_name, ext);
299+
if (extract_entry(appimage_path, icon_root, rel)) {
300+
var path = Path.build_filename(icon_root, rel);
301+
if (FileUtils.test(path, FileTest.IS_REGULAR)) {
302+
return path;
303+
}
304+
}
305+
}
290306
}
291307

292308
return null;

0 commit comments

Comments
 (0)