Skip to content
This repository has been archived by the owner on Mar 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #844 from laverya/copy-local-files
Browse files Browse the repository at this point in the history
copy, not symlink, local files
  • Loading branch information
laverya authored Feb 26, 2019
2 parents 80d5281 + e4fd25d commit 7656021
Show file tree
Hide file tree
Showing 4 changed files with 250 additions and 3 deletions.
6 changes: 6 additions & 0 deletions pkg/specs/apptype/determine_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/replicatedhq/ship/pkg/constants"
"github.com/replicatedhq/ship/pkg/specs/githubclient"
"github.com/replicatedhq/ship/pkg/specs/gogetter"
"github.com/replicatedhq/ship/pkg/specs/localgetter"
"github.com/replicatedhq/ship/pkg/state"
"github.com/replicatedhq/ship/pkg/util"
errors2 "github.com/replicatedhq/ship/pkg/util/errors"
Expand Down Expand Up @@ -86,6 +87,11 @@ func (r *inspector) DetermineApplicationType(ctx context.Context, upstream strin
return r.determineTypeFromContents(ctx, upstream, githubClient)
}

if localgetter.IsLocalFile(&r.fs, upstream) {
fetcher := localgetter.LocalGetter{Logger: r.logger, FS: r.fs}
return r.determineTypeFromContents(ctx, upstream, &fetcher)
}

upstream, subdir, isSingleFile := gogetter.UntreeGithub(upstream)
if !isSingleFile {
isSingleFile = gogetter.IsShipYaml(upstream)
Expand Down
6 changes: 3 additions & 3 deletions pkg/specs/gogetter/go_getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ func (g *GoGetter) GetFiles(ctx context.Context, upstream, savePath string) (str
}

if g.IsSingleFile {
debug.Log("event", "gogetter.GetSingleFile", "upstream", upstream, "savePath", savePath)
return g.GetSingleFile(ctx, upstream, savePath)
debug.Log("event", "gogetter.getSingleFile", "upstream", upstream, "savePath", savePath)
return g.getSingleFile(ctx, upstream, savePath)
}

err = getter.GetAny(savePath, upstream)
Expand Down Expand Up @@ -65,7 +65,7 @@ func (g *GoGetter) GetFiles(ctx context.Context, upstream, savePath string) (str
return filepath.Join(savePath, g.Subdir), nil
}

func (g *GoGetter) GetSingleFile(ctx context.Context, upstream, savePath string) (string, error) {
func (g *GoGetter) getSingleFile(ctx context.Context, upstream, savePath string) (string, error) {
tmpDir := filepath.Join(constants.ShipPathInternalTmp, "gogetter-file")

err := getter.GetAny(tmpDir, upstream)
Expand Down
96 changes: 96 additions & 0 deletions pkg/specs/localgetter/local_getter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package localgetter

import (
"context"
"os"
"path/filepath"

"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/level"
"github.com/pkg/errors"
"github.com/spf13/afero"
)

type LocalGetter struct {
Logger log.Logger
FS afero.Afero
}

func (g *LocalGetter) GetFiles(ctx context.Context, upstream, savePath string) (string, error) {
debug := level.Debug(g.Logger)
debug.Log("event", "localgetter.GetFiles", "upstream", upstream, "savePath", savePath)

err := g.copyDir(ctx, upstream, savePath)
if err != nil {
return "", errors.Wrap(err, "copy files")
}
return savePath, nil
}

func (g *LocalGetter) copyDir(ctx context.Context, upstream, savePath string) error {
isDir, err := g.FS.IsDir(upstream)
if err != nil {
return errors.Wrapf(err, "check if %s is dir", upstream)
}
if !isDir {
// copy a single file
return g.copyFile(ctx, upstream, savePath, os.FileMode(777))
}

files, err := g.FS.ReadDir(upstream)
if err != nil {
return errors.Wrapf(err, "read files in dir %s", upstream)
}

for _, file := range files {
loopFile := filepath.Join(upstream, file.Name())
loopDest := filepath.Join(savePath, file.Name())
if file.IsDir() {
err = g.FS.MkdirAll(loopDest, file.Mode())
if err != nil {
return errors.Wrapf(err, "create dest dir %s", loopDest)
}

err = g.copyDir(ctx, loopFile, loopDest)
if err != nil {
return errors.Wrapf(err, "copy dir %s", file.Name())
}
} else {
err = g.copyFile(ctx, loopFile, loopDest, file.Mode())
if err != nil {
return errors.Wrapf(err, "copy file %s", file.Name())
}
}
}
return nil
}

func (g *LocalGetter) copyFile(ctx context.Context, upstream, savePath string, mode os.FileMode) error {
saveDir := filepath.Dir(savePath)
exists, err := g.FS.Exists(saveDir)
if err != nil {
return errors.Wrapf(err, "determine if path %s exists", saveDir)
}
if !exists {
err = g.FS.MkdirAll(saveDir, os.ModePerm)
if err != nil {
return errors.Wrapf(err, "create dest dir %s", saveDir)
}
}

contents, err := g.FS.ReadFile(upstream)
if err != nil {
return errors.Wrapf(err, "read %s file contents", upstream)
}

err = g.FS.WriteFile(savePath, contents, mode)
return errors.Wrapf(err, "write %s file contents", savePath)
}

func IsLocalFile(FS *afero.Afero, upstream string) bool {
exists, err := FS.Exists(upstream)
if err != nil {
return false
}
return exists
}
145 changes: 145 additions & 0 deletions pkg/specs/localgetter/local_getter_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package localgetter

import (
"context"
"os"
"path/filepath"
"testing"

"github.com/go-kit/kit/log"
"github.com/spf13/afero"
"github.com/stretchr/testify/require"
)

func TestLocalGetter_copyDir(t *testing.T) {
type file struct {
contents []byte
path string
}
tests := []struct {
name string
upstream string
savePath string
inFiles []file
outFiles []file
wantErr bool
}{
{
name: "single file",
upstream: "/upstream/file",
savePath: "/save/file",
inFiles: []file{
{
contents: []byte("hello world"),
path: "/upstream/file",
},
},
outFiles: []file{
{
contents: []byte("hello world"),
path: "/upstream/file",
},
{
contents: []byte("hello world"),
path: "/save/file",
},
},
},
{
name: "single file in dir",
upstream: "/upstream/dir",
savePath: "/save/dir",
inFiles: []file{
{
contents: []byte("hello world"),
path: "/upstream/dir/file",
},
},
outFiles: []file{
{
contents: []byte("hello world"),
path: "/upstream/dir/file",
},
{
contents: []byte("hello world"),
path: "/save/dir/file",
},
},
},
{
name: "file plus subdirs",
upstream: "/upstream/",
savePath: "/save/",
inFiles: []file{
{
contents: []byte("hello world"),
path: "/upstream/dir/file",
},
{
contents: []byte("abc xyz"),
path: "/upstream/dir2/file",
},
{
contents: []byte("123456789"),
path: "/upstream/file",
},
},
outFiles: []file{
{
contents: []byte("hello world"),
path: "/upstream/dir/file",
},
{
contents: []byte("abc xyz"),
path: "/upstream/dir2/file",
},
{
contents: []byte("123456789"),
path: "/upstream/file",
},
{
contents: []byte("hello world"),
path: "/save/dir/file",
},
{
contents: []byte("abc xyz"),
path: "/save/dir2/file",
},
{
contents: []byte("123456789"),
path: "/save/file",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req := require.New(t)

mmFs := afero.Afero{Fs: afero.NewMemMapFs()}

g := &LocalGetter{
Logger: log.NewNopLogger(),
FS: mmFs,
}

for _, file := range tt.inFiles {
req.NoError(mmFs.MkdirAll(filepath.Dir(file.path), os.ModePerm))
req.NoError(mmFs.WriteFile(file.path, file.contents, os.ModePerm))
}

err := g.copyDir(context.Background(), tt.upstream, tt.savePath)
if tt.wantErr {
req.Error(err)
} else {
req.NoError(err)
}

for _, file := range tt.outFiles {
contents, err := mmFs.ReadFile(file.path)
req.NoError(err)
req.Equal(file.contents, contents, "expected equal contents: expected %q, got %q", string(file.contents), string(contents))
}
})
}
}

0 comments on commit 7656021

Please sign in to comment.