完成一个简易的全局skill、command管理器
This commit is contained in:
62
manager/pkg/fileutil/fileutil.go
Normal file
62
manager/pkg/fileutil/fileutil.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// CopyFile 复制文件,保留权限
|
||||
func CopyFile(src, dst string) error {
|
||||
srcFile, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer srcFile.Close()
|
||||
|
||||
// 确保目标目录存在
|
||||
if err := os.MkdirAll(filepath.Dir(dst), 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dstFile, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dstFile.Close()
|
||||
|
||||
if _, err := io.Copy(dstFile, srcFile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 保留文件权限,移除特殊权限位(SETUID/SETGID/STICKY)
|
||||
srcInfo, err := os.Stat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 只保留标准权限位,移除特殊权限位
|
||||
mode := srcInfo.Mode() & os.ModePerm
|
||||
return os.Chmod(dst, mode)
|
||||
}
|
||||
|
||||
// CopyDir 递归复制目录
|
||||
func CopyDir(src, dst string) error {
|
||||
return filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
relPath, err := filepath.Rel(src, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dstPath := filepath.Join(dst, relPath)
|
||||
|
||||
if info.IsDir() {
|
||||
return os.MkdirAll(dstPath, info.Mode())
|
||||
}
|
||||
|
||||
return CopyFile(path, dstPath)
|
||||
})
|
||||
}
|
||||
100
manager/pkg/fileutil/fileutil_test.go
Normal file
100
manager/pkg/fileutil/fileutil_test.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package fileutil
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCopyFile(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "skillmgr-fileutil-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("创建临时目录失败: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// 创建源文件
|
||||
srcFile := filepath.Join(tmpDir, "src.txt")
|
||||
content := []byte("test content")
|
||||
if err := os.WriteFile(srcFile, content, 0644); err != nil {
|
||||
t.Fatalf("创建源文件失败: %v", err)
|
||||
}
|
||||
|
||||
// 复制
|
||||
destFile := filepath.Join(tmpDir, "dest.txt")
|
||||
if err := CopyFile(srcFile, destFile); err != nil {
|
||||
t.Fatalf("CopyFile 失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证
|
||||
destContent, err := os.ReadFile(destFile)
|
||||
if err != nil {
|
||||
t.Fatalf("读取目标文件失败: %v", err)
|
||||
}
|
||||
|
||||
if string(destContent) != string(content) {
|
||||
t.Errorf("内容不匹配:期望 %s,得到 %s", content, destContent)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyDir(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "skillmgr-fileutil-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("创建临时目录失败: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// 创建源目录结构
|
||||
srcDir := filepath.Join(tmpDir, "src")
|
||||
os.MkdirAll(filepath.Join(srcDir, "subdir"), 0755)
|
||||
os.WriteFile(filepath.Join(srcDir, "file1.txt"), []byte("file1"), 0644)
|
||||
os.WriteFile(filepath.Join(srcDir, "subdir", "file2.txt"), []byte("file2"), 0644)
|
||||
|
||||
// 复制
|
||||
destDir := filepath.Join(tmpDir, "dest")
|
||||
if err := CopyDir(srcDir, destDir); err != nil {
|
||||
t.Fatalf("CopyDir 失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证文件存在
|
||||
files := []string{
|
||||
filepath.Join(destDir, "file1.txt"),
|
||||
filepath.Join(destDir, "subdir", "file2.txt"),
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if _, err := os.Stat(file); os.IsNotExist(err) {
|
||||
t.Errorf("文件应该存在: %s", file)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyFile_PreservePermissions(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp("", "skillmgr-fileutil-test-*")
|
||||
if err != nil {
|
||||
t.Fatalf("创建临时目录失败: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
// 创建可执行文件
|
||||
srcFile := filepath.Join(tmpDir, "src.sh")
|
||||
if err := os.WriteFile(srcFile, []byte("#!/bin/bash"), 0755); err != nil {
|
||||
t.Fatalf("创建源文件失败: %v", err)
|
||||
}
|
||||
|
||||
// 复制
|
||||
destFile := filepath.Join(tmpDir, "dest.sh")
|
||||
if err := CopyFile(srcFile, destFile); err != nil {
|
||||
t.Fatalf("CopyFile 失败: %v", err)
|
||||
}
|
||||
|
||||
// 验证权限
|
||||
info, err := os.Stat(destFile)
|
||||
if err != nil {
|
||||
t.Fatalf("获取文件信息失败: %v", err)
|
||||
}
|
||||
|
||||
if info.Mode().Perm() != 0755 {
|
||||
t.Errorf("权限不匹配:期望 0755,得到 %o", info.Mode().Perm())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user