mirror of
https://github.com/aptly-dev/aptly.git
synced 2026-05-09 22:39:53 +00:00
Add 'force' to LinkFromPool method: overwrite file even if exists and different content. #90
This commit is contained in:
+1
-1
@@ -34,7 +34,7 @@ type PublishedStorage interface {
|
|||||||
// Remove removes single file under public path
|
// Remove removes single file under public path
|
||||||
Remove(path string) error
|
Remove(path string) error
|
||||||
// LinkFromPool links package file from pool to dist's pool location
|
// LinkFromPool links package file from pool to dist's pool location
|
||||||
LinkFromPool(publishedDirectory string, sourcePool PackagePool, sourcePath, sourceMD5 string) error
|
LinkFromPool(publishedDirectory string, sourcePool PackagePool, sourcePath, sourceMD5 string, force bool) error
|
||||||
// Filelist returns list of files under prefix
|
// Filelist returns list of files under prefix
|
||||||
Filelist(prefix string) ([]string, error)
|
Filelist(prefix string) ([]string, error)
|
||||||
// RenameFile renames (moves) file
|
// RenameFile renames (moves) file
|
||||||
|
|||||||
+1
-1
@@ -477,7 +477,7 @@ func (p *Package) LinkFromPool(publishedStorage aptly.PublishedStorage, packageP
|
|||||||
relPath := filepath.Join("pool", component, poolDir)
|
relPath := filepath.Join("pool", component, poolDir)
|
||||||
publishedDirectory := filepath.Join(prefix, relPath)
|
publishedDirectory := filepath.Join(prefix, relPath)
|
||||||
|
|
||||||
err = publishedStorage.LinkFromPool(publishedDirectory, packagePool, sourcePath, f.Checksums.MD5)
|
err = publishedStorage.LinkFromPool(publishedDirectory, packagePool, sourcePath, f.Checksums.MD5, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-4
@@ -79,7 +79,8 @@ func (storage *PublishedStorage) RemoveDirs(path string, progress aptly.Progress
|
|||||||
// sourcePath is filepath to package file in package pool
|
// sourcePath is filepath to package file in package pool
|
||||||
//
|
//
|
||||||
// LinkFromPool returns relative path for the published file to be included in package index
|
// LinkFromPool returns relative path for the published file to be included in package index
|
||||||
func (storage *PublishedStorage) LinkFromPool(publishedDirectory string, sourcePool aptly.PackagePool, sourcePath, sourceMD5 string) error {
|
func (storage *PublishedStorage) LinkFromPool(publishedDirectory string, sourcePool aptly.PackagePool,
|
||||||
|
sourcePath, sourceMD5 string, force bool) error {
|
||||||
// verify that package pool is local pool is filesystem pool
|
// verify that package pool is local pool is filesystem pool
|
||||||
_ = sourcePool.(*PackagePool)
|
_ = sourcePool.(*PackagePool)
|
||||||
|
|
||||||
@@ -105,10 +106,18 @@ func (storage *PublishedStorage) LinkFromPool(publishedDirectory string, sourceP
|
|||||||
srcSys := srcStat.Sys().(*syscall.Stat_t)
|
srcSys := srcStat.Sys().(*syscall.Stat_t)
|
||||||
dstSys := dstStat.Sys().(*syscall.Stat_t)
|
dstSys := dstStat.Sys().(*syscall.Stat_t)
|
||||||
|
|
||||||
if srcSys.Ino != dstSys.Ino {
|
if srcSys.Ino == dstSys.Ino {
|
||||||
return fmt.Errorf("error linking file to %s: file already exists and is different", filepath.Join(poolPath, baseName))
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !force {
|
||||||
|
return fmt.Errorf("error linking file to %s: file already exists and is different", filepath.Join(poolPath, baseName))
|
||||||
|
} else {
|
||||||
|
err = os.Remove(filepath.Join(poolPath, baseName))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return os.Link(sourcePath, filepath.Join(poolPath, baseName))
|
return os.Link(sourcePath, filepath.Join(poolPath, baseName))
|
||||||
|
|||||||
+18
-2
@@ -153,7 +153,7 @@ func (s *PublishedStorageSuite) TestLinkFromPool(c *C) {
|
|||||||
err = ioutil.WriteFile(t.sourcePath, []byte("Contents"), 0644)
|
err = ioutil.WriteFile(t.sourcePath, []byte("Contents"), 0644)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.storage.LinkFromPool(filepath.Join(t.prefix, "pool", t.component, t.poolDirectory), pool, t.sourcePath, "")
|
err = s.storage.LinkFromPool(filepath.Join(t.prefix, "pool", t.component, t.poolDirectory), pool, t.sourcePath, "", false)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
st, err := os.Stat(filepath.Join(s.storage.rootPath, t.prefix, t.expectedFilename))
|
st, err := os.Stat(filepath.Join(s.storage.rootPath, t.prefix, t.expectedFilename))
|
||||||
@@ -171,6 +171,22 @@ func (s *PublishedStorageSuite) TestLinkFromPool(c *C) {
|
|||||||
err = ioutil.WriteFile(sourcePath, []byte("Contents"), 0644)
|
err = ioutil.WriteFile(sourcePath, []byte("Contents"), 0644)
|
||||||
c.Assert(err, IsNil)
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath, "")
|
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath, "", false)
|
||||||
c.Check(err, ErrorMatches, ".*file already exists and is different")
|
c.Check(err, ErrorMatches, ".*file already exists and is different")
|
||||||
|
|
||||||
|
st, err := os.Stat(sourcePath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
info := st.Sys().(*syscall.Stat_t)
|
||||||
|
c.Check(int(info.Nlink), Equals, 1)
|
||||||
|
|
||||||
|
// linking with force
|
||||||
|
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath, "", true)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
st, err = os.Stat(sourcePath)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
info = st.Sys().(*syscall.Stat_t)
|
||||||
|
c.Check(int(info.Nlink), Equals, 2)
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -140,7 +140,8 @@ func (storage *PublishedStorage) RemoveDirs(path string, progress aptly.Progress
|
|||||||
// sourcePath is filepath to package file in package pool
|
// sourcePath is filepath to package file in package pool
|
||||||
//
|
//
|
||||||
// LinkFromPool returns relative path for the published file to be included in package index
|
// LinkFromPool returns relative path for the published file to be included in package index
|
||||||
func (storage *PublishedStorage) LinkFromPool(publishedDirectory string, sourcePool aptly.PackagePool, sourcePath, sourceMD5 string) error {
|
func (storage *PublishedStorage) LinkFromPool(publishedDirectory string, sourcePool aptly.PackagePool,
|
||||||
|
sourcePath, sourceMD5 string, force bool) error {
|
||||||
// verify that package pool is local pool in filesystem
|
// verify that package pool is local pool in filesystem
|
||||||
_ = sourcePool.(*files.PackagePool)
|
_ = sourcePool.(*files.PackagePool)
|
||||||
|
|
||||||
@@ -159,9 +160,15 @@ func (storage *PublishedStorage) LinkFromPool(publishedDirectory string, sourceP
|
|||||||
return fmt.Errorf("error getting information about %s from %s: %s", poolPath, storage, err)
|
return fmt.Errorf("error getting information about %s from %s: %s", poolPath, storage, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if strings.Replace(dstKey.ETag, "\"", "", -1) == sourceMD5 {
|
destinationMD5 := strings.Replace(dstKey.ETag, "\"", "", -1)
|
||||||
|
if destinationMD5 == sourceMD5 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !force && destinationMD5 != sourceMD5 {
|
||||||
|
return fmt.Errorf("error putting file to %s: file already exists and is different: %s", poolPath, storage)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return storage.PutFile(relPath, sourcePath)
|
return storage.PutFile(relPath, sourcePath)
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package s3
|
|||||||
import (
|
import (
|
||||||
"github.com/mitchellh/goamz/aws"
|
"github.com/mitchellh/goamz/aws"
|
||||||
"github.com/mitchellh/goamz/s3/s3test"
|
"github.com/mitchellh/goamz/s3/s3test"
|
||||||
|
"github.com/smira/aptly/files"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
. "launchpad.net/gocheck"
|
. "launchpad.net/gocheck"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -114,3 +116,58 @@ func (s *PublishedStorageSuite) TestRemoveDirs(c *C) {
|
|||||||
c.Check(list, DeepEquals, []string{"a", "b", "c", "lala/a", "lala/b", "lala/c", "test/a", "test/b", "testa"})
|
c.Check(list, DeepEquals, []string{"a", "b", "c", "lala/a", "lala/b", "lala/c", "test/a", "test/b", "testa"})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PublishedStorageSuite) TestRenameFile(c *C) {
|
||||||
|
c.Skip("copy not available in s3test")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *PublishedStorageSuite) TestLinkFromPool(c *C) {
|
||||||
|
root := c.MkDir()
|
||||||
|
pool := files.NewPackagePool(root)
|
||||||
|
|
||||||
|
sourcePath := filepath.Join(root, "pool/c1/df/mars-invaders_1.03.deb")
|
||||||
|
err := os.MkdirAll(filepath.Dir(sourcePath), 0755)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(sourcePath, []byte("Contents"), 0644)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
sourcePath2 := filepath.Join(root, "pool/e9/df/mars-invaders_1.03.deb")
|
||||||
|
err = os.MkdirAll(filepath.Dir(sourcePath2), 0755)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(sourcePath2, []byte("Spam"), 0644)
|
||||||
|
c.Assert(err, IsNil)
|
||||||
|
|
||||||
|
// first link from pool
|
||||||
|
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath, "c1df1da7a1ce305a3b60af9d5733ac1d", false)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
data, err := s.storage.bucket.Get("pool/main/m/mars-invaders/mars-invaders_1.03.deb")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(data, DeepEquals, []byte("Contents"))
|
||||||
|
|
||||||
|
// duplicate link from pool
|
||||||
|
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath, "c1df1da7a1ce305a3b60af9d5733ac1d", false)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
data, err = s.storage.bucket.Get("pool/main/m/mars-invaders/mars-invaders_1.03.deb")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(data, DeepEquals, []byte("Contents"))
|
||||||
|
|
||||||
|
// link from pool with conflict
|
||||||
|
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath2, "e9dfd31cc505d51fc26975250750deab", false)
|
||||||
|
c.Check(err, ErrorMatches, ".*file already exists and is different.*")
|
||||||
|
|
||||||
|
data, err = s.storage.bucket.Get("pool/main/m/mars-invaders/mars-invaders_1.03.deb")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(data, DeepEquals, []byte("Contents"))
|
||||||
|
|
||||||
|
// link from pool with conflict and force
|
||||||
|
err = s.storage.LinkFromPool(filepath.Join("", "pool", "main", "m/mars-invaders"), pool, sourcePath2, "e9dfd31cc505d51fc26975250750deab", true)
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
|
||||||
|
data, err = s.storage.bucket.Get("pool/main/m/mars-invaders/mars-invaders_1.03.deb")
|
||||||
|
c.Check(err, IsNil)
|
||||||
|
c.Check(data, DeepEquals, []byte("Spam"))
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user