2022-04-01 19:34:57 +03:00
// Copyright 2022 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2022-04-01 19:34:57 +03:00
package unittest
import (
"errors"
"io"
"os"
"path"
"strings"
"code.gitea.io/gitea/modules/util"
)
// Copy copies file from source to target path.
func Copy ( src , dest string ) error {
// Gather file information to set back later.
si , err := os . Lstat ( src )
if err != nil {
return err
}
// Handle symbolic link.
if si . Mode ( ) & os . ModeSymlink != 0 {
target , err := os . Readlink ( src )
if err != nil {
return err
}
// NOTE: os.Chmod and os.Chtimes don't recognize symbolic link,
// which will lead "no such file or directory" error.
return os . Symlink ( target , dest )
}
sr , err := os . Open ( src )
if err != nil {
return err
}
defer sr . Close ( )
dw , err := os . Create ( dest )
if err != nil {
return err
}
defer dw . Close ( )
if _ , err = io . Copy ( dw , sr ) ; err != nil {
return err
}
// Set back file information.
if err = os . Chtimes ( dest , si . ModTime ( ) , si . ModTime ( ) ) ; err != nil {
return err
}
return os . Chmod ( dest , si . Mode ( ) )
}
// CopyDir copy files recursively from source to target directory.
//
// The filter accepts a function that process the path info.
// and should return true for need to filter.
//
// It returns error when error occurs in underlying functions.
func CopyDir ( srcPath , destPath string , filters ... func ( filePath string ) bool ) error {
// Check if target directory exists.
if _ , err := os . Stat ( destPath ) ; ! errors . Is ( err , os . ErrNotExist ) {
2022-12-31 14:49:37 +03:00
return util . NewAlreadyExistErrorf ( "file or directory already exists: %s" , destPath )
2022-04-01 19:34:57 +03:00
}
err := os . MkdirAll ( destPath , os . ModePerm )
if err != nil {
return err
}
// Gather directory info.
infos , err := util . StatDir ( srcPath , true )
if err != nil {
return err
}
var filter func ( filePath string ) bool
if len ( filters ) > 0 {
filter = filters [ 0 ]
}
for _ , info := range infos {
if filter != nil && filter ( info ) {
continue
}
curPath := path . Join ( destPath , info )
if strings . HasSuffix ( info , "/" ) {
err = os . MkdirAll ( curPath , os . ModePerm )
} else {
err = Copy ( path . Join ( srcPath , info ) , curPath )
}
if err != nil {
return err
}
}
return nil
}