...
1
16
17 package continuity
18
19 import (
20 "fmt"
21 "io"
22 "os"
23 "sort"
24
25 pb "github.com/containerd/continuity/proto"
26 "google.golang.org/protobuf/encoding/prototext"
27 "google.golang.org/protobuf/proto"
28 )
29
30
31
32 type Manifest struct {
33
34 Resources []Resource
35 }
36
37 func Unmarshal(p []byte) (*Manifest, error) {
38 var bm pb.Manifest
39
40 if err := proto.Unmarshal(p, &bm); err != nil {
41 return nil, err
42 }
43
44 var m Manifest
45 for _, b := range bm.Resource {
46 r, err := fromProto(b)
47 if err != nil {
48 return nil, err
49 }
50
51 m.Resources = append(m.Resources, r)
52 }
53
54 return &m, nil
55 }
56
57 func Marshal(m *Manifest) ([]byte, error) {
58 var bm pb.Manifest
59 for _, resource := range m.Resources {
60 bm.Resource = append(bm.Resource, toProto(resource))
61 }
62
63 return proto.Marshal(&bm)
64 }
65
66 func MarshalText(w io.Writer, m *Manifest) error {
67 var bm pb.Manifest
68 for _, resource := range m.Resources {
69 bm.Resource = append(bm.Resource, toProto(resource))
70 }
71
72 b, err := prototext.Marshal(&bm)
73 if err != nil {
74 return err
75 }
76 _, err = w.Write(b)
77 return err
78 }
79
80
81 func BuildManifest(ctx Context) (*Manifest, error) {
82 resourcesByPath := map[string]Resource{}
83 hardLinks := newHardlinkManager()
84
85 if err := ctx.Walk(func(p string, fi os.FileInfo, err error) error {
86 if err != nil {
87 return fmt.Errorf("error walking %s: %w", p, err)
88 }
89
90 if p == string(os.PathSeparator) {
91
92 return nil
93 }
94
95 resource, err := ctx.Resource(p, fi)
96 if err != nil {
97 if err == ErrNotFound {
98 return nil
99 }
100 return fmt.Errorf("failed to get resource %q: %w", p, err)
101 }
102
103
104 if err := hardLinks.Add(fi, resource); err == nil {
105
106
107 return nil
108 } else if err != errNotAHardLink {
109
110 return fmt.Errorf("adding hardlink %s: %w", p, err)
111 }
112
113 resourcesByPath[p] = resource
114
115 return nil
116 }); err != nil {
117 return nil, err
118 }
119
120
121 hardLinked, err := hardLinks.Merge()
122 if err != nil {
123 return nil, err
124 }
125
126 for _, resource := range hardLinked {
127 resourcesByPath[resource.Path()] = resource
128 }
129
130 var resources []Resource
131 for _, resource := range resourcesByPath {
132 resources = append(resources, resource)
133 }
134
135 sort.Stable(ByPath(resources))
136
137 return &Manifest{
138 Resources: resources,
139 }, nil
140 }
141
142
143
144 func VerifyManifest(ctx Context, manifest *Manifest) error {
145 for _, resource := range manifest.Resources {
146 if err := ctx.Verify(resource); err != nil {
147 return err
148 }
149 }
150
151 return nil
152 }
153
154
155
156 func ApplyManifest(ctx Context, manifest *Manifest) error {
157 for _, resource := range manifest.Resources {
158 if err := ctx.Apply(resource); err != nil {
159 return err
160 }
161 }
162
163 return nil
164 }
165
View as plain text