Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 30 additions & 25 deletions add.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@ type AddAndCopyOptions struct {
// inheritAnnotations, newAnnotations). This field is internally managed and should
// not be set by external API users.
BuildMetadata string
// FollowSymlink controls whether symlinks should be followed when copying content.
// When set to false, symlinks are not dereferenced.
FollowSymlink types.OptionalBool
}

// gitURLFragmentSuffix matches fragments to use as Git reference and build
Expand Down Expand Up @@ -610,18 +613,19 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
return
}
getOptions := copier.GetOptions{
UIDMap: srcUIDMap,
GIDMap: srcGIDMap,
Excludes: options.Excludes,
ExpandArchives: extract,
ChownDirs: chownDirs,
ChmodDirs: chmodDirsFiles,
ChownFiles: chownFiles,
ChmodFiles: chmodDirsFiles,
StripSetuidBit: options.StripSetuidBit,
StripSetgidBit: options.StripSetgidBit,
StripStickyBit: options.StripStickyBit,
Timestamp: options.Timestamp,
UIDMap: srcUIDMap,
GIDMap: srcGIDMap,
Excludes: options.Excludes,
ExpandArchives: extract,
ChownDirs: chownDirs,
ChmodDirs: chmodDirsFiles,
ChownFiles: chownFiles,
ChmodFiles: chmodDirsFiles,
StripSetuidBit: options.StripSetuidBit,
StripSetgidBit: options.StripSetgidBit,
StripStickyBit: options.StripStickyBit,
NoDerefSymlinks: options.FollowSymlink == types.OptionalBoolFalse,
Timestamp: options.Timestamp,
}
writer := io.WriteCloser(pipeWriter)
repositoryDir := filepath.Join(cloneDir, subdir)
Expand Down Expand Up @@ -777,19 +781,20 @@ func (b *Builder) Add(destination string, extract bool, options AddAndCopyOption
return false, false, nil
})
getOptions := copier.GetOptions{
UIDMap: srcUIDMap,
GIDMap: srcGIDMap,
Excludes: options.Excludes,
ExpandArchives: extract,
ChownDirs: chownDirs,
ChmodDirs: chmodDirsFiles,
ChownFiles: chownFiles,
ChmodFiles: chmodDirsFiles,
StripSetuidBit: options.StripSetuidBit,
StripSetgidBit: options.StripSetgidBit,
StripStickyBit: options.StripStickyBit,
Parents: options.Parents,
Timestamp: options.Timestamp,
UIDMap: srcUIDMap,
GIDMap: srcGIDMap,
Excludes: options.Excludes,
ExpandArchives: extract,
ChownDirs: chownDirs,
ChmodDirs: chmodDirsFiles,
ChownFiles: chownFiles,
ChmodFiles: chmodDirsFiles,
StripSetuidBit: options.StripSetuidBit,
StripSetgidBit: options.StripSetgidBit,
StripStickyBit: options.StripStickyBit,
Parents: options.Parents,
NoDerefSymlinks: options.FollowSymlink == types.OptionalBoolFalse,
Timestamp: options.Timestamp,
}
getErr = copier.Get(contextDir, contextDir, getOptions, []string{globbedToGlobbable(globbed)}, writer)
closeErr = writer.Close()
Expand Down
9 changes: 9 additions & 0 deletions cmd/buildah/addcopy.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"go.podman.io/buildah/pkg/cli"
"go.podman.io/buildah/pkg/parse"
"go.podman.io/common/pkg/auth"
"go.podman.io/image/v5/types"
"go.podman.io/storage"
)

Expand All @@ -42,6 +43,7 @@ type addCopyResults struct {
parents bool
timestamp string
link bool
noFollowSymlinks bool
}

func createCommand(addCopy string, desc string, short string, opts *addCopyResults) *cobra.Command {
Expand Down Expand Up @@ -77,6 +79,7 @@ func applyFlagVars(flags *pflag.FlagSet, opts *addCopyResults) {
flags.StringVar(&opts.chmod, "chmod", "", "set the access permissions of the destination content")
flags.StringVar(&opts.creds, "creds", "", "use `[username[:password]]` for accessing registries when pulling images")
flags.BoolVar(&opts.link, "link", false, "enable layer caching for this operation (creates an independent layer)")
flags.BoolVar(&opts.noFollowSymlinks, "no-follow-symlinks", false, "do not follow symlinks when copying content (copy the symlink itself)")
if err := flags.MarkHidden("creds"); err != nil {
panic(fmt.Sprintf("error marking creds as hidden: %v", err))
}
Expand Down Expand Up @@ -251,6 +254,11 @@ func addAndCopyCmd(c *cobra.Command, args []string, verb string, iopts addCopyRe
timestamp = &t
}

followSymlink := types.OptionalBoolUndefined
if iopts.noFollowSymlinks {
followSymlink = types.OptionalBoolFalse
}

options := buildah.AddAndCopyOptions{
Chmod: iopts.chmod,
Chown: iopts.chown,
Expand All @@ -267,6 +275,7 @@ func addAndCopyCmd(c *cobra.Command, args []string, verb string, iopts addCopyRe
Parents: iopts.parents,
Timestamp: timestamp,
Link: iopts.link,
FollowSymlink: followSymlink,
}
if iopts.contextdir != "" {
var excludes []string
Expand Down
5 changes: 5 additions & 0 deletions docs/buildah-add.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ container's filesystem. If `buildah run` creates a file and `buildah add --link`
to the same path, the file from `buildah add --link` will be present in the committed image.
The --link layer is applied after all container filesystem changes at commit time.

**--no-follow-symlinks**

When a local source is a symbolic link, copy the link as a symbolic link
instead of dereferencing the link and copying the contents of the target.

**--quiet**, **-q**

Refrain from printing a digest of the added content.
Expand Down
5 changes: 5 additions & 0 deletions docs/buildah-copy.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ container's filesystem. If `buildah run` creates a file and `buildah copy --link
to the same path, the file from `buildah copy --link` will be present in the committed image.
The --link layer is applied after all container filesystem changes at commit time.

**--no-follow-symlinks**

Don't follow and dereference the symlinks when copying the files. Instead, copy
the symlinks themselves.

**--parents**

Preserve leading directories in the paths of items being copied, relative to either the
Expand Down
69 changes: 69 additions & 0 deletions tests/add.bats
Original file line number Diff line number Diff line change
Expand Up @@ -509,3 +509,72 @@ EOF
cmp ${TEST_SCRATCH_DIR}/testdir/file1 $newroot/testdir/file1
cmp ${TEST_SCRATCH_DIR}/testdir/subdir/file2 $newroot/testdir/subdir/file2
}

@test "add-symlink-root-follow-default" {
createrandom ${TEST_SCRATCH_DIR}/file
ln -s ./file ${TEST_SCRATCH_DIR}/symlink

run_buildah from $WITH_POLICY_JSON scratch
cid=$output

run_buildah add $cid ${TEST_SCRATCH_DIR}/symlink /dest

run_buildah mount $cid
root=$output
ls -lahR $root
cmp ${TEST_SCRATCH_DIR}/file $root/dest
test -f $root/dest
}

@test "add-symlink-root-no-follow" {
createrandom ${TEST_SCRATCH_DIR}/file
ln -s ./file ${TEST_SCRATCH_DIR}/symlink

run_buildah from $WITH_POLICY_JSON scratch
cid=$output

# The symlink needs to point to something existing
run_buildah add --no-follow-symlinks $cid ${TEST_SCRATCH_DIR}/file /file
run_buildah add --no-follow-symlinks $cid ${TEST_SCRATCH_DIR}/symlink /dest

run_buildah mount $cid
root=$output
ls -lahR $root
cmp ${TEST_SCRATCH_DIR}/file $root/dest
test -L $root/dest
test "$(readlink $root/dest)" = "./file"
}

@test "add-symlink-child-follow-default" {
mkdir ${TEST_SCRATCH_DIR}/src
createrandom ${TEST_SCRATCH_DIR}/src/file
ln -s ./file ${TEST_SCRATCH_DIR}/src/symlink

run_buildah from $WITH_POLICY_JSON scratch
cid=$output

run_buildah add $cid ${TEST_SCRATCH_DIR}/src /dest

run_buildah mount $cid
root=$output
ls -lahR $root
cmp ${TEST_SCRATCH_DIR}/src/file $root/dest/symlink
test -f $root/dest/symlink
}

@test "add-symlink-child-no-follow" {
mkdir ${TEST_SCRATCH_DIR}/src
createrandom ${TEST_SCRATCH_DIR}/src/file
ln -s ./file ${TEST_SCRATCH_DIR}/src/symlink

run_buildah from $WITH_POLICY_JSON scratch
cid=$output

run_buildah add --no-follow-symlinks $cid ${TEST_SCRATCH_DIR}/src /dest

run_buildah mount $cid
root=$output
ls -lahR $root
test -L $root/dest/symlink
test "$(readlink $root/dest/symlink)" = "./file"
}
Loading