From 8d41659bee93bb972c09a57540a992f24f6493a0 Mon Sep 17 00:00:00 2001 From: Oliver Calder Date: Tue, 4 Feb 2025 18:59:41 -0600 Subject: [PATCH] daemon: look for snap icon in icons directory as fallback If a snap doesn't ship an icon in `meta/gui/icon.*`, then look for an icon for the snap in question in the snap icons install directory. Signed-off-by: Oliver Calder --- daemon/api_icons.go | 2 +- daemon/api_icons_test.go | 2 +- daemon/snap.go | 22 ++++++++++++++++------ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/daemon/api_icons.go b/daemon/api_icons.go index aaeeefdfcd9..cfed29f02c1 100644 --- a/daemon/api_icons.go +++ b/daemon/api_icons.go @@ -61,7 +61,7 @@ func iconGet(st *state.State, name string) Response { return NotFound("snap has no current revision") } - icon := snapIcon(snap.MinimalPlaceInfo(name, sideInfo.Revision)) + icon := snapIcon(snap.MinimalPlaceInfo(name, sideInfo.Revision), sideInfo.SnapID) if icon == "" { return NotFound("local snap has no icon") diff --git a/daemon/api_icons_test.go b/daemon/api_icons_test.go index fc4ce44bedd..ce49a6ab45b 100644 --- a/daemon/api_icons_test.go +++ b/daemon/api_icons_test.go @@ -112,6 +112,6 @@ func (s *iconsSuite) TestAppIconGetNoApp(c *check.C) { func (s *iconsSuite) TestNotInstalledSnapIcon(c *check.C) { info := &snap.Info{SuggestedName: "notInstalledSnap", Media: []snap.MediaInfo{{Type: "icon", URL: "icon.svg"}}} - iconfile := daemon.SnapIcon(info) + iconfile := daemon.SnapIcon(info, "notInstalledSnapID") c.Check(iconfile, check.Equals, "") } diff --git a/daemon/snap.go b/daemon/snap.go index 2cd2313f67c..112e8b68d25 100644 --- a/daemon/snap.go +++ b/daemon/snap.go @@ -30,6 +30,7 @@ import ( "github.com/snapcore/snapd/client" "github.com/snapcore/snapd/client/clientutil" "github.com/snapcore/snapd/logger" + "github.com/snapcore/snapd/osutil" "github.com/snapcore/snapd/overlord/assertstate" "github.com/snapcore/snapd/overlord/healthstate" "github.com/snapcore/snapd/overlord/snapstate" @@ -241,7 +242,7 @@ func mapLocal(about aboutSnap, sd clientutil.StatusDecorator) *client.Snap { } result.InstalledSize = localSnap.Size - if icon := snapIcon(localSnap); icon != "" { + if icon := snapIcon(localSnap, localSnap.SnapID); icon != "" { result.Icon = icon } @@ -339,12 +340,21 @@ func fillComponentInfo(about aboutSnap) []client.Component { return comps } -// snapIcon tries to find the icon inside the snap -func snapIcon(info snap.PlaceInfo) string { +// snapIcon tries to find the icon inside the snap at meta/gui/icon.*, and if +// the snap does not ship an icon there, then tries to find the fallback icon +// in the icons install directory. +func snapIcon(info snap.PlaceInfo, snapID string) string { + // Look in the snap itself found, _ := filepath.Glob(filepath.Join(info.MountDir(), "meta", "gui", "icon.*")) - if len(found) == 0 { - return "" + if len(found) > 0 { + return found[0] } - return found[0] + // Look in the snap icons directory as a fallback + if fallback := snapstate.IconInstallFilename(snapID); fallback != "" && osutil.FileExists(fallback) { + return fallback + } + + // Didn't find an icon + return "" }