mirror of
https://github.com/genuinetools/reg.git
synced 2024-08-21 06:10:23 -04:00
157 lines
2.7 KiB
Go
157 lines
2.7 KiB
Go
![]() |
package continuity
|
||
|
|
||
|
type resourceUpdate struct {
|
||
|
Original Resource
|
||
|
Updated Resource
|
||
|
}
|
||
|
|
||
|
type resourceListDifference struct {
|
||
|
Additions []Resource
|
||
|
Deletions []Resource
|
||
|
Updates []resourceUpdate
|
||
|
}
|
||
|
|
||
|
func (l resourceListDifference) HasDiff() bool {
|
||
|
return len(l.Additions) > 0 || len(l.Deletions) > 0 || len(l.Updates) > 0
|
||
|
}
|
||
|
|
||
|
// diffManifest compares two resource lists and returns the list
|
||
|
// of adds updates and deletes, resource lists are not reordered
|
||
|
// before doing difference.
|
||
|
func diffResourceList(r1, r2 []Resource) resourceListDifference {
|
||
|
i1 := 0
|
||
|
i2 := 0
|
||
|
var d resourceListDifference
|
||
|
|
||
|
for i1 < len(r1) && i2 < len(r2) {
|
||
|
p1 := r1[i1].Path()
|
||
|
p2 := r2[i2].Path()
|
||
|
switch {
|
||
|
case p1 < p2:
|
||
|
d.Deletions = append(d.Deletions, r1[i1])
|
||
|
i1++
|
||
|
case p1 == p2:
|
||
|
if !compareResource(r1[i1], r2[i2]) {
|
||
|
d.Updates = append(d.Updates, resourceUpdate{
|
||
|
Original: r1[i1],
|
||
|
Updated: r2[i2],
|
||
|
})
|
||
|
}
|
||
|
i1++
|
||
|
i2++
|
||
|
case p1 > p2:
|
||
|
d.Additions = append(d.Additions, r2[i2])
|
||
|
i2++
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for i1 < len(r1) {
|
||
|
d.Deletions = append(d.Deletions, r1[i1])
|
||
|
i1++
|
||
|
|
||
|
}
|
||
|
for i2 < len(r2) {
|
||
|
d.Additions = append(d.Additions, r2[i2])
|
||
|
i2++
|
||
|
}
|
||
|
|
||
|
return d
|
||
|
}
|
||
|
|
||
|
func compareResource(r1, r2 Resource) bool {
|
||
|
if r1.Path() != r2.Path() {
|
||
|
return false
|
||
|
}
|
||
|
if r1.Mode() != r2.Mode() {
|
||
|
return false
|
||
|
}
|
||
|
if r1.UID() != r2.UID() {
|
||
|
return false
|
||
|
}
|
||
|
if r1.GID() != r2.GID() {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
// TODO(dmcgowan): Check if is XAttrer
|
||
|
|
||
|
switch t1 := r1.(type) {
|
||
|
case RegularFile:
|
||
|
t2, ok := r2.(RegularFile)
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
return compareRegularFile(t1, t2)
|
||
|
case Directory:
|
||
|
t2, ok := r2.(Directory)
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
return compareDirectory(t1, t2)
|
||
|
case SymLink:
|
||
|
t2, ok := r2.(SymLink)
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
return compareSymLink(t1, t2)
|
||
|
case NamedPipe:
|
||
|
t2, ok := r2.(NamedPipe)
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
return compareNamedPipe(t1, t2)
|
||
|
case Device:
|
||
|
t2, ok := r2.(Device)
|
||
|
if !ok {
|
||
|
return false
|
||
|
}
|
||
|
return compareDevice(t1, t2)
|
||
|
default:
|
||
|
// TODO(dmcgowan): Should this panic?
|
||
|
return r1 == r2
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func compareRegularFile(r1, r2 RegularFile) bool {
|
||
|
if r1.Size() != r2.Size() {
|
||
|
return false
|
||
|
}
|
||
|
p1 := r1.Paths()
|
||
|
p2 := r2.Paths()
|
||
|
if len(p1) != len(p2) {
|
||
|
return false
|
||
|
}
|
||
|
for i := range p1 {
|
||
|
if p1[i] != p2[i] {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
d1 := r1.Digests()
|
||
|
d2 := r2.Digests()
|
||
|
if len(d1) != len(d2) {
|
||
|
return false
|
||
|
}
|
||
|
for i := range d1 {
|
||
|
if d1[i] != d2[i] {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func compareSymLink(r1, r2 SymLink) bool {
|
||
|
return r1.Target() == r2.Target()
|
||
|
}
|
||
|
|
||
|
func compareDirectory(r1, r2 Directory) bool {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func compareNamedPipe(r1, r2 NamedPipe) bool {
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func compareDevice(r1, r2 Device) bool {
|
||
|
return r1.Major() == r2.Major() && r1.Minor() == r2.Minor()
|
||
|
}
|