...

Source file src/github.com/containerd/continuity/fs/fstest/continuity_util.go

Documentation: github.com/containerd/continuity/fs/fstest

     1  /*
     2     Copyright The containerd Authors.
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package fstest
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  
    23  	"github.com/containerd/continuity"
    24  )
    25  
    26  type resourceUpdate struct {
    27  	Original continuity.Resource
    28  	Updated  continuity.Resource
    29  }
    30  
    31  func (u resourceUpdate) String() string {
    32  	return fmt.Sprintf("%s(mode: %o, uid: %d, gid: %d) -> %s(mode: %o, uid: %d, gid: %d)",
    33  		u.Original.Path(), u.Original.Mode(), u.Original.UID(), u.Original.GID(),
    34  		u.Updated.Path(), u.Updated.Mode(), u.Updated.UID(), u.Updated.GID(),
    35  	)
    36  }
    37  
    38  type resourceListDifference struct {
    39  	Additions []continuity.Resource
    40  	Deletions []continuity.Resource
    41  	Updates   []resourceUpdate
    42  }
    43  
    44  func (l resourceListDifference) HasDiff() bool {
    45  	if len(l.Deletions) > 0 || len(l.Updates) > 0 || (len(metadataFiles) == 0 && len(l.Additions) > 0) {
    46  		return true
    47  	}
    48  
    49  	for _, add := range l.Additions {
    50  		if ok := metadataFiles[add.Path()]; !ok {
    51  			return true
    52  		}
    53  	}
    54  
    55  	return false
    56  }
    57  
    58  func (l resourceListDifference) String() string {
    59  	buf := bytes.NewBuffer(nil)
    60  	for _, add := range l.Additions {
    61  		fmt.Fprintf(buf, "+ %s\n", add.Path())
    62  	}
    63  	for _, del := range l.Deletions {
    64  		fmt.Fprintf(buf, "- %s\n", del.Path())
    65  	}
    66  	for _, upt := range l.Updates {
    67  		fmt.Fprintf(buf, "~ %s\n", upt.String())
    68  	}
    69  	return buf.String()
    70  }
    71  
    72  // diffManifest compares two resource lists and returns the list
    73  // of adds updates and deletes, resource lists are not reordered
    74  // before doing difference.
    75  func diffResourceList(r1, r2 []continuity.Resource) resourceListDifference {
    76  	i1 := 0
    77  	i2 := 0
    78  	var d resourceListDifference
    79  
    80  	for i1 < len(r1) && i2 < len(r2) {
    81  		p1 := r1[i1].Path()
    82  		p2 := r2[i2].Path()
    83  		switch {
    84  		case p1 < p2:
    85  			d.Deletions = append(d.Deletions, r1[i1])
    86  			i1++
    87  		case p1 == p2:
    88  			if !compareResource(r1[i1], r2[i2]) {
    89  				d.Updates = append(d.Updates, resourceUpdate{
    90  					Original: r1[i1],
    91  					Updated:  r2[i2],
    92  				})
    93  			}
    94  			i1++
    95  			i2++
    96  		case p1 > p2:
    97  			d.Additions = append(d.Additions, r2[i2])
    98  			i2++
    99  		}
   100  	}
   101  
   102  	for i1 < len(r1) {
   103  		d.Deletions = append(d.Deletions, r1[i1])
   104  		i1++
   105  
   106  	}
   107  	for i2 < len(r2) {
   108  		d.Additions = append(d.Additions, r2[i2])
   109  		i2++
   110  	}
   111  
   112  	return d
   113  }
   114  
   115  func compareResource(r1, r2 continuity.Resource) bool {
   116  	if r1.Path() != r2.Path() {
   117  		return false
   118  	}
   119  	if r1.Mode() != r2.Mode() {
   120  		return false
   121  	}
   122  	if r1.UID() != r2.UID() {
   123  		return false
   124  	}
   125  	if r1.GID() != r2.GID() {
   126  		return false
   127  	}
   128  
   129  	// TODO(dmcgowan): Check if is XAttrer
   130  
   131  	return compareResourceTypes(r1, r2)
   132  }
   133  
   134  func compareResourceTypes(r1, r2 continuity.Resource) bool {
   135  	switch t1 := r1.(type) {
   136  	case continuity.RegularFile:
   137  		t2, ok := r2.(continuity.RegularFile)
   138  		if !ok {
   139  			return false
   140  		}
   141  		return compareRegularFile(t1, t2)
   142  	case continuity.Directory:
   143  		t2, ok := r2.(continuity.Directory)
   144  		if !ok {
   145  			return false
   146  		}
   147  		return compareDirectory(t1, t2)
   148  	case continuity.SymLink:
   149  		t2, ok := r2.(continuity.SymLink)
   150  		if !ok {
   151  			return false
   152  		}
   153  		return compareSymLink(t1, t2)
   154  	case continuity.NamedPipe:
   155  		t2, ok := r2.(continuity.NamedPipe)
   156  		if !ok {
   157  			return false
   158  		}
   159  		return compareNamedPipe(t1, t2)
   160  	case continuity.Device:
   161  		t2, ok := r2.(continuity.Device)
   162  		if !ok {
   163  			return false
   164  		}
   165  		return compareDevice(t1, t2)
   166  	default:
   167  		// TODO(dmcgowan): Should this panic?
   168  		return r1 == r2
   169  	}
   170  }
   171  
   172  func compareRegularFile(r1, r2 continuity.RegularFile) bool {
   173  	if r1.Size() != r2.Size() {
   174  		return false
   175  	}
   176  	p1 := r1.Paths()
   177  	p2 := r2.Paths()
   178  	if len(p1) != len(p2) {
   179  		return false
   180  	}
   181  	for i := range p1 {
   182  		if p1[i] != p2[i] {
   183  			return false
   184  		}
   185  	}
   186  	d1 := r1.Digests()
   187  	d2 := r2.Digests()
   188  	if len(d1) != len(d2) {
   189  		return false
   190  	}
   191  	for i := range d1 {
   192  		if d1[i] != d2[i] {
   193  			return false
   194  		}
   195  	}
   196  
   197  	return true
   198  }
   199  
   200  func compareSymLink(r1, r2 continuity.SymLink) bool {
   201  	return r1.Target() == r2.Target()
   202  }
   203  
   204  func compareDirectory(r1, r2 continuity.Directory) bool {
   205  	return true
   206  }
   207  
   208  func compareNamedPipe(r1, r2 continuity.NamedPipe) bool {
   209  	return true
   210  }
   211  
   212  func compareDevice(r1, r2 continuity.Device) bool {
   213  	return r1.Major() == r2.Major() && r1.Minor() == r2.Minor()
   214  }
   215  

View as plain text