Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add linkMethod relative symlink #1092

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,4 @@ List of contributors, in chronological order:
* Samuel Mutel (https://github.com/smutel)
* Russell Greene (https://github.com/russelltg)
* Wade Simmons (https://github.com/wadey)
* Tuan Lee (https://github.com/vleedev)
2 changes: 1 addition & 1 deletion aptly/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ type LocalPackagePool interface {
// Link generates hardlink to destination path
Link(path, dstPath string) error
// Symlink generates symlink to destination path
Symlink(path, dstPath string) error
Symlink(path, dstPath string, makeRelative bool) error
// FullPath generates full path to the file in pool
//
// Please use with care: it's not supposed to be used to access files
Expand Down
16 changes: 14 additions & 2 deletions files/package_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,20 @@
}

// Symlink generates symlink to destination path
func (pool *PackagePool) Symlink(path, dstPath string) error {
return os.Symlink(filepath.Join(pool.rootPath, path), dstPath)
func (pool *PackagePool) Symlink(path, dstPath string, makeRelative bool) error {
// Convert path to absolute path
path = filepath.Join(pool.rootPath, path)
if makeRelative {
// Take dir of dst
dstDir := filepath.Dir(dstPath)
// Take relative path to go from path to destination directory
relativePath, err := filepath.Rel(dstDir, path)
if err != nil {
return err
}

Check warning on line 407 in files/package_pool.go

View check run for this annotation

Codecov / codecov/patch

files/package_pool.go#L406-L407

Added lines #L406 - L407 were not covered by tests
path = relativePath
}
return os.Symlink(path, dstPath)
}

// FullPath generates full path to the file in pool
Expand Down
39 changes: 21 additions & 18 deletions files/package_pool_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -352,25 +352,28 @@ func (s *PackagePoolSuite) TestLink(c *C) {
}

func (s *PackagePoolSuite) TestSymlink(c *C) {
path, err := s.pool.Import(s.debFile, filepath.Base(s.debFile), &s.checksum, false, s.cs)
c.Check(err, IsNil)

tmpDir := c.MkDir()
dstPath := filepath.Join(tmpDir, filepath.Base(s.debFile))
c.Check(s.pool.Symlink(path, dstPath), IsNil)

info, err := os.Stat(dstPath)
c.Assert(err, IsNil)
c.Check(info.Size(), Equals, int64(2738))
if isSameDevice(s) {
c.Check(info.Sys().(*syscall.Stat_t).Nlink > 2, Equals, true)
} else {
c.Check(info.Sys().(*syscall.Stat_t).Nlink, Equals, uint64(1))
// Test absolute symlink: makeRelative = false
// Test relative symlink: makeRelative = true
for _, makeRelative := range []bool{false, true} {
path, err := s.pool.Import(s.debFile, filepath.Base(s.debFile), &s.checksum, false, s.cs)
c.Check(err, IsNil)

tmpDir := c.MkDir()
dstPath := filepath.Join(tmpDir, filepath.Base(s.debFile))
c.Check(s.pool.Symlink(path, dstPath, makeRelative), IsNil)
info, err := os.Stat(dstPath)
c.Assert(err, IsNil)
c.Check(info.Size(), Equals, int64(2738))
if isSameDevice(s) {
c.Check(info.Sys().(*syscall.Stat_t).Nlink > 2, Equals, true)
} else {
c.Check(info.Sys().(*syscall.Stat_t).Nlink, Equals, uint64(1))
}

info, err = os.Lstat(dstPath)
c.Assert(err, IsNil)
c.Check(int(info.Sys().(*syscall.Stat_t).Mode&syscall.S_IFMT), Equals, int(syscall.S_IFLNK))
}

info, err = os.Lstat(dstPath)
c.Assert(err, IsNil)
c.Check(int(info.Sys().(*syscall.Stat_t).Mode&syscall.S_IFMT), Equals, int(syscall.S_IFLNK))
}

func (s *PackagePoolSuite) TestGenerateRandomPath(c *C) {
Expand Down
16 changes: 11 additions & 5 deletions files/public.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
// Constants defining the type of creating links
const (
LinkMethodHardLink uint = iota
LinkMethodSymLink
LinkMethodAbsoluteSymLink
LinkMethodRelativeSymLink
LinkMethodCopy
)

Expand All @@ -45,8 +46,11 @@

if strings.EqualFold(linkMethod, "copy") {
verifiedLinkMethod = LinkMethodCopy
} else if strings.EqualFold(linkMethod, "symlink") {
verifiedLinkMethod = LinkMethodSymLink
} else if strings.EqualFold(linkMethod, "symlink") || strings.EqualFold(linkMethod, "absoluteSymlink") {
// By default: symlink is absolute symlink
verifiedLinkMethod = LinkMethodAbsoluteSymLink
} else if strings.EqualFold(linkMethod, "relativeSymlink") {
verifiedLinkMethod = LinkMethodRelativeSymLink
} else {
verifiedLinkMethod = LinkMethodHardLink
}
Expand Down Expand Up @@ -218,8 +222,10 @@
}

err = dst.Close()
} else if storage.linkMethod == LinkMethodSymLink {
err = sourcePool.(aptly.LocalPackagePool).Symlink(sourcePath, filepath.Join(poolPath, baseName))
} else if storage.linkMethod == LinkMethodAbsoluteSymLink {
err = sourcePool.(aptly.LocalPackagePool).Symlink(sourcePath, filepath.Join(poolPath, baseName), false)
} else if storage.linkMethod == LinkMethodRelativeSymLink {
err = sourcePool.(aptly.LocalPackagePool).Symlink(sourcePath, filepath.Join(poolPath, baseName), true)

Check warning on line 228 in files/public.go

View check run for this annotation

Codecov / codecov/patch

files/public.go#L228

Added line #L228 was not covered by tests
} else {
err = sourcePool.(aptly.LocalPackagePool).Link(sourcePath, filepath.Join(poolPath, baseName))
}
Expand Down
22 changes: 15 additions & 7 deletions files/public_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ import (
)

type PublishedStorageSuite struct {
root string
storage *PublishedStorage
storageSymlink *PublishedStorage
storageCopy *PublishedStorage
storageCopySize *PublishedStorage
cs aptly.ChecksumStorage
root string
storage *PublishedStorage
storageSymlink *PublishedStorage
storageAbsoluteSymlink *PublishedStorage
storageRelativeSymlink *PublishedStorage
storageCopy *PublishedStorage
storageCopySize *PublishedStorage
cs aptly.ChecksumStorage
}

var _ = Suite(&PublishedStorageSuite{})
Expand All @@ -27,14 +29,18 @@ func (s *PublishedStorageSuite) SetUpTest(c *C) {
s.root = c.MkDir()
s.storage = NewPublishedStorage(filepath.Join(s.root, "public"), "", "")
s.storageSymlink = NewPublishedStorage(filepath.Join(s.root, "public_symlink"), "symlink", "")
s.storageAbsoluteSymlink = NewPublishedStorage(filepath.Join(s.root, "public_absolute_symlink"), "absoluteSymlink", "")
s.storageRelativeSymlink = NewPublishedStorage(filepath.Join(s.root, "public_relative_symlink"), "relativeSymlink", "")
s.storageCopy = NewPublishedStorage(filepath.Join(s.root, "public_copy"), "copy", "")
s.storageCopySize = NewPublishedStorage(filepath.Join(s.root, "public_copysize"), "copy", "size")
s.cs = NewMockChecksumStorage()
}

func (s *PublishedStorageSuite) TestLinkMethodField(c *C) {
c.Assert(s.storage.linkMethod, Equals, LinkMethodHardLink)
c.Assert(s.storageSymlink.linkMethod, Equals, LinkMethodSymLink)
c.Assert(s.storageSymlink.linkMethod, Equals, LinkMethodAbsoluteSymLink)
c.Assert(s.storageAbsoluteSymlink.linkMethod, Equals, LinkMethodAbsoluteSymLink)
c.Assert(s.storageRelativeSymlink.linkMethod, Equals, LinkMethodRelativeSymLink)
c.Assert(s.storageCopy.linkMethod, Equals, LinkMethodCopy)
c.Assert(s.storageCopySize.linkMethod, Equals, LinkMethodCopy)
}
Expand All @@ -47,6 +53,8 @@ func (s *PublishedStorageSuite) TestVerifyMethodField(c *C) {
func (s *PublishedStorageSuite) TestPublicPath(c *C) {
c.Assert(s.storage.PublicPath(), Equals, filepath.Join(s.root, "public"))
c.Assert(s.storageSymlink.PublicPath(), Equals, filepath.Join(s.root, "public_symlink"))
c.Assert(s.storageAbsoluteSymlink.PublicPath(), Equals, filepath.Join(s.root, "public_absolute_symlink"))
c.Assert(s.storageRelativeSymlink.PublicPath(), Equals, filepath.Join(s.root, "public_relative_symlink"))
c.Assert(s.storageCopy.PublicPath(), Equals, filepath.Join(s.root, "public_copy"))
c.Assert(s.storageCopySize.PublicPath(), Equals, filepath.Join(s.root, "public_copysize"))
}
Expand Down
14 changes: 11 additions & 3 deletions man/aptly.1
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,19 @@ Configuration file is stored in JSON format (default values shown below):
},
"test2": {
"rootDir": "/opt/srv2/aptly_public",
"linkMethod": "copy",
"verifyMethod": "md5"
"linkMethod": "absoluteSymlink"
},
"test3": {
"rootDir": "/opt/srv3/aptly_public",
"linkMethod": "relativeSymlink"
},
"test4": {
"rootDir": "/opt/srv4/aptly_public",
"linkMethod": "copy",
"verifyMethod": "md5"
},
"test5": {
"rootDir": "/opt/srv5/aptly_public",
"linkMethod": "hardlink"
}
},
Expand Down Expand Up @@ -205,7 +213,7 @@ The publish directory, e\.g\., \fB/opt/srv/aptly_public\fR\.
.
.TP
\fBlinkMethod\fR
This is one of \fBhardlink\fR, \fBsymlink\fR or \fBcopy\fR\. It specifies how aptly links the files from the internal pool to the published directory\. If not specified, empty or wrong, this defaults to \fBhardlink\fR\.
This is one of \fBhardlink\fR, \fBsymlink\fR, \fBabsoluteSymlink\fR, \fBrelativeSymlink\fR or \fBcopy\fR\. It specifies how aptly links the files from the internal pool to the published directory\. The option \fBsymlink\fR will be treated as \fBabsoluteSymlink\fR\. If not specified, empty or wrong, this defaults to \fBhardlink\fR\.
.
.TP
\fBverifyMethod\fR
Expand Down
17 changes: 13 additions & 4 deletions man/aptly.1.ronn.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,19 @@ Configuration file is stored in JSON format (default values shown below):
},
"test2": {
"rootDir": "/opt/srv2/aptly_public",
"linkMethod": "copy",
"verifyMethod": "md5"
"linkMethod": "absoluteSymlink"
},
"test3": {
"rootDir": "/opt/srv3/aptly_public",
"linkMethod": "relativeSymlink"
},
"test4": {
"rootDir": "/opt/srv4/aptly_public",
"linkMethod": "copy",
"verifyMethod": "md5"
},
"test5": {
"rootDir": "/opt/srv5/aptly_public",
"linkMethod": "hardlink"
}
},
Expand Down Expand Up @@ -187,8 +195,9 @@ and the following associated settings:
* `rootDir`:
The publish directory, e.g., `/opt/srv/aptly_public`.
* `linkMethod`:
This is one of `hardlink`, `symlink` or `copy`. It specifies how aptly links the
files from the internal pool to the published directory.
This is one of `hardlink`, `symlink`, `absoluteSymlink`, `relativeSymlink` or `copy`.
It specifies how aptly links the files from the internal pool to the published directory.
The option `symlink` will be treated as `absoluteSymlink`.
If not specified, empty or wrong, this defaults to `hardlink`.
* `verifyMethod`:
This is used only when setting the `linkMethod` to `copy`. Possible values are
Expand Down