Платформа ЦРНП "Мирокод" для разработки проектов
https://git.mirocod.ru
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
103 lines
2.2 KiB
103 lines
2.2 KiB
// Copyright 2022 The Gitea Authors. All rights reserved. |
|
// Use of this source code is governed by a MIT-style |
|
// license that can be found in the LICENSE file. |
|
|
|
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) { |
|
return errors.New("file or directory already exists: " + destPath) |
|
} |
|
|
|
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 |
|
}
|
|
|