mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-01-11 03:11:50 +00:00
Extend s3 storage with link and file exists methods
This commit is contained in:
@@ -186,24 +186,27 @@ func packageIndexByHash(file *indexFile, ext string, hash string, sum string) er
|
||||
src = src + file.parent.suffix + ext
|
||||
filedir := filepath.Dir(filepath.Join(file.parent.basePath, file.relativePath))
|
||||
dst := filepath.Join(filedir, "by-hash", hash)
|
||||
sumfilePath := filepath.Join(dst, sum)
|
||||
|
||||
// link already exists? do nothing
|
||||
if file.parent.publishedStorage.FileExists(filepath.Join(dst, sum)) {
|
||||
if file.parent.publishedStorage.FileExists(sumfilePath) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// create the link
|
||||
err := file.parent.publishedStorage.HardLink(src, filepath.Join(dst, sum))
|
||||
err := file.parent.publishedStorage.HardLink(src, sumfilePath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Access-By-Hash: error creating hardlink %s: %s", filepath.Join(dst, sum), err)
|
||||
return fmt.Errorf("Access-By-Hash: error creating hardlink %s: %s", sumfilePath, err)
|
||||
}
|
||||
|
||||
// if exists, backup symlink
|
||||
// if a previous index file already exists exists, backup symlink
|
||||
if file.parent.publishedStorage.FileExists(filepath.Join(dst, indexfile)) {
|
||||
// if exists, remove old symlink
|
||||
if file.parent.publishedStorage.FileExists(filepath.Join(dst, indexfile+".old")) {
|
||||
link, _ := file.parent.publishedStorage.ReadLink(filepath.Join(dst, indexfile+".old"))
|
||||
file.parent.publishedStorage.Remove(filepath.Join(dst, link))
|
||||
link, err := file.parent.publishedStorage.ReadLink(filepath.Join(dst, indexfile+".old"))
|
||||
if err != nil {
|
||||
file.parent.publishedStorage.Remove(link)
|
||||
}
|
||||
file.parent.publishedStorage.Remove(filepath.Join(dst, indexfile+".old"))
|
||||
}
|
||||
file.parent.publishedStorage.RenameFile(filepath.Join(dst, indexfile),
|
||||
|
||||
61
s3/public.go
61
s3/public.go
@@ -385,26 +385,65 @@ func (storage *PublishedStorage) RenameFile(oldName, newName string) error {
|
||||
return storage.Remove(oldName)
|
||||
}
|
||||
|
||||
// SymLink creates a symbolic link, which can be read with ReadLink
|
||||
// SymLink creates a copy of src file and adds link information as meta data
|
||||
func (storage *PublishedStorage) SymLink(src string, dst string) error {
|
||||
// TODO: create a file containing dst
|
||||
return fmt.Errorf("s3: symlinks not implemented")
|
||||
|
||||
params := &s3.CopyObjectInput{
|
||||
Bucket: aws.String(storage.bucket),
|
||||
CopySource: aws.String(src),
|
||||
Key: aws.String(filepath.Join(storage.prefix, dst)),
|
||||
ACL: aws.String(storage.acl),
|
||||
Metadata: map[string]*string{
|
||||
"SymLink": aws.String(src),
|
||||
},
|
||||
MetadataDirective: aws.String("REPLACE"),
|
||||
}
|
||||
|
||||
if storage.storageClass != "" {
|
||||
params.StorageClass = aws.String(storage.storageClass)
|
||||
}
|
||||
if storage.encryptionMethod != "" {
|
||||
params.ServerSideEncryption = aws.String(storage.encryptionMethod)
|
||||
}
|
||||
|
||||
_, err := storage.s3.CopyObject(params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error symlinking %s -> %s in %s: %s", src, dst, storage, err)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// HardLink creates a hardlink of a file
|
||||
// HardLink using symlink functionality as hard links do not exist
|
||||
func (storage *PublishedStorage) HardLink(src string, dst string) error {
|
||||
// TODO: create a copy of the file
|
||||
return fmt.Errorf("s3: hardlinks not implemented")
|
||||
return storage.SymLink(src, dst)
|
||||
}
|
||||
|
||||
// FileExists returns true if path exists
|
||||
func (storage *PublishedStorage) FileExists(path string) bool {
|
||||
// TODO: implement
|
||||
return false
|
||||
params := &s3.HeadObjectInput{
|
||||
Bucket: aws.String(storage.bucket),
|
||||
Key: aws.String(filepath.Join(storage.prefix, path)),
|
||||
}
|
||||
_, err := storage.s3.HeadObject(params)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// ReadLink returns the symbolic link pointed to by path
|
||||
// ReadLink returns the symbolic link pointed to by path.
|
||||
// This simply reads text file created with SymLink
|
||||
func (storage *PublishedStorage) ReadLink(path string) (string, error) {
|
||||
// TODO: read the path and return the content of the file
|
||||
return "", fmt.Errorf("s3: ReadLink not implemented")
|
||||
params := &s3.HeadObjectInput{
|
||||
Bucket: aws.String(storage.bucket),
|
||||
Key: aws.String(filepath.Join(storage.prefix, path)),
|
||||
}
|
||||
output, err := storage.s3.HeadObject(params)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return aws.StringValue(output.Metadata["SymLink"]), nil
|
||||
}
|
||||
|
||||
@@ -280,3 +280,29 @@ func (s *PublishedStorageSuite) TestLinkFromPool(c *C) {
|
||||
c.Check(s.GetFile(c, "lala/pool/main/m/mars-invaders/mars-invaders_1.03.deb"), DeepEquals, []byte("Contents"))
|
||||
|
||||
}
|
||||
|
||||
func (s *PublishedStorageSuite) TestSymLink(c *C) {
|
||||
s.PutFile(c, "a/b", []byte("test"))
|
||||
|
||||
var err error
|
||||
err = s.storage.SymLink("a/b", "a/b.link")
|
||||
c.Check(err, IsNil)
|
||||
|
||||
var link string
|
||||
link, err = s.storage.ReadLink("a/b.link")
|
||||
c.Check(err, IsNil)
|
||||
c.Check(link, Equals, "a/b")
|
||||
|
||||
c.Skip("copy not available in s3test")
|
||||
}
|
||||
|
||||
|
||||
func (s *PublishedStorageSuite) TestFileExists(c *C) {
|
||||
s.PutFile(c, "a/b", []byte("test"))
|
||||
|
||||
exists := s.storage.FileExists("a/b")
|
||||
c.Check(exists, Equals, true)
|
||||
|
||||
exists = s.storage.FileExists("a/b.invalid")
|
||||
c.Check(exists, Equals, false)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user