forked from aptly-dev/aptly
/
public.go
156 lines (130 loc) · 4.23 KB
/
public.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
package files
import (
"fmt"
"github.com/smira/aptly/aptly"
"io"
"os"
"path/filepath"
"syscall"
)
// PublishedStorage abstract file system with public dirs (published repos)
type PublishedStorage struct {
rootPath string
}
// Check interfaces
var (
_ aptly.PublishedStorage = (*PublishedStorage)(nil)
_ aptly.LocalPublishedStorage = (*PublishedStorage)(nil)
)
// NewPublishedStorage creates new instance of PublishedStorage which specified root
func NewPublishedStorage(root string) *PublishedStorage {
return &PublishedStorage{rootPath: filepath.Join(root, "public")}
}
// PublicPath returns root of public part
func (storage *PublishedStorage) PublicPath() string {
return storage.rootPath
}
// MkDir creates directory recursively under public path
func (storage *PublishedStorage) MkDir(path string) error {
return os.MkdirAll(filepath.Join(storage.rootPath, path), 0777)
}
// PutFile puts file into published storage at specified path
func (storage *PublishedStorage) PutFile(path string, sourceFilename string) error {
var (
source, f *os.File
err error
)
source, err = os.Open(sourceFilename)
if err != nil {
return err
}
defer source.Close()
f, err = os.Create(filepath.Join(storage.rootPath, path))
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, source)
return err
}
// Remove removes single file under public path
func (storage *PublishedStorage) Remove(path string) error {
filepath := filepath.Join(storage.rootPath, path)
return os.Remove(filepath)
}
// RemoveDirs removes directory structure under public path
func (storage *PublishedStorage) RemoveDirs(path string, progress aptly.Progress) error {
filepath := filepath.Join(storage.rootPath, path)
if progress != nil {
progress.Printf("Removing %s...\n", filepath)
}
return os.RemoveAll(filepath)
}
// LinkFromPool links package file from pool to dist's pool location
//
// publishedDirectory is desired location in pool (like prefix/pool/component/liba/libav/)
// sourcePool is instance of aptly.PackagePool
// sourcePath is filepath to package file in package pool
//
// 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, force bool) error {
// verify that package pool is local pool is filesystem pool
_ = sourcePool.(*PackagePool)
baseName := filepath.Base(sourcePath)
poolPath := filepath.Join(storage.rootPath, publishedDirectory)
err := os.MkdirAll(poolPath, 0777)
if err != nil {
return err
}
var dstStat, srcStat os.FileInfo
dstStat, err = os.Stat(filepath.Join(poolPath, baseName))
if err == nil {
// already exists, check source file
srcStat, err = os.Stat(sourcePath)
if err != nil {
// source file doesn't exist? problem!
return err
}
srcSys := srcStat.Sys().(*syscall.Stat_t)
dstSys := dstStat.Sys().(*syscall.Stat_t)
// source and destination inodes match, no need to link
if srcSys.Ino == dstSys.Ino {
return nil
}
// source and destination have different inodes, if !forced, this is fatal error
if !force {
return fmt.Errorf("error linking file to %s: file already exists and is different", filepath.Join(poolPath, baseName))
}
// forced, so remove destination
err = os.Remove(filepath.Join(poolPath, baseName))
if err != nil {
return err
}
}
// destination doesn't exist (or forced), create link
return os.Link(sourcePath, filepath.Join(poolPath, baseName))
}
// Filelist returns list of files under prefix
func (storage *PublishedStorage) Filelist(prefix string) ([]string, error) {
root := filepath.Join(storage.rootPath, prefix)
result := []string{}
err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
result = append(result, path[len(root)+1:])
}
return nil
})
if err != nil && os.IsNotExist(err) {
// file path doesn't exist, consider it empty
return []string{}, nil
}
return result, err
}
// RenameFile renames (moves) file
func (storage *PublishedStorage) RenameFile(oldName, newName string) error {
return os.Rename(filepath.Join(storage.rootPath, oldName), filepath.Join(storage.rootPath, newName))
}