1package releasedir_test
2
3import (
4	"errors"
5	"path/filepath"
6	"strings"
7
8	fakesys "github.com/cloudfoundry/bosh-utils/system/fakes"
9	fakeuuid "github.com/cloudfoundry/bosh-utils/uuid/fakes"
10	semver "github.com/cppforlife/go-semi-semantic/version"
11	. "github.com/onsi/ginkgo"
12	. "github.com/onsi/gomega"
13
14	boshman "github.com/cloudfoundry/bosh-cli/release/manifest"
15	fakerel "github.com/cloudfoundry/bosh-cli/release/releasefakes"
16	. "github.com/cloudfoundry/bosh-cli/releasedir"
17	fakereldir "github.com/cloudfoundry/bosh-cli/releasedir/releasedirfakes"
18)
19
20var _ = Describe("FSReleaseIndex", func() {
21	var (
22		reporter *fakereldir.FakeReleaseIndexReporter
23		uuidGen  *fakeuuid.FakeGenerator
24		fs       *fakesys.FakeFileSystem
25		index    FSReleaseIndex
26	)
27
28	BeforeEach(func() {
29		reporter = &fakereldir.FakeReleaseIndexReporter{}
30		uuidGen = &fakeuuid.FakeGenerator{}
31		fs = fakesys.NewFakeFileSystem()
32		index = NewFSReleaseIndex("index-name", filepath.Join("/", "dir"), reporter, uuidGen, fs)
33	})
34
35	Describe("LastVersion", func() {
36		It("returns nil when there is no index file", func() {
37			ver, err := index.LastVersion("name")
38			Expect(err).ToNot(HaveOccurred())
39			Expect(ver).To(BeNil())
40		})
41
42		It("returns nil when index file is empty", func() {
43			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "")
44
45			ver, err := index.LastVersion("name")
46			Expect(err).ToNot(HaveOccurred())
47			Expect(ver).To(BeNil())
48		})
49
50		It("returns greater version", func() {
51			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), `---
52builds:
53  uuid1: {version: "1.1"}
54  uuid2: {version: "1"}
55format-version: "2"`)
56
57			ver, err := index.LastVersion("name")
58			Expect(err).ToNot(HaveOccurred())
59			Expect(ver.String()).To(Equal(semver.MustNewVersionFromString("1.1").String()))
60		})
61
62		It("returns error if version cannot be parsed", func() {
63			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), `---
64builds:
65  uuid2: {version: "-"}
66format-version: "2"`)
67
68			_, err := index.LastVersion("name")
69			Expect(err).To(HaveOccurred())
70			Expect(err.Error()).To(ContainSubstring("Parsing release versions"))
71		})
72
73		It("returns error if name is empty", func() {
74			_, err := index.LastVersion("")
75			Expect(err).To(HaveOccurred())
76			Expect(err.Error()).To(Equal("Expected non-empty release name"))
77		})
78
79		It("returns error if index file cannot be unmarshalled", func() {
80			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "-")
81
82			_, err := index.LastVersion("name")
83			Expect(err).To(HaveOccurred())
84			Expect(err.Error()).To(ContainSubstring("line 1"))
85		})
86
87		It("returns error if reading index file fails", func() {
88			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "")
89			fs.ReadFileError = errors.New("fake-err")
90
91			_, err := index.LastVersion("name")
92			Expect(err).To(HaveOccurred())
93			Expect(err.Error()).To(ContainSubstring("fake-err"))
94		})
95	})
96
97	Describe("Contains", func() {
98		var (
99			release *fakerel.FakeRelease
100		)
101
102		BeforeEach(func() {
103			release = &fakerel.FakeRelease{}
104			release.NameReturns("name")
105			release.VersionReturns("ver1")
106		})
107
108		It("returns false when there is no index file", func() {
109			exists, err := index.Contains(release)
110			Expect(err).ToNot(HaveOccurred())
111			Expect(exists).To(BeFalse())
112		})
113
114		It("returns false when index file is empty", func() {
115			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "")
116
117			exists, err := index.Contains(release)
118			Expect(err).ToNot(HaveOccurred())
119			Expect(exists).To(BeFalse())
120		})
121
122		It("returns true if version is exists", func() {
123			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), `---
124builds:
125  uuid1: {version: "1.1"}
126  uuid2: {version: "ver1"}
127format-version: "2"`)
128
129			exists, err := index.Contains(release)
130			Expect(err).ToNot(HaveOccurred())
131			Expect(exists).To(BeTrue())
132		})
133
134		It("returns false if version is not exists", func() {
135			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), `---
136builds:
137  uuid1: {version: "1.1"}
138format-version: "2"`)
139
140			exists, err := index.Contains(release)
141			Expect(err).ToNot(HaveOccurred())
142			Expect(exists).To(BeFalse())
143		})
144
145		It("returns error if name is empty", func() {
146			release.NameReturns("")
147
148			_, err := index.Contains(release)
149			Expect(err).To(HaveOccurred())
150			Expect(err.Error()).To(Equal("Expected non-empty release name"))
151		})
152
153		It("returns error if version is empty", func() {
154			release.VersionReturns("")
155
156			_, err := index.Contains(release)
157			Expect(err).To(HaveOccurred())
158			Expect(err.Error()).To(Equal("Expected non-empty release version"))
159		})
160
161		It("returns error if index file cannot be unmarshalled", func() {
162			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "-")
163
164			_, err := index.Contains(release)
165			Expect(err).To(HaveOccurred())
166			Expect(err.Error()).To(ContainSubstring("line 1"))
167		})
168
169		It("returns error if reading index file fails", func() {
170			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "")
171			fs.ReadFileError = errors.New("fake-err")
172
173			_, err := index.Contains(release)
174			Expect(err).To(HaveOccurred())
175			Expect(err.Error()).To(ContainSubstring("fake-err"))
176		})
177	})
178
179	Describe("Add", func() {
180		var (
181			manifest boshman.Manifest
182		)
183
184		BeforeEach(func() {
185			manifest.Name = "name"
186			manifest.Version = "ver1"
187			uuidGen.GeneratedUUID = "new-uuid"
188		})
189
190		It("saves manifest and adds version entry when there is no index file", func() {
191			err := index.Add(manifest)
192			Expect(err).ToNot(HaveOccurred())
193
194			Expect(fs.ReadFileString(filepath.Join("/", "dir", "name", "name-ver1.yml"))).To(Equal(`name: name
195version: ver1
196commit_hash: ""
197uncommitted_changes: false
198`))
199
200			Expect(fs.ReadFileString(filepath.Join("/", "dir", "name", "index.yml"))).To(Equal(`builds:
201  new-uuid:
202    version: ver1
203format-version: "2"
204`))
205
206			name, desc, err := reporter.ReleaseIndexAddedArgsForCall(0)
207			Expect(name).To(Equal("index-name"))
208			Expect(desc).To(Equal("name/ver1"))
209			Expect(err).To(BeNil())
210		})
211
212		It("saves manifest and adds version entry", func() {
213			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), `---
214builds:
215  uuid: {version: "1.1"}
216format-version: "2"
217`)
218
219			err := index.Add(manifest)
220			Expect(err).ToNot(HaveOccurred())
221
222			Expect(fs.ReadFileString(filepath.Join("/", "dir", "name", "name-ver1.yml"))).To(Equal(`name: name
223version: ver1
224commit_hash: ""
225uncommitted_changes: false
226`))
227
228			Expect(fs.ReadFileString(filepath.Join("/", "dir", "name", "index.yml"))).To(Equal(`builds:
229  new-uuid:
230    version: ver1
231  uuid:
232    version: "1.1"
233format-version: "2"
234`))
235
236			name, desc, err := reporter.ReleaseIndexAddedArgsForCall(0)
237			Expect(name).To(Equal("index-name"))
238			Expect(desc).To(Equal("name/ver1"))
239			Expect(err).To(BeNil())
240		})
241
242		It("returns and reports error if writing manifest fails", func() {
243			fs.WriteFileErrors[filepath.Join("/", "dir", "name", "name-ver1.yml")] = errors.New("fake-err")
244
245			err := index.Add(manifest)
246			Expect(err).To(HaveOccurred())
247
248			name, desc, err := reporter.ReleaseIndexAddedArgsForCall(0)
249			Expect(name).To(Equal("index-name"))
250			Expect(desc).To(Equal("name/ver1"))
251			Expect(err).ToNot(BeNil())
252		})
253
254		It("returns and reports error if writing index fails", func() {
255			fs.WriteFileErrors[filepath.Join("/", "dir", "name", "index.yml")] = errors.New("fake-err")
256
257			err := index.Add(manifest)
258			Expect(err).To(HaveOccurred())
259
260			name, desc, err := reporter.ReleaseIndexAddedArgsForCall(0)
261			Expect(name).To(Equal("index-name"))
262			Expect(desc).To(Equal("name/ver1"))
263			Expect(err).ToNot(BeNil())
264		})
265
266		It("returns error if generating uuid fails", func() {
267			uuidGen.GenerateError = errors.New("fake-err")
268
269			err := index.Add(manifest)
270			Expect(err).To(HaveOccurred())
271			Expect(err.Error()).To(ContainSubstring("fake-err"))
272		})
273
274		It("returns error if version is exists", func() {
275			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), `---
276builds:
277  uuid1: {version: "1.1"}
278  uuid2: {version: "ver1"}
279format-version: "2"`)
280
281			err := index.Add(manifest)
282			Expect(err).To(HaveOccurred())
283			Expect(err.Error()).To(Equal("Release version 'ver1' already exists"))
284		})
285
286		It("returns error if name is empty", func() {
287			manifest.Name = ""
288
289			err := index.Add(manifest)
290			Expect(err).To(HaveOccurred())
291			Expect(err.Error()).To(Equal("Expected non-empty release name"))
292		})
293
294		It("returns error if version is empty", func() {
295			manifest.Version = ""
296
297			err := index.Add(manifest)
298			Expect(err).To(HaveOccurred())
299			Expect(err.Error()).To(Equal("Expected non-empty release version"))
300		})
301
302		It("returns error if index file cannot be unmarshalled", func() {
303			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "-")
304
305			err := index.Add(manifest)
306			Expect(err).To(HaveOccurred())
307			Expect(err.Error()).To(ContainSubstring("line 1"))
308		})
309
310		It("returns error if reading index file fails", func() {
311			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), "")
312			fs.ReadFileError = errors.New("fake-err")
313
314			err := index.Add(manifest)
315			Expect(err).To(HaveOccurred())
316			Expect(err.Error()).To(ContainSubstring("fake-err"))
317		})
318
319		It("does not reorder keys needlessly", func() {
320			fs.WriteFileString(filepath.Join("/", "dir", "name", "index.yml"), fsReleaseIndexSortingFixture)
321
322			uuidGen.GeneratedUUID = "new-uuid"
323			manifest.Version = "new"
324
325			err := index.Add(manifest)
326			Expect(err).ToNot(HaveOccurred())
327
328			afterFirstSort, err := fs.ReadFileString(filepath.Join("/", "dir", "name", "index.yml"))
329			Expect(err).ToNot(HaveOccurred())
330
331			Expect(afterFirstSort).ToNot(Equal(fsReleaseIndexSortingFixture)) // sanity check
332
333			uuidGen.GeneratedUUID = "another-uuid"
334			manifest.Version = "another"
335
336			err = index.Add(manifest)
337			Expect(err).ToNot(HaveOccurred())
338
339			after, err := fs.ReadFileString(filepath.Join("/", "dir", "name", "index.yml"))
340			Expect(err).ToNot(HaveOccurred())
341
342			Expect(after).ToNot(Equal(afterFirstSort)) // sanity check
343			Expect(strings.Replace(after, "  another-uuid:\n    version: another\n", "", 1)).To(Equal(afterFirstSort))
344		})
345	})
346
347	Describe("ManifestPath", func() {
348		It("returns path to a manifest", func() {
349			Expect(index.ManifestPath("name", "ver1")).To(Equal(filepath.Join("/", "dir", "name", "name-ver1.yml")))
350		})
351	})
352})
353
354// Fixture needs to be long because natural sort may succeed for smaller sizes
355const fsReleaseIndexSortingFixture = `
356builds:
357  0a09e695-c0d6-4283-ad1e-132a336095d6:
358    version: "184"
359  0be3304e-c217-4b0b-8f21-2b4ae1811f02:
360    version: "96"
361  0c3ce4ae-2ad7-4b70-bf68-3a11c199694d:
362    version: "140"
363  0c923cc3-49ee-4376-9033-c51f7380794b:
364    version: "256.7"
365  0d469717-3f49-4e68-8472-7e11ddcd8a44:
366    version: "132"
367  0dcbed5b-7245-4223-b99a-35d7b5ddade4:
368    version: "189"
369  0e3ed48f-d647-44c3-804b-e44bda1f9e55:
370    version: "105"
371  1abbb9d95dd0121a238e319580cda00dcc9d6e82:
372    version: "86"
373  1bb45287-c018-4e39-86a1-6b5a65c49668:
374    version: "97"
375  1bc91aed-94f9-40db-962a-2dae64bcbd10:
376    version: "130"
377  1eb2cc5facfa83077237c30d3ef8a875ba76dda6:
378    version: "25"
379  2cd44cf882745de94eb4b470d9f5659f6d752388:
380    version: "2"
381  2e47bdf8-79fb-4b5f-8a18-8c00a08df116:
382    version: "257"
383  2e2889bbd5168b5c8daff2a42ae2bf7aaec22126:
384    version: "10"
385  2efbb96d-7e98-42b0-a0aa-1e20f090a755:
386    version: "183"
387  2f343a15-b377-4761-a72c-43f06ceed112:
388    version: "243"
389  002f99bb-3087-461a-bd93-9cef673f04a7:
390    version: "237"
391  3b1fd3e4-7756-459d-8930-68c8fcbd6a3f:
392    version: "247"
393  3b6704a1-f33e-49eb-924a-af53f9bd47e4:
394    version: "104"
395  3bb433e7-370d-444a-8a27-14871de4e7c0:
396    version: "145"
397  3cc94519942dd522508a487a3282956d84c3b21c:
398    version: "8"
399  3d933826-e485-47d4-938a-0da83afba887:
400    version: "211"
401  3f36e5523e474c55424543334971ddbf578a354f:
402    version: "24"
403  4a1784f3-90d3-4e10-80a9-7084dfeae145:
404    version: "129"
405  4a2233a4-edf6-4095-a91b-bbd5386b240e:
406    version: "255.9"
407  4b3c83cbb984ef05560e51077e42aa91567eb91b:
408    version: "47"
409  4b5ddee8-a565-47c0-a962-57544778769c:
410    version: "203"
411  4b375c21-0fe1-43e7-b588-c77e8fd07d72:
412    version: "151"
413  4b685ba7-d4b2-4d4a-84fd-a728dce65bd5:
414    version: "239"
415  4c43ec6fe8ac88358c106675b0979b0b32b60db0:
416    version: "19"
417  4d28e0be-b536-4d3a-a5c8-6003cffa0063:
418    version: "125"
419  4d48c371-a4fb-4887-b00c-1c2496fc530c:
420    version: "255.8"
421  4df46a47ec8514b03157cb5bfab95c79b2e10965:
422    version: "16"
423  4e2a2400-1659-4170-b1a8-926638d6ed73:
424    version: "114"
425  4e2d1d17-3965-4022-8323-c016036866bf:
426    version: "167"
427  4e05dc91f07ea0fbaef82c09a0f67f4017c1a6db:
428    version: "34"
429  4ef38824-c4e8-46fc-8c09-65d6352ee018:
430    version: "255.3"
431  4f1c7a7af09b3564c53f1ce978832c99ee284b48:
432    version: "57"
433  04ed089c-86ec-4b3f-b77f-2dfaadc30101:
434    version: "116"
435  51e5280d-c00c-4fbe-9854-1650e21c23e0:
436    version: "255"
437  565db893e00b6743e688026817a9f318bb434035:
438    version: "37"
439  56b8711d637ca966d83dc70785f382db04b0d2ed:
440    version: "74"
441  56d23a64-5615-49ae-9142-66a49191bd11:
442    version: "138"
443  515e1ed5-c6db-4548-8e45-a2fd857dd96e:
444    version: "218"
445  5a691f4cca5237a2dcc09eb3b3fd95fe65f2c434:
446    version: "90"
447  5b2fac9f-7e26-4e03-a71a-083248a6d923:
448    version: "200"
449  5b8cc42918a1ba56d8d08cb7efaa4ab88312cf12:
450    version: "75"
451  5c0a4550-88ce-450e-a025-6664a4f3ffaa:
452    version: "99"
453  5c7e6536ca86a51a5cb2982d5c7a6bf735a28587:
454    version: "6"
455  5e35aa8c-b86b-4f12-8008-f55b448c996e:
456    version: "245"
457  5e548ed3-311c-4058-ac72-82aa8c6e77f1:
458    version: "255.1"
459  5ebdc4fb89b80130073a1a9e4e0f0f9d32d6b90a:
460    version: "93"
461  5f75bc56-4974-43a0-9c30-761f09ccef4b:
462    version: "133"
463  61c073cd-1d75-4278-6332-fef80546f494:
464    version: "257.23"
465  8a3f7bc77714e234002ab5f6b4e1b89a79db2060:
466    version: "83"
467  8b15bb32-d191-44b3-8914-883a195b3805:
468    version: "223"
469  8df8e9ef-fbc6-42fc-b689-3d82d4f8532d:
470    version: "154"
471  8eb56d4e-8fd5-48d3-b0fc-4801840d83f1:
472    version: "256.10"
473  8f9964a522c45c13c1c5c678a03c3314ae016a9a:
474    version: "18"
475  9b6ba124-d4ba-4749-abbf-be58aff92034:
476    version: "136"
477  9b12286c2f3b83e091190ccabc83e08d91371b69:
478    version: "78"
479  9b961347-9053-4fd1-8906-dce81072b44f:
480    version: "127"
481  9bfc22ad-642c-4271-900a-d070556ea2dc:
482    version: "157"
483  9dfd44e4-58d1-473d-91d8-95fd7af980dd:
484    version: "139"
485  9e2cfee4-23d2-4333-826f-e3643397925d:
486    version: "149"
487  9e944111-3908-4def-a928-8a102515881b:
488    version: "159"
489  09b2f0f1123984e6de289a5276c4f327ff6a4431:
490    version: "79"
491  10c1abeb97555968f827625b88b82d37fa6d5631:
492    version: "70"
493  11d6cbdbe2b2f7a7d89c3b238a73753b5aef56cf:
494    version: "54"
495  15b5afb5-ab70-42a5-bb26-62cd41b0ff83:
496    version: "215"
497  15d07e9c-e4ce-4980-936e-30f21ffb3e0f:
498    version: "214"
499  16fdbd44-0cd7-4b3d-939d-a47166146a2a:
500    version: "124"
501  19e85380-7867-4ad3-a222-fc973f414762:
502    version: "255.5"
503  27d3af15-dca6-4dd6-9008-83476d87fd4d:
504    version: "257.1"
505  33e8dd59-6755-4cd7-a3c9-524e5ebe9f71:
506    version: "232"
507  37cae4d6-12a6-424f-bc6e-d0c8660845a6:
508    version: "226"
509  40badd7e05dc716feaef7fa7b643ab23b12bc40d:
510    version: "73"
511  45d5d809-366d-400b-a5c8-92c13be4ecf3:
512    version: "217"
513  45f55b5020e1002a0eec171f92a4f3543e192e61:
514    version: "81"
515  47bf7323-8c26-4b70-883d-2a9cc98d707e:
516    version: "196"
517  63fc1567-7c24-4191-8593-09bc492ef628:
518    version: "175"
519  70ea18ac-b5f8-4995-8ea9-b33e68b8d5e2:
520    version: "173"
521  75fc1bea-06a9-4c86-a45f-c04eb960136e:
522    version: "187"
523  7ab647f56af79aa55544514ace3b100374d9fa0c:
524    version: "11"
525  7ad3ae21c4ed8b13c89231bafd7488346a2d33cd:
526    version: "87"
527  7bfc2ae8-f9bd-4801-b116-c37261b31537:
528    version: "255.11"
529  7cccb6b9-e265-4ea3-8136-e87f09c06dbc:
530    version: "238"
531  7ccf7897e726ffcd0609a4355034e7500e0b9992:
532    version: "5"
533  7d958a6c-7c5e-4879-9099-18e8b1f56ce2:
534    version: "241"
535  80cebae99ee55ecfd1ba543612ba440400b66d6a:
536    version: "64"
537  84bf30ee-5717-4f43-9c35-45c0b02c963a:
538    version: "256"
539  84fcfb0e-6a95-4ca4-b501-de607be32277:
540    version: "171"
541  90d22154-7639-40e5-abdb-9b179056f3e7:
542    version: "194"
543  92de234b-2361-4fa6-b8e5-48db2c77efa7:
544    version: "121"
545  93c66707a644f0704cf95ca67235d30ec4ac1706:
546    version: "61"
547  106d1c7461492a62f6d3ac9e069906183f9839f2:
548    version: "20"
549  140c3d64ece43e7b182c3d5704553c52b39e08d6:
550    version: "80"
551  249c9868-7a8b-4a75-9341-4ed3c3f91c81:
552    version: "147"
553  274cbf9640a23e5287c692bc44f7e155545e199e:
554    version: "26"
555  328bbda7-5539-47bd-89bf-fac5f004f0dc:
556    version: "235"
557  335f52e9-4f9d-43fb-bca6-de7bf1cc41cc:
558    version: "208"
559  424cb5ab917266d52cacd0f5d48a7961bfb18f89:
560    version: "59"
561  425b86ac-b97e-4905-82ce-1d60597c6bf8:
562    version: "152"
563  442ab1a9-5598-4962-a8ae-8f9fc027d79f:
564    version: "250"
565  462af3279520d4041ab444c21bc442865a155f3b:
566    version: "9"
567  475c9a93753be28b09398dd529e3bb143931a00b:
568    version: "36"
569  478fc29c04c8e510a6ca0c7e89573b04084cbf89:
570    version: "38"
571  483be75c-bc09-465d-bec2-3fc2f3a1d564:
572    version: "257.14"
573  628dc87805e060af7506bc5f5df4ababa8873eaf:
574    version: "22"
575  00650b34-7377-444e-8317-5033f892602e:
576    version: "255.7"
577  669d530b-a551-475d-9267-241d16bb2641:
578    version: "202"
579  66da66653bd20753c15ea5a04c26b857c36eeb98:
580    version: "46"
581  6b93e0d4-f067-4328-a2c1-9ff3cb2bb808:
582    version: "166"
583  6c1f79fae1eb0d9b507bfbe7c7651b66b46ab6a5:
584    version: "62"
585  6d93d456a2d1b7d698893bf826cbd43907740f93:
586    version: "68"
587  6e2c768f-a6b3-4ea5-a4a6-55ecb1eb4141:
588    version: "163"
589  6e39c67b-82f4-4b09-84cc-2c8b71889de8:
590    version: "248"
591  6eb8b63373d273160b71470b1621ccd347a1c429:
592    version: "50"
593  6ee52fcf-d3a0-4ba5-9dd2-5ca8738875d7:
594    version: "225"
595  6f03636b-8735-4a90-8c65-e57b88e498d1:
596    version: "190"
597  6f0cc9b8-be9f-4e91-a354-35a9b69433f7:
598    version: "160"
599  6fb0e10df7413b89ad6b34e7e92f2fc5f8c50c51:
600    version: "13"
601  818f7e1675ec75cf1280c3acc76306b28a32708f:
602    version: "84"
603  824d8f31-bc7a-4a1f-aac2-aaf612d0b016:
604    version: "186"
605  839b8c7a-275e-46eb-95d4-1db6d69be656:
606    version: "221"
607  922df222-bbd8-4dec-9cde-efca62eb1d40:
608    version: "210"
609  971c567baf65344247252f7149887826dcf48521:
610    version: "91"
611  1386de6b29c9e67be05850f8fa56fccdd98d1783:
612    version: "60"
613  2011ffa8-cd0d-460b-b1ca-606e5eeebd1d:
614    version: "207"
615  2946c7ac-ee50-437d-a21a-9e969cfb63bd:
616    version: "229"
617  3656d798-fa97-4ecc-8f85-05b602ec22d6:
618    version: "107"
619  4271d8f3-ce32-4a50-b0e2-a1bf0be4fdd8:
620    version: "195"
621  5347b0a8-7569-42ca-a1ae-02317e584600:
622    version: "246"
623  5801ac09-3c64-46ba-a39e-3b55336e0036:
624    version: "180"
625  6295f56b-1d46-4ddb-9491-4d1369f7c77c:
626    version: "148"
627  6982c119-c61c-441a-9e2d-a91fb22a1c5f:
628    version: "141"
629  7231a284-2989-4767-9501-618978362f5b:
630    version: "227"
631  8044cc21-21fd-49eb-903f-cc625b21c4bf:
632    version: "257.3"
633  8263f0f077b494e90efe16b7fe311b5001a91c9c:
634    version: "30"
635  9105f65b-9977-402a-bcf1-2341c30de953:
636    version: "101"
637  9150c4bd-ca2b-4fb3-9997-dc4124a63a94:
638    version: "228"
639  9296c8d5-2188-454f-8db0-2c754c831d22:
640    version: "179"
641  9565cc7d-5f58-4a0a-ac67-77094433ceeb:
642    version: "108"
643  9792e9c92a4a3e9af8f713c49aab48dc2b3698de:
644    version: "58"
645  9936c4bc-aee0-48dd-8cbf-9cc6d8d1953c:
646    version: "231"
647  19200fec012800c5725bf021e47c2ce8baa784f1:
648    version: "39"
649  22392d51-744e-4699-9a53-763460ff6f42:
650    version: "249"
651  26869a72-c9e8-40e0-a2cb-55409340c54c:
652    version: "112"
653  35318da9-3e5f-4f4d-896b-e96a95bf07f8:
654    version: "212"
655  39420de6b806036821fcdafacd7b2ecf2137e77e:
656    version: "21"
657  40331cf7-6b02-41ad-9277-b275378c5e78:
658    version: "255.6"
659  4491ef460d717fec1bef687196299e71663243f7:
660    version: "23"
661  4744a426-ce86-4bd6-8f5a-0cffc681743d:
662    version: "111"
663  4987d9d7-ff36-40ca-b01b-fab5eecb791f:
664    version: "255.12"
665  57966e1cfe9fc55f66933db1de64ba5efc52dbf7:
666    version: "12"
667  60589dad-345b-4126-87c9-cce546bb52dd:
668    version: "176"
669  63710ebfa1a5424130d07ce5e621cc91691aa878:
670    version: "43"
671  66055d1cd1283d54927f0cfe2326dcdb0df02141:
672    version: "85"
673  81323ee570aac0a8974bb83ea2cb57b40f43b0d4:
674    version: "67"
675  94066ea7-4d83-4e1b-9fcf-e0fed64eb769:
676    version: "233"
677  340877edee9f64e8fd9b6897cbe5725fa0b9c244:
678    version: "14"
679  0360627f-9013-4438-92fa-d65431142bdf:
680    version: "156"
681  9005037e0772d33a692945597112fa54d542f69d:
682    version: "17"
683  959408ddcf0a6130e717b3ed4cf2a9a2bdce8604:
684    version: "15"
685  0990824d-224b-4b71-a9dd-d88231ce4a6f:
686    version: "256.9"
687  09277055-30c0-4e67-a114-c096c0ee9904:
688    version: "164"
689  9828318f-1a40-43ed-91d9-22546972d3b6:
690    version: "256.2"
691  25453110-2f68-490b-ac11-821d518379e0:
692    version: "95"
693  38053593ac5f3a5032d3e79f153bc286f3a91e50:
694    version: "72"
695  71305490f6ffab6c14983d0f45f82fd28d3b7144:
696    version: "89"
697  88231922-cb9a-47bb-a74d-0d1f466afc3a:
698    version: "222"
699  186178684f3ac482f8cc0c99342376d691de64e1:
700    version: "82"
701  a3bcfc74-e2bc-4e47-a674-146879b32e60:
702    version: "192"
703  a5fbc3ce4e3885fd5e1ca0136272afbb873e7161:
704    version: "31"
705  a6ecc248-0bb1-4365-a657-d950a8536c5e:
706    version: "206"
707  a06f534a-cf6d-4249-823e-4816de40c395:
708    version: "113"
709  a11c17b3-ad57-46d8-b782-849e70b5a444:
710    version: "102"
711  a93bb59a-ca40-4b26-b6f3-45e205312fce:
712    version: "137"
713  a484d99e74fc3f90d926663a32057e600af7a51f:
714    version: "35"
715  a0863b1f-4d75-49ea-a8df-ac288e49f4a8:
716    version: "100"
717  aa6ead50-f2a2-4a78-9b05-3a1e52527c64:
718    version: "118"
719  aa98b942ac6cef30d7308426fa9b2d0edafd921a:
720    version: "3"
721  ab0a77d8-b553-4cb2-b653-2c0ced83e106:
722    version: "94"
723  ab280975f4e4a942c60437846730eeddd9028317:
724    version: "92"
725  aba487a20d8619d87a74957dc9d988fbcca6064d:
726    version: "71"
727  ac386c8c-614c-4404-933b-36c2d57e860f:
728    version: "252"
729  aca1c7ca826b6fc6d945a9d2fc665a40734193a3:
730    version: "63"
731  acb2b04843353e96041cc588d26016d555823ebf:
732    version: "27"
733  ad9371f3ba0d55ff061d75a443c44edcc33c5b23:
734    version: "28"
735  adb10e2a94fc8c26e17fb47f28794ac0a642754e:
736    version: "88"
737  adb789f6e29f4b70b6dea7fef01144d2d3199120:
738    version: "32"
739  adb1272a-924c-45ab-a902-bd0f90eca4a1:
740    version: "117"
741  adcad85a-3cfd-4df9-8a21-bd8525fddaca:
742    version: "199"
743  addb77c6-4e8d-411f-ab13-b8556faf6464:
744    version: "224"
745  ae2383a3-4e31-4935-bc5e-fb448ca19a4e:
746    version: "144"
747  af08a25c725515de237cfd92e4d556fc3a647b56:
748    version: "76"
749  af749790-d3a7-43cd-9dbc-6d1feaacf199:
750    version: "110"
751  afed33da-19ac-43f9-ac81-b34716f11f49:
752    version: "188"
753  b0b251bf-5118-445d-8683-6c5f993ee825:
754    version: "216"
755  b1af8426-6140-469e-afd1-0ef5860f8857:
756    version: "213"
757  b1e8e307-778b-498c-9c5f-6d61fd7e8271:
758    version: "244"
759  b7a3954a-44ec-4267-9846-a85c2d6cee85:
760    version: "191"
761  b09a26d9-2ef2-4032-918a-d91f05264420:
762    version: "181"
763  b962c80a-c270-48b6-87c3-fcda9ca34919:
764    version: "205"
765  b412118f99ad8284b7ba77efc06dbce2dd6d50f6:
766    version: "42"
767  b9804136-798f-44b7-9b66-434423390161:
768    version: "126"
769  ba0be057-0474-43f2-6df6-ad3d0b8904fc:
770    version: "259"
771  ba88d357-e22d-4f4b-9ad0-0707ae477220:
772    version: "230"
773  ba484e77-1db4-4110-98e3-36967aee4e41:
774    version: "172"
775  bbfad792cb93660fc7ea7f1020bd6a603f2ed5a3:
776    version: "7"
777  bc0ff53f-67d5-47d7-872a-d649bc3d9d2a:
778    version: "109"
779  bde951be-4e44-42fc-6959-208e3b9d634e:
780    version: "260.1"
781  bdeb4342-53c5-4474-8d17-a0095ef8b680:
782    version: "119"
783  be6f4858-1fd0-42cc-a251-8fc07f4b80b5:
784    version: "197"
785  bf1fe13f-7077-405e-b69f-eb62412d2284:
786    version: "120"
787  bf9678dc-ee9c-4811-a329-223f481411a8:
788    version: "103"
789  c7a3396f0f19e4433921c3bc9cea01b097b2aec9:
790    version: "52"
791  c31b8fec04fdf27f8e7a3a361ae0019bf4d0c3b4:
792    version: "1"
793  c36ae721-65b6-4a7c-b06d-f1218a5395c0:
794    version: "106"
795  c80ca2f7cfa2a0476e6177abe3dc5c7d09ce154f:
796    version: "55"
797  c678afe7-7d7f-49cf-9d40-c1e8d8117e71:
798    version: "255.4"
799  c911d85f806a1b70bd4735c65c3375bd48eb0191:
800    version: "66"
801  c943e343-214b-408a-9dde-a7188ef2a888:
802    version: "142"
803  c983fc6800d69b696b23a8b4cc5d29b2c6f07c12:
804    version: "77"
805  c349618d-11e2-4cdb-9286-8da52620951d:
806    version: "158"
807  cb987be0-807c-484b-a86a-c28c5af535cc:
808    version: "98"
809  ce409cc0-f4ff-44eb-ac67-ad22b0a3100d:
810    version: "155"
811  cec65c68-e31d-4f1b-a9b9-94e0c6ffec64:
812    version: "165"
813  cf05fee0-79f1-4635-b45d-46a324968d16:
814    version: "236"
815  cf832f81-b7e9-4a20-82da-27df449e0484:
816    version: "256.1"
817  cfc286d5-b82d-44af-bd7f-42878150dcff:
818    version: "168"
819  d00fe303-49ae-4bd5-bdb0-ff10d28f19e7:
820    version: "257.15"
821  d1dc9119-0910-4d1a-a0fe-8b62129bef39:
822    version: "115"
823  d5cfd8f9d0c72587e65f7dd498dde62a8794dce6:
824    version: "29"
825  d78b3b54-b41d-409c-a63b-0af31edc1c60:
826    version: "170"
827  d7732540-808f-498a-ad97-c826d7db9e7b:
828    version: "254"
829  d7e497f9-e620-4e47-4065-9a71c0e8b399:
830    version: "258"
831  d29f79c32afe72544d59598cca3c0e65fbad9db5:
832    version: "4"
833  d30a5097-c32d-40e9-a402-0e527dd8fea1:
834    version: "161"
835  d82af44e2c103a8bc7b20d0b8ccc88a266750b3d:
836    version: "33"
837  d8ba86a3-c25c-4c57-a45a-4587a51b6cda:
838    version: "182"
839  d514d2325bacf762d34a0642bb7cacd4bd61cfab:
840    version: "40"
841  d673a62319f43c39b37db7062dec46db2cb66dff:
842    version: "44"
843  d67965fd-91ac-4551-b091-952c26dd8497:
844    version: "234"
845  daab772b-3563-4d21-5b39-b1a6acc6fff6:
846    version: "260"
847  db34bbbb-e923-4e4f-92ec-04a7b94b9886:
848    version: "134"
849  dc94014e-80a0-41d7-a241-67e0dfee5053:
850    version: "153"
851  def2b40d-ecf3-470d-8751-773d1cd629d0:
852    version: "219"
853  df424425-71d3-4df1-b6cd-17cc5c5bff00:
854    version: "178"
855  dfad3f59-fe62-45d1-9d10-e200a69ebc68:
856    version: "209"
857  e2c8fc6e-84a0-4d36-b2d5-354b4b2bac91:
858    version: "150"
859  e38055cd-d428-4d1c-8a3f-a3e983bb5af7:
860    version: "253"
861  e3a8008cfe47ede4c046c31d5500f9a1a08b002f:
862    version: "41"
863  e6ca9318-87d9-4ed0-9e99-7232607e253a:
864    version: "162"
865  e23c7fca-8f19-463f-b479-5e04049ffaa6:
866    version: "255.2"
867  e45c2bf6dbbddfab0fb29c24c0acf693aec68a1a:
868    version: "65"
869  e67dc9d432c433516868b216c18b1295f2d29b27:
870    version: "53"
871  e802a7e147e7fd70e7484fcbaaa65c4f85cd2191:
872    version: "45"
873  e87ff8de-160c-4096-a29e-753edb103487:
874    version: "242"
875  e8cc700e-a776-40d4-86a9-60a59eafebfe:
876    version: "169"
877  e96bb4c6be3a00b24777f57995d3215ff9c92093:
878    version: "49"
879  e703b2c4-f18e-41e5-836c-59689f88394a:
880    version: "220"
881  ea25fd55-ae57-4071-9d25-fcd832f38680:
882    version: "185"
883  ea92a4e7b0bccb29526e9861fe6c77eb5db79062:
884    version: "69"
885  ea1248de-4029-4c4a-8dae-c36f7c5d307a:
886    version: "240"
887  eb4a3116-29cb-47b6-99ad-3fa06388eea2:
888    version: "122"
889  ec126ab0-3eab-453a-9891-2ce83b402dd1:
890    version: "251"
891  ecb7f48d4c97aff8fc7ce0ccde7ea3efc4c987bb:
892    version: "51"
893  ece39b52-2478-4d40-9049-e9931663b98e:
894    version: "193"
895  f3adf894ee76ef6f5c0f7591abb63eaccf06eeea:
896    version: "48"
897  f3fbedf7-9e2c-4741-abca-fd0a1f7904ab:
898    version: "135"
899  f6e9386b-bc55-473a-9112-834dbaef0d8b:
900    version: "143"
901  f7a6d2d5-d843-49a8-9ab5-2d6c5c3a6eb4:
902    version: "128"
903  f44d6266-fc52-4553-9c63-ce6c2797a022:
904    version: "177"
905  f65f663c-613c-459f-8338-86d4bdc608c3:
906    version: "204"
907  f80bc7bd-6234-4246-bc6b-aebeda396176:
908    version: "257.9"
909  f716dfbc-b698-432e-a9a4-6b094ad82d99:
910    version: "174"
911  f7442b1f-8a86-467a-8fcb-84b73b11afde:
912    version: "201"
913  f837286a-38b0-4212-a2d3-8ab18ca8ac5b:
914    version: "131"
915  fa6df185-8f2a-4a0b-93e5-cf998470c1e9:
916    version: "198"
917  facaf6f4-8a6e-413e-9cad-34c703ca4880:
918    version: "123"
919  fc6ec52c08857bc55de73bb81c0016d901644fad:
920    version: "56"
921  fd075e95-9646-4eb0-81e3-1842bb82e0e5:
922    version: "146"
923format-version: "2"
924`
925