@@ -14,6 +14,13 @@ import (
1414 "github.com/pkg/errors"
1515)
1616
17+ // ExtractedApp represents a potentially extracted application package
18+ type ExtractedApp struct {
19+ OriginalAppName string
20+ AppName string
21+ Cleanup func ()
22+ }
23+
1724var (
1825 noop = func () {}
1926)
@@ -47,7 +54,7 @@ func findApp() (string, error) {
4754}
4855
4956// extractImage extracts a docker application in a docker image to a temporary directory
50- func extractImage (appname string ) (string , func () , error ) {
57+ func extractImage (appname string ) (ExtractedApp , error ) {
5158 var imagename string
5259 if strings .Contains (appname , ":" ) {
5360 nametag := strings .Split (appname , ":" )
@@ -65,42 +72,49 @@ func extractImage(appname string) (string, func(), error) {
6572 }
6673 tempDir , err := ioutil .TempDir ("" , "dockerapp" )
6774 if err != nil {
68- return "" , noop , errors .Wrap (err , "failed to create temporary directory" )
75+ return ExtractedApp {} , errors .Wrap (err , "failed to create temporary directory" )
6976 }
7077 defer os .RemoveAll (tempDir )
7178 err = Load (imagename , tempDir )
7279 if err != nil {
7380 if ! strings .Contains (imagename , "/" ) {
74- return "" , noop , fmt .Errorf ("could not locate application in either filesystem or docker image" )
81+ return ExtractedApp {} , fmt .Errorf ("could not locate application in either filesystem or docker image" )
7582 }
7683 // Try to pull it
7784 cmd := exec .Command ("docker" , "pull" , imagename )
7885 if err := cmd .Run (); err != nil {
79- return "" , noop , fmt .Errorf ("could not locate application in filesystem, docker image or registry" )
86+ return ExtractedApp {} , fmt .Errorf ("could not locate application in filesystem, docker image or registry" )
8087 }
8188 if err := Load (imagename , tempDir ); err != nil {
82- return "" , noop , errors .Wrap (err , "failed to load pulled image" )
89+ return ExtractedApp {} , errors .Wrap (err , "failed to load pulled image" )
8390 }
8491 }
8592 // this gave us a compressed app, run through extract again
86- return Extract (filepath .Join (tempDir , appname ))
93+ appname , cleanup , err := Extract (filepath .Join (tempDir , appname ))
94+ return ExtractedApp {"" , appname , cleanup }, err
95+ }
96+
97+ // Extract extracts the app content if it's an archive or single-file
98+ func Extract (appname string ) (string , func (), error ) {
99+ extracted , err := ExtractWithOrigin (appname )
100+ return extracted .AppName , extracted .Cleanup , err
87101}
88102
89- // Extract extracts the app content if argument is an archive, or does nothing if a dir.
90- // It returns effective app name, and cleanup function
103+ // ExtractWithOrigin extracts the app content if argument is an archive, or does nothing if a dir.
104+ // It returns source file, effective app name, and cleanup function
91105// If appname is empty, it looks into cwd, and all subdirs for a single matching .dockerapp
92106// If nothing is found, it looks for an image and loads it
93- func Extract (appname string ) (string , func () , error ) {
107+ func ExtractWithOrigin (appname string ) (ExtractedApp , error ) {
94108 if appname == "" {
95109 var err error
96110 if appname , err = findApp (); err != nil {
97- return "" , nil , err
111+ return ExtractedApp {} , err
98112 }
99113 }
100114 if appname == "." {
101115 var err error
102116 if appname , err = os .Getwd (); err != nil {
103- return "" , nil , errors .Wrap (err , "cannot resolve current working directory" )
117+ return ExtractedApp {} , errors .Wrap (err , "cannot resolve current working directory" )
104118 }
105119 }
106120 originalAppname := appname
@@ -118,12 +132,12 @@ func Extract(appname string) (string, func(), error) {
118132 }
119133 if s .IsDir () {
120134 // directory: already decompressed
121- return appname , noop , nil
135+ return ExtractedApp { appname , appname , noop } , nil
122136 }
123137 // not a dir: single-file or a tarball package, extract that in a temp dir
124138 tempDir , err := ioutil .TempDir ("" , "dockerapp" )
125139 if err != nil {
126- return "" , noop , errors .Wrap (err , "failed to create temporary directory" )
140+ return ExtractedApp {} , errors .Wrap (err , "failed to create temporary directory" )
127141 }
128142 defer func () {
129143 if err != nil {
@@ -132,16 +146,16 @@ func Extract(appname string) (string, func(), error) {
132146 }()
133147 appDir := filepath .Join (tempDir , filepath .Base (appname ))
134148 if err = os .Mkdir (appDir , 0755 ); err != nil {
135- return "" , noop , errors .Wrap (err , "failed to create application in temporary directory" )
149+ return ExtractedApp {} , errors .Wrap (err , "failed to create application in temporary directory" )
136150 }
137151 if err = extract (appname , appDir ); err == nil {
138- return appDir , func () { os .RemoveAll (tempDir ) }, nil
152+ return ExtractedApp { appname , appDir , func () { os .RemoveAll (tempDir ) } }, nil
139153 }
140154 if err = extractSingleFile (appname , appDir ); err != nil {
141- return "" , noop , err
155+ return ExtractedApp {} , err
142156 }
143157 // not a tarball, single-file then
144- return appDir , func () { os .RemoveAll (tempDir ) }, nil
158+ return ExtractedApp { appname , appDir , func () { os .RemoveAll (tempDir ) } }, nil
145159}
146160
147161func extractSingleFile (appname , appDir string ) error {
@@ -177,6 +191,7 @@ func extract(appname, outputDir string) error {
177191 if err != nil {
178192 return errors .Wrap (err , "failed to open application package" )
179193 }
194+ defer f .Close ()
180195 tarReader := tar .NewReader (f )
181196 outputDir = outputDir + "/"
182197 for {
0 commit comments