diff --git a/.appveyor.yml b/.appveyor.yml index e4a66fe..220a3ca 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -16,6 +16,6 @@ install: - 7z x -y cf-cli.zip - choco install virtualbox - choco install docker-machine -- docker-machine create -d virtualbox --virtualbox-no-vtx-check --virtualbox-nat-nictype "Am79C973" --virtualbox-hostonly-nictype "Am79C973" default -- docker-machine env --shell powershell default | iex -- docker run -it --rm cloudfoundry/cflinuxfs2 ls +#- docker-machine create -d virtualbox --virtualbox-no-vtx-check --virtualbox-nat-nictype "Am79C973" --virtualbox-hostonly-nictype "Am79C973" default +#- docker-machine env --shell powershell default | iex +#- docker run -it --rm cloudfoundry/cflinuxfs2 ls diff --git a/README.md b/README.md index 53f46dd..d37b982 100644 --- a/README.md +++ b/README.md @@ -163,6 +163,10 @@ OK Plugin cflocal successfully uninstalled. ``` +## Known Issues + +* JAR files currently must be unzipped to push + ## Security Notes * Service forwarding tunnels are not active during staging @@ -171,14 +175,8 @@ Plugin cflocal successfully uninstalled. * CF Local should not be used to download untrusted CF applications * CF Local is not intended for production use and is offered without warranty -# Major Issues - -* No support for .cfignore files -* JAR files must be unzipped to push - ## TODO -* Respect .cfignore * Issue #4 * Allow local buildpacks to be specified * Permit specification of cflinuxfs2 version diff --git a/cf/cmd/cmd.go b/cf/cmd/cmd.go index d8b231d..f801490 100644 --- a/cf/cmd/cmd.go +++ b/cf/cmd/cmd.go @@ -46,10 +46,10 @@ type Runner interface { //go:generate mockgen -package mocks -destination mocks/fs.go github.com/sclevine/cflocal/cf/cmd FS type FS interface { - Tar(path string) (io.ReadCloser, error) - OpenFile(path string) (fs.ReadResetWriteCloser, int64, error) + TarApp(path string) (io.ReadCloser, error) ReadFile(path string) (io.ReadCloser, int64, error) WriteFile(path string) (io.WriteCloser, error) + OpenFile(path string) (fs.ReadResetWriteCloser, int64, error) MakeDirAll(path string) error IsDirEmpty(path string) (bool, error) Abs(path string) (string, error) diff --git a/cf/cmd/mocks/fs.go b/cf/cmd/mocks/fs.go index 65e3a9f..000aa0d 100644 --- a/cf/cmd/mocks/fs.go +++ b/cf/cmd/mocks/fs.go @@ -86,15 +86,15 @@ func (_mr *_MockFSRecorder) ReadFile(arg0 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "ReadFile", arg0) } -func (_m *MockFS) Tar(_param0 string) (io.ReadCloser, error) { - ret := _m.ctrl.Call(_m, "Tar", _param0) +func (_m *MockFS) TarApp(_param0 string) (io.ReadCloser, error) { + ret := _m.ctrl.Call(_m, "TarApp", _param0) ret0, _ := ret[0].(io.ReadCloser) ret1, _ := ret[1].(error) return ret0, ret1 } -func (_mr *_MockFSRecorder) Tar(arg0 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "Tar", arg0) +func (_mr *_MockFSRecorder) TarApp(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "TarApp", arg0) } func (_m *MockFS) WriteFile(_param0 string) (io.WriteCloser, error) { diff --git a/cf/cmd/stage.go b/cf/cmd/stage.go index c02b279..5fa4a90 100644 --- a/cf/cmd/stage.go +++ b/cf/cmd/stage.go @@ -42,7 +42,7 @@ func (s *Stage) Run(args []string) error { if err != nil { return err } - appTar, err := s.FS.Tar(".") + appTar, err := s.FS.TarApp(".") if err != nil { return err } diff --git a/fixtures/go-app/.cfignore b/fixtures/go-app/.cfignore new file mode 100644 index 0000000..526fd03 --- /dev/null +++ b/fixtures/go-app/.cfignore @@ -0,0 +1,2 @@ +/broken.go +!main.go diff --git a/fixtures/go-app/broken.go b/fixtures/go-app/broken.go new file mode 100644 index 0000000..e3b0f5f --- /dev/null +++ b/fixtures/go-app/broken.go @@ -0,0 +1,3 @@ +package main + +const broken = valueNotPresent diff --git a/fs/fs.go b/fs/fs.go index 963ea6c..a045f1f 100644 --- a/fs/fs.go +++ b/fs/fs.go @@ -4,32 +4,50 @@ import ( "io" "os" "path/filepath" + "regexp" + "code.cloudfoundry.org/cli/cf/appfiles" "github.com/docker/docker/pkg/archive" ) type FS struct{} -func (f *FS) Tar(path string) (io.ReadCloser, error) { +func (f *FS) TarApp(path string) (io.ReadCloser, error) { absPath, err := filepath.Abs(path) if err != nil { return nil, err } - // TODO: ignore these files in subdirs + obey .cfignore + files, err := appFiles(absPath) + if err != nil { + return nil, err + } return archive.TarWithOptions(absPath, &archive.TarOptions{ - ExcludePatterns: []string{ - "*.droplet", - ".*.cache", - ".cfignore", - "manifest.yml", - ".gitignore", - ".git", - ".hg", - ".svn", - "_darcs", - ".DS_Store", - }, + IncludeFiles: files, + }) +} + +func appFiles(path string) ([]string, error) { + var files []string + err := appfiles.ApplicationFiles{}.WalkAppFiles(path, func(relpath string, fullpath string) error { + filename := filepath.Base(relpath) + switch { + case + regexp.MustCompile(`^.+\.droplet$`).MatchString(filename), + regexp.MustCompile(`^\..+\.cache$`).MatchString(filename): + return nil + } + files = append(files, relpath) + return nil }) + return files, err +} + +func (f *FS) ReadFile(path string) (io.ReadCloser, int64, error) { + return f.openFile(path, os.O_RDONLY, 0) +} + +func (f *FS) WriteFile(path string) (io.WriteCloser, error) { + return os.Create(path) } type ReadResetWriteCloser interface { @@ -53,10 +71,6 @@ func (r resetFile) Reset() error { return r.Truncate(0) } -func (f *FS) ReadFile(path string) (io.ReadCloser, int64, error) { - return f.openFile(path, os.O_RDONLY, 0) -} - func (f *FS) openFile(path string, flag int, perm os.FileMode) (*os.File, int64, error) { file, err := os.OpenFile(path, flag, perm) if err != nil { @@ -69,10 +83,6 @@ func (f *FS) openFile(path string, flag int, perm os.FileMode) (*os.File, int64, return file, fileInfo.Size(), nil } -func (f *FS) WriteFile(path string) (io.WriteCloser, error) { - return os.Create(path) -} - func (f *FS) MakeDirAll(path string) error { return os.MkdirAll(path, 0777) }