Skip to content

Commit

Permalink
Merge pull request #100 from tonistiigi/differ
Browse files Browse the repository at this point in the history
receive: add differ selection
  • Loading branch information
tonistiigi authored Apr 15, 2021
2 parents 03711f9 + b59b502 commit 8599091
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
51 changes: 47 additions & 4 deletions diff_containerd.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package fsutil

import (
"bytes"
"context"
"io"
"os"
"strings"

Expand Down Expand Up @@ -35,14 +37,16 @@ const (
// computed during a directory changes calculation.
type ChangeFunc func(ChangeKind, string, os.FileInfo, error) error

const compareChunkSize = 32 * 1024

type currentPath struct {
path string
stat *types.Stat
// fullPath string
}

// doubleWalkDiff walks both directories to create a diff
func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn, filter FilterFunc) (err error) {
func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn, filter FilterFunc, differ DiffType) (err error) {
g, ctx := errgroup.WithContext(ctx)

var (
Expand Down Expand Up @@ -116,7 +120,7 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn, fil
}
f1 = nil
case ChangeKindModify:
same, err := sameFile(f1, f2copy)
same, err := sameFile(f1, f2copy, differ)
if err != nil {
return err
}
Expand Down Expand Up @@ -165,7 +169,10 @@ func pathChange(lower, upper *currentPath) (ChangeKind, string) {
}
}

func sameFile(f1, f2 *currentPath) (same bool, retErr error) {
func sameFile(f1, f2 *currentPath, differ DiffType) (same bool, retErr error) {
if differ == DiffNone {
return false, nil
}
// If not a directory also check size, modtime, and content
if !f1.stat.IsDir() {
if f1.stat.Size_ != f2.stat.Size_ {
Expand All @@ -177,7 +184,43 @@ func sameFile(f1, f2 *currentPath) (same bool, retErr error) {
}
}

return compareStat(f1.stat, f2.stat)
same, err := compareStat(f1.stat, f2.stat)
if err != nil || !same || differ == DiffMetadata {
return same, err
}
return compareFileContent(f1.path, f2.path)
}

func compareFileContent(p1, p2 string) (bool, error) {
f1, err := os.Open(p1)
if err != nil {
return false, err
}
defer f1.Close()
f2, err := os.Open(p2)
if err != nil {
return false, err
}
defer f2.Close()

b1 := make([]byte, compareChunkSize)
b2 := make([]byte, compareChunkSize)
for {
n1, err1 := f1.Read(b1)
if err1 != nil && err1 != io.EOF {
return false, err1
}
n2, err2 := f2.Read(b2)
if err2 != nil && err2 != io.EOF {
return false, err2
}
if n1 != n2 || !bytes.Equal(b1[:n1], b2[:n2]) {
return false, nil
}
if err1 == io.EOF && err2 == io.EOF {
return true, nil
}
}
}

// compareStat returns whether the stats are equivalent,
Expand Down
13 changes: 12 additions & 1 deletion receive.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,21 @@ import (
"golang.org/x/sync/errgroup"
)

type DiffType int

const (
DiffMetadata DiffType = iota
DiffNone
DiffContent
)

type ReceiveOpt struct {
NotifyHashed ChangeFunc
ContentHasher ContentHasher
ProgressCb func(int, bool)
Merge bool
Filter FilterFunc
Differ DiffType
}

func Receive(ctx context.Context, conn Stream, dest string, opt ReceiveOpt) error {
Expand All @@ -33,6 +42,7 @@ func Receive(ctx context.Context, conn Stream, dest string, opt ReceiveOpt) erro
progressCb: opt.ProgressCb,
merge: opt.Merge,
filter: opt.Filter,
differ: opt.Differ,
}
return r.run(ctx)
}
Expand All @@ -47,6 +57,7 @@ type receiver struct {
progressCb func(int, bool)
merge bool
filter FilterFunc
differ DiffType

notifyHashed ChangeFunc
contentHasher ContentHasher
Expand Down Expand Up @@ -132,7 +143,7 @@ func (r *receiver) run(ctx context.Context) error {
if !r.merge {
destWalker = getWalkerFn(r.dest)
}
err := doubleWalkDiff(ctx, dw.HandleChange, destWalker, w.fill, r.filter)
err := doubleWalkDiff(ctx, dw.HandleChange, destWalker, w.fill, r.filter, r.differ)
if err != nil {
return err
}
Expand Down

0 comments on commit 8599091

Please sign in to comment.