| Index: go/src/infra/tools/cipd/deployer_test.go
|
| diff --git a/go/src/infra/tools/cipd/deployer_test.go b/go/src/infra/tools/cipd/deployer_test.go
|
| deleted file mode 100644
|
| index b6b171f25b677b82a4e6d6ddf9fe1e0877701c09..0000000000000000000000000000000000000000
|
| --- a/go/src/infra/tools/cipd/deployer_test.go
|
| +++ /dev/null
|
| @@ -1,469 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -package cipd
|
| -
|
| -import (
|
| - "bytes"
|
| - "fmt"
|
| - "io"
|
| - "io/ioutil"
|
| - "os"
|
| - "path/filepath"
|
| - "sort"
|
| - "testing"
|
| -
|
| - . "github.com/smartystreets/goconvey/convey"
|
| -)
|
| -
|
| -func TestUtilities(t *testing.T) {
|
| - Convey("Given a temp directory", t, func() {
|
| - tempDir, err := ioutil.TempDir("", "cipd_test")
|
| - So(err, ShouldBeNil)
|
| - Reset(func() { os.RemoveAll(tempDir) })
|
| -
|
| - // Wrappers that accept paths relative to tempDir.
|
| - touch := func(rel string) {
|
| - abs := filepath.Join(tempDir, filepath.FromSlash(rel))
|
| - err := os.MkdirAll(filepath.Dir(abs), 0777)
|
| - So(err, ShouldBeNil)
|
| - f, err := os.Create(abs)
|
| - So(err, ShouldBeNil)
|
| - f.Close()
|
| - }
|
| - ensureLink := func(symlinkRel string, target string) error {
|
| - return ensureSymlink(filepath.Join(tempDir, symlinkRel), target)
|
| - }
|
| - readLink := func(symlinkRel string) string {
|
| - val, err := os.Readlink(filepath.Join(tempDir, symlinkRel))
|
| - So(err, ShouldBeNil)
|
| - return val
|
| - }
|
| -
|
| - Convey("ensureSymlink creates new symlink", func() {
|
| - So(ensureLink("symlink", "target"), ShouldBeNil)
|
| - So(readLink("symlink"), ShouldEqual, "target")
|
| - })
|
| -
|
| - Convey("ensureSymlink builds full path", func() {
|
| - So(ensureLink(filepath.Join("a", "b", "c"), "target"), ShouldBeNil)
|
| - So(readLink(filepath.Join("a", "b", "c")), ShouldEqual, "target")
|
| - })
|
| -
|
| - Convey("ensureSymlink replaces existing one", func() {
|
| - So(ensureLink("symlink", "target"), ShouldBeNil)
|
| - So(ensureLink("symlink", "another"), ShouldBeNil)
|
| - So(readLink("symlink"), ShouldEqual, "another")
|
| - })
|
| -
|
| - Convey("scanPackageDir works with empty dir", func() {
|
| - err := os.Mkdir(filepath.Join(tempDir, "dir"), 0777)
|
| - So(err, ShouldBeNil)
|
| - files := makeStringSet()
|
| - err = scanPackageDir(filepath.Join(tempDir, "dir"), files)
|
| - So(err, ShouldBeNil)
|
| - So(len(files), ShouldEqual, 0)
|
| - })
|
| -
|
| - Convey("scanPackageDir works", func() {
|
| - touch("unrelated/1")
|
| - touch("dir/a/1")
|
| - touch("dir/a/2")
|
| - touch("dir/b/1")
|
| - touch("dir/.cipdpkg/abc")
|
| - touch("dir/.cipd/abc")
|
| - ensureLink("dir/a/sym_link", "target")
|
| - files := makeStringSet()
|
| - err := scanPackageDir(filepath.Join(tempDir, "dir"), files)
|
| - So(err, ShouldBeNil)
|
| - names := sort.StringSlice{}
|
| - for n := range files {
|
| - names = append(names, filepath.ToSlash(n))
|
| - }
|
| - names.Sort()
|
| - So(names, ShouldResemble, sort.StringSlice{
|
| - "a/1",
|
| - "a/2",
|
| - "a/sym_link",
|
| - "b/1",
|
| - })
|
| - })
|
| -
|
| - Convey("ensureDirectoryGone works with missing dir", func() {
|
| - So(ensureDirectoryGone(filepath.Join(tempDir, "missing")), ShouldBeNil)
|
| - })
|
| -
|
| - Convey("ensureDirectoryGone works", func() {
|
| - touch("dir/a/1")
|
| - touch("dir/a/2")
|
| - touch("dir/b/1")
|
| - So(ensureDirectoryGone(filepath.Join(tempDir, "dir")), ShouldBeNil)
|
| - _, err := os.Stat(filepath.Join(tempDir, "dir"))
|
| - So(os.IsNotExist(err), ShouldBeTrue)
|
| - })
|
| -
|
| - Convey("ensureFileGone works", func() {
|
| - touch("abc")
|
| - So(ensureFileGone(filepath.Join(tempDir, "abc")), ShouldBeNil)
|
| - _, err := os.Stat(filepath.Join(tempDir, "abc"))
|
| - So(os.IsNotExist(err), ShouldBeTrue)
|
| - })
|
| -
|
| - Convey("ensureFileGone works with missing file", func() {
|
| - So(ensureFileGone(filepath.Join(tempDir, "abc")), ShouldBeNil)
|
| - })
|
| -
|
| - Convey("ensureFileGone works with symlink", func() {
|
| - ensureLink("abc", "target")
|
| - So(ensureFileGone(filepath.Join(tempDir, "abc")), ShouldBeNil)
|
| - _, err := os.Stat(filepath.Join(tempDir, "abc"))
|
| - So(os.IsNotExist(err), ShouldBeTrue)
|
| - })
|
| - })
|
| -}
|
| -
|
| -func TestDeployInstance(t *testing.T) {
|
| - Convey("Given a temp directory", t, func() {
|
| - tempDir, err := ioutil.TempDir("", "cipd_test")
|
| - So(err, ShouldBeNil)
|
| - Reset(func() { os.RemoveAll(tempDir) })
|
| -
|
| - Convey("DeployInstance new empty package instance", func() {
|
| - inst := makeTestInstance("test/package", nil)
|
| - info, err := DeployInstance(tempDir, inst)
|
| - So(err, ShouldBeNil)
|
| - So(info, ShouldResemble, PackageState{
|
| - PackageName: "test/package",
|
| - InstanceID: inst.InstanceID(),
|
| - })
|
| - So(scanDir(tempDir), ShouldResemble, []string{
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/_current:0123456789abcdef00000123456789abcdef0000",
|
| - })
|
| - })
|
| -
|
| - Convey("DeployInstance new non-empty package instance", func() {
|
| - inst := makeTestInstance("test/package", []File{
|
| - makeTestFile("some/file/path", "data a", false),
|
| - makeTestFile("some/executable", "data b", true),
|
| - makeTestSymlink("some/symlink", "executable"),
|
| - })
|
| - _, err := DeployInstance(tempDir, inst)
|
| - So(err, ShouldBeNil)
|
| - So(scanDir(tempDir), ShouldResemble, []string{
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/some/executable*",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/some/file/path",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/some/symlink:executable",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/_current:0123456789abcdef00000123456789abcdef0000",
|
| - "some/executable:../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/executable",
|
| - "some/file/path:../../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/file/path",
|
| - "some/symlink:../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/symlink",
|
| - })
|
| - // Ensure symlinks are actually traversable.
|
| - body, err := ioutil.ReadFile(filepath.Join(tempDir, "some", "file", "path"))
|
| - So(err, ShouldBeNil)
|
| - So(string(body), ShouldEqual, "data a")
|
| - // Symlink to symlink is traversable too.
|
| - body, err = ioutil.ReadFile(filepath.Join(tempDir, "some", "symlink"))
|
| - So(err, ShouldBeNil)
|
| - So(string(body), ShouldEqual, "data b")
|
| - })
|
| -
|
| - Convey("Redeploy same package instance", func() {
|
| - inst := makeTestInstance("test/package", []File{
|
| - makeTestFile("some/file/path", "data a", false),
|
| - makeTestFile("some/executable", "data b", true),
|
| - makeTestSymlink("some/symlink", "executable"),
|
| - })
|
| - _, err := DeployInstance(tempDir, inst)
|
| - So(err, ShouldBeNil)
|
| - _, err = DeployInstance(tempDir, inst)
|
| - So(err, ShouldBeNil)
|
| - So(scanDir(tempDir), ShouldResemble, []string{
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/some/executable*",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/some/file/path",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0123456789abcdef00000123456789abcdef0000/some/symlink:executable",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/_current:0123456789abcdef00000123456789abcdef0000",
|
| - "some/executable:../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/executable",
|
| - "some/file/path:../../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/file/path",
|
| - "some/symlink:../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/symlink",
|
| - })
|
| - })
|
| -
|
| - Convey("DeployInstance package update", func() {
|
| - oldPkg := makeTestInstance("test/package", []File{
|
| - makeTestFile("some/file/path", "data a old", false),
|
| - makeTestFile("some/executable", "data b old", true),
|
| - makeTestFile("old only", "data c old", true),
|
| - makeTestFile("mode change 1", "data d", true),
|
| - makeTestFile("mode change 2", "data e", false),
|
| - makeTestSymlink("symlink unchanged", "target"),
|
| - makeTestSymlink("symlink changed", "old target"),
|
| - makeTestSymlink("symlink removed", "target"),
|
| - })
|
| - oldPkg.instanceID = "0000000000000000000000000000000000000000"
|
| -
|
| - newPkg := makeTestInstance("test/package", []File{
|
| - makeTestFile("some/file/path", "data a new", false),
|
| - makeTestFile("some/executable", "data b new", true),
|
| - makeTestFile("mode change 1", "data d", false),
|
| - makeTestFile("mode change 2", "data d", true),
|
| - makeTestSymlink("symlink unchanged", "target"),
|
| - makeTestSymlink("symlink changed", "new target"),
|
| - })
|
| - newPkg.instanceID = "1111111111111111111111111111111111111111"
|
| -
|
| - _, err := DeployInstance(tempDir, oldPkg)
|
| - So(err, ShouldBeNil)
|
| - _, err = DeployInstance(tempDir, newPkg)
|
| - So(err, ShouldBeNil)
|
| -
|
| - So(scanDir(tempDir), ShouldResemble, []string{
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/mode change 1",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/mode change 2*",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/some/executable*",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/some/file/path",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/symlink changed:new target",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/1111111111111111111111111111111111111111/symlink unchanged:target",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/_current:1111111111111111111111111111111111111111",
|
| - "mode change 1:.cipd/pkgs/test_package_B6R4ErK5ko/_current/mode change 1",
|
| - "mode change 2:.cipd/pkgs/test_package_B6R4ErK5ko/_current/mode change 2",
|
| - "some/executable:../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/executable",
|
| - "some/file/path:../../.cipd/pkgs/test_package_B6R4ErK5ko/_current/some/file/path",
|
| - "symlink changed:.cipd/pkgs/test_package_B6R4ErK5ko/_current/symlink changed",
|
| - "symlink unchanged:.cipd/pkgs/test_package_B6R4ErK5ko/_current/symlink unchanged",
|
| - })
|
| - })
|
| -
|
| - Convey("DeployInstance two different packages", func() {
|
| - pkg1 := makeTestInstance("test/package", []File{
|
| - makeTestFile("some/file/path", "data a old", false),
|
| - makeTestFile("some/executable", "data b old", true),
|
| - makeTestFile("pkg1 file", "data c", false),
|
| - })
|
| - pkg1.instanceID = "0000000000000000000000000000000000000000"
|
| -
|
| - // Nesting in package names is allowed.
|
| - pkg2 := makeTestInstance("test/package/another", []File{
|
| - makeTestFile("some/file/path", "data a new", false),
|
| - makeTestFile("some/executable", "data b new", true),
|
| - makeTestFile("pkg2 file", "data d", false),
|
| - })
|
| - pkg2.instanceID = "1111111111111111111111111111111111111111"
|
| -
|
| - _, err := DeployInstance(tempDir, pkg1)
|
| - So(err, ShouldBeNil)
|
| - _, err = DeployInstance(tempDir, pkg2)
|
| - So(err, ShouldBeNil)
|
| -
|
| - // TODO: Conflicting symlinks point to last installed package, it is not
|
| - // very deterministic.
|
| - So(scanDir(tempDir), ShouldResemble, []string{
|
| - ".cipd/pkgs/package_another_4HL4H61fGm/1111111111111111111111111111111111111111/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/package_another_4HL4H61fGm/1111111111111111111111111111111111111111/pkg2 file",
|
| - ".cipd/pkgs/package_another_4HL4H61fGm/1111111111111111111111111111111111111111/some/executable*",
|
| - ".cipd/pkgs/package_another_4HL4H61fGm/1111111111111111111111111111111111111111/some/file/path",
|
| - ".cipd/pkgs/package_another_4HL4H61fGm/_current:1111111111111111111111111111111111111111",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0000000000000000000000000000000000000000/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0000000000000000000000000000000000000000/pkg1 file",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0000000000000000000000000000000000000000/some/executable*",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/0000000000000000000000000000000000000000/some/file/path",
|
| - ".cipd/pkgs/test_package_B6R4ErK5ko/_current:0000000000000000000000000000000000000000",
|
| - "pkg1 file:.cipd/pkgs/test_package_B6R4ErK5ko/_current/pkg1 file",
|
| - "pkg2 file:.cipd/pkgs/package_another_4HL4H61fGm/_current/pkg2 file",
|
| - "some/executable:../.cipd/pkgs/package_another_4HL4H61fGm/_current/some/executable",
|
| - "some/file/path:../../.cipd/pkgs/package_another_4HL4H61fGm/_current/some/file/path",
|
| - })
|
| - })
|
| -
|
| - Convey("Try to deploy package instance with bad package name", func() {
|
| - _, err := DeployInstance(tempDir, makeTestInstance("../test/package", nil))
|
| - So(err, ShouldNotBeNil)
|
| - })
|
| -
|
| - Convey("Try to deploy package instance with bad instance ID", func() {
|
| - inst := makeTestInstance("test/package", nil)
|
| - inst.instanceID = "../000000000"
|
| - _, err := DeployInstance(tempDir, inst)
|
| - So(err, ShouldNotBeNil)
|
| - })
|
| - })
|
| -}
|
| -
|
| -func TestFindDeployed(t *testing.T) {
|
| - Convey("Given a temp directory", t, func() {
|
| - tempDir, err := ioutil.TempDir("", "cipd_test")
|
| - So(err, ShouldBeNil)
|
| - Reset(func() { os.RemoveAll(tempDir) })
|
| -
|
| - Convey("FindDeployed works with empty dir", func() {
|
| - out, err := FindDeployed(tempDir)
|
| - So(err, ShouldBeNil)
|
| - So(out, ShouldBeNil)
|
| - })
|
| -
|
| - Convey("FindDeployed works", func() {
|
| - // Deploy a bunch of stuff.
|
| - _, err := DeployInstance(tempDir, makeTestInstance("test/pkg/123", nil))
|
| - So(err, ShouldBeNil)
|
| - _, err = DeployInstance(tempDir, makeTestInstance("test/pkg/456", nil))
|
| - So(err, ShouldBeNil)
|
| - _, err = DeployInstance(tempDir, makeTestInstance("test/pkg", nil))
|
| - So(err, ShouldBeNil)
|
| - _, err = DeployInstance(tempDir, makeTestInstance("test", nil))
|
| - So(err, ShouldBeNil)
|
| -
|
| - // Verify it is discoverable.
|
| - out, err := FindDeployed(tempDir)
|
| - So(err, ShouldBeNil)
|
| - So(out, ShouldResemble, []PackageState{
|
| - PackageState{
|
| - PackageName: "test",
|
| - InstanceID: "0123456789abcdef00000123456789abcdef0000",
|
| - },
|
| - PackageState{
|
| - PackageName: "test/pkg",
|
| - InstanceID: "0123456789abcdef00000123456789abcdef0000",
|
| - },
|
| - PackageState{
|
| - PackageName: "test/pkg/123",
|
| - InstanceID: "0123456789abcdef00000123456789abcdef0000",
|
| - },
|
| - PackageState{
|
| - PackageName: "test/pkg/456",
|
| - InstanceID: "0123456789abcdef00000123456789abcdef0000",
|
| - },
|
| - })
|
| - })
|
| - })
|
| -}
|
| -
|
| -func TestRemoveDeployed(t *testing.T) {
|
| - Convey("Given a temp directory", t, func() {
|
| - tempDir, err := ioutil.TempDir("", "cipd_test")
|
| - So(err, ShouldBeNil)
|
| - Reset(func() { os.RemoveAll(tempDir) })
|
| -
|
| - Convey("RemoveDeployed works with missing package", func() {
|
| - err := RemoveDeployed(tempDir, "package/path")
|
| - So(err, ShouldBeNil)
|
| - })
|
| -
|
| - Convey("RemoveDeployed works", func() {
|
| - // Deploy some instance (to keep it).
|
| - inst := makeTestInstance("test/package/123", []File{
|
| - makeTestFile("some/file/path1", "data a", false),
|
| - makeTestFile("some/executable1", "data b", true),
|
| - })
|
| - _, err := DeployInstance(tempDir, inst)
|
| - So(err, ShouldBeNil)
|
| -
|
| - // Deploy another instance (to remove it).
|
| - inst = makeTestInstance("test/package", []File{
|
| - makeTestFile("some/file/path2", "data a", false),
|
| - makeTestFile("some/executable2", "data b", true),
|
| - makeTestSymlink("some/symlink", "executable"),
|
| - })
|
| - _, err = DeployInstance(tempDir, inst)
|
| - So(err, ShouldBeNil)
|
| -
|
| - // Now remove the second package.
|
| - err = RemoveDeployed(tempDir, "test/package")
|
| - So(err, ShouldBeNil)
|
| -
|
| - // Verify the final state (only first package should survive).
|
| - So(scanDir(tempDir), ShouldResemble, []string{
|
| - ".cipd/pkgs/package_123_Wnok5l4iFr/0123456789abcdef00000123456789abcdef0000/.cipdpkg/manifest.json",
|
| - ".cipd/pkgs/package_123_Wnok5l4iFr/0123456789abcdef00000123456789abcdef0000/some/executable1*",
|
| - ".cipd/pkgs/package_123_Wnok5l4iFr/0123456789abcdef00000123456789abcdef0000/some/file/path1",
|
| - ".cipd/pkgs/package_123_Wnok5l4iFr/_current:0123456789abcdef00000123456789abcdef0000",
|
| - "some/executable1:../.cipd/pkgs/package_123_Wnok5l4iFr/_current/some/executable1",
|
| - "some/file/path1:../../.cipd/pkgs/package_123_Wnok5l4iFr/_current/some/file/path1",
|
| - })
|
| - })
|
| - })
|
| -}
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -type testPackageInstance struct {
|
| - packageName string
|
| - instanceID string
|
| - files []File
|
| -}
|
| -
|
| -// makeTestInstance returns PackageInstance implementation with mocked guts.
|
| -func makeTestInstance(name string, files []File) *testPackageInstance {
|
| - // Generate and append manifest file.
|
| - out := bytes.Buffer{}
|
| - err := writeManifest(&Manifest{
|
| - FormatVersion: manifestFormatVersion,
|
| - PackageName: name,
|
| - }, &out)
|
| - if err != nil {
|
| - panic("Failed to write a manifest")
|
| - }
|
| - files = append(files, makeTestFile(manifestName, string(out.Bytes()), false))
|
| - return &testPackageInstance{
|
| - packageName: name,
|
| - instanceID: "0123456789abcdef00000123456789abcdef0000",
|
| - files: files,
|
| - }
|
| -}
|
| -
|
| -func (f *testPackageInstance) Close() error { return nil }
|
| -func (f *testPackageInstance) PackageName() string { return f.packageName }
|
| -func (f *testPackageInstance) InstanceID() string { return f.instanceID }
|
| -func (f *testPackageInstance) Files() []File { return f.files }
|
| -func (f *testPackageInstance) DataReader() io.ReadSeeker { panic("Not implemented") }
|
| -
|
| -////////////////////////////////////////////////////////////////////////////////
|
| -
|
| -// scanDir returns list of files (regular and symlinks) it finds in a directory.
|
| -// Symlinks are returned as "path:target". Regular executable files are suffixed
|
| -// with '*'. All paths are relative to the scanned directory and slash
|
| -// separated. Symlink targets are slash separated too, but otherwise not
|
| -// modified. Does not look inside symlinked directories.
|
| -func scanDir(root string) (out []string) {
|
| - err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
|
| - if err != nil {
|
| - return err
|
| - }
|
| - rel, err := filepath.Rel(root, path)
|
| - if err != nil {
|
| - return err
|
| - }
|
| - if info.Mode().IsDir() {
|
| - return nil
|
| - }
|
| -
|
| - rel = filepath.ToSlash(rel)
|
| - target, err := os.Readlink(path)
|
| - var item string
|
| - if err == nil {
|
| - item = fmt.Sprintf("%s:%s", rel, filepath.ToSlash(target))
|
| - } else {
|
| - if info.Mode().IsRegular() {
|
| - item = rel
|
| - } else {
|
| - item = fmt.Sprintf("%s:??????", rel)
|
| - }
|
| - }
|
| -
|
| - suffix := ""
|
| - if info.Mode().IsRegular() && (info.Mode().Perm()&0100) != 0 {
|
| - suffix = "*"
|
| - }
|
| -
|
| - out = append(out, item+suffix)
|
| - return nil
|
| - })
|
| - if err != nil {
|
| - panic("Failed to walk a directory")
|
| - }
|
| - return
|
| -}
|
|
|