From 8811713ef489a12fec2d9b6e5bc5291a9da6b57c Mon Sep 17 00:00:00 2001 From: Daniel Mikusa Date: Thu, 10 Oct 2024 16:57:28 -0400 Subject: [PATCH] Add CopyFileFrom Resolves #354. Adds CopyFileFrom convenience method that opens the source file and delegates to CopyFile. Signed-off-by: Daniel Mikusa --- sherpa/copy_file.go | 14 +++++++++- sherpa/copy_file_test.go | 55 ++++++++++++++++++++++++++++++---------- 2 files changed, 54 insertions(+), 15 deletions(-) diff --git a/sherpa/copy_file.go b/sherpa/copy_file.go index a3bece6..9c8b12b 100644 --- a/sherpa/copy_file.go +++ b/sherpa/copy_file.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -48,3 +48,15 @@ func CopyFile(source *os.File, destination string) error { return nil } + +// CopyFileFrom copies a file from the source to the destination. It ensures that the parent directory is created and +// matches the source and destination permissions. +func CopyFileFrom(source string, destination string) error { + in, err := os.Open(source) + if err != nil { + return fmt.Errorf("unable to open %s\n%w", source, err) + } + defer in.Close() + + return CopyFile(in, destination) +} diff --git a/sherpa/copy_file_test.go b/sherpa/copy_file_test.go index ffceee7..875ef08 100644 --- a/sherpa/copy_file_test.go +++ b/sherpa/copy_file_test.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 the original author or authors. + * Copyright 2018-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,9 @@ package sherpa_test import ( + "fmt" "os" + "path/filepath" "testing" . "github.com/onsi/gomega" @@ -30,35 +32,60 @@ func testCopyFile(t *testing.T, context spec.G, it spec.S) { var ( Expect = NewWithT(t).Expect - source *os.File - destination string + rootPath string + sourcePath string ) + expectFilePermissionsToMatch := func(destination string, fileMode os.FileMode) { + fileInfo, err := os.Stat(destination) + fmt.Println("eperms:", fileInfo.Mode().Perm().String()) + Expect(err).NotTo(HaveOccurred()) + Expect(fileInfo.Mode().Perm().String()).To(Equal(fileMode.String())) + } + it.Before(func() { var err error - source, err = os.CreateTemp("", "copy-file") + rootPath = t.TempDir() + + source, err := os.CreateTemp(rootPath, "source.txt") Expect(err).NotTo(HaveOccurred()) + sourcePath = source.Name() + _, err = source.WriteString("test") Expect(err).NotTo(HaveOccurred()) Expect(source.Close()).To(Succeed()) - source, err = os.Open(source.Name()) - Expect(err).NotTo(HaveOccurred()) - - f, err := os.CreateTemp("", "copy-file") - Expect(err).NotTo(HaveOccurred()) - Expect(f.Close()).To(Succeed()) - destination = f.Name() }) it.After(func() { - Expect(os.RemoveAll(source.Name())).To(Succeed()) - Expect(os.RemoveAll(destination)).To(Succeed()) + Expect(os.RemoveAll(rootPath)).To(Succeed()) }) - it("create listing", func() { + it("copy file with permissions", func() { + destination := filepath.Join(rootPath, "destination/nested/destination.txt") + + source, err := os.Open(sourcePath) + Expect(err).NotTo(HaveOccurred()) defer source.Close() + + expectedMode := os.FileMode(0640) + Expect(os.Chmod(sourcePath, expectedMode)).To(Succeed()) + Expect(sherpa.CopyFile(source, destination)).To(Succeed()) Expect(os.ReadFile(destination)).To(Equal([]byte("test"))) + + expectFilePermissionsToMatch(destination, expectedMode) + }) + + it.Focus("copy file from string path with permissions", func() { + destination := filepath.Join(rootPath, "destination/other-nested/destination.txt") + + expectedMode := os.FileMode(0440) + Expect(os.Chmod(sourcePath, expectedMode)).To(Succeed()) + + Expect(sherpa.CopyFileFrom(sourcePath, destination)).To(Succeed()) + Expect(os.ReadFile(destination)).To(Equal([]byte("test"))) + + expectFilePermissionsToMatch(destination, expectedMode) }) }