summaryrefslogtreecommitdiff
path: root/advisor
diff options
authorMichael Vogt <michael.vogt@gmail.com>2018-02-01 09:41:06 +0100
committerGitHub <noreply@github.com>2018-02-01 09:41:06 +0100
commitac14cf92398883d7558589d97ae815d9df86d998 (patch)
treeb04c7342b501595ca7cf5c4da1ba6163815f623a /advisor
parentb6e6ebb4b106243507b232f2059bdec5f7046f3b (diff)
parentf045cbda14a614821b279a94f37dfc3af212bcab (diff)
Merge pull request #4459 from mvo5/snap-advise-snap
snap: add support for `snap advise-snap pkgName`
Diffstat (limited to 'advisor')
-rw-r--r--advisor/backend.go69
-rw-r--r--advisor/cmdfinder.go19
-rw-r--r--advisor/cmdfinder_test.go8
-rw-r--r--advisor/finder.go36
-rw-r--r--advisor/pkgfinder.go35
5 files changed, 132 insertions, 35 deletions
diff --git a/advisor/backend.go b/advisor/backend.go
index 8856b5a7a3..6166513b18 100644
--- a/advisor/backend.go
+++ b/advisor/backend.go
@@ -28,18 +28,22 @@ import (
"github.com/snapcore/snapd/dirs"
)
-var cmdBucketKey = []byte("Commands")
+var (
+ cmdBucketKey = []byte("Commands")
+ pkgBucketKey = []byte("Snaps")
+)
type writer struct {
- db *bolt.DB
- tx *bolt.Tx
- bucket *bolt.Bucket
+ db *bolt.DB
+ tx *bolt.Tx
+ cmdBucket *bolt.Bucket
+ pkgBucket *bolt.Bucket
}
type CommandDB interface {
// AddSnap adds the entries for commands pointing to the given
// snap name to the commands database.
- AddSnap(snapName string, commands []string) error
+ AddSnap(snapName, 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
@@ -64,12 +68,23 @@ func Create() (CommandDB, error) {
t.tx, err = t.db.Begin(true)
if err == nil {
- err = t.tx.DeleteBucket(cmdBucketKey)
+ err := t.tx.DeleteBucket(cmdBucketKey)
if err == nil || err == bolt.ErrBucketNotFound {
- t.bucket, err = t.tx.CreateBucket(cmdBucketKey)
+ t.cmdBucket, err = t.tx.CreateBucket(cmdBucketKey)
}
if err != nil {
t.tx.Rollback()
+
+ }
+
+ if err == nil {
+ err := t.tx.DeleteBucket(pkgBucketKey)
+ if err == nil || err == bolt.ErrBucketNotFound {
+ t.pkgBucket, err = t.tx.CreateBucket(pkgBucketKey)
+ }
+ if err != nil {
+ t.tx.Rollback()
+ }
}
}
@@ -81,22 +96,26 @@ func Create() (CommandDB, error) {
return t, nil
}
-func (t *writer) AddSnap(snapName string, commands []string) error {
+func (t *writer) AddSnap(snapName, summary string, commands []string) error {
bname := []byte(snapName)
for _, cmd := range commands {
bcmd := []byte(cmd)
- row := t.bucket.Get(bcmd)
+ row := t.cmdBucket.Get(bcmd)
if row == nil {
row = bname
} else {
row = append(append(row, ','), bname...)
}
- if err := t.bucket.Put(bcmd, row); err != nil {
+ if err := t.cmdBucket.Put(bcmd, row); err != nil {
return err
}
}
+ if err := t.pkgBucket.Put([]byte(snapName), []byte(summary)); err != nil {
+ return err
+ }
+
return nil
}
@@ -111,7 +130,8 @@ func (t *writer) Rollback() error {
func (t *writer) done(commit bool) error {
var e1, e2 error
- t.bucket = nil
+ t.cmdBucket = nil
+ t.pkgBucket = nil
if t.tx != nil {
if commit {
e1 = t.tx.Commit()
@@ -130,8 +150,9 @@ func (t *writer) done(commit bool) error {
return e1
}
-// Dump returns the whole database as a map. For use in testing and debugging.
-func Dump() (map[string][]string, error) {
+// DumpCommands returns the whole database as a map. For use in
+// testing and debugging.
+func DumpCommands() (map[string][]string, error) {
db, err := bolt.Open(dirs.SnapCommandsDB, 0600, &bolt.Options{
ReadOnly: true,
Timeout: 1 * time.Second,
@@ -178,7 +199,7 @@ func Open() (Finder, error) {
return &boltFinder{*db}, nil
}
-func (f *boltFinder) Find(command string) ([]Command, error) {
+func (f *boltFinder) FindCommand(command string) ([]Command, error) {
tx, err := f.Begin(false)
if err != nil {
return nil, err
@@ -206,3 +227,23 @@ func (f *boltFinder) Find(command string) ([]Command, error) {
return cmds, nil
}
+
+func (f *boltFinder) FindPackage(pkgName string) (*Package, error) {
+ tx, err := f.Begin(false)
+ if err != nil {
+ return nil, err
+ }
+ defer tx.Rollback()
+
+ b := tx.Bucket(pkgBucketKey)
+ if b == nil {
+ return nil, nil
+ }
+
+ bsummary := b.Get([]byte(pkgName))
+ if bsummary == nil {
+ return nil, nil
+ }
+
+ return &Package{Snap: pkgName, Summary: string(bsummary)}, nil
+}
diff --git a/advisor/cmdfinder.go b/advisor/cmdfinder.go
index 0960dfda08..15d50eb388 100644
--- a/advisor/cmdfinder.go
+++ b/advisor/cmdfinder.go
@@ -24,8 +24,6 @@ type Command struct {
Command string
}
-var newFinder = Open
-
func FindCommand(command string) ([]Command, error) {
finder, err := newFinder()
if err != nil {
@@ -33,7 +31,7 @@ func FindCommand(command string) ([]Command, error) {
}
defer finder.Close()
- return finder.Find(command)
+ return finder.FindCommand(command)
}
const (
@@ -88,7 +86,7 @@ func FindMisspelledCommand(command string) ([]Command, error) {
alternatives := make([]Command, 0, 32)
for _, w := range similarWords(command) {
- res, err := finder.Find(w)
+ res, err := finder.FindCommand(w)
if err != nil {
return nil, err
}
@@ -99,16 +97,3 @@ func FindMisspelledCommand(command string) ([]Command, error) {
return alternatives, nil
}
-
-type Finder interface {
- Find(command string) ([]Command, error)
- Close() error
-}
-
-func ReplaceCommandsFinder(constructor func() (Finder, error)) (restore func()) {
- old := newFinder
- newFinder = constructor
- return func() {
- newFinder = old
- }
-}
diff --git a/advisor/cmdfinder_test.go b/advisor/cmdfinder_test.go
index c84c918615..da8c1028c1 100644
--- a/advisor/cmdfinder_test.go
+++ b/advisor/cmdfinder_test.go
@@ -44,8 +44,8 @@ func (s *cmdfinderSuite) SetUpTest(c *C) {
db, err := advisor.Create()
c.Assert(err, IsNil)
- c.Assert(db.AddSnap("foo", []string{"foo", "meh"}), IsNil)
- c.Assert(db.AddSnap("bar", []string{"bar", "meh"}), 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.Commit(), IsNil)
}
@@ -125,8 +125,8 @@ func (s *cmdfinderSuite) TestFindMisspelledCommandMiss(c *C) {
c.Check(cmds, HasLen, 0)
}
-func (s *cmdfinderSuite) TestDump(c *C) {
- cmds, err := advisor.Dump()
+func (s *cmdfinderSuite) TestDumpCommands(c *C) {
+ cmds, err := advisor.DumpCommands()
c.Assert(err, IsNil)
c.Check(cmds, DeepEquals, map[string][]string{
"foo": {"foo"},
diff --git a/advisor/finder.go b/advisor/finder.go
new file mode 100644
index 0000000000..ca3b9982fe
--- /dev/null
+++ b/advisor/finder.go
@@ -0,0 +1,36 @@
+// -*- 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
+
+var newFinder = Open
+
+type Finder interface {
+ FindCommand(command string) ([]Command, error)
+ FindPackage(pkgName string) (*Package, error)
+ Close() error
+}
+
+func ReplaceCommandsFinder(constructor func() (Finder, error)) (restore func()) {
+ old := newFinder
+ newFinder = constructor
+ return func() {
+ newFinder = old
+ }
+}
diff --git a/advisor/pkgfinder.go b/advisor/pkgfinder.go
new file mode 100644
index 0000000000..43dd143203
--- /dev/null
+++ b/advisor/pkgfinder.go
@@ -0,0 +1,35 @@
+// -*- 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
+
+type Package struct {
+ Snap string
+ Summary string
+}
+
+func FindPackage(pkgName string) (*Package, error) {
+ finder, err := newFinder()
+ if err != nil {
+ return nil, err
+ }
+ defer finder.Close()
+
+ return finder.FindPackage(pkgName)
+}