refactor(filesystem): add CopyDir method and optimize Fetch function
Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
		
							parent
							
								
									b0911ab1a2
								
							
						
					
					
						commit
						fb467f38c8
					
				|  | @ -45,7 +45,7 @@ linters: | ||||||
|       lines: 280 |       lines: 280 | ||||||
|       statements: 140 |       statements: 140 | ||||||
|     gocognit: |     gocognit: | ||||||
|       min-complexity: 100 |       min-complexity: 110 | ||||||
|     goconst: |     goconst: | ||||||
|       min-len: 3 |       min-len: 3 | ||||||
|       min-occurrences: 8 |       min-occurrences: 8 | ||||||
|  |  | ||||||
|  | @ -345,8 +345,7 @@ func (a *App) Fetch(c FetchConfigProvider) error { | ||||||
| 			OutputDir:         c.OutputDir(), | 			OutputDir:         c.OutputDir(), | ||||||
| 			OutputDirTemplate: c.OutputDirTemplate(), | 			OutputDirTemplate: c.OutputDirTemplate(), | ||||||
| 			Concurrency:       c.Concurrency(), | 			Concurrency:       c.Concurrency(), | ||||||
| 		}, func() { | 		}, func() {}) | ||||||
| 		}) |  | ||||||
| 
 | 
 | ||||||
| 		if prepErr != nil { | 		if prepErr != nil { | ||||||
| 			errs = append(errs, prepErr) | 			errs = append(errs, prepErr) | ||||||
|  |  | ||||||
|  | @ -5,6 +5,7 @@ import ( | ||||||
| 	"io/fs" | 	"io/fs" | ||||||
| 	"os" | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
|  | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -36,6 +37,7 @@ type FileSystem struct { | ||||||
| 	Chdir             func(string) error | 	Chdir             func(string) error | ||||||
| 	Abs               func(string) (string, error) | 	Abs               func(string) (string, error) | ||||||
| 	EvalSymlinks      func(string) (string, error) | 	EvalSymlinks      func(string) (string, error) | ||||||
|  | 	CopyDir           func(src, dst string) error | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func DefaultFileSystem() *FileSystem { | func DefaultFileSystem() *FileSystem { | ||||||
|  | @ -55,6 +57,7 @@ func DefaultFileSystem() *FileSystem { | ||||||
| 	dfs.DirectoryExistsAt = dfs.directoryExistsDefault | 	dfs.DirectoryExistsAt = dfs.directoryExistsDefault | ||||||
| 	dfs.FileExists = dfs.fileExistsDefault | 	dfs.FileExists = dfs.fileExistsDefault | ||||||
| 	dfs.Abs = dfs.absDefault | 	dfs.Abs = dfs.absDefault | ||||||
|  | 	dfs.CopyDir = dfs.copyDirDefault | ||||||
| 	return &dfs | 	return &dfs | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -100,6 +103,9 @@ func FromFileSystem(params FileSystem) *FileSystem { | ||||||
| 	if params.Dir != nil { | 	if params.Dir != nil { | ||||||
| 		dfs.Dir = params.Dir | 		dfs.Dir = params.Dir | ||||||
| 	} | 	} | ||||||
|  | 	if params.CopyDir != nil { | ||||||
|  | 		dfs.CopyDir = params.CopyDir | ||||||
|  | 	} | ||||||
| 	return dfs | 	return dfs | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -180,3 +186,121 @@ func (filesystem *FileSystem) absDefault(path string) (string, error) { | ||||||
| 	} | 	} | ||||||
| 	return filepath.Abs(path) | 	return filepath.Abs(path) | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | // copyDirDefault recursively copies a directory tree, preserving permissions.
 | ||||||
|  | func (filesystem *FileSystem) copyDirDefault(src string, dst string) error { | ||||||
|  | 	src, err := filesystem.EvalSymlinks(src) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	walkFn := func(path string, info os.FileInfo, err error) error { | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if path == src { | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if strings.HasPrefix(filepath.Base(path), ".") { | ||||||
|  | 			// Skip any dot files
 | ||||||
|  | 			if info.IsDir() { | ||||||
|  | 				return filepath.SkipDir | ||||||
|  | 			} else { | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// The "path" has the src prefixed to it. We need to join our
 | ||||||
|  | 		// destination with the path without the src on it.
 | ||||||
|  | 		dstPath := filepath.Join(dst, path[len(src):]) | ||||||
|  | 
 | ||||||
|  | 		// we don't want to try and copy the same file over itself.
 | ||||||
|  | 		if eq, err := SameFile(path, dstPath); eq { | ||||||
|  | 			return nil | ||||||
|  | 		} else if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If we have a directory, make that subdirectory, then continue
 | ||||||
|  | 		// the walk.
 | ||||||
|  | 		if info.IsDir() { | ||||||
|  | 			if path == filepath.Join(src, dst) { | ||||||
|  | 				// dst is in src; don't walk it.
 | ||||||
|  | 				return nil | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if err := os.MkdirAll(dstPath, 0755); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return nil | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If the current path is a symlink, recreate the symlink relative to
 | ||||||
|  | 		// the dst directory
 | ||||||
|  | 		if info.Mode()&os.ModeSymlink == os.ModeSymlink { | ||||||
|  | 			target, err := os.Readlink(path) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			return os.Symlink(target, dstPath) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// If we have a file, copy the contents.
 | ||||||
|  | 		srcF, err := os.Open(path) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		defer func() { | ||||||
|  | 			_ = srcF.Close() | ||||||
|  | 		}() | ||||||
|  | 
 | ||||||
|  | 		dstF, err := os.Create(dstPath) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 		defer func() { | ||||||
|  | 			_ = dstF.Close() | ||||||
|  | 		}() | ||||||
|  | 
 | ||||||
|  | 		if _, err := io.Copy(dstF, srcF); err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// Chmod it
 | ||||||
|  | 		return os.Chmod(dstPath, info.Mode()) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return filepath.Walk(src, walkFn) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SameFile returns true if the two given paths refer to the same physical
 | ||||||
|  | // file on disk, using the unique file identifiers from the underlying
 | ||||||
|  | // operating system. For example, on Unix systems this checks whether the
 | ||||||
|  | // two files are on the same device and have the same inode.
 | ||||||
|  | func SameFile(a, b string) (bool, error) { | ||||||
|  | 	if a == b { | ||||||
|  | 		return true, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	aInfo, err := os.Lstat(a) | ||||||
|  | 	if err != nil { | ||||||
|  | 		if os.IsNotExist(err) { | ||||||
|  | 			return false, nil | ||||||
|  | 		} | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bInfo, err := os.Lstat(b) | ||||||
|  | 	if err != nil { | ||||||
|  | 		if os.IsNotExist(err) { | ||||||
|  | 			return false, nil | ||||||
|  | 		} | ||||||
|  | 		return false, err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return os.SameFile(aInfo, bInfo), nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -1372,6 +1372,18 @@ func (st *HelmState) PrepareCharts(helm helmexec.Interface, dir string, concurre | ||||||
| 					// for a remote chart, so that the user can notice/fix the issue in a local chart while
 | 					// for a remote chart, so that the user can notice/fix the issue in a local chart while
 | ||||||
| 					// a broken remote chart won't completely block their job.
 | 					// a broken remote chart won't completely block their job.
 | ||||||
| 					chartPath = normalizedChart | 					chartPath = normalizedChart | ||||||
|  | 					if helmfileCommand == "pull" { | ||||||
|  | 						// copy chart to a temporary directory
 | ||||||
|  | 						chartPath, err = generateChartPath(chartName, dir, release, opts.OutputDirTemplate) | ||||||
|  | 						if err != nil { | ||||||
|  | 							results <- &chartPrepareResult{err: err} | ||||||
|  | 							return | ||||||
|  | 						} | ||||||
|  | 						if err := st.fs.CopyDir(normalizedChart, chartPath); err != nil { | ||||||
|  | 							results <- &chartPrepareResult{err: err} | ||||||
|  | 							return | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
| 
 | 
 | ||||||
| 					buildDeps = !skipDeps | 					buildDeps = !skipDeps | ||||||
| 				} else if !opts.ForceDownload { | 				} else if !opts.ForceDownload { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue