Merge lp:~mvo/snappy/snappy-snapfs-install-via-unpack into lp:~snappy-dev/snappy/snappy-moved-to-github

Proposed by Michael Vogt
Status: Merged
Approved by: John Lenton
Approved revision: 751
Merged at revision: 753
Proposed branch: lp:~mvo/snappy/snappy-snapfs-install-via-unpack
Merge into: lp:~snappy-dev/snappy/snappy-moved-to-github
Prerequisite: lp:~mvo/snappy/snappy-snapfs-tests
Diff against target: 288 lines (+191/-10)
6 files modified
pkg/clickdeb/deb.go (+5/-0)
pkg/snapfs/pkg.go (+26/-0)
snappy/common_test.go (+4/-1)
snappy/pkgformat.go (+64/-0)
snappy/snapp.go (+8/-9)
snappy/snapp_snapfs_test.go (+84/-0)
To merge this branch: bzr merge lp:~mvo/snappy/snappy-snapfs-install-via-unpack
Reviewer Review Type Date Requested Status
John Lenton (community) Approve
Review via email: mp+273810@code.launchpad.net

Commit message

Add install support (via unpack) to new style snaps

Description of the change

This branch adds support for install of new style snaps via unpack.

To post a comment you must log in.
Revision history for this message
John Lenton (chipaca) wrote :

lgtm, beyond conflicts and nits below

750. By Michael Vogt

merged lp:snappy and resolved conflicts

751. By Michael Vogt

address execllent review comments

Revision history for this message
Michael Vogt (mvo) wrote :

Thanks, your review is invaluable!

Revision history for this message
Michael Vogt (mvo) wrote :

I addressed the comments.

Revision history for this message
John Lenton (chipaca) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'pkg/clickdeb/deb.go'
--- pkg/clickdeb/deb.go 2015-09-16 11:02:59 +0000
+++ pkg/clickdeb/deb.go 2015-10-08 17:42:26 +0000
@@ -155,6 +155,11 @@
155 return d.file.Close()155 return d.file.Close()
156}156}
157157
158// Verify checks that the clickdeb is signed
159func (d *ClickDeb) Verify(allowUnauthenticated bool) error {
160 return Verify(d.Name(), allowUnauthenticated)
161}
162
158// ControlMember returns the content of the given control member file163// ControlMember returns the content of the given control member file
159// (e.g. the content of the "manifest" file in the control.tar.gz ar member)164// (e.g. the content of the "manifest" file in the control.tar.gz ar member)
160func (d *ClickDeb) ControlMember(controlMember string) (content []byte, err error) {165func (d *ClickDeb) ControlMember(controlMember string) (content []byte, err error) {
161166
=== modified file 'pkg/snapfs/pkg.go'
--- pkg/snapfs/pkg.go 2015-10-08 07:44:05 +0000
+++ pkg/snapfs/pkg.go 2015-10-08 17:42:26 +0000
@@ -45,6 +45,32 @@
45 return &Snap{path: path}45 return &Snap{path: path}
46}46}
4747
48// Close is not doing anything for snapfs - COMPAT
49func (s *Snap) Close() error {
50 return nil
51}
52
53// ControlMember extracts from meta/ - COMPAT
54func (s *Snap) ControlMember(controlMember string) ([]byte, error) {
55 return s.ReadFile(filepath.Join("DEBIAN", controlMember))
56}
57
58// MetaMember extracts from meta/ - COMPAT
59func (s *Snap) MetaMember(metaMember string) ([]byte, error) {
60 return s.ReadFile(filepath.Join("meta", metaMember))
61}
62
63// ExtractHashes does notthing for snapfs snaps - COMAPT
64func (s *Snap) ExtractHashes(dir string) error {
65 return nil
66}
67
68// UnpackWithDropPrivs unpacks the meta and puts stuff in place - COMAPT
69func (s *Snap) UnpackWithDropPrivs(instDir, rootdir string) error {
70 // FIXME: actually drop privs
71 return s.Unpack("*", instDir)
72}
73
48// UnpackMeta unpacks just the meta/* directory of the given snap74// UnpackMeta unpacks just the meta/* directory of the given snap
49func (s *Snap) UnpackMeta(dst string) error {75func (s *Snap) UnpackMeta(dst string) error {
50 if err := s.Unpack("meta/*", dst); err != nil {76 if err := s.Unpack("meta/*", dst); err != nil {
5177
=== modified file 'snappy/common_test.go'
--- snappy/common_test.go 2015-10-08 06:25:35 +0000
+++ snappy/common_test.go 2015-10-08 17:42:26 +0000
@@ -39,6 +39,9 @@
39 helloAppComposedName = "hello-app.testspacethename"39 helloAppComposedName = "hello-app.testspacethename"
40)40)
4141
42// here to make it easy to switch in tests to "BuildSnapfsSnap"
43var snapBuilderFunc = BuildLegacySnap
44
42// makeInstalledMockSnap creates a installed mock snap without any45// makeInstalledMockSnap creates a installed mock snap without any
43// content other than the meta data46// content other than the meta data
44func makeInstalledMockSnap(tempdir, packageYamlContent string) (yamlFile string, err error) {47func makeInstalledMockSnap(tempdir, packageYamlContent string) (yamlFile string, err error) {
@@ -142,7 +145,7 @@
142 // build it145 // build it
143 err := helpers.ChDir(tmpdir, func() error {146 err := helpers.ChDir(tmpdir, func() error {
144 var err error147 var err error
145 snapFile, err = BuildLegacySnap(tmpdir, "")148 snapFile, err = snapBuilderFunc(tmpdir, "")
146 c.Assert(err, IsNil)149 c.Assert(err, IsNil)
147 return err150 return err
148 })151 })
149152
=== added file 'snappy/pkgformat.go'
--- snappy/pkgformat.go 1970-01-01 00:00:00 +0000
+++ snappy/pkgformat.go 2015-10-08 17:42:26 +0000
@@ -0,0 +1,64 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2014-2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package snappy
21
22import (
23 "bytes"
24 "fmt"
25 "os"
26 "strings"
27
28 "launchpad.net/snappy/pkg/clickdeb"
29 "launchpad.net/snappy/pkg/snapfs"
30)
31
32// PackageFile is the interface to interact with the low-level snap files
33type PackageFile interface {
34 Verify(allowUnauthenticated bool) error
35 Close() error
36 UnpackWithDropPrivs(targetDir, rootDir string) error
37 ControlMember(name string) ([]byte, error)
38 MetaMember(name string) ([]byte, error)
39 ExtractHashes(targetDir string) error
40}
41
42// OpenPackageFile opens a given snap file with the right backend
43func OpenPackageFile(path string) (PackageFile, error) {
44 f, err := os.Open(path)
45 if err != nil {
46 return nil, err
47 }
48 defer f.Close()
49
50 // look, libmagic!
51 header := make([]byte, 20)
52 if _, err := f.Read(header); err != nil {
53 return nil, err
54 }
55 // note that we only support little endian squashfs for now
56 if bytes.HasPrefix(header, []byte{'h', 's', 'q', 's'}) {
57 return snapfs.New(path), nil
58 }
59 if strings.HasPrefix(string(header), "!<arch>\ndebian") {
60 return clickdeb.Open(path)
61 }
62
63 return nil, fmt.Errorf("unknown header %v", header)
64}
065
=== modified file 'snappy/snapp.go'
--- snappy/snapp.go 2015-10-08 12:20:09 +0000
+++ snappy/snapp.go 2015-10-08 17:42:26 +0000
@@ -43,7 +43,6 @@
43 "launchpad.net/snappy/logger"43 "launchpad.net/snappy/logger"
44 "launchpad.net/snappy/oauth"44 "launchpad.net/snappy/oauth"
45 "launchpad.net/snappy/pkg"45 "launchpad.net/snappy/pkg"
46 "launchpad.net/snappy/pkg/clickdeb"
47 "launchpad.net/snappy/pkg/remote"46 "launchpad.net/snappy/pkg/remote"
48 "launchpad.net/snappy/policy"47 "launchpad.net/snappy/policy"
49 "launchpad.net/snappy/progress"48 "launchpad.net/snappy/progress"
@@ -182,7 +181,7 @@
182 isActive bool181 isActive bool
183 isInstalled bool182 isInstalled bool
184 description string183 description string
185 deb *clickdeb.ClickDeb184 deb PackageFile
186 basedir string185 basedir string
187}186}
188187
@@ -433,7 +432,7 @@
433// package, as deduced from the license agreement (which might involve asking432// package, as deduced from the license agreement (which might involve asking
434// the user), or an error that explains the reason why installation should not433// the user), or an error that explains the reason why installation should not
435// proceed.434// proceed.
436func (m *packageYaml) checkLicenseAgreement(ag agreer, d *clickdeb.ClickDeb, currentActiveDir string) error {435func (m *packageYaml) checkLicenseAgreement(ag agreer, d PackageFile, currentActiveDir string) error {
437 if !m.ExplicitLicenseAgreement {436 if !m.ExplicitLicenseAgreement {
438 return nil437 return nil
439 }438 }
@@ -541,18 +540,18 @@
541}540}
542541
543// NewSnapPartFromSnapFile loads a snap from the given (clickdeb) snap file.542// NewSnapPartFromSnapFile loads a snap from the given (clickdeb) snap file.
544// Caller should call Close on the clickdeb.543// Caller should call Close on the pkg.
545// TODO: expose that Close.544// TODO: expose that Close.
546func NewSnapPartFromSnapFile(snapFile string, origin string, unauthOk bool) (*SnapPart, error) {545func NewSnapPartFromSnapFile(snapFile string, origin string, unauthOk bool) (*SnapPart, error) {
547 if err := clickdeb.Verify(snapFile, unauthOk); err != nil {546 d, err := OpenPackageFile(snapFile)
548 return nil, err
549 }
550
551 d, err := clickdeb.Open(snapFile)
552 if err != nil {547 if err != nil {
553 return nil, err548 return nil, err
554 }549 }
555550
551 if err := d.Verify(unauthOk); err != nil {
552 return nil, err
553 }
554
556 yamlData, err := d.MetaMember("package.yaml")555 yamlData, err := d.MetaMember("package.yaml")
557 if err != nil {556 if err != nil {
558 return nil, err557 return nil, err
559558
=== added file 'snappy/snapp_snapfs_test.go'
--- snappy/snapp_snapfs_test.go 1970-01-01 00:00:00 +0000
+++ snappy/snapp_snapfs_test.go 2015-10-08 17:42:26 +0000
@@ -0,0 +1,84 @@
1// -*- Mode: Go; indent-tabs-mode: t -*-
2
3/*
4 * Copyright (C) 2014-2015 Canonical Ltd
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 3 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20package snappy
21
22import (
23 "path/filepath"
24
25 "launchpad.net/snappy/dirs"
26 "launchpad.net/snappy/helpers"
27 "launchpad.net/snappy/pkg/snapfs"
28
29 . "gopkg.in/check.v1"
30)
31
32type SnapfsTestSuite struct {
33}
34
35func (s *SnapfsTestSuite) SetUpTest(c *C) {
36 // mocks
37 aaClickHookCmd = "/bin/true"
38 dirs.SetRootDir(c.MkDir())
39
40 // ensure we use the right builder func (snapfs)
41 snapBuilderFunc = BuildSnapfsSnap
42}
43
44func (s *SnapfsTestSuite) TearDownTest(c *C) {
45 snapBuilderFunc = BuildLegacySnap
46}
47
48var _ = Suite(&SnapfsTestSuite{})
49
50const packageHello = `name: hello-app
51version: 1.10
52vendor: Somebody
53icon: meta/hello.svg
54`
55
56func (s *SnapfsTestSuite) TestMakeSnapMakesSnapfs(c *C) {
57 snapPkg := makeTestSnapPackage(c, packageHello)
58 part, err := NewSnapPartFromSnapFile(snapPkg, "origin", true)
59 c.Assert(err, IsNil)
60
61 // ensure the right backend got picked up
62 c.Assert(part.deb, FitsTypeOf, &snapfs.Snap{})
63}
64
65func (s *SnapfsTestSuite) TestInstallViaSnapfsWorks(c *C) {
66 snapPkg := makeTestSnapPackage(c, packageHello)
67 part, err := NewSnapPartFromSnapFile(snapPkg, "origin", true)
68 c.Assert(err, IsNil)
69
70 _, err = part.Install(&MockProgressMeter{}, 0)
71 c.Assert(err, IsNil)
72
73 // after install its just on disk for now, note that this will
74 // change once the mounting gets added
75 base := filepath.Join(dirs.SnapAppsDir, "hello-app.origin", "1.10")
76 for _, needle := range []string{
77 "bin/foo",
78 "meta/package.yaml",
79 ".click/info/hello-app.origin.manifest",
80 } {
81 println(needle)
82 c.Assert(helpers.FileExists(filepath.Join(base, needle)), Equals, true)
83 }
84}

Subscribers

People subscribed via source and target branches