forked from chartmuseum/storage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
storage.go
110 lines (97 loc) · 3.06 KB
/
storage.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
/*
Copyright The Helm Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package storage
import (
"fmt"
"path/filepath"
"strings"
"time"
)
type (
// Object is a generic representation of a storage object
Object struct {
Meta Metadata
Path string
Content []byte
LastModified time.Time
}
// Metadata represents the meta information of the object
// includes object name , object version , etc...
Metadata struct {
Name string
Version string
}
// ObjectSliceDiff provides information on what has changed since last calling ListObjects
ObjectSliceDiff struct {
Change bool
Removed []Object
Added []Object
Updated []Object
}
// Backend is a generic interface for storage backends
Backend interface {
ListObjects(prefix string) ([]Object, error)
GetObject(path string) (Object, error)
PutObject(path string, content []byte) error
DeleteObject(path string) error
}
)
// HasExtension determines whether or not an object contains a file extension
func (object Object) HasExtension(extension string) bool {
return filepath.Ext(object.Path) == fmt.Sprintf(".%s", extension)
}
// GetObjectSliceDiff takes two objects slices and returns an ObjectSliceDiff
func GetObjectSliceDiff(prev []Object, curr []Object, timestampTolerance time.Duration) ObjectSliceDiff {
var diff ObjectSliceDiff
pos := make(map[string]Object)
cos := make(map[string]Object)
for _, o := range prev {
pos[o.Path] = o
}
for _, o := range curr {
cos[o.Path] = o
}
// for every object in the previous slice, if it exists in the current slice, check if it is *considered as* updated;
// otherwise, mark it as removed
for _, p := range prev {
if c, found := cos[p.Path]; found {
if c.LastModified.Sub(p.LastModified) > timestampTolerance {
diff.Updated = append(diff.Updated, c)
}
} else {
diff.Removed = append(diff.Removed, p)
}
}
// for every object in the current slice, if it does not exist in the previous slice, mark it as added
for _, c := range curr {
if _, found := pos[c.Path]; !found {
diff.Added = append(diff.Added, c)
}
}
// if any object is marked as removed or added or updated, set change to true
diff.Change = len(diff.Removed)+len(diff.Added)+len(diff.Updated) > 0
return diff
}
func cleanPrefix(prefix string) string {
return strings.Trim(prefix, "/")
}
func removePrefixFromObjectPath(prefix string, path string) string {
if prefix == "" {
return path
}
path = strings.Replace(path, fmt.Sprintf("%s/", prefix), "", 1)
return path
}
func objectPathIsInvalid(path string) bool {
return strings.Contains(path, "/") || path == ""
}