@@ -80,51 +80,72 @@ func decompressResponse(bodyBytes []byte, contentLength int64, cacheLocator Cach
80
80
return errorFetchingPostgres (err )
81
81
}
82
82
83
+ cacheLocation , _ := cacheLocator ()
84
+
85
+ if err := os .MkdirAll (filepath .Dir (cacheLocation ), 0755 ); err != nil {
86
+ return errorExtractingPostgres (err )
87
+ }
88
+
83
89
for _ , file := range zipReader .File {
84
90
if ! file .FileHeader .FileInfo ().IsDir () && strings .HasSuffix (file .FileHeader .Name , ".txz" ) {
85
- archiveReader , err := file .Open ()
86
- if err != nil {
87
- return errorExtractingPostgres (err )
91
+ if err := decompressSingleFile (file , cacheLocation ); err != nil {
92
+ return err
88
93
}
89
94
90
- archiveBytes , err := io . ReadAll ( archiveReader )
91
- if err != nil {
92
- return errorExtractingPostgres ( err )
93
- }
95
+ // we have successfully found the file, return early
96
+ return nil
97
+ }
98
+ }
94
99
95
- // if multiple processes attempt to extract
96
- // to prevent file corruption when multiple processes attempt to extract at the same time
97
- // first to a cache location, and then move the file into place.
98
- tmp , err := os .CreateTemp ("" , "embedded_postgres" )
99
- if err != nil {
100
- return errorExtractingPostgres (err )
101
- }
100
+ return fmt .Errorf ("error fetching postgres: cannot find binary in archive retrieved from %s" , downloadURL )
101
+ }
102
102
103
- if err := os .WriteFile (tmp .Name (), archiveBytes , file .FileHeader .Mode ()); err != nil {
104
- return errorExtractingPostgres (err )
105
- }
103
+ func decompressSingleFile (file * zip.File , cacheLocation string ) error {
104
+ renamed := false
105
+
106
+ archiveReader , err := file .Open ()
107
+ if err != nil {
108
+ return errorExtractingPostgres (err )
109
+ }
106
110
107
- cacheLocation , _ := cacheLocator ()
111
+ archiveBytes , err := io .ReadAll (archiveReader )
112
+ if err != nil {
113
+ return errorExtractingPostgres (err )
114
+ }
108
115
109
- if err := os .MkdirAll (filepath .Dir (cacheLocation ), 0755 ); err != nil {
110
- return errorExtractingPostgres (err )
116
+ // if multiple processes attempt to extract
117
+ // to prevent file corruption when multiple processes attempt to extract at the same time
118
+ // first to a cache location, and then move the file into place.
119
+ tmp , err := os .CreateTemp (filepath .Dir (cacheLocation ), "temp_" )
120
+ if err != nil {
121
+ return errorExtractingPostgres (err )
122
+ }
123
+ defer func () {
124
+ // if anything failed before the rename then the temporary file should be cleaned up.
125
+ // if the rename was successful then there is no temporary file to remove.
126
+ if ! renamed {
127
+ if err := os .Remove (tmp .Name ()); err != nil {
128
+ panic (err )
111
129
}
130
+ }
131
+ }()
112
132
113
- // Windows cannot rename a file if is it still open.
114
- // The file needs to be manually closed to allow the rename to happen
115
- if err := tmp .Close (); err != nil {
116
- return errorExtractingPostgres (err )
117
- }
133
+ if err := os .WriteFile (tmp .Name (), archiveBytes , file .FileHeader .Mode ()); err != nil {
134
+ return errorExtractingPostgres (err )
135
+ }
118
136
119
- if err := renameOrIgnore (tmp .Name (), cacheLocation ); err != nil {
120
- return errorExtractingPostgres (err )
121
- }
137
+ // Windows cannot rename a file if is it still open.
138
+ // The file needs to be manually closed to allow the rename to happen
139
+ if err := tmp .Close (); err != nil {
140
+ return errorExtractingPostgres (err )
141
+ }
122
142
123
- return nil
124
- }
143
+ if err := renameOrIgnore ( tmp . Name (), cacheLocation ); err != nil {
144
+ return errorExtractingPostgres ( err )
125
145
}
146
+ renamed = true
126
147
127
- return fmt . Errorf ( "error fetching postgres: cannot find binary in archive retrieved from %s" , downloadURL )
148
+ return nil
128
149
}
129
150
130
151
func errorExtractingPostgres (err error ) error {
0 commit comments