Merge lp:~chipaca/snappy/husk into lp:snappy/15.04

Proposed by John Lenton on 2015-09-22
Status: Superseded
Proposed branch: lp:~chipaca/snappy/husk
Merge into: lp:snappy/15.04
Diff against target: 804 lines (+697/-14)
7 files modified
pkg/husk/example_test.go (+50/-0)
pkg/husk/husk.go (+253/-0)
pkg/husk/husk_test.go (+204/-0)
pkg/husk/split_test.go (+55/-0)
pkg/removed/removed.go (+116/-0)
snappy/systemimage.go (+14/-9)
snappy/systemimage_test.go (+5/-5)
To merge this branch: bzr merge lp:~chipaca/snappy/husk
Reviewer Review Type Date Requested Status
Snappy Developers 2015-09-22 Pending
Review via email: mp+271965@code.launchpad.net

This proposal has been superseded by a proposal from 2015-09-23.

Commit Message

Husks and removed packages.

To post a comment you must log in.
lp:~chipaca/snappy/husk updated on 2015-10-08
711. By Michael Vogt on 2015-09-23

merged lp:snappy

712. By Michael Vogt on 2015-09-23

Fix incorrect untar permissions due to umask settings. by mvo approved by chipaca

713. By John Lenton on 2015-09-23

Make the updates call use the qualified name. by chipaca approved by mvo

714. By Launchpad Translations on behalf of snappy-dev on 2015-09-24

Launchpad automatic translations update.

715. By Leo Arias on 2015-09-25

Added the origin to the expected info output in the integration tests. by elopio approved by fgimenez

716. By John Lenton on 2015-09-25

Speed up VersionCompare. by chipaca approved by mvo

717. By Leo Arias on 2015-09-25

On integration tests, fixed newKernelFilenamePattern. by elopio approved by fgimenez

718. By Carlo Lobrano on 2015-09-25

Description of the changes:

- hw-assign now appends each new udev rule for snap to the existing file, if any, in place of overwriting the same file
- hw-unassign now removes only the single udev rule related to the device unassigned, in place of just deleting the file by c-lobrano approved by chipaca

719. By Leo Arias on 2015-09-28

Skip the ubuntu fan tests in 15.04. by elopio approved by fgimenez

720. By Leo Arias on 2015-09-28

Fixed the configfor updates and rollbacks in the integration tests. by elopio approved by fgimenez

721. By Federico Gimenez on 2015-09-28

functions for building snaps moved to the testutils/build package by fgimenez approved by elopio

722. By Federico Gimenez on 2015-09-28

Added wait.ForFunction to the integration test suite. by fgimenez approved by elopio

723. By Federico Gimenez on 2015-09-28

Added apiExerciser and api<Method>Exerciser interfaces and root resource refactored to use them by fgimenez approved by elopio

724. By Federico Gimenez on 2015-09-28

Added test for /1.0/packages resource by fgimenez approved by elopio

725. By John Lenton on 2015-09-29

Have a “current” symlink in the system data dir ($SNAP_APP_DATA_DIR). by chipaca approved by elopio

726. By John Lenton on 2015-09-29

Move snappy/dirs.go into its own package. by chipaca approved by sergiusens

727. By Ricardo Mendoza on 2015-09-30

Update ubuntu-core description with the right snippet. by ricmm approved by mvo

728. By Leo Arias on 2015-09-30

On the integration tests, print the boot log to stdout. by elopio approved by fgimenez

729. By Michael Vogt on 2015-09-30

Nuke "auto eth0". by mvo approved by chipaca

730. By Leo Arias on 2015-10-01

On the rollback tests, wait for boot-ok to run. Workaround for bug #1498293. by elopio approved by fgimenez

731. By Federico Gimenez on 2015-10-01

Added test for /1.0 resource by fgimenez approved by elopio

732. By Federico Gimenez on 2015-10-01

Config test by fgimenez approved by elopio

733. By Federico Gimenez on 2015-10-02

cli package with ExecCommand functions by fgimenez approved by fgimenez

734. By Federico Gimenez on 2015-10-02

MakeWritable and MakeReadonly moved from common to partition by fgimenez approved by elopio

735. By Launchpad Translations on behalf of snappy-dev on 2015-10-03

Launchpad automatic translations update.

736. By John Lenton on 2015-10-05

activate/deactivate packages. by chipaca approved by mvo

737. By John Lenton on 2015-10-05

Use staging CPI if SNAPPY_USE_STAGING_CPI environment variable is set; use staging system-image if SNAPPY_USE_STAGING_SYSIMG environment variable is set. by chipaca approved by mvo,chipaca

738. By John Lenton on 2015-10-05

use a compiled regexp instead of a string for whitelisting by chipaca approved by mvo

739. By John Lenton on 2015-10-05

Use full names when querying the cpi's .../click-metadata url (i.e., for updates). by chipaca approved by mvo

740. By John Lenton on 2015-10-05

export systemimage's name, origin and vendor

741. By John Lenton on 2015-10-05

moved remote snap (not part (yet (ok?))) into its own package. Also exported snappy.ManifestPath.

742. By John Lenton on 2015-10-05

removed packages

743. By John Lenton on 2015-10-05

husks

744. By John Lenton on 2015-10-07

Merged removed-pkg into husk.

745. By John Lenton on 2015-10-08

husk.Husk -> lightweight.PartBag

746. By John Lenton on 2015-10-08

Merged removed-pkg into husk.

747. By John Lenton on 2015-10-08

fixed for 1.3

748. By John Lenton on 2015-10-08

installed size seems brittle (no tarmac)

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'pkg/husk'
2=== added file 'pkg/husk/example_test.go'
3--- pkg/husk/example_test.go 1970-01-01 00:00:00 +0000
4+++ pkg/husk/example_test.go 2015-09-22 13:56:40 +0000
5@@ -0,0 +1,50 @@
6+// -*- Mode: Go; indent-tabs-mode: t -*-
7+
8+/*
9+ * Copyright (C) 2014-2015 Canonical Ltd
10+ *
11+ * This program is free software: you can redistribute it and/or modify
12+ * it under the terms of the GNU General Public License version 3 as
13+ * published by the Free Software Foundation.
14+ *
15+ * This program is distributed in the hope that it will be useful,
16+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+ * GNU General Public License for more details.
19+ *
20+ * You should have received a copy of the GNU General Public License
21+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
22+ *
23+ */
24+
25+package husk_test
26+
27+import (
28+ "fmt"
29+ "io/ioutil"
30+ "os"
31+ "path/filepath"
32+
33+ "launchpad.net/snappy/pkg/husk"
34+)
35+
36+func ExampleHusk() {
37+ d, _ := ioutil.TempDir("", "test-xyzzy-")
38+ defer os.RemoveAll(d)
39+ os.MkdirAll(filepath.Join(d, "foo.bar", "0.1"), 0755)
40+ os.MkdirAll(filepath.Join(d, "foo.bar", "0.2"), 0755)
41+ os.MkdirAll(filepath.Join(d, "foo.bar", "0.5"), 0755)
42+ os.MkdirAll(filepath.Join(d, "foo", "0.4"), 0755)
43+ os.MkdirAll(filepath.Join(d, "foo.baz", "0.5"), 0755)
44+
45+ finder := husk.Finder{AppDataPath: d, FmkDataPath: d}
46+
47+ for _, found := range finder.ByName("foo") {
48+ fmt.Printf("Found %d versions for %s, type %q: %s\n",
49+ len(found.Versions), found.QualifiedName(), found.Type, found.Versions)
50+ }
51+ // Output:
52+ // Found 3 versions for foo.bar, type "app": [0.5 0.2 0.1]
53+ // Found 1 versions for foo.baz, type "app": [0.5]
54+ // Found 1 versions for foo, type "framework": [0.4]
55+}
56
57=== added file 'pkg/husk/husk.go'
58--- pkg/husk/husk.go 1970-01-01 00:00:00 +0000
59+++ pkg/husk/husk.go 2015-09-22 13:56:40 +0000
60@@ -0,0 +1,253 @@
61+// -*- Mode: Go; indent-tabs-mode: t -*-
62+
63+/*
64+ * Copyright (C) 2014-2015 Canonical Ltd
65+ *
66+ * This program is free software: you can redistribute it and/or modify
67+ * it under the terms of the GNU General Public License version 3 as
68+ * published by the Free Software Foundation.
69+ *
70+ * This program is distributed in the hope that it will be useful,
71+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
72+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73+ * GNU General Public License for more details.
74+ *
75+ * You should have received a copy of the GNU General Public License
76+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
77+ *
78+ */
79+
80+// Package husk provides a quick way of loading things that can become snaps.
81+//
82+// A husk has a name and n versions; it might not even know its origin.
83+package husk
84+
85+import (
86+ "errors"
87+ "fmt"
88+ "os"
89+ "path/filepath"
90+ "sort"
91+ "strings"
92+
93+ "launchpad.net/snappy/helpers"
94+ "launchpad.net/snappy/pkg"
95+ "launchpad.net/snappy/pkg/removed"
96+ "launchpad.net/snappy/snappy"
97+)
98+
99+// A Finder knows how to find parts in the system
100+type Finder struct {
101+ OEMPath string
102+ AppPath string
103+ AppDataPath string
104+ FmkPath string
105+ FmkDataPath string
106+ MetaDir string
107+}
108+
109+// split a path into the name and extension of the directory, and the file.
110+// e.g. foo/bar.baz/quux -> bar, baz, quux
111+//
112+// panics if given path is lacking at least one separator (ie bar/quux
113+// works; quux panics)
114+func split(path string) (name string, ext string, file string) {
115+ idxFileSep := strings.LastIndexByte(path, os.PathSeparator)
116+ if idxFileSep < 0 {
117+ panic("bad path given to split: must have at least two separators")
118+ }
119+
120+ file = path[idxFileSep+1:]
121+ path = path[:idxFileSep]
122+ name = path
123+
124+ idxDirSep := strings.LastIndexByte(path, os.PathSeparator)
125+ if idxDirSep > -1 {
126+ name = path[idxDirSep+1:]
127+ }
128+
129+ idxOrig := strings.LastIndexByte(name, '.')
130+ if idxOrig < 0 {
131+ return name, "", file
132+ }
133+
134+ return name[:idxOrig], name[idxOrig+1:], file
135+}
136+
137+// extract the name, origin and list of versions from a list of paths that
138+// end {name}[.{origin}]/{version}. If the origin changes, stop and
139+// return the versions so far, and the remaining paths.
140+func extract(paths []string) (string, string, []string, []string) {
141+ name, origin, _ := split(paths[0])
142+
143+ var versions []string
144+ for len(paths) > 0 {
145+ n, o, v := split(paths[0])
146+ if name != n || origin != o {
147+ break
148+ }
149+
150+ versions = append(versions, v)
151+ paths = paths[1:]
152+ }
153+
154+ return name, origin, versions, paths
155+}
156+
157+func versionSort(versions []string) {
158+ sort.Sort(sort.Reverse(snappy.ByVersion(versions)))
159+}
160+
161+// ByName finds husks with the given name.
162+func (finder *Finder) ByName(name string) []*Husk {
163+ if strings.ContainsAny(name, ".*?/") {
164+ panic("invalid name " + name)
165+ }
166+
167+ return finder.find(name)
168+}
169+
170+// All the husks in the system.
171+func (finder *Finder) All() []*Husk {
172+ return finder.find("*")
173+}
174+
175+type repo interface {
176+ All() ([]snappy.Part, error)
177+}
178+
179+func newCoreRepoImpl() repo {
180+ return snappy.NewSystemImageRepository()
181+}
182+
183+var newCoreRepo = newCoreRepoImpl
184+
185+func (finder *Finder) find(name string) []*Husk {
186+
187+ var husks []*Husk
188+
189+ if name == snappy.SystemImagePartName || name == "*" {
190+ // TODO: make this do less work
191+ repo := newCoreRepo()
192+ parts, err := repo.All()
193+ if err != nil {
194+ // can't really happen
195+ panic(fmt.Sprintf("Bad SystemImageRepository: %v", err))
196+ }
197+
198+ versions := make([]string, len(parts))
199+ for i, part := range parts {
200+ versions[i] = part.Version()
201+ }
202+ versionSort(versions)
203+
204+ husks = append(husks, &Husk{
205+ Name: snappy.SystemImagePartName,
206+ Origin: snappy.SystemImagePartOrigin,
207+ Type: pkg.TypeCore,
208+ Versions: versions,
209+ Paths: finder,
210+ })
211+ }
212+
213+ type T struct {
214+ base string
215+ full string
216+ typ pkg.Type
217+ }
218+
219+ for _, s := range []T{
220+ {finder.AppDataPath, name + ".*", pkg.TypeApp},
221+ {finder.FmkDataPath, name, pkg.TypeFramework},
222+ {finder.OEMPath, name, pkg.TypeOem},
223+ } {
224+ paths, _ := filepath.Glob(filepath.Join(s.base, s.full, "*"))
225+ for len(paths) > 0 {
226+ var name string
227+ var origin string
228+ var versions []string
229+
230+ name, origin, versions, paths = extract(paths)
231+ if origin != "" && s.typ != pkg.TypeApp {
232+ continue
233+ }
234+ versionSort(versions)
235+ husks = append(husks, &Husk{
236+ Name: name,
237+ Origin: origin,
238+ Type: s.typ,
239+ Versions: versions,
240+ Paths: finder,
241+ })
242+ }
243+ }
244+
245+ return husks
246+}
247+
248+// A Husk is a lightweight object that represents and knows how to
249+// load a Part on demand.
250+type Husk struct {
251+ Name string
252+ Origin string
253+ Type pkg.Type
254+ Versions []string
255+ Paths *Finder
256+}
257+
258+// QualifiedName of the husk.
259+func (h *Husk) QualifiedName() string {
260+ if h.Origin == "" {
261+ return h.Name
262+ }
263+ return h.Name + "." + h.Origin
264+}
265+
266+var (
267+ // ErrBadVersionIndex is returned by Load when asked to load a
268+ // non-existent version.
269+ ErrBadVersionIndex = errors.New("Bad version index")
270+ // ErrVersionGone is returned in the case where we find a
271+ // version and it disappears before we get to load it.
272+ ErrVersionGone = errors.New("Version gone")
273+)
274+
275+// Load a Part from the Husk
276+func (h *Husk) Load(versionIdx int) (snappy.Part, error) {
277+ if versionIdx < 0 || versionIdx >= len(h.Versions) {
278+ return nil, ErrBadVersionIndex
279+ }
280+ version := h.Versions[versionIdx]
281+
282+ var basedir string
283+ switch h.Type {
284+ case pkg.TypeCore:
285+ repo := newCoreRepo()
286+ parts, err := repo.All()
287+ if err != nil {
288+ // can't really happen
289+ return nil, fmt.Errorf("Bad SystemImageRepository: %v", err)
290+ }
291+
292+ for _, part := range parts {
293+ if part.Version() == version {
294+ return part, nil
295+ }
296+ }
297+
298+ return nil, ErrVersionGone
299+ case pkg.TypeApp:
300+ basedir = h.Paths.AppPath
301+ case pkg.TypeFramework:
302+ basedir = h.Paths.FmkPath
303+ case pkg.TypeOem:
304+ basedir = h.Paths.OEMPath
305+ }
306+
307+ yamlPath := filepath.Join(basedir, h.QualifiedName(), version, "meta", "package.yaml")
308+ if !helpers.FileExists(yamlPath) {
309+ return removed.New(basedir, h.Name, h.Origin, version, h.Type), nil
310+ }
311+
312+ return snappy.NewInstalledSnapPart(yamlPath, h.Origin)
313+}
314
315=== added file 'pkg/husk/husk_test.go'
316--- pkg/husk/husk_test.go 1970-01-01 00:00:00 +0000
317+++ pkg/husk/husk_test.go 2015-09-22 13:56:40 +0000
318@@ -0,0 +1,204 @@
319+// -*- Mode: Go; indent-tabs-mode: t -*-
320+
321+/*
322+ * Copyright (C) 2014-2015 Canonical Ltd
323+ *
324+ * This program is free software: you can redistribute it and/or modify
325+ * it under the terms of the GNU General Public License version 3 as
326+ * published by the Free Software Foundation.
327+ *
328+ * This program is distributed in the hope that it will be useful,
329+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
330+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
331+ * GNU General Public License for more details.
332+ *
333+ * You should have received a copy of the GNU General Public License
334+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
335+ *
336+ */
337+
338+package husk
339+
340+import (
341+ "fmt"
342+ "io/ioutil"
343+ "os"
344+ "path/filepath"
345+ "testing"
346+
347+ "gopkg.in/check.v1"
348+
349+ "launchpad.net/snappy/pkg"
350+ "launchpad.net/snappy/pkg/removed"
351+ "launchpad.net/snappy/snappy"
352+)
353+
354+type huskSuite struct {
355+ appd string
356+ datad string
357+ oemd string
358+ metad string
359+ finder *Finder
360+}
361+
362+func Test(t *testing.T) { check.TestingT(t) }
363+
364+var _ = check.Suite(&huskSuite{})
365+
366+func (s *huskSuite) SetUpTest(c *check.C) {
367+ s.appd = c.MkDir()
368+ s.datad = c.MkDir()
369+ s.oemd = c.MkDir()
370+ s.metad = c.MkDir()
371+
372+ s.finder = &Finder{
373+ OEMPath: s.oemd,
374+ AppPath: s.appd,
375+ AppDataPath: s.datad,
376+ FmkPath: s.appd,
377+ FmkDataPath: s.datad,
378+ MetaDir: s.metad,
379+ }
380+
381+ s.MkInstalled(c, s.appd, "foo", "bar", "1.0")
382+ s.MkRemoved(c, "foo.bar", "0.9")
383+ s.MkRemoved(c, "foo.baz", "0.8")
384+
385+ s.MkInstalled(c, s.appd, "fmk", "", "123")
386+ s.MkRemoved(c, "fmk", "120")
387+ s.MkRemoved(c, "fmk", "12a1")
388+
389+ s.MkInstalled(c, s.oemd, "oem", "", "3")
390+
391+ newCoreRepo = func() repo {
392+ // you can't ever have a removed systemimagepart, but for testing it'll do
393+ return mockrepo{removed.New(c.MkDir(), snappy.SystemImagePartName, snappy.SystemImagePartOrigin, "1", pkg.TypeCore)}
394+ }
395+}
396+
397+func (s *huskSuite) TearDownTest(c *check.C) {
398+ newCoreRepo = newCoreRepoImpl
399+}
400+
401+func (s *huskSuite) MkInstalled(c *check.C, appdir, name, origin, version string) {
402+ // this is logic that should be encapsulated inside the different package types, but isn't (yet).
403+ qn := name
404+ if origin != "" {
405+ qn += "." + origin
406+ }
407+
408+ if appdir != s.oemd {
409+ s.MkRemoved(c, qn, version)
410+ }
411+ // end logic (mostly)
412+
413+ apath := filepath.Join(appdir, qn, version, "meta")
414+ yaml := fmt.Sprintf("name: %s\nversion: %s\nvendor: example.com\n", name, version)
415+ c.Check(os.MkdirAll(apath, 0755), check.IsNil)
416+ c.Check(ioutil.WriteFile(filepath.Join(apath, "package.yaml"), []byte(yaml), 0644), check.IsNil)
417+ c.Check(ioutil.WriteFile(filepath.Join(apath, "hashes.yaml"), nil, 0644), check.IsNil)
418+}
419+
420+func (s *huskSuite) MkRemoved(c *check.C, qn, version string) {
421+ dpath := filepath.Join(s.datad, qn, version)
422+ c.Check(os.MkdirAll(dpath, 0755), check.IsNil)
423+ c.Check(ioutil.WriteFile(filepath.Join(dpath, "test.txt"), []byte("hello there\n"), 0644), check.IsNil)
424+
425+}
426+
427+func (s *huskSuite) TestLoadBadName(c *check.C) {
428+ c.Check(func() { s.finder.ByName("*") }, check.PanicMatches, "invalid name .*")
429+}
430+
431+func (s *huskSuite) TestLoadFmk(c *check.C) {
432+ fmk := s.finder.ByName("fmk")
433+ // two versions of the same framework are present, so one Husk, with three versions:
434+ c.Assert(fmk, check.HasLen, 1)
435+ h := fmk[0]
436+ c.Assert(h.Versions, check.HasLen, 3)
437+ // versions are sorted backwards by version -- index 0 is always newest version
438+ c.Check(h.Versions, check.DeepEquals, []string{"123", "120", "12a1"})
439+ // other things are as expected
440+ c.Check(h.Name, check.Equals, "fmk")
441+ c.Check(h.Type, check.Equals, pkg.TypeFramework)
442+
443+ p, err := h.Load(0)
444+ c.Check(err, check.IsNil)
445+ // load loaded the right implementation of Part
446+ c.Check(p, check.FitsTypeOf, new(snappy.SnapPart))
447+ c.Check(p.Version(), check.Equals, "123")
448+
449+ p, err = h.Load(1)
450+ c.Check(err, check.IsNil)
451+ c.Check(p, check.FitsTypeOf, new(removed.Removed))
452+ c.Check(p.Version(), check.Equals, "120")
453+
454+ _, err = h.Load(42)
455+ c.Check(err, check.Equals, ErrBadVersionIndex)
456+
457+}
458+
459+func (s *huskSuite) TestLoadApp(c *check.C) {
460+ foo := s.finder.ByName("foo")
461+ // there are two husks: one for foo.bar, one for foo.baz:
462+ c.Assert(foo, check.HasLen, 2)
463+
464+ h0, h1 := foo[0], foo[1]
465+
466+ c.Check(h0.QualifiedName(), check.Equals, "foo.bar")
467+ c.Check(h0.Versions, check.DeepEquals, []string{"1.0", "0.9"})
468+ c.Check(h0.Type, check.Equals, pkg.TypeApp)
469+
470+ c.Check(h1.QualifiedName(), check.Equals, "foo.baz")
471+ c.Check(h1.Versions, check.DeepEquals, []string{"0.8"})
472+ c.Check(h1.Type, check.Equals, pkg.TypeApp)
473+
474+ p, err := h0.Load(0)
475+ c.Check(err, check.IsNil)
476+ c.Check(p, check.FitsTypeOf, new(snappy.SnapPart))
477+ c.Check(p.Version(), check.Equals, "1.0")
478+
479+ p, err = h0.Load(1)
480+ c.Check(err, check.IsNil)
481+ c.Check(p, check.FitsTypeOf, new(removed.Removed))
482+ c.Check(p.Version(), check.Equals, "0.9")
483+
484+ p, err = h1.Load(0)
485+ c.Check(err, check.IsNil)
486+ c.Check(p, check.FitsTypeOf, new(removed.Removed))
487+ c.Check(p.Version(), check.Equals, "0.8")
488+}
489+
490+func (s *huskSuite) TestLoadOem(c *check.C) {
491+ oem := s.finder.ByName("oem")
492+ c.Check(oem, check.HasLen, 1)
493+ c.Check(oem[0].Versions, check.DeepEquals, []string{"3"})
494+ c.Check(oem[0].Type, check.Equals, pkg.TypeOem)
495+
496+ p, err := oem[0].Load(0)
497+ c.Check(err, check.IsNil)
498+ c.Check(p, check.FitsTypeOf, new(snappy.SnapPart))
499+ c.Check(p.Version(), check.Equals, "3")
500+}
501+
502+type mockrepo struct{ p snappy.Part }
503+
504+func (r mockrepo) All() ([]snappy.Part, error) {
505+ return []snappy.Part{r.p}, nil
506+}
507+
508+func (s *huskSuite) TestLoadCore(c *check.C) {
509+ core := s.finder.ByName(snappy.SystemImagePartName)
510+ c.Check(core, check.HasLen, 1)
511+ c.Check(core[0].Versions, check.DeepEquals, []string{"1"})
512+
513+ p, err := core[0].Load(0)
514+ c.Check(err, check.IsNil)
515+ c.Check(p.Version(), check.Equals, "1")
516+}
517+
518+func (s *huskSuite) TestAll(c *check.C) {
519+ all := s.finder.All()
520+
521+ c.Check(all, check.HasLen, 5) // 1 fmk, 2 app, 1 oem, 1 core
522+}
523
524=== added file 'pkg/husk/split_test.go'
525--- pkg/husk/split_test.go 1970-01-01 00:00:00 +0000
526+++ pkg/husk/split_test.go 2015-09-22 13:56:40 +0000
527@@ -0,0 +1,55 @@
528+// -*- Mode: Go; indent-tabs-mode: t -*-
529+
530+/*
531+ * Copyright (C) 2014-2015 Canonical Ltd
532+ *
533+ * This program is free software: you can redistribute it and/or modify
534+ * it under the terms of the GNU General Public License version 3 as
535+ * published by the Free Software Foundation.
536+ *
537+ * This program is distributed in the hope that it will be useful,
538+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
539+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
540+ * GNU General Public License for more details.
541+ *
542+ * You should have received a copy of the GNU General Public License
543+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
544+ *
545+ */
546+
547+package husk
548+
549+import (
550+ "gopkg.in/check.v1"
551+)
552+
553+type splitSuite struct{}
554+
555+var _ = check.Suite(&splitSuite{})
556+
557+func (s *splitSuite) TestSplitRegular(c *check.C) {
558+ for _, s := range []string{"meh/foo.bar/baz", "foo.bar/baz"} {
559+ n, e, f := split(s)
560+ c.Check(n, check.Equals, "foo")
561+ c.Check(e, check.Equals, "bar")
562+ c.Check(f, check.Equals, "baz")
563+ }
564+}
565+
566+func (s *splitSuite) TestSplitExtless(c *check.C) {
567+ for _, s := range []string{"meh/foo/baz", "foo/baz"} {
568+ n, e, f := split(s)
569+ c.Check(n, check.Equals, "foo")
570+ c.Check(e, check.Equals, "")
571+ c.Check(f, check.Equals, "baz")
572+ }
573+}
574+
575+func (s *splitSuite) TestExtract(c *check.C) {
576+ ps := []string{"meh/foo.bar/v1", "meh/foo.bar/v2", "meh/foo.baz/v3"}
577+ n, o, vs, ps := extract(ps)
578+ c.Check(n, check.Equals, "foo")
579+ c.Check(o, check.Equals, "bar")
580+ c.Check(vs, check.DeepEquals, []string{"v1", "v2"})
581+ c.Check(ps, check.DeepEquals, []string{"meh/foo.baz/v3"})
582+}
583
584=== added directory 'pkg/removed'
585=== added file 'pkg/removed/removed.go'
586--- pkg/removed/removed.go 1970-01-01 00:00:00 +0000
587+++ pkg/removed/removed.go 2015-09-22 13:56:40 +0000
588@@ -0,0 +1,116 @@
589+// -*- Mode: Go; indent-tabs-mode: t -*-
590+
591+/*
592+ * Copyright (C) 2014-2015 Canonical Ltd
593+ *
594+ * This program is free software: you can redistribute it and/or modify
595+ * it under the terms of the GNU General Public License version 3 as
596+ * published by the Free Software Foundation.
597+ *
598+ * This program is distributed in the hope that it will be useful,
599+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
600+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
601+ * GNU General Public License for more details.
602+ *
603+ * You should have received a copy of the GNU General Public License
604+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
605+ *
606+ */
607+
608+// Package removed implements Removed packages, that are packages that
609+// have been installed, removed, but not purged: there is no
610+// application, but there might be data.
611+package removed
612+
613+import (
614+ "errors"
615+ "time"
616+
617+ "launchpad.net/snappy/pkg"
618+ "launchpad.net/snappy/progress"
619+ "launchpad.net/snappy/snappy"
620+)
621+
622+// ErrRemoved is returned when you ask to operate on a removed package.
623+var ErrRemoved = errors.New("package is removed")
624+
625+// Removed represents a removed package.
626+type Removed struct {
627+ basedir string
628+ name string
629+ origin string
630+ version string
631+ pkgType pkg.Type
632+}
633+
634+// New removed package.
635+func New(basedir, name, origin, version string, pkgType pkg.Type) snappy.Part {
636+ return &Removed{
637+ basedir: basedir,
638+ name: name,
639+ origin: origin,
640+ version: version,
641+ pkgType: pkgType,
642+ }
643+}
644+
645+// Name from the snappy.Part interface
646+func (r *Removed) Name() string { return r.name }
647+
648+// Version from the snappy.Part interface
649+func (r *Removed) Version() string { return r.version }
650+
651+// Description from the snappy.Part interface
652+func (r *Removed) Description() string { return "" }
653+
654+// Origin from the snappy.Part interface
655+func (r *Removed) Origin() string { return r.origin }
656+
657+// Vendor from the snappy.Part interface
658+func (r *Removed) Vendor() string { return "" }
659+
660+// Hash from the snappy.Part interface
661+func (r *Removed) Hash() string { return "" }
662+
663+// IsActive from the snappy.Part interface
664+func (r *Removed) IsActive() bool { return false }
665+
666+// IsInstalled from the snappy.Part interface
667+func (r *Removed) IsInstalled() bool { return false }
668+
669+// NeedsReboot from the snappy.Part interface
670+func (r *Removed) NeedsReboot() bool { return false }
671+
672+// Date from the snappy.Part interface
673+func (r *Removed) Date() time.Time { return time.Time{} } // XXX: keep track of when the package was removed
674+// Channel from the snappy.Part interface
675+func (r *Removed) Channel() string { return "" }
676+
677+// Icon from the snappy.Part interface
678+func (r *Removed) Icon() string { return "" }
679+
680+// Type from the snappy.Part interface
681+func (r *Removed) Type() pkg.Type { return r.pkgType }
682+
683+// InstalledSize from the snappy.Part interface
684+func (r *Removed) InstalledSize() int64 { return -1 }
685+
686+// DownloadSize from the snappy.Part interface
687+func (r *Removed) DownloadSize() int64 { return -1 }
688+
689+// Install from the snappy.Part interface
690+func (r *Removed) Install(pb progress.Meter, flags snappy.InstallFlags) (name string, err error) {
691+ return "", ErrRemoved
692+}
693+
694+// Uninstall from the snappy.Part interface
695+func (r *Removed) Uninstall(pb progress.Meter) error { return ErrRemoved }
696+
697+// Config from the snappy.Part interface
698+func (r *Removed) Config(configuration []byte) (newConfig string, err error) { return "", ErrRemoved }
699+
700+// SetActive from the snappy.Part interface
701+func (r *Removed) SetActive(pb progress.Meter) error { return ErrRemoved }
702+
703+// Frameworks from the snappy.Part interface
704+func (r *Removed) Frameworks() ([]string, error) { return nil, ErrRemoved }
705
706=== modified file 'snappy/systemimage.go'
707--- snappy/systemimage.go 2015-09-15 12:55:09 +0000
708+++ snappy/systemimage.go 2015-09-22 13:56:40 +0000
709@@ -39,11 +39,16 @@
710 "launchpad.net/snappy/provisioning"
711 )
712
713+// SystemImagePart have constant name, origin, and vendor.
714 const (
715- systemImagePartName = "ubuntu-core"
716- systemImagePartOrigin = "ubuntu"
717- systemImagePartVendor = "Canonical Ltd."
718+ SystemImagePartName = "ubuntu-core"
719+ // SystemImagePartOrigin is the origin of any system image part
720+ SystemImagePartOrigin = "ubuntu"
721+ // SystemImagePartVendor is the vendor of any system image part
722+ SystemImagePartVendor = "Canonical Ltd."
723+)
724
725+const (
726 // location of the channel config on the filesystem.
727 //
728 // This file specifies the s-i version installed on the rootfs
729@@ -97,17 +102,17 @@
730
731 // Name returns the name
732 func (s *SystemImagePart) Name() string {
733- return systemImagePartName
734+ return SystemImagePartName
735 }
736
737 // Origin returns the origin ("ubuntu")
738 func (s *SystemImagePart) Origin() string {
739- return systemImagePartOrigin
740+ return SystemImagePartOrigin
741 }
742
743 // Vendor returns the vendor ("Canonical Ltd.")
744 func (s *SystemImagePart) Vendor() string {
745- return systemImagePartVendor
746+ return SystemImagePartVendor
747 }
748
749 // Version returns the version
750@@ -236,7 +241,7 @@
751 if err = s.partition.ToggleNextBoot(); err != nil {
752 return "", err
753 }
754- return systemImagePartName, nil
755+ return SystemImagePartName, nil
756 }
757
758 // Ensure the expected version update was applied to the expected partition.
759@@ -428,7 +433,7 @@
760
761 // Search searches the SystemImageRepository for the given terms
762 func (s *SystemImageRepository) Search(terms string) (versions []Part, err error) {
763- if strings.Contains(terms, systemImagePartName) {
764+ if strings.Contains(terms, SystemImagePartName) {
765 part := makeCurrentPart(s.partition)
766 versions = append(versions, part)
767 }
768@@ -437,7 +442,7 @@
769
770 // Details returns details for the given snap
771 func (s *SystemImageRepository) Details(name string, origin string) ([]Part, error) {
772- if name == systemImagePartName && origin == systemImagePartOrigin {
773+ if name == SystemImagePartName && origin == SystemImagePartOrigin {
774 return []Part{makeCurrentPart(s.partition)}, nil
775 }
776
777
778=== modified file 'snappy/systemimage_test.go'
779--- snappy/systemimage_test.go 2015-07-15 07:53:43 +0000
780+++ snappy/systemimage_test.go 2015-09-22 13:56:40 +0000
781@@ -115,9 +115,9 @@
782 c.Assert(err, IsNil)
783 // we have one active and one inactive
784 c.Assert(parts, HasLen, 2)
785- c.Assert(parts[0].Name(), Equals, systemImagePartName)
786- c.Assert(parts[0].Origin(), Equals, systemImagePartOrigin)
787- c.Assert(parts[0].Vendor(), Equals, systemImagePartVendor)
788+ c.Assert(parts[0].Name(), Equals, SystemImagePartName)
789+ c.Assert(parts[0].Origin(), Equals, SystemImagePartOrigin)
790+ c.Assert(parts[0].Vendor(), Equals, SystemImagePartVendor)
791 c.Assert(parts[0].Version(), Equals, "1")
792 c.Assert(parts[0].Hash(), Equals, "e09c13f68fccef3b2fe0f5c8ff5c61acf2173b170b1f2a3646487147690b0970ef6f2c555d7bcb072035f29ee4ea66a6df7f6bb320d358d3a7d78a0c37a8a549")
793 c.Assert(parts[0].IsActive(), Equals, true)
794@@ -378,8 +378,8 @@
795 parts, err := s.systemImage.Installed()
796 c.Assert(err, IsNil)
797 c.Assert(parts, HasLen, 2)
798- c.Assert(parts[0].Origin(), Equals, systemImagePartOrigin)
799- c.Assert(parts[1].Origin(), Equals, systemImagePartOrigin)
800+ c.Assert(parts[0].Origin(), Equals, SystemImagePartOrigin)
801+ c.Assert(parts[1].Origin(), Equals, SystemImagePartOrigin)
802 }
803
804 func (s *SITestSuite) TestCannotUpdateIfSideLoaded(c *C) {

Subscribers

People subscribed via source and target branches

to all changes: