github.com/docker/app@v0.9.1-beta3.0.20210611140623-a48f773ab002/internal/packager/extract.go (about) 1 package packager 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 10 "github.com/docker/app/internal" 11 "github.com/docker/app/internal/validator" 12 "github.com/docker/app/loader" 13 "github.com/docker/app/types" 14 "github.com/pkg/errors" 15 ) 16 17 // findApp looks for an app in CWD or subdirs 18 func findApp(cwd string) (string, error) { 19 if strings.HasSuffix(cwd, internal.AppExtension) { 20 return cwd, nil 21 } 22 content, err := ioutil.ReadDir(cwd) 23 if err != nil { 24 return "", errors.Wrap(err, "failed to read current working directory") 25 } 26 hit := "" 27 for _, c := range content { 28 if strings.HasSuffix(c.Name(), internal.AppExtension) { 29 if hit != "" { 30 return "", fmt.Errorf("multiple applications found in current directory, specify the application name on the command line") 31 } 32 hit = c.Name() 33 } 34 } 35 if hit == "" { 36 return "", fmt.Errorf("no application found in current directory") 37 } 38 return filepath.Join(cwd, hit), nil 39 } 40 41 // Extract extracts the app content if argument is an archive, or does nothing if a dir. 42 // It returns source file, effective app name, and cleanup function 43 // If appname is empty, it looks into cwd, and all subdirs for a single matching .dockerapp 44 // If nothing is found, it looks for an image and loads it 45 func Extract(name string, ops ...func(*types.App) error) (*types.App, error) { 46 if name == "" { 47 cwd, err := os.Getwd() 48 if err != nil { 49 return nil, errors.Wrap(err, "cannot resolve current working directory") 50 } 51 if name, err = findApp(cwd); err != nil { 52 return nil, err 53 } 54 } 55 if name == "." { 56 var err error 57 if name, err = os.Getwd(); err != nil { 58 return nil, errors.Wrap(err, "cannot resolve current working directory") 59 } 60 } 61 ops = append(ops, types.WithName(name)) 62 appname := internal.DirNameFromAppName(name) 63 s, err := os.Stat(appname) 64 if err != nil { 65 return nil, errors.Wrapf(err, "cannot locate application %q in filesystem", name) 66 } 67 if s.IsDir() { 68 v := validator.NewValidatorWithDefaults() 69 err := v.Validate(filepath.Join(appname, internal.ComposeFileName)) 70 if err != nil { 71 return nil, err 72 } 73 74 // directory: already decompressed 75 appOpts := append(ops, 76 types.WithPath(appname), 77 types.WithSource(types.AppSourceSplit), 78 ) 79 return loader.LoadFromDirectory(appname, appOpts...) 80 } 81 // not a dir: a tarball package, extract that in a temp dir 82 app, err := loader.LoadFromTar(appname, ops...) 83 if err != nil { 84 return nil, err 85 } 86 app.Source = types.AppSourceArchive 87 return app, nil 88 }