mirror of
https://github.com/token2/snapd.git
synced 2026-03-13 11:15:47 -07:00
* store: Return categories in find results This allows clients to show the categories as snapcraft.io does. Fixes https://bugs.launchpad.net/snapd/+bug/1838786 * Remove unnecessary CategoryInfos type * Only show categories when using --verbose * Add tests for snap info printing categories * Update cmd/snap/cmd_info.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update cmd/snap/cmd_info.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * v1 store API doesn't return categories * Drop category information from snap info Other snap commands don't support categories yet, this change should be part of that. * Add /v2/categories and support /v2/find?category=foo * Add note that section is deprecated * Update client/packages.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update daemon/api_categories.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update daemon/api_categories.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update daemon/api_categories.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update store/store.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update store/details_v2.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Update client/packages.go Co-authored-by: Miguel Pires <miguelpires94@gmail.com> * Improve test error message * Drop copy/pasted comments that doesn't seem relevant * Remove unused import * Reorder CategoryInfo struct * Fix accepted content type for store v2/snaps/categories request * Set APILevel for v2/snaps/categories request * Update accept string used to get data for store test * Make /v2/categories return objects not just strings --------- Co-authored-by: Miguel Pires <miguelpires94@gmail.com>
161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
// -*- Mode: Go; indent-tabs-mode: t -*-
|
|
|
|
/*
|
|
* Copyright (C) 2018-2020 Canonical Ltd
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 3 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
// Package clientutil offers utilities to turn snap.Info and related
|
|
// structs into client structs and to work with the latter.
|
|
package clientutil
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/snapcore/snapd/client"
|
|
"github.com/snapcore/snapd/osutil"
|
|
"github.com/snapcore/snapd/snap"
|
|
)
|
|
|
|
// A StatusDecorator is able to decorate client.AppInfos with service status.
|
|
type StatusDecorator interface {
|
|
DecorateWithStatus(appInfo *client.AppInfo, snapApp *snap.AppInfo) error
|
|
}
|
|
|
|
// ClientSnapFromSnapInfo returns a client.Snap derived from snap.Info.
|
|
// If an optional StatusDecorator is provided it will be used to
|
|
// add service status information.
|
|
func ClientSnapFromSnapInfo(snapInfo *snap.Info, decorator StatusDecorator) (*client.Snap, error) {
|
|
var publisher *snap.StoreAccount
|
|
if snapInfo.Publisher.Username != "" {
|
|
publisher = &snapInfo.Publisher
|
|
}
|
|
|
|
confinement := snapInfo.Confinement
|
|
if confinement == "" {
|
|
confinement = snap.StrictConfinement
|
|
}
|
|
|
|
snapapps := make([]*snap.AppInfo, 0, len(snapInfo.Apps))
|
|
for _, app := range snapInfo.Apps {
|
|
snapapps = append(snapapps, app)
|
|
}
|
|
sort.Sort(snap.AppInfoBySnapApp(snapapps))
|
|
|
|
apps, err := ClientAppInfosFromSnapAppInfos(snapapps, decorator)
|
|
result := &client.Snap{
|
|
Description: snapInfo.Description(),
|
|
Developer: snapInfo.Publisher.Username,
|
|
Publisher: publisher,
|
|
Icon: snapInfo.Media.IconURL(),
|
|
ID: snapInfo.ID(),
|
|
InstallDate: snapInfo.InstallDate(),
|
|
Name: snapInfo.InstanceName(),
|
|
Revision: snapInfo.Revision,
|
|
Summary: snapInfo.Summary(),
|
|
Type: string(snapInfo.Type()),
|
|
Base: snapInfo.Base,
|
|
Version: snapInfo.Version,
|
|
Channel: snapInfo.Channel,
|
|
Private: snapInfo.Private,
|
|
Confinement: string(confinement),
|
|
Apps: apps,
|
|
Broken: snapInfo.Broken,
|
|
Title: snapInfo.Title(),
|
|
License: snapInfo.License,
|
|
Media: snapInfo.Media,
|
|
Prices: snapInfo.Prices,
|
|
Channels: snapInfo.Channels,
|
|
Tracks: snapInfo.Tracks,
|
|
CommonIDs: snapInfo.CommonIDs,
|
|
Links: snapInfo.Links(),
|
|
Contact: snapInfo.Contact(),
|
|
Website: snapInfo.Website(),
|
|
StoreURL: snapInfo.StoreURL,
|
|
Categories: snapInfo.Categories,
|
|
}
|
|
|
|
return result, err
|
|
}
|
|
|
|
func ClientAppInfoNotes(app *client.AppInfo) string {
|
|
if !app.IsService() {
|
|
return "-"
|
|
}
|
|
|
|
var notes = make([]string, 0, 4)
|
|
if app.DaemonScope == snap.UserDaemon {
|
|
notes = append(notes, "user")
|
|
}
|
|
var seenTimer, seenSocket, seenDbus bool
|
|
for _, act := range app.Activators {
|
|
switch act.Type {
|
|
case "timer":
|
|
seenTimer = true
|
|
case "socket":
|
|
seenSocket = true
|
|
case "dbus":
|
|
seenDbus = true
|
|
}
|
|
}
|
|
if seenTimer {
|
|
notes = append(notes, "timer-activated")
|
|
}
|
|
if seenSocket {
|
|
notes = append(notes, "socket-activated")
|
|
}
|
|
if seenDbus {
|
|
notes = append(notes, "dbus-activated")
|
|
}
|
|
if len(notes) == 0 {
|
|
return "-"
|
|
}
|
|
return strings.Join(notes, ",")
|
|
}
|
|
|
|
// ClientAppInfosFromSnapAppInfos returns client.AppInfos derived from
|
|
// the given snap.AppInfos.
|
|
// If an optional StatusDecorator is provided it will be used to add
|
|
// service status information as well, this will be done only if the
|
|
// snap is active and when the app is a service.
|
|
func ClientAppInfosFromSnapAppInfos(apps []*snap.AppInfo, decorator StatusDecorator) ([]client.AppInfo, error) {
|
|
out := make([]client.AppInfo, 0, len(apps))
|
|
for _, app := range apps {
|
|
appInfo := client.AppInfo{
|
|
Snap: app.Snap.InstanceName(),
|
|
Name: app.Name,
|
|
CommonID: app.CommonID,
|
|
}
|
|
if fn := app.DesktopFile(); osutil.FileExists(fn) {
|
|
appInfo.DesktopFile = fn
|
|
}
|
|
|
|
appInfo.Daemon = app.Daemon
|
|
appInfo.DaemonScope = app.DaemonScope
|
|
if !app.IsService() || decorator == nil || !app.Snap.IsActive() {
|
|
out = append(out, appInfo)
|
|
continue
|
|
}
|
|
|
|
if err := decorator.DecorateWithStatus(&appInfo, app); err != nil {
|
|
return nil, err
|
|
}
|
|
out = append(out, appInfo)
|
|
}
|
|
|
|
return out, nil
|
|
}
|