...
1
16
17
18 package continuity
19
20 type resourceUpdate struct {
21 Original Resource
22 Updated Resource
23 }
24
25 type resourceListDifference struct {
26 Additions []Resource
27 Deletions []Resource
28 Updates []resourceUpdate
29 }
30
31 func (l resourceListDifference) HasDiff() bool {
32 return len(l.Additions) > 0 || len(l.Deletions) > 0 || len(l.Updates) > 0
33 }
34
35
36
37
38 func diffResourceList(r1, r2 []Resource) resourceListDifference {
39 i1 := 0
40 i2 := 0
41 var d resourceListDifference
42
43 for i1 < len(r1) && i2 < len(r2) {
44 p1 := r1[i1].Path()
45 p2 := r2[i2].Path()
46 switch {
47 case p1 < p2:
48 d.Deletions = append(d.Deletions, r1[i1])
49 i1++
50 case p1 == p2:
51 if !compareResource(r1[i1], r2[i2]) {
52 d.Updates = append(d.Updates, resourceUpdate{
53 Original: r1[i1],
54 Updated: r2[i2],
55 })
56 }
57 i1++
58 i2++
59 case p1 > p2:
60 d.Additions = append(d.Additions, r2[i2])
61 i2++
62 }
63 }
64
65 for i1 < len(r1) {
66 d.Deletions = append(d.Deletions, r1[i1])
67 i1++
68
69 }
70 for i2 < len(r2) {
71 d.Additions = append(d.Additions, r2[i2])
72 i2++
73 }
74
75 return d
76 }
77
78 func compareResource(r1, r2 Resource) bool {
79 if r1.Path() != r2.Path() {
80 return false
81 }
82 if r1.Mode() != r2.Mode() {
83 return false
84 }
85 if r1.UID() != r2.UID() {
86 return false
87 }
88 if r1.GID() != r2.GID() {
89 return false
90 }
91
92
93
94 switch t1 := r1.(type) {
95 case RegularFile:
96 t2, ok := r2.(RegularFile)
97 if !ok {
98 return false
99 }
100 return compareRegularFile(t1, t2)
101 case Directory:
102 t2, ok := r2.(Directory)
103 if !ok {
104 return false
105 }
106 return compareDirectory(t1, t2)
107 case SymLink:
108 t2, ok := r2.(SymLink)
109 if !ok {
110 return false
111 }
112 return compareSymLink(t1, t2)
113 case NamedPipe:
114 t2, ok := r2.(NamedPipe)
115 if !ok {
116 return false
117 }
118 return compareNamedPipe(t1, t2)
119 case Device:
120 t2, ok := r2.(Device)
121 if !ok {
122 return false
123 }
124 return compareDevice(t1, t2)
125 default:
126
127 return r1 == r2
128 }
129 }
130
131 func compareRegularFile(r1, r2 RegularFile) bool {
132 if r1.Size() != r2.Size() {
133 return false
134 }
135 p1 := r1.Paths()
136 p2 := r2.Paths()
137 if len(p1) != len(p2) {
138 return false
139 }
140 for i := range p1 {
141 if p1[i] != p2[i] {
142 return false
143 }
144 }
145 d1 := r1.Digests()
146 d2 := r2.Digests()
147 if len(d1) != len(d2) {
148 return false
149 }
150 for i := range d1 {
151 if d1[i] != d2[i] {
152 return false
153 }
154 }
155
156 return true
157 }
158
159 func compareSymLink(r1, r2 SymLink) bool {
160 return r1.Target() == r2.Target()
161 }
162
163 func compareDirectory(r1, r2 Directory) bool {
164 return true
165 }
166
167 func compareNamedPipe(r1, r2 NamedPipe) bool {
168 return true
169 }
170
171 func compareDevice(r1, r2 Device) bool {
172 return r1.Major() == r2.Major() && r1.Minor() == r2.Minor()
173 }
174
View as plain text