Merge lp:~sergiusens/snappy/originsOrNamespaceWhatever into lp:~snappy-dev/snappy/15.04-deprecated

Proposed by Sergio Schvezov
Status: Merged
Approved by: Ricardo Salveti
Approved revision: 454
Merged at revision: 457
Proposed branch: lp:~sergiusens/snappy/originsOrNamespaceWhatever
Merge into: lp:~snappy-dev/snappy/15.04-deprecated
Diff against target: 278 lines (+127/-4)
5 files modified
snappy/dirs.go (+4/-0)
snappy/errors.go (+12/-0)
snappy/parts.go (+30/-0)
snappy/snapp.go (+44/-4)
snappy/snapp_test.go (+37/-0)
To merge this branch: bzr merge lp:~sergiusens/snappy/originsOrNamespaceWhatever
Reviewer Review Type Date Requested Status
Ricardo Salveti (community) Approve
Review via email: mp+263960@code.launchpad.net

Commit message

Save store manifest on install and use that information to present the namespace/origin.

Description of the change

This wasn't a straightforward backport.

To post a comment you must log in.
454. By Sergio Schvezov

Read the type from the store

Revision history for this message
Ricardo Salveti (rsalveti) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'snappy/dirs.go'
2--- snappy/dirs.go 2015-04-20 16:51:29 +0000
3+++ snappy/dirs.go 2015-07-06 19:42:05 +0000
4@@ -30,6 +30,7 @@
5 snapAppArmorDir string
6 snapSeccompDir string
7 snapUdevRulesDir string
8+ snapMetaDir string
9
10 snapBinariesDir string
11 snapServicesDir string
12@@ -39,6 +40,8 @@
13 cloudMetaDataFile string
14 )
15
16+var snappyDir = filepath.Join("var", "lib", "snappy")
17+
18 // SetRootDir allows settings a new global root directory, this is useful
19 // for e.g. chroot operations
20 func SetRootDir(rootdir string) {
21@@ -50,6 +53,7 @@
22 snapDataHomeGlob = filepath.Join(rootdir, "/home/*/apps/")
23 snapAppArmorDir = filepath.Join(rootdir, "/var/lib/apparmor/clicks")
24 snapSeccompDir = filepath.Join(rootdir, "/var/lib/snappy/seccomp/profiles")
25+ snapMetaDir = filepath.Join(rootdir, snappyDir, "meta")
26
27 snapBinariesDir = filepath.Join(snapAppsDir, "bin")
28 snapServicesDir = filepath.Join(rootdir, "/etc/systemd/system")
29
30=== modified file 'snappy/errors.go'
31--- snappy/errors.go 2015-06-04 15:00:44 +0000
32+++ snappy/errors.go 2015-07-06 19:42:05 +0000
33@@ -269,3 +269,15 @@
34 func (e ErrApparmorGenerate) Error() string {
35 return fmt.Sprintf("apparmor generate fails with %v: '%v'", e.exitCode, string(e.output))
36 }
37+
38+// ErrInvalidYaml is returned if a yaml file can not be parsed
39+type ErrInvalidYaml struct {
40+ file string
41+ err error
42+ yaml []byte
43+}
44+
45+func (e *ErrInvalidYaml) Error() string {
46+ // %#v of string(yaml) so the yaml is presented as a human-readable string, but in a single greppable line
47+ return fmt.Sprintf("can not parse %s: %v (from: %#v)", e.file, e.err, string(e.yaml))
48+}
49
50=== modified file 'snappy/parts.go'
51--- snappy/parts.go 2015-04-30 16:56:15 +0000
52+++ snappy/parts.go 2015-07-06 19:42:05 +0000
53@@ -18,9 +18,11 @@
54 package snappy
55
56 import (
57+ "encoding/json"
58 "fmt"
59 "net"
60 "net/url"
61+ "path/filepath"
62 "strings"
63 "time"
64
65@@ -30,6 +32,29 @@
66 // SnapType represents the kind of snap (app, core, frameworks, oem)
67 type SnapType string
68
69+// MarshalJSON returns *m as the JSON encoding of m.
70+func (m SnapType) MarshalJSON() ([]byte, error) {
71+ return json.Marshal(string(m))
72+}
73+
74+// UnmarshalJSON sets *m to a copy of data.
75+func (m *SnapType) UnmarshalJSON(data []byte) error {
76+ var str string
77+ if err := json.Unmarshal(data, &str); err != nil {
78+ return err
79+ }
80+
81+ // this is a workaround as the store sends "application" but snappy uses
82+ // "app" for TypeApp
83+ if str == "application" {
84+ *m = SnapTypeApp
85+ } else {
86+ *m = SnapType(str)
87+ }
88+
89+ return nil
90+}
91+
92 // SystemConfig is a config map holding configs for multiple packages
93 type SystemConfig map[string]interface{}
94
95@@ -339,3 +364,8 @@
96 func PackageNameActive(name string) bool {
97 return ActiveSnapByName(name) != nil
98 }
99+
100+// manifestPath returns the would be path for the store manifest meta data
101+func manifestPath(s Part) string {
102+ return filepath.Join(snapMetaDir, fmt.Sprintf("%s_%s.manifest", Dirname(s), s.Version()))
103+}
104
105=== modified file 'snappy/snapp.go'
106--- snappy/snapp.go 2015-07-06 15:35:48 +0000
107+++ snappy/snapp.go 2015-07-06 19:42:05 +0000
108@@ -163,6 +163,7 @@
109 // SnapPart represents a generic snap type
110 type SnapPart struct {
111 m *packageYaml
112+ remoteM *remoteSnap
113 namespace string
114 hash string
115 isActive bool
116@@ -214,13 +215,13 @@
117 IconURL string `json:"icon_url"`
118 LastUpdated string `json:"last_updated,omitempty"`
119 Name string `json:"package_name"`
120- Namespace string `json:"origin"`
121+ Namespace string `json:"origin" yaml:"origin"`
122 Prices map[string]float64 `json:"prices,omitempty"`
123 Publisher string `json:"publisher,omitempty"`
124 RatingsAverage float64 `json:"ratings_average,omitempty"`
125 SupportURL string `json:"support_url"`
126 Title string `json:"title"`
127- Type string `json:"content,omitempty"`
128+ Type SnapType `json:"content"`
129 Version string `json:"version"`
130 }
131
132@@ -478,6 +479,20 @@
133 }
134 part.hash = h.ArchiveSha512
135
136+ remoteManifestPath := manifestPath(part)
137+ if helpers.FileExists(remoteManifestPath) {
138+ content, err := ioutil.ReadFile(remoteManifestPath)
139+ if err != nil {
140+ return nil, err
141+ }
142+
143+ var r remoteSnap
144+ if err := yaml.Unmarshal(content, &r); err != nil {
145+ return nil, &ErrInvalidYaml{file: remoteManifestPath, err: err, yaml: content}
146+ }
147+ part.remoteM = &r
148+ }
149+
150 return part, nil
151 }
152
153@@ -509,6 +524,10 @@
154
155 // Namespace returns the namespace
156 func (s *SnapPart) Namespace() string {
157+ if r := s.remoteM; r != nil {
158+ return r.Namespace
159+ }
160+
161 return s.namespace
162 }
163
164@@ -552,6 +571,10 @@
165
166 // DownloadSize returns the dowload size
167 func (s *SnapPart) DownloadSize() int64 {
168+ if r := s.remoteM; r != nil {
169+ return r.DownloadSize
170+ }
171+
172 return -1
173 }
174
175@@ -852,8 +875,7 @@
176
177 // Type returns the type of the SnapPart (app, oem, ...)
178 func (s *RemoteSnapPart) Type() SnapType {
179- // FIXME: the store does not publish this info
180- return SnapTypeApp
181+ return s.pkg.Type
182 }
183
184 // Name returns the name
185@@ -981,6 +1003,20 @@
186 return w.Name(), w.Sync()
187 }
188
189+func (s *RemoteSnapPart) saveStoreManifest() error {
190+ content, err := yaml.Marshal(s.pkg)
191+ if err != nil {
192+ return err
193+ }
194+
195+ if err := os.MkdirAll(snapMetaDir, 0755); err != nil {
196+ return err
197+ }
198+
199+ // don't worry about previous contents
200+ return ioutil.WriteFile(manifestPath(s), content, 0644)
201+}
202+
203 // Install installs the snap
204 func (s *RemoteSnapPart) Install(pbar progress.Meter, flags InstallFlags) (string, error) {
205 downloadedSnap, err := s.Download(pbar)
206@@ -989,6 +1025,10 @@
207 }
208 defer os.Remove(downloadedSnap)
209
210+ if err := s.saveStoreManifest(); err != nil {
211+ return "", err
212+ }
213+
214 return installClick(downloadedSnap, flags, pbar, s.Namespace())
215 }
216
217
218=== modified file 'snappy/snapp_test.go'
219--- snappy/snapp_test.go 2015-06-04 15:00:44 +0000
220+++ snappy/snapp_test.go 2015-07-06 19:42:05 +0000
221@@ -656,6 +656,10 @@
222
223 snap := RemoteSnapPart{}
224 snap.pkg.AnonDownloadURL = mockServer.URL + "/snap"
225+ snap.pkg.IconURL = mockServer.URL + "/icon"
226+ snap.pkg.Name = "foo"
227+ snap.pkg.Namespace = "bar"
228+ snap.pkg.Version = "1.0"
229
230 p := &MockProgressMeter{}
231 name, err := snap.Install(p, 0)
232@@ -664,6 +668,15 @@
233 st, err := os.Stat(snapPackage)
234 c.Assert(err, IsNil)
235 c.Assert(p.written, Equals, int(st.Size()))
236+
237+ installed, err := ListInstalled()
238+ c.Assert(err, IsNil)
239+ c.Assert(installed, HasLen, 1)
240+
241+ c.Check(installed[0].Namespace(), Equals, "bar")
242+
243+ _, err = os.Stat(filepath.Join(snapMetaDir, "foo.bar_1.0.manifest"))
244+ c.Check(err, IsNil)
245 }
246
247 func (s *SnapTestSuite) TestRemoteSnapUpgradeService(c *C) {
248@@ -1026,6 +1039,30 @@
249 c.Check(yaml.checkForPackageInstalled("otherns"), IsNil)
250 }
251
252+func (s *SnapTestSuite) TestUsesStoreMetaData(c *C) {
253+ data := "name: afoo\nversion: 1\nvendor: foo\ntype: framework"
254+ yamlPath, err := makeInstalledMockSnap(s.tempdir, data)
255+ c.Assert(err, IsNil)
256+ c.Assert(makeSnapActive(yamlPath), IsNil)
257+
258+ err = os.MkdirAll(snapMetaDir, 0755)
259+ c.Assert(err, IsNil)
260+
261+ data = "name: afoo\nalias: afoo\ndescription: something nice\ndownloadsize: 10\norigin: someplace"
262+ err = ioutil.WriteFile(filepath.Join(snapMetaDir, "afoo_1.manifest"), []byte(data), 0644)
263+ c.Assert(err, IsNil)
264+
265+ snaps, err := ListInstalled()
266+ c.Assert(err, IsNil)
267+ c.Assert(snaps, HasLen, 1)
268+
269+ c.Check(snaps[0].Name(), Equals, "afoo")
270+ c.Check(snaps[0].Version(), Equals, "1")
271+ c.Check(snaps[0].Type(), Equals, SnapTypeFramework)
272+ c.Check(snaps[0].Namespace(), Equals, "someplace")
273+ c.Check(snaps[0].DownloadSize(), Equals, int64(10))
274+}
275+
276 func (s *SnapTestSuite) TestDetectsNameClash(c *C) {
277 data := []byte(`name: afoo
278 version: 1.0

Subscribers

People subscribed via source and target branches