Merge pull request #10421 from rhatdan/build
Handle hard links in remote builds
This commit is contained in:
		
						commit
						2311a02c38
					
				
							
								
								
									
										3
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										3
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -382,6 +382,9 @@ bin/podman.cross.%: .gopathok
 | 
			
		|||
.PHONY: local-cross
 | 
			
		||||
local-cross: $(CROSS_BUILD_TARGETS) ## Cross compile podman binary for multiple architectures
 | 
			
		||||
 | 
			
		||||
.PHONY: cross
 | 
			
		||||
cross: local-cross
 | 
			
		||||
 | 
			
		||||
# Update nix/nixpkgs.json its latest stable commit
 | 
			
		||||
.PHONY: nixpkgs
 | 
			
		||||
nixpkgs:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,11 @@ import (
 | 
			
		|||
	"github.com/sirupsen/logrus"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type devino struct {
 | 
			
		||||
	Dev uint64
 | 
			
		||||
	Ino uint64
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	iidRegex = regexp.MustCompile(`^[0-9a-f]{12}`)
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -402,7 +407,7 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
 | 
			
		|||
		defer pw.Close()
 | 
			
		||||
		defer gw.Close()
 | 
			
		||||
		defer tw.Close()
 | 
			
		||||
 | 
			
		||||
		seen := make(map[devino]string)
 | 
			
		||||
		for _, src := range sources {
 | 
			
		||||
			s, err := filepath.Abs(src)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -431,25 +436,40 @@ func nTar(excludes []string, sources ...string) (io.ReadCloser, error) {
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
				if info.Mode().IsRegular() { // add file item
 | 
			
		||||
					f, lerr := os.Open(path)
 | 
			
		||||
					if lerr != nil {
 | 
			
		||||
						return lerr
 | 
			
		||||
					di, isHardLink := checkHardLink(info)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					hdr, lerr := tar.FileInfoHeader(info, name)
 | 
			
		||||
					if lerr != nil {
 | 
			
		||||
						f.Close()
 | 
			
		||||
						return lerr
 | 
			
		||||
					hdr, err := tar.FileInfoHeader(info, "")
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
					orig, ok := seen[di]
 | 
			
		||||
					if ok {
 | 
			
		||||
						hdr.Typeflag = tar.TypeLink
 | 
			
		||||
						hdr.Linkname = orig
 | 
			
		||||
						hdr.Size = 0
 | 
			
		||||
 | 
			
		||||
						return tw.WriteHeader(hdr)
 | 
			
		||||
					}
 | 
			
		||||
					f, err := os.Open(path)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					hdr.Name = name
 | 
			
		||||
					if lerr := tw.WriteHeader(hdr); lerr != nil {
 | 
			
		||||
					if err := tw.WriteHeader(hdr); err != nil {
 | 
			
		||||
						f.Close()
 | 
			
		||||
						return lerr
 | 
			
		||||
						return err
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					_, cerr := io.Copy(tw, f)
 | 
			
		||||
					_, err = io.Copy(tw, f)
 | 
			
		||||
					f.Close()
 | 
			
		||||
					return cerr
 | 
			
		||||
					if err == nil && isHardLink {
 | 
			
		||||
						seen[di] = name
 | 
			
		||||
					}
 | 
			
		||||
					return err
 | 
			
		||||
				} else if info.Mode().IsDir() { // add folders
 | 
			
		||||
					hdr, lerr := tar.FileInfoHeader(info, name)
 | 
			
		||||
					if lerr != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
// +build !windows
 | 
			
		||||
 | 
			
		||||
package images
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"syscall"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func checkHardLink(fi os.FileInfo) (devino, bool) {
 | 
			
		||||
	st := fi.Sys().(*syscall.Stat_t)
 | 
			
		||||
	return devino{
 | 
			
		||||
		Dev: uint64(st.Dev),
 | 
			
		||||
		Ino: uint64(st.Ino),
 | 
			
		||||
	}, st.Nlink > 1
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
package images
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func checkHardLink(fi os.FileInfo) (devino, bool) {
 | 
			
		||||
	return devino{}, false
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -766,6 +766,26 @@ EOF
 | 
			
		|||
    is "$output" ".*/tmp/bogus: no such file or directory"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@test "podman build COPY hardlinks " {
 | 
			
		||||
    tmpdir=$PODMAN_TMPDIR/build-test
 | 
			
		||||
    mkdir -p $tmpdir
 | 
			
		||||
 | 
			
		||||
    dockerfile=$tmpdir/Dockerfile
 | 
			
		||||
    cat >$dockerfile <<EOF
 | 
			
		||||
FROM $IMAGE
 | 
			
		||||
COPY . /test
 | 
			
		||||
EOF
 | 
			
		||||
    ln $dockerfile $tmpdir/hardlink
 | 
			
		||||
 | 
			
		||||
    run_podman build -t build_test $tmpdir
 | 
			
		||||
    run_podman run --rm build_test stat -c '%i' /test/Dockerfile
 | 
			
		||||
    dinode=$output
 | 
			
		||||
    run_podman run --rm build_test stat -c '%i' /test/hardlink
 | 
			
		||||
    is "$output"   "$dinode"   "COPY hardlinks work"
 | 
			
		||||
 | 
			
		||||
    run_podman rmi -f build_test
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function teardown() {
 | 
			
		||||
    # A timeout or other error in 'build' can leave behind stale images
 | 
			
		||||
    # that podman can't even see and which will cascade into subsequent
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue