@@ -32,6 +32,7 @@ import (
3232 "bytes"
3333 "compress/bzip2"
3434 "compress/gzip"
35+ "context"
3536 "io"
3637 "io/ioutil"
3738 "os"
@@ -52,44 +53,29 @@ type Renamer func(string) string
5253// It automatically detects the archive type and accepts a rename function to
5354// handle the names of the files.
5455// If the file is not an archive, an error is returned.
55- func Archive (body io.Reader , location string , rename Renamer ) error {
56- dummy := make (chan bool , 1 )
57- defer close (dummy )
58- return ArchiveCancel (body , location , rename , dummy )
59- }
60-
61- // ArchiveCancel is the same as Archive but with an extra channel to stop
62- // the extraction.
63- func ArchiveCancel (body io.Reader , location string , rename Renamer , cancel <- chan bool ) error {
56+ func Archive (ctx context.Context , body io.Reader , location string , rename Renamer ) error {
6457 body , kind , err := match (body )
6558 if err != nil {
6659 errors .Annotatef (err , "Detect archive type" )
6760 }
6861
6962 switch kind .Extension {
7063 case "zip" :
71- return ZipCancel ( body , location , rename , cancel )
64+ return Zip ( ctx , body , location , rename )
7265 case "gz" :
73- return GzCancel ( body , location , rename , cancel )
66+ return Gz ( ctx , body , location , rename )
7467 case "bz2" :
75- return Bz2Cancel ( body , location , rename , cancel )
68+ return Bz2 ( ctx , body , location , rename )
7669 case "tar" :
77- return TarCancel ( body , location , rename , cancel )
70+ return Tar ( ctx , body , location , rename )
7871 default :
7972 return errors .New ("Not a supported archive" )
8073 }
8174}
8275
8376// Bz2 extracts a .bz2 or .tar.bz2 archived stream of data in the specified location.
8477// It accepts a rename function to handle the names of the files (see the example)
85- func Bz2 (body io.Reader , location string , rename Renamer ) error {
86- dummy := make (chan bool , 1 )
87- defer close (dummy )
88- return Bz2Cancel (body , location , rename , dummy )
89- }
90-
91- // Bz2Cancel is the same as Bz2 but with an extra channel to stop the extraction.
92- func Bz2Cancel (body io.Reader , location string , rename Renamer , cancel <- chan bool ) error {
78+ func Bz2 (ctx context.Context , body io.Reader , location string , rename Renamer ) error {
9379 reader := bzip2 .NewReader (body )
9480
9581 body , kind , err := match (reader )
@@ -98,10 +84,10 @@ func Bz2Cancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
9884 }
9985
10086 if kind .Extension == "tar" {
101- return TarCancel ( body , location , rename , cancel )
87+ return Tar ( ctx , body , location , rename )
10288 }
10389
104- err = copy (location , 0666 , body , cancel )
90+ err = copy (ctx , location , 0666 , body )
10591 if err != nil {
10692 return err
10793 }
@@ -110,14 +96,7 @@ func Bz2Cancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
11096
11197// Gz extracts a .gz or .tar.gz archived stream of data in the specified location.
11298// It accepts a rename function to handle the names of the files (see the example)
113- func Gz (body io.Reader , location string , rename Renamer ) error {
114- dummy := make (chan bool , 1 )
115- defer close (dummy )
116- return GzCancel (body , location , rename , dummy )
117- }
118-
119- // GzCancel is the same as Gz but with an extra channel to stop the extraction.
120- func GzCancel (body io.Reader , location string , rename Renamer , cancel <- chan bool ) error {
99+ func Gz (ctx context.Context , body io.Reader , location string , rename Renamer ) error {
121100 reader , err := gzip .NewReader (body )
122101 if err != nil {
123102 return errors .Annotatef (err , "Gunzip" )
@@ -129,9 +108,9 @@ func GzCancel(body io.Reader, location string, rename Renamer, cancel <-chan boo
129108 }
130109
131110 if kind .Extension == "tar" {
132- return TarCancel ( body , location , rename , cancel )
111+ return Tar ( ctx , body , location , rename )
133112 }
134- err = copy (location , 0666 , body , cancel )
113+ err = copy (ctx , location , 0666 , body )
135114 if err != nil {
136115 return err
137116 }
@@ -150,14 +129,7 @@ type link struct {
150129
151130// Tar extracts a .tar archived stream of data in the specified location.
152131// It accepts a rename function to handle the names of the files (see the example)
153- func Tar (body io.Reader , location string , rename Renamer ) error {
154- dummy := make (chan bool , 1 )
155- defer close (dummy )
156- return TarCancel (body , location , rename , dummy )
157- }
158-
159- // TarCancel is the same as Tar but with an extra channel to stop the extraction.
160- func TarCancel (body io.Reader , location string , rename Renamer , cancel <- chan bool ) error {
132+ func Tar (ctx context.Context , body io.Reader , location string , rename Renamer ) error {
161133 files := []file {}
162134 links := []link {}
163135 symlinks := []link {}
@@ -167,7 +139,7 @@ func TarCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
167139 tr := tar .NewReader (body )
168140 for {
169141 select {
170- case <- cancel :
142+ case <- ctx . Done () :
171143 return errors .New ("interrupted" )
172144 default :
173145 }
@@ -200,7 +172,7 @@ func TarCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
200172 }
201173 case tar .TypeReg , tar .TypeRegA :
202174 var data bytes.Buffer
203- if _ , err := copyCancel (& data , tr , cancel ); err != nil {
175+ if _ , err := copyCancel (ctx , & data , tr ); err != nil {
204176 return errors .Annotatef (err , "Read contents of file %s" , path )
205177 }
206178 files = append (files , file {Path : path , Mode : info .Mode (), Data : data })
@@ -219,14 +191,14 @@ func TarCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
219191
220192 // Now we make another pass creating the files and links
221193 for i := range files {
222- if err := copy (files [i ].Path , files [i ].Mode , & files [i ].Data , cancel ); err != nil {
194+ if err := copy (ctx , files [i ].Path , files [i ].Mode , & files [i ].Data ); err != nil {
223195 return errors .Annotatef (err , "Create file %s" , files [i ].Path )
224196 }
225197 }
226198
227199 for i := range links {
228200 select {
229- case <- cancel :
201+ case <- ctx . Done () :
230202 return errors .New ("interrupted" )
231203 default :
232204 }
@@ -237,7 +209,7 @@ func TarCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
237209
238210 for i := range symlinks {
239211 select {
240- case <- cancel :
212+ case <- ctx . Done () :
241213 return errors .New ("interrupted" )
242214 default :
243215 }
@@ -250,17 +222,10 @@ func TarCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
250222
251223// Zip extracts a .zip archived stream of data in the specified location.
252224// It accepts a rename function to handle the names of the files (see the example).
253- func Zip (body io.Reader , location string , rename Renamer ) error {
254- dummy := make (chan bool , 1 )
255- defer close (dummy )
256- return ZipCancel (body , location , rename , dummy )
257- }
258-
259- // ZipCancel is the same as Bz2 but with an extra channel to stop the extraction.
260- func ZipCancel (body io.Reader , location string , rename Renamer , cancel <- chan bool ) error {
225+ func Zip (ctx context.Context , body io.Reader , location string , rename Renamer ) error {
261226 // read the whole body into a buffer. Not sure this is the best way to do it
262227 buffer := bytes .NewBuffer ([]byte {})
263- copyCancel (buffer , body , cancel )
228+ copyCancel (ctx , buffer , body )
264229
265230 archive , err := zip .NewReader (bytes .NewReader (buffer .Bytes ()), int64 (buffer .Len ()))
266231 if err != nil {
@@ -274,7 +239,7 @@ func ZipCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
274239 // attempting to create a file where there's no folder
275240 for _ , header := range archive .File {
276241 select {
277- case <- cancel :
242+ case <- ctx . Done () :
278243 return errors .New ("interrupted" )
279244 default :
280245 }
@@ -313,7 +278,7 @@ func ZipCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
313278 return errors .Annotatef (err , "Open file %s" , path )
314279 }
315280 var data bytes.Buffer
316- if _ , err := copyCancel (& data , f , cancel ); err != nil {
281+ if _ , err := copyCancel (ctx , & data , f ); err != nil {
317282 return errors .Annotatef (err , "Read contents of file %s" , path )
318283 }
319284 files = append (files , file {Path : path , Mode : info .Mode (), Data : data })
@@ -322,14 +287,14 @@ func ZipCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
322287
323288 // Now we make another pass creating the files and links
324289 for i := range files {
325- if err := copy (files [i ].Path , files [i ].Mode , & files [i ].Data , cancel ); err != nil {
290+ if err := copy (ctx , files [i ].Path , files [i ].Mode , & files [i ].Data ); err != nil {
326291 return errors .Annotatef (err , "Create file %s" , files [i ].Path )
327292 }
328293 }
329294
330295 for i := range links {
331296 select {
332- case <- cancel :
297+ case <- ctx . Done () :
333298 return errors .New ("interrupted" )
334299 default :
335300 }
@@ -341,7 +306,7 @@ func ZipCancel(body io.Reader, location string, rename Renamer, cancel <-chan bo
341306 return nil
342307}
343308
344- func copy (path string , mode os.FileMode , src io.Reader , cancel <- chan bool ) error {
309+ func copy (ctx context. Context , path string , mode os.FileMode , src io.Reader ) error {
345310 // We add the execution permission to be able to create files inside it
346311 err := os .MkdirAll (filepath .Dir (path ), mode | os .ModeDir | 100 )
347312 if err != nil {
@@ -352,7 +317,7 @@ func copy(path string, mode os.FileMode, src io.Reader, cancel <-chan bool) erro
352317 return err
353318 }
354319 defer file .Close ()
355- _ , err = copyCancel (file , src , cancel )
320+ _ , err = copyCancel (ctx , file , src )
356321 return err
357322}
358323
0 commit comments