1
1
// Copyright 2020 The Gitea Authors. All rights reserved.
2
2
// SPDX-License-Identifier: MIT
3
3
4
- //go:build bindata
5
-
6
4
package cmd
7
5
8
6
import (
9
7
"errors"
10
8
"fmt"
11
9
"os"
12
10
"path/filepath"
13
- "sort"
14
11
"strings"
15
12
13
+ "code.gitea.io/gitea/modules/assetfs"
16
14
"code.gitea.io/gitea/modules/log"
17
15
"code.gitea.io/gitea/modules/options"
18
16
"code.gitea.io/gitea/modules/public"
@@ -89,24 +87,20 @@ var (
89
87
},
90
88
}
91
89
92
- sections map [string ]* section
93
- assets []asset
90
+ matchedAssetFiles []assetFile
94
91
)
95
92
96
- type section struct {
97
- Path string
98
- Names func () []string
99
- IsDir func (string ) (bool , error )
100
- Asset func (string ) ([]byte , error )
101
- }
102
-
103
- type asset struct {
104
- Section * section
105
- Name string
106
- Path string
93
+ type assetFile struct {
94
+ fs * assetfs.LayeredFS
95
+ name string
96
+ path string
107
97
}
108
98
109
99
func initEmbeddedExtractor (c * cli.Context ) error {
100
+ // FIXME: there is a bug, if the user runs `gitea embedded` with a different user or root,
101
+ // The setting.Init (loadRunModeFrom) will fail and do log.Fatal
102
+ // But the console logger has been deleted, so nothing is printed, the user sees nothing and Gitea just exits.
103
+
110
104
// Silence the console logger
111
105
log .DelNamedLogger ("console" )
112
106
log .DelNamedLogger (log .DEFAULT )
@@ -115,24 +109,14 @@ func initEmbeddedExtractor(c *cli.Context) error {
115
109
setting .InitProviderAllowEmpty ()
116
110
setting .LoadCommonSettings ()
117
111
118
- pats , err := getPatterns (c .Args ())
112
+ patterns , err := compileCollectPatterns (c .Args ())
119
113
if err != nil {
120
114
return err
121
115
}
122
- sections := make (map [string ]* section , 3 )
123
-
124
- sections ["public" ] = & section {Path : "public" , Names : public .AssetNames , IsDir : public .AssetIsDir , Asset : public .Asset }
125
- sections ["options" ] = & section {Path : "options" , Names : options .AssetNames , IsDir : options .AssetIsDir , Asset : options .Asset }
126
- sections ["templates" ] = & section {Path : "templates" , Names : templates .BuiltinAssetNames , IsDir : templates .BuiltinAssetIsDir , Asset : templates .BuiltinAsset }
127
116
128
- for _ , sec := range sections {
129
- assets = append (assets , buildAssetList (sec , pats , c )... )
130
- }
131
-
132
- // Sort assets
133
- sort .SliceStable (assets , func (i , j int ) bool {
134
- return assets [i ].Path < assets [j ].Path
135
- })
117
+ collectAssetFilesByPattern (c , patterns , "options" , options .BuiltinAssets ())
118
+ collectAssetFilesByPattern (c , patterns , "public" , public .BuiltinAssets ())
119
+ collectAssetFilesByPattern (c , patterns , "templates" , templates .BuiltinAssets ())
136
120
137
121
return nil
138
122
}
@@ -166,8 +150,8 @@ func runListDo(c *cli.Context) error {
166
150
return err
167
151
}
168
152
169
- for _ , a := range assets {
170
- fmt .Println (a .Path )
153
+ for _ , a := range matchedAssetFiles {
154
+ fmt .Println (a .path )
171
155
}
172
156
173
157
return nil
@@ -178,19 +162,19 @@ func runViewDo(c *cli.Context) error {
178
162
return err
179
163
}
180
164
181
- if len (assets ) == 0 {
182
- return fmt .Errorf ("No files matched the given pattern" )
183
- } else if len (assets ) > 1 {
184
- return fmt .Errorf ("Too many files matched the given pattern; try to be more specific" )
165
+ if len (matchedAssetFiles ) == 0 {
166
+ return fmt .Errorf ("no files matched the given pattern" )
167
+ } else if len (matchedAssetFiles ) > 1 {
168
+ return fmt .Errorf ("too many files matched the given pattern, try to be more specific" )
185
169
}
186
170
187
- data , err := assets [0 ].Section . Asset ( assets [0 ].Name )
171
+ data , err := matchedAssetFiles [0 ].fs . ReadFile ( matchedAssetFiles [0 ].name )
188
172
if err != nil {
189
- return fmt .Errorf ("%s: %w" , assets [0 ].Path , err )
173
+ return fmt .Errorf ("%s: %w" , matchedAssetFiles [0 ].path , err )
190
174
}
191
175
192
176
if _ , err = os .Stdout .Write (data ); err != nil {
193
- return fmt .Errorf ("%s: %w" , assets [0 ].Path , err )
177
+ return fmt .Errorf ("%s: %w" , matchedAssetFiles [0 ].path , err )
194
178
}
195
179
196
180
return nil
@@ -202,7 +186,7 @@ func runExtractDo(c *cli.Context) error {
202
186
}
203
187
204
188
if len (c .Args ()) == 0 {
205
- return fmt .Errorf ("A list of pattern of files to extract is mandatory (e.g. '**' for all)" )
189
+ return fmt .Errorf ("a list of pattern of files to extract is mandatory (e.g. '**' for all)" )
206
190
}
207
191
208
192
destdir := "."
@@ -227,31 +211,31 @@ func runExtractDo(c *cli.Context) error {
227
211
if err != nil {
228
212
return fmt .Errorf ("%s: %s" , destdir , err )
229
213
} else if ! fi .IsDir () {
230
- return fmt .Errorf ("%s is not a directory. " , destdir )
214
+ return fmt .Errorf ("destination %q is not a directory" , destdir )
231
215
}
232
216
233
217
fmt .Printf ("Extracting to %s:\n " , destdir )
234
218
235
219
overwrite := c .Bool ("overwrite" )
236
220
rename := c .Bool ("rename" )
237
221
238
- for _ , a := range assets {
222
+ for _ , a := range matchedAssetFiles {
239
223
if err := extractAsset (destdir , a , overwrite , rename ); err != nil {
240
224
// Non-fatal error
241
- fmt .Fprintf (os .Stderr , "%s: %v" , a .Path , err )
225
+ fmt .Fprintf (os .Stderr , "%s: %v" , a .path , err )
242
226
}
243
227
}
244
228
245
229
return nil
246
230
}
247
231
248
- func extractAsset (d string , a asset , overwrite , rename bool ) error {
249
- dest := filepath .Join (d , filepath .FromSlash (a .Path ))
232
+ func extractAsset (d string , a assetFile , overwrite , rename bool ) error {
233
+ dest := filepath .Join (d , filepath .FromSlash (a .path ))
250
234
dir := filepath .Dir (dest )
251
235
252
- data , err := a .Section . Asset (a .Name )
236
+ data , err := a .fs . ReadFile (a .name )
253
237
if err != nil {
254
- return fmt .Errorf ("%s: %w" , a .Path , err )
238
+ return fmt .Errorf ("%s: %w" , a .path , err )
255
239
}
256
240
257
241
if err := os .MkdirAll (dir , os .ModePerm ); err != nil {
@@ -272,7 +256,7 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
272
256
return fmt .Errorf ("%s already exists, but it's not a regular file" , dest )
273
257
} else if rename {
274
258
if err := util .Rename (dest , dest + ".bak" ); err != nil {
275
- return fmt .Errorf ("Error creating backup for %s: %w" , dest , err )
259
+ return fmt .Errorf ("error creating backup for %s: %w" , dest , err )
276
260
}
277
261
// Attempt to respect file permissions mask (even if user:group will be set anew)
278
262
perms = fi .Mode ()
@@ -293,40 +277,38 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
293
277
return nil
294
278
}
295
279
296
- func buildAssetList (sec * section , globs []glob.Glob , c * cli.Context ) []asset {
297
- results := make ([]asset , 0 , 64 )
298
- for _ , name := range sec .Names () {
299
- if isdir , err := sec .IsDir (name ); ! isdir && err == nil {
300
- if sec .Path == "public" &&
301
- strings .HasPrefix (name , "vendor/" ) &&
302
- ! c .Bool ("include-vendored" ) {
303
- continue
304
- }
305
- matchName := sec .Path + "/" + name
306
- for _ , g := range globs {
307
- if g .Match (matchName ) {
308
- results = append (results , asset {
309
- Section : sec ,
310
- Name : name ,
311
- Path : sec .Path + "/" + name ,
312
- })
313
- break
314
- }
280
+ func collectAssetFilesByPattern (c * cli.Context , globs []glob.Glob , path string , layer * assetfs.Layer ) {
281
+ fs := assetfs .Layered (layer )
282
+ files , err := fs .ListAllFiles ("." , true )
283
+ if err != nil {
284
+ log .Error ("Error listing files in %q: %v" , path , err )
285
+ return
286
+ }
287
+ for _ , name := range files {
288
+ if path == "public" &&
289
+ strings .HasPrefix (name , "vendor/" ) &&
290
+ ! c .Bool ("include-vendored" ) {
291
+ continue
292
+ }
293
+ matchName := path + "/" + name
294
+ for _ , g := range globs {
295
+ if g .Match (matchName ) {
296
+ matchedAssetFiles = append (matchedAssetFiles , assetFile {fs : fs , name : name , path : path + "/" + name })
297
+ break
315
298
}
316
299
}
317
300
}
318
- return results
319
301
}
320
302
321
- func getPatterns (args []string ) ([]glob.Glob , error ) {
303
+ func compileCollectPatterns (args []string ) ([]glob.Glob , error ) {
322
304
if len (args ) == 0 {
323
305
args = []string {"**" }
324
306
}
325
307
pat := make ([]glob.Glob , len (args ))
326
308
for i := range args {
327
309
if g , err := glob .Compile (args [i ], '/' ); err != nil {
328
310
return nil , fmt .Errorf ("'%s': Invalid glob pattern: %w" , args [i ], err )
329
- } else {
311
+ } else { //nolint:revive
330
312
pat [i ] = g
331
313
}
332
314
}
0 commit comments