forked from cloudfoundry/cli
-
Notifications
You must be signed in to change notification settings - Fork 0
/
push.go
150 lines (126 loc) · 4.46 KB
/
push.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package actors
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/cloudfoundry/cli/cf/api/application_bits"
"github.com/cloudfoundry/cli/cf/api/resources"
"github.com/cloudfoundry/cli/cf/app_files"
"github.com/cloudfoundry/cli/cf/errors"
"github.com/cloudfoundry/cli/cf/models"
"github.com/cloudfoundry/gofileutils/fileutils"
)
//go:generate counterfeiter -o fakes/fake_push_actor.go . PushActor
type PushActor interface {
UploadApp(appGuid string, zipFile *os.File, presentFiles []resources.AppFileResource) error
PopulateFileMode(appDir string, presentFiles []resources.AppFileResource) ([]resources.AppFileResource, error)
GatherFiles(appDir string, uploadDir string) ([]resources.AppFileResource, bool, error)
}
type PushActorImpl struct {
appBitsRepo application_bits.ApplicationBitsRepository
appfiles app_files.AppFiles
zipper app_files.Zipper
}
func NewPushActor(appBitsRepo application_bits.ApplicationBitsRepository, zipper app_files.Zipper, appfiles app_files.AppFiles) PushActor {
return PushActorImpl{
appBitsRepo: appBitsRepo,
appfiles: appfiles,
zipper: zipper,
}
}
func (actor PushActorImpl) PopulateFileMode(appDir string, presentFiles []resources.AppFileResource) ([]resources.AppFileResource, error) {
for i, _ := range presentFiles {
fileInfo, err := os.Lstat(filepath.Join(appDir, presentFiles[i].Path))
if err != nil {
return presentFiles, err
}
presentFiles[i].Mode = fmt.Sprintf("%#o", fileInfo.Mode())
}
return presentFiles, nil
}
func (actor PushActorImpl) GatherFiles(appDir string, uploadDir string) ([]resources.AppFileResource, bool, error) {
var finalDir string
if actor.zipper.IsZipFile(appDir) {
tmpDir, err := ioutil.TempDir("", "unzipped-app")
if err != nil {
return []resources.AppFileResource{}, false, err
}
defer os.RemoveAll(tmpDir)
err = actor.zipper.Unzip(appDir, tmpDir)
if err != nil {
return []resources.AppFileResource{}, false, err
}
finalDir = tmpDir
} else {
finalDir = appDir
}
files, hasFileToUpload, err := actor.copyUploadableFiles(finalDir, uploadDir)
if err != nil {
return []resources.AppFileResource{}, false, err
}
filesWithFileMode, err := actor.PopulateFileMode(finalDir, files)
if err != nil {
return []resources.AppFileResource{}, false, err
}
return filesWithFileMode, hasFileToUpload, nil
}
func (actor PushActorImpl) UploadApp(appGuid string, zipFile *os.File, presentFiles []resources.AppFileResource) error {
return actor.appBitsRepo.UploadBits(appGuid, zipFile, presentFiles)
}
func (actor PushActorImpl) copyUploadableFiles(appDir string, uploadDir string) (presentFiles []resources.AppFileResource, hasFileToUpload bool, err error) {
// Find which files need to be uploaded
var allAppFiles []models.AppFileFields
allAppFiles, err = actor.appfiles.AppFilesInDir(appDir)
if err != nil {
return
}
appFilesToUpload, presentFiles, apiErr := actor.getFilesToUpload(allAppFiles)
if apiErr != nil {
err = errors.New(apiErr.Error())
return
}
hasFileToUpload = len(appFilesToUpload) > 0
// Copy files into a temporary directory and return it
err = actor.appfiles.CopyFiles(appFilesToUpload, appDir, uploadDir)
if err != nil {
return
}
// copy cfignore if present
fileutils.CopyPathToPath(filepath.Join(appDir, ".cfignore"), filepath.Join(uploadDir, ".cfignore")) //error handling?
return
}
func (actor PushActorImpl) getFilesToUpload(allAppFiles []models.AppFileFields) (appFilesToUpload []models.AppFileFields, presentFiles []resources.AppFileResource, apiErr error) {
appFilesRequest := []resources.AppFileResource{}
for _, file := range allAppFiles {
appFilesRequest = append(appFilesRequest, resources.AppFileResource{
Path: file.Path,
Sha1: file.Sha1,
Size: file.Size,
})
}
presentFiles, apiErr = actor.appBitsRepo.GetApplicationFiles(appFilesRequest)
if apiErr != nil {
return nil, nil, apiErr
}
appFilesToUpload = make([]models.AppFileFields, len(allAppFiles))
copy(appFilesToUpload, allAppFiles)
for _, file := range presentFiles {
appFile := models.AppFileFields{
Path: file.Path,
Sha1: file.Sha1,
Size: file.Size,
}
appFilesToUpload = actor.deleteAppFile(appFilesToUpload, appFile)
}
return
}
func (actor PushActorImpl) deleteAppFile(appFiles []models.AppFileFields, targetFile models.AppFileFields) []models.AppFileFields {
for i, file := range appFiles {
if file.Path == targetFile.Path {
appFiles[i] = appFiles[len(appFiles)-1]
return appFiles[:len(appFiles)-1]
}
}
return appFiles
}