mirror of
				https://github.com/golang/go.git
				synced 2025-11-04 02:30:57 +00:00 
			
		
		
		
	Otherwise, the test cannot create new files in the directory. Updates #32407 Updates #30316 Change-Id: Ief0df94a202be92f57d458d4ab4e4daa9ec189b1 Reviewed-on: https://go-review.googlesource.com/c/go/+/206458 Run-TryBot: Bryan C. Mills <bcmills@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
		
			
				
	
	
		
			81 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			81 lines
		
	
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2019 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package carchive_test
 | 
						|
 | 
						|
import (
 | 
						|
	"io"
 | 
						|
	"os"
 | 
						|
	"path/filepath"
 | 
						|
	"strings"
 | 
						|
)
 | 
						|
 | 
						|
// overlayDir makes a minimal-overhead copy of srcRoot in which new files may be added.
 | 
						|
//
 | 
						|
// TODO: Once we no longer need to support the misc module in GOPATH mode,
 | 
						|
// factor this function out into a package to reduce duplication.
 | 
						|
func overlayDir(dstRoot, srcRoot string) error {
 | 
						|
	dstRoot = filepath.Clean(dstRoot)
 | 
						|
	if err := os.MkdirAll(dstRoot, 0777); err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
 | 
						|
	symBase, err := filepath.Rel(srcRoot, dstRoot)
 | 
						|
	if err != nil {
 | 
						|
		symBase, err = filepath.Abs(srcRoot)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
 | 
						|
		if err != nil || srcPath == srcRoot {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		suffix := strings.TrimPrefix(srcPath, srcRoot)
 | 
						|
		for len(suffix) > 0 && suffix[0] == filepath.Separator {
 | 
						|
			suffix = suffix[1:]
 | 
						|
		}
 | 
						|
		dstPath := filepath.Join(dstRoot, suffix)
 | 
						|
 | 
						|
		perm := info.Mode() & os.ModePerm
 | 
						|
		if info.Mode()&os.ModeSymlink != 0 {
 | 
						|
			info, err = os.Stat(srcPath)
 | 
						|
			if err != nil {
 | 
						|
				return err
 | 
						|
			}
 | 
						|
			perm = info.Mode() & os.ModePerm
 | 
						|
		}
 | 
						|
 | 
						|
		// Always copy directories (don't symlink them).
 | 
						|
		// If we add a file in the overlay, we don't want to add it in the original.
 | 
						|
		if info.IsDir() {
 | 
						|
			return os.Mkdir(dstPath, perm|0200)
 | 
						|
		}
 | 
						|
 | 
						|
		// If the OS supports symlinks, use them instead of copying bytes.
 | 
						|
		if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
 | 
						|
		// Otherwise, copy the bytes.
 | 
						|
		src, err := os.Open(srcPath)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		defer src.Close()
 | 
						|
 | 
						|
		dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
 | 
						|
		_, err = io.Copy(dst, src)
 | 
						|
		if closeErr := dst.Close(); err == nil {
 | 
						|
			err = closeErr
 | 
						|
		}
 | 
						|
		return err
 | 
						|
	})
 | 
						|
}
 |