Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

advisor: use json for package database #4999

Merged
merged 7 commits into from Apr 9, 2018
65 changes: 44 additions & 21 deletions advisor/backend.go
Expand Up @@ -20,8 +20,8 @@
package advisor

import (
"encoding/json"
"os"
"strings"
"time"

"github.com/snapcore/bolt"
Expand All @@ -45,7 +45,7 @@ type writer struct {
type CommandDB interface {
// AddSnap adds the entries for commands pointing to the given
// snap name to the commands database.
AddSnap(snapName, summary string, commands []string) error
AddSnap(snapName, version, summary string, commands []string) error
// Commit persist the changes, and closes the database. If the
// database has already been committed/rollbacked, does nothing.
Commit() error
Expand Down Expand Up @@ -98,23 +98,38 @@ func Create() (CommandDB, error) {
return t, nil
}

func (t *writer) AddSnap(snapName, summary string, commands []string) error {
bname := []byte(snapName)

func (t *writer) AddSnap(snapName, version, summary string, commands []string) error {
for _, cmd := range commands {
var sil []Package

bcmd := []byte(cmd)
row := t.cmdBucket.Get(bcmd)
if row == nil {
row = bname
} else {
row = append(append(row, ','), bname...)
if row != nil {
if err := json.Unmarshal(row, &sil); err != nil {
return err
}
}
// For the mapping of command->snap we do not need the summary, nothing is using that.
sil = append(sil, Package{Snap: snapName, Version: version})
row, err := json.Marshal(sil)
if err != nil {
return err
}
if err := t.cmdBucket.Put(bcmd, row); err != nil {
return err
}
}

if err := t.pkgBucket.Put([]byte(snapName), []byte(summary)); err != nil {
// TODO: use json here as well and put the version information here
bj, err := json.Marshal(Package{
Snap: snapName,
Version: version,
Summary: summary,
})
if err != nil {
return err
}
if err := t.pkgBucket.Put([]byte(snapName), bj); err != nil {
return err
}

Expand Down Expand Up @@ -154,7 +169,7 @@ func (t *writer) done(commit bool) error {

// DumpCommands returns the whole database as a map. For use in
// testing and debugging.
func DumpCommands() (map[string][]string, error) {
func DumpCommands() (map[string]string, error) {
db, err := bolt.Open(dirs.SnapCommandsDB, 0644, &bolt.Options{
ReadOnly: true,
Timeout: 1 * time.Second,
Expand All @@ -175,10 +190,10 @@ func DumpCommands() (map[string][]string, error) {
return nil, nil
}

m := map[string][]string{}
m := map[string]string{}
c := b.Cursor()
for k, v := c.First(); k != nil; k, v = c.Next() {
m[string(k)] = strings.Split(string(v), ",")
m[string(k)] = string(v)
}

return m, nil
Expand Down Expand Up @@ -224,12 +239,15 @@ func (f *boltFinder) FindCommand(command string) ([]Command, error) {
if buf == nil {
return nil, nil
}

snaps := strings.Split(string(buf), ",")
cmds := make([]Command, len(snaps))
for i, snap := range snaps {
var sil []Package
if err := json.Unmarshal(buf, &sil); err != nil {
return nil, err
}
cmds := make([]Command, len(sil))
for i, si := range sil {
cmds[i] = Command{
Snap: snap,
Snap: si.Snap,
Version: si.Version,
Command: command,
}
}
Expand All @@ -249,10 +267,15 @@ func (f *boltFinder) FindPackage(pkgName string) (*Package, error) {
return nil, nil
}

bsummary := b.Get([]byte(pkgName))
if bsummary == nil {
bj := b.Get([]byte(pkgName))
if bj == nil {
return nil, nil
}
var si Package
err = json.Unmarshal(bj, &si)
if err != nil {
return nil, err
}

return &Package{Snap: pkgName, Summary: string(bsummary)}, nil
return &Package{Snap: pkgName, Version: si.Version, Summary: si.Summary}, nil
}
1 change: 1 addition & 0 deletions advisor/cmdfinder.go
Expand Up @@ -25,6 +25,7 @@ import (

type Command struct {
Snap string
Version string `json:"Version,omitempty"`
Command string
}

Expand Down
20 changes: 10 additions & 10 deletions advisor/cmdfinder_test.go
Expand Up @@ -44,8 +44,8 @@ func (s *cmdfinderSuite) SetUpTest(c *C) {

db, err := advisor.Create()
c.Assert(err, IsNil)
c.Assert(db.AddSnap("foo", "foo summary", []string{"foo", "meh"}), IsNil)
c.Assert(db.AddSnap("bar", "bar summary", []string{"bar", "meh"}), IsNil)
c.Assert(db.AddSnap("foo", "1.0", "foo summary", []string{"foo", "meh"}), IsNil)
c.Assert(db.AddSnap("bar", "2.0", "bar summary", []string{"bar", "meh"}), IsNil)
c.Assert(db.Commit(), IsNil)
}

Expand Down Expand Up @@ -99,8 +99,8 @@ func (s *cmdfinderSuite) TestFindCommandHit(c *C) {
cmds, err := advisor.FindCommand("meh")
c.Assert(err, IsNil)
c.Check(cmds, DeepEquals, []advisor.Command{
{Snap: "foo", Command: "meh"},
{Snap: "bar", Command: "meh"},
{Snap: "foo", Version: "1.0", Command: "meh"},
{Snap: "bar", Version: "2.0", Command: "meh"},
})
}

Expand All @@ -114,8 +114,8 @@ func (s *cmdfinderSuite) TestFindMisspelledCommandHit(c *C) {
cmds, err := advisor.FindMisspelledCommand("moh")
c.Assert(err, IsNil)
c.Check(cmds, DeepEquals, []advisor.Command{
{Snap: "foo", Command: "meh"},
{Snap: "bar", Command: "meh"},
{Snap: "foo", Version: "1.0", Command: "meh"},
{Snap: "bar", Version: "2.0", Command: "meh"},
})
}

Expand All @@ -128,10 +128,10 @@ func (s *cmdfinderSuite) TestFindMisspelledCommandMiss(c *C) {
func (s *cmdfinderSuite) TestDumpCommands(c *C) {
cmds, err := advisor.DumpCommands()
c.Assert(err, IsNil)
c.Check(cmds, DeepEquals, map[string][]string{
"foo": {"foo"},
"bar": {"bar"},
"meh": {"foo", "bar"},
c.Check(cmds, DeepEquals, map[string]string{
"foo": `[{"snap":"foo","version":"1.0"}]`,
"bar": `[{"snap":"bar","version":"2.0"}]`,
"meh": `[{"snap":"foo","version":"1.0"},{"snap":"bar","version":"2.0"}]`,
})
}

Expand Down
5 changes: 3 additions & 2 deletions advisor/pkgfinder.go
Expand Up @@ -24,8 +24,9 @@ import (
)

type Package struct {
Snap string
Summary string
Snap string `json:"snap"`
Version string `json:"version"`
Summary string `json:"summary,omitempty"`
}

func FindPackage(pkgName string) (*Package, error) {
Expand Down
40 changes: 40 additions & 0 deletions advisor/pkgfinder_test.go
@@ -0,0 +1,40 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2018 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 advisor_test

import (
. "gopkg.in/check.v1"

"github.com/snapcore/snapd/advisor"
)

func (s *cmdfinderSuite) TestFindPackageHit(c *C) {
pkg, err := advisor.FindPackage("foo")
c.Assert(err, IsNil)
c.Check(pkg, DeepEquals, &advisor.Package{
Snap: "foo", Version: "1.0", Summary: "foo summary",
})
}

func (s *cmdfinderSuite) TestFindPackageMiss(c *C) {
pkg, err := advisor.FindPackage("moh")
c.Assert(err, IsNil)
c.Check(pkg, IsNil)
}
14 changes: 7 additions & 7 deletions overlord/snapstate/catalogrefresh_test.go
@@ -1,7 +1,7 @@
// -*- Mode: Go; indent-tabs-mode: t -*-

/*
* Copyright (C) 2017 Canonical Ltd
* Copyright (C) 2017-2018 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
Expand Down Expand Up @@ -50,8 +50,8 @@ func (r *catalogStore) WriteCatalogs(ctx context.Context, w io.Writer, a store.S
}
r.ops = append(r.ops, "write-catalog")
w.Write([]byte("pkg1\npkg2"))
a.AddSnap("foo", "foo summary", []string{"foo", "meh"})
a.AddSnap("bar", "bar summray", []string{"bar", "meh"})
a.AddSnap("foo", "1.0", "foo summary", []string{"foo", "meh"})
a.AddSnap("bar", "2.0", "bar summray", []string{"bar", "meh"})
return nil
}

Expand Down Expand Up @@ -105,10 +105,10 @@ func (s *catalogRefreshTestSuite) TestCatalogRefresh(c *C) {
c.Check(osutil.FileExists(dirs.SnapCommandsDB), Equals, true)
dump, err := advisor.DumpCommands()
c.Assert(err, IsNil)
c.Check(dump, DeepEquals, map[string][]string{
"foo": {"foo"},
"bar": {"bar"},
"meh": {"foo", "bar"},
c.Check(dump, DeepEquals, map[string]string{
"foo": `[{"snap":"foo","version":"1.0"}]`,
"bar": `[{"snap":"bar","version":"2.0"}]`,
"meh": `[{"snap":"foo","version":"1.0"},{"snap":"bar","version":"2.0"}]`,
})
}

Expand Down
5 changes: 3 additions & 2 deletions store/store.go
Expand Up @@ -675,13 +675,14 @@ type alias struct {

type catalogItem struct {
Name string `json:"package_name"`
Version string `json:"version"`
Summary string `json:"summary"`
Aliases []alias `json:"aliases"`
Apps []string `json:"apps"`
}

type SnapAdder interface {
AddSnap(snapName, summary string, commands []string) error
AddSnap(snapName, version, summary string, commands []string) error
}

func decodeCatalog(resp *http.Response, names io.Writer, db SnapAdder) error {
Expand Down Expand Up @@ -722,7 +723,7 @@ func decodeCatalog(resp *http.Response, names io.Writer, db SnapAdder) error {
commands = append(commands, snap.JoinSnapApp(v.Name, app))
}

if err := db.AddSnap(v.Name, v.Summary, commands); err != nil {
if err := db.AddSnap(v.Name, v.Version, v.Summary, commands); err != nil {
return err
}
}
Expand Down
16 changes: 9 additions & 7 deletions store/store_test.go
Expand Up @@ -2855,12 +2855,14 @@ const mockNamesJSON = `
"apps": ["baz"],
"title": "a title",
"summary": "oneary plus twoary",
"package_name": "bar"
"package_name": "bar",
"version": "2.0"
},
{
"aliases": [{"name": "meh", "target": "foo"}],
"apps": ["foo"],
"package_name": "foo"
"package_name": "foo",
"version": "1.0"
}
]
}
Expand Down Expand Up @@ -2921,11 +2923,11 @@ func (s *storeTestSuite) testSnapCommands(c *C, onClassic bool) {

dump, err := advisor.DumpCommands()
c.Assert(err, IsNil)
c.Check(dump, DeepEquals, map[string][]string{
"foo": {"foo"},
"bar.baz": {"bar"},
"potato": {"bar"},
"meh": {"bar", "foo"},
c.Check(dump, DeepEquals, map[string]string{
"foo": `[{"snap":"foo","version":"1.0"}]`,
"bar.baz": `[{"snap":"bar","version":"2.0"}]`,
"potato": `[{"snap":"bar","version":"2.0"}]`,
"meh": `[{"snap":"bar","version":"2.0"},{"snap":"foo","version":"1.0"}]`,
})
}

Expand Down