2022-08-28 12:43:25 +03:00
// Copyright 2022 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2022-08-28 12:43:25 +03:00
package options
import (
"fmt"
"io/fs"
"os"
"path/filepath"
2023-03-21 23:02:49 +03:00
"code.gitea.io/gitea/modules/log"
2023-03-08 12:31:27 +03:00
"code.gitea.io/gitea/modules/setting"
2022-08-28 12:43:25 +03:00
"code.gitea.io/gitea/modules/util"
)
2023-03-21 23:02:49 +03:00
var directories = make ( directorySet )
2023-03-08 12:31:27 +03:00
// Locale reads the content of a specific locale from static/bindata or custom path.
func Locale ( name string ) ( [ ] byte , error ) {
2023-03-21 23:02:49 +03:00
return fileFromOptionsDir ( "locale" , name )
2023-03-08 12:31:27 +03:00
}
// Readme reads the content of a specific readme from static/bindata or custom path.
func Readme ( name string ) ( [ ] byte , error ) {
2023-03-21 23:02:49 +03:00
return fileFromOptionsDir ( "readme" , name )
2023-03-08 12:31:27 +03:00
}
// Gitignore reads the content of a gitignore locale from static/bindata or custom path.
func Gitignore ( name string ) ( [ ] byte , error ) {
2023-03-21 23:02:49 +03:00
return fileFromOptionsDir ( "gitignore" , name )
2023-03-08 12:31:27 +03:00
}
// License reads the content of a specific license from static/bindata or custom path.
func License ( name string ) ( [ ] byte , error ) {
2023-03-21 23:02:49 +03:00
return fileFromOptionsDir ( "license" , name )
2023-03-08 12:31:27 +03:00
}
// Labels reads the content of a specific labels from static/bindata or custom path.
func Labels ( name string ) ( [ ] byte , error ) {
2023-03-21 23:02:49 +03:00
return fileFromOptionsDir ( "label" , name )
2023-03-08 12:31:27 +03:00
}
// WalkLocales reads the content of a specific locale
func WalkLocales ( callback func ( path , name string , d fs . DirEntry , err error ) error ) error {
if IsDynamic ( ) {
if err := walkAssetDir ( filepath . Join ( setting . StaticRootPath , "options" , "locale" ) , callback ) ; err != nil && ! os . IsNotExist ( err ) {
return fmt . Errorf ( "failed to walk locales. Error: %w" , err )
}
}
if err := walkAssetDir ( filepath . Join ( setting . CustomPath , "options" , "locale" ) , callback ) ; err != nil && ! os . IsNotExist ( err ) {
return fmt . Errorf ( "failed to walk locales. Error: %w" , err )
}
return nil
}
2022-08-28 12:43:25 +03:00
func walkAssetDir ( root string , callback func ( path , name string , d fs . DirEntry , err error ) error ) error {
if err := filepath . WalkDir ( root , func ( path string , d fs . DirEntry , err error ) error {
// name is the path relative to the root
name := path [ len ( root ) : ]
if len ( name ) > 0 && name [ 0 ] == '/' {
name = name [ 1 : ]
}
if err != nil {
if os . IsNotExist ( err ) {
return callback ( path , name , d , err )
}
return err
}
if util . CommonSkip ( d . Name ( ) ) {
if d . IsDir ( ) {
return fs . SkipDir
}
return nil
}
return callback ( path , name , d , err )
} ) ; err != nil && ! os . IsNotExist ( err ) {
return fmt . Errorf ( "unable to get files for assets in %s: %w" , root , err )
}
return nil
}
2023-03-08 12:31:27 +03:00
2023-03-21 23:02:49 +03:00
// mustLocalPathAbs coverts a path to absolute path
// FIXME: the old behavior (StaticRootPath might not be absolute), not ideal, just keep the same as before
func mustLocalPathAbs ( s string ) string {
abs , err := filepath . Abs ( s )
2023-03-08 12:31:27 +03:00
if err != nil {
2023-03-21 23:02:49 +03:00
// This should never happen in a real system. If it happens, the user must have already been in trouble: the system is not able to resolve its own paths.
log . Fatal ( "Unable to get absolute path for %q: %v" , s , err )
2023-03-08 12:31:27 +03:00
}
2023-03-21 23:02:49 +03:00
return abs
}
func joinLocalPaths ( baseDirs [ ] string , subDir string , elems ... string ) ( paths [ ] string ) {
abs := make ( [ ] string , len ( elems ) + 2 )
abs [ 1 ] = subDir
copy ( abs [ 2 : ] , elems )
for _ , baseDir := range baseDirs {
abs [ 0 ] = mustLocalPathAbs ( baseDir )
paths = append ( paths , util . FilePathJoinAbs ( abs ... ) )
2023-03-08 12:31:27 +03:00
}
2023-03-21 23:02:49 +03:00
return paths
}
func listLocalDirIfExist ( baseDirs [ ] string , subDir string , elems ... string ) ( files [ ] string , err error ) {
for _ , localPath := range joinLocalPaths ( baseDirs , subDir , elems ... ) {
isDir , err := util . IsDir ( localPath )
if err != nil {
return nil , fmt . Errorf ( "unable to check if path %q is a directory. %w" , localPath , err )
} else if ! isDir {
continue
}
dirFiles , err := util . StatDir ( localPath , true )
if err != nil {
return nil , fmt . Errorf ( "unable to read directory %q. %w" , localPath , err )
}
files = append ( files , dirFiles ... )
2023-03-08 12:31:27 +03:00
}
return files , nil
}
2023-03-21 23:02:49 +03:00
func readLocalFile ( baseDirs [ ] string , subDir string , elems ... string ) ( [ ] byte , error ) {
for _ , localPath := range joinLocalPaths ( baseDirs , subDir , elems ... ) {
data , err := os . ReadFile ( localPath )
if err == nil {
return data , nil
} else if ! os . IsNotExist ( err ) {
log . Error ( "Unable to read file %q. Error: %v" , localPath , err )
}
}
return nil , os . ErrNotExist
}