11// Copyright 2020 The Gitea Authors. All rights reserved.
22// SPDX-License-Identifier: MIT
33
4- //go:build bindata
5-
64package cmd
75
86import (
97 "errors"
108 "fmt"
119 "os"
1210 "path/filepath"
13- "sort"
1411 "strings"
1512
13+ "code.gitea.io/gitea/modules/assetfs"
1614 "code.gitea.io/gitea/modules/log"
1715 "code.gitea.io/gitea/modules/options"
1816 "code.gitea.io/gitea/modules/public"
@@ -89,24 +87,20 @@ var (
8987 },
9088 }
9189
92- sections map [string ]* section
93- assets []asset
90+ matchedAssetFiles []assetFile
9491)
9592
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
10797}
10898
10999func 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+
110104 // Silence the console logger
111105 log .DelNamedLogger ("console" )
112106 log .DelNamedLogger (log .DEFAULT )
@@ -115,24 +109,14 @@ func initEmbeddedExtractor(c *cli.Context) error {
115109 setting .InitProviderAllowEmpty ()
116110 setting .LoadCommonSettings ()
117111
118- pats , err := getPatterns (c .Args ())
112+ patterns , err := compileCollectPatterns (c .Args ())
119113 if err != nil {
120114 return err
121115 }
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 }
127116
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 ())
136120
137121 return nil
138122}
@@ -166,8 +150,8 @@ func runListDo(c *cli.Context) error {
166150 return err
167151 }
168152
169- for _ , a := range assets {
170- fmt .Println (a .Path )
153+ for _ , a := range matchedAssetFiles {
154+ fmt .Println (a .path )
171155 }
172156
173157 return nil
@@ -178,19 +162,19 @@ func runViewDo(c *cli.Context) error {
178162 return err
179163 }
180164
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" )
185169 }
186170
187- data , err := assets [0 ].Section . Asset ( assets [0 ].Name )
171+ data , err := matchedAssetFiles [0 ].fs . ReadFile ( matchedAssetFiles [0 ].name )
188172 if err != nil {
189- return fmt .Errorf ("%s: %w" , assets [0 ].Path , err )
173+ return fmt .Errorf ("%s: %w" , matchedAssetFiles [0 ].path , err )
190174 }
191175
192176 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 )
194178 }
195179
196180 return nil
@@ -202,7 +186,7 @@ func runExtractDo(c *cli.Context) error {
202186 }
203187
204188 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)" )
206190 }
207191
208192 destdir := "."
@@ -227,31 +211,31 @@ func runExtractDo(c *cli.Context) error {
227211 if err != nil {
228212 return fmt .Errorf ("%s: %s" , destdir , err )
229213 } 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 )
231215 }
232216
233217 fmt .Printf ("Extracting to %s:\n " , destdir )
234218
235219 overwrite := c .Bool ("overwrite" )
236220 rename := c .Bool ("rename" )
237221
238- for _ , a := range assets {
222+ for _ , a := range matchedAssetFiles {
239223 if err := extractAsset (destdir , a , overwrite , rename ); err != nil {
240224 // Non-fatal error
241- fmt .Fprintf (os .Stderr , "%s: %v" , a .Path , err )
225+ fmt .Fprintf (os .Stderr , "%s: %v" , a .path , err )
242226 }
243227 }
244228
245229 return nil
246230}
247231
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 ))
250234 dir := filepath .Dir (dest )
251235
252- data , err := a .Section . Asset (a .Name )
236+ data , err := a .fs . ReadFile (a .name )
253237 if err != nil {
254- return fmt .Errorf ("%s: %w" , a .Path , err )
238+ return fmt .Errorf ("%s: %w" , a .path , err )
255239 }
256240
257241 if err := os .MkdirAll (dir , os .ModePerm ); err != nil {
@@ -272,7 +256,7 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
272256 return fmt .Errorf ("%s already exists, but it's not a regular file" , dest )
273257 } else if rename {
274258 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 )
276260 }
277261 // Attempt to respect file permissions mask (even if user:group will be set anew)
278262 perms = fi .Mode ()
@@ -293,40 +277,38 @@ func extractAsset(d string, a asset, overwrite, rename bool) error {
293277 return nil
294278}
295279
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
315298 }
316299 }
317300 }
318- return results
319301}
320302
321- func getPatterns (args []string ) ([]glob.Glob , error ) {
303+ func compileCollectPatterns (args []string ) ([]glob.Glob , error ) {
322304 if len (args ) == 0 {
323305 args = []string {"**" }
324306 }
325307 pat := make ([]glob.Glob , len (args ))
326308 for i := range args {
327309 if g , err := glob .Compile (args [i ], '/' ); err != nil {
328310 return nil , fmt .Errorf ("'%s': Invalid glob pattern: %w" , args [i ], err )
329- } else {
311+ } else { //nolint:revive
330312 pat [i ] = g
331313 }
332314 }
0 commit comments