github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/app/fetcher_file.go (about) 1 package app 2 3 import ( 4 "io" 5 "net/url" 6 "os" 7 "path/filepath" 8 9 "github.com/cozy/cozy-stack/pkg/appfs" 10 "github.com/cozy/cozy-stack/pkg/logger" 11 "github.com/cozy/cozy-stack/pkg/utils" 12 ) 13 14 type fileFetcher struct { 15 manFilename string 16 log logger.Logger 17 } 18 19 // The file fetcher is mostly used in development mode. The version of the 20 // application installed with this mode is appended with a random number so 21 // that multiple version can be installed from the same directory without 22 // having to increase the version number from the manifest. 23 func newFileFetcher(manFilename string, log logger.Logger) *fileFetcher { 24 return &fileFetcher{ 25 manFilename: manFilename, 26 log: log, 27 } 28 } 29 30 func (f *fileFetcher) FetchManifest(src *url.URL) (io.ReadCloser, error) { 31 r, err := os.Open(filepath.Join(src.Path, f.manFilename)) 32 if os.IsNotExist(err) { 33 return nil, ErrManifestNotReachable 34 } 35 if err != nil { 36 return nil, err 37 } 38 return r, nil 39 } 40 41 func (f *fileFetcher) Fetch(src *url.URL, fs appfs.Copier, man Manifest) (err error) { 42 version := man.Version() + "-" + utils.RandomString(10) 43 man.SetVersion(version) 44 exists, err := fs.Start(man.Slug(), man.Version(), "") 45 if err != nil || exists { 46 return err 47 } 48 defer func() { 49 if err != nil { 50 _ = fs.Abort() 51 } else { 52 err = fs.Commit() 53 } 54 }() 55 return copyRec(src.Path, "/", fs) 56 } 57 58 func copyRec(root, path string, fs appfs.Copier) error { 59 files, err := os.ReadDir(filepath.Join(root, path)) 60 if err != nil { 61 return err 62 } 63 for _, file := range files { 64 relpath := filepath.Join(path, file.Name()) 65 if file.IsDir() { 66 if file.Name() == ".git" { 67 continue 68 } 69 if err = copyRec(root, relpath, fs); err != nil { 70 return err 71 } 72 continue 73 } 74 fullpath := filepath.Join(root, path, file.Name()) 75 f, err := os.Open(fullpath) 76 if err != nil { 77 return err 78 } 79 fileinfo, err := file.Info() 80 if err != nil { 81 return err 82 } 83 info := appfs.NewFileInfo(relpath, fileinfo.Size(), fileinfo.Mode()) 84 err = fs.Copy(info, f) 85 f.Close() 86 if err != nil { 87 return err 88 } 89 } 90 return nil 91 }