// This is essentially the same as tools.MergeAndWriteMetadata, but also // resolves metadata for existing tools by fetching them and computing // size/sha256 locally. func mergeAndWriteMetadata(stor storage.Storage, toolsList coretools.List, writeMirrors envtools.ShouldWriteMirrors) error { existing, err := envtools.ReadMetadata(stor) if err != nil { return err } metadata := envtools.MetadataFromTools(toolsList) if metadata, err = envtools.MergeMetadata(metadata, existing); err != nil { return err } if err = envtools.ResolveMetadata(stor, metadata); err != nil { return err } return envtools.WriteMetadata(stor, metadata, writeMirrors) }
// This is essentially the same as tools.MergeAndWriteMetadata, but also // resolves metadata for existing tools by fetching them and computing // size/sha256 locally. func mergeAndWriteMetadata( stor storage.Storage, toolsDir, stream string, clean bool, toolsList coretools.List, writeMirrors envtools.ShouldWriteMirrors, ) error { existing, err := envtools.ReadAllMetadata(stor) if err != nil { return err } if clean { delete(existing, stream) } metadata := envtools.MetadataFromTools(toolsList, toolsDir) var mergedMetadata []*envtools.ToolsMetadata if mergedMetadata, err = envtools.MergeMetadata(metadata, existing[stream]); err != nil { return err } if err = envtools.ResolveMetadata(stor, toolsDir, mergedMetadata); err != nil { return err } existing[stream] = mergedMetadata return envtools.WriteMetadata(stor, existing, []string{stream}, writeMirrors) }
func (*metadataHelperSuite) TestMergeMetadata(c *gc.C) { md1 := &tools.ToolsMetadata{ Release: "precise", Version: "1.2.3", Arch: "amd64", Path: "path1", } md2 := &tools.ToolsMetadata{ Release: "precise", Version: "1.2.3", Arch: "amd64", Path: "path2", } md3 := &tools.ToolsMetadata{ Release: "raring", Version: "1.2.3", Arch: "amd64", Path: "path3", } withSize := func(md *tools.ToolsMetadata, size int64) *tools.ToolsMetadata { clone := *md clone.Size = size return &clone } withSHA256 := func(md *tools.ToolsMetadata, sha256 string) *tools.ToolsMetadata { clone := *md clone.SHA256 = sha256 return &clone } type mdlist []*tools.ToolsMetadata type test struct { name string lhs, rhs, merged []*tools.ToolsMetadata err string } tests := []test{{ name: "non-empty lhs, empty rhs", lhs: mdlist{md1}, rhs: nil, merged: mdlist{md1}, }, { name: "empty lhs, non-empty rhs", lhs: nil, rhs: mdlist{md2}, merged: mdlist{md2}, }, { name: "identical lhs, rhs", lhs: mdlist{md1}, rhs: mdlist{md1}, merged: mdlist{md1}, }, { name: "same tools in lhs and rhs, neither have size: prefer lhs", lhs: mdlist{md1}, rhs: mdlist{md2}, merged: mdlist{md1}, }, { name: "same tools in lhs and rhs, only lhs has a size: prefer lhs", lhs: mdlist{withSize(md1, 123)}, rhs: mdlist{md2}, merged: mdlist{withSize(md1, 123)}, }, { name: "same tools in lhs and rhs, only rhs has a size: prefer rhs", lhs: mdlist{md1}, rhs: mdlist{withSize(md2, 123)}, merged: mdlist{withSize(md2, 123)}, }, { name: "same tools in lhs and rhs, both have the same size: prefer lhs", lhs: mdlist{withSize(md1, 123)}, rhs: mdlist{withSize(md2, 123)}, merged: mdlist{withSize(md1, 123)}, }, { name: "same tools in lhs and rhs, both have different sizes: error", lhs: mdlist{withSize(md1, 123)}, rhs: mdlist{withSize(md2, 456)}, err: "metadata mismatch for 1\\.2\\.3-precise-amd64: sizes=\\(123,456\\) sha256=\\(,\\)", }, { name: "same tools in lhs and rhs, both have same size but different sha256: error", lhs: mdlist{withSHA256(withSize(md1, 123), "a")}, rhs: mdlist{withSHA256(withSize(md2, 123), "b")}, err: "metadata mismatch for 1\\.2\\.3-precise-amd64: sizes=\\(123,123\\) sha256=\\(a,b\\)", }, { name: "lhs is a proper superset of rhs: union of lhs and rhs", lhs: mdlist{md1, md3}, rhs: mdlist{md1}, merged: mdlist{md1, md3}, }, { name: "rhs is a proper superset of lhs: union of lhs and rhs", lhs: mdlist{md1}, rhs: mdlist{md1, md3}, merged: mdlist{md1, md3}, }} for i, test := range tests { c.Logf("test %d: %s", i, test.name) merged, err := tools.MergeMetadata(test.lhs, test.rhs) if test.err == "" { c.Assert(err, jc.ErrorIsNil) c.Assert(merged, gc.DeepEquals, test.merged) } else { c.Assert(err, gc.ErrorMatches, test.err) c.Assert(merged, gc.IsNil) } } }