|
|
@ -1,10 +1,9 @@ |
|
|
|
package main |
|
|
|
package main |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"bytes" |
|
|
|
|
|
|
|
"flag" |
|
|
|
"flag" |
|
|
|
"github.com/cheggaaa/pb/v3" |
|
|
|
"github.com/cheggaaa/pb/v3" |
|
|
|
"io" |
|
|
|
"github.com/udhos/equalfile" |
|
|
|
"log" |
|
|
|
"log" |
|
|
|
"os" |
|
|
|
"os" |
|
|
|
"path" |
|
|
|
"path" |
|
|
@ -18,6 +17,7 @@ type TopLevel struct { |
|
|
|
RightOutput string |
|
|
|
RightOutput string |
|
|
|
DryRun bool |
|
|
|
DryRun bool |
|
|
|
Bar *pb.ProgressBar |
|
|
|
Bar *pb.ProgressBar |
|
|
|
|
|
|
|
Comparer *equalfile.Cmp |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type Step struct { |
|
|
|
type Step struct { |
|
|
@ -214,67 +214,12 @@ func (s *Step) ListChildren() []string { |
|
|
|
func (s *Step) AreFilesIdentical(child string) bool { |
|
|
|
func (s *Step) AreFilesIdentical(child string) bool { |
|
|
|
leftInPath := s.InputPath(child, LEFT) |
|
|
|
leftInPath := s.InputPath(child, LEFT) |
|
|
|
rightInPath := s.InputPath(child, RIGHT) |
|
|
|
rightInPath := s.InputPath(child, RIGHT) |
|
|
|
leftInfo, err := os.Stat(leftInPath) |
|
|
|
equal, err := s.Comparer.CompareFile(leftInPath, rightInPath) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
log.Printf("Error statting path %s: %s\n", leftInPath, err) |
|
|
|
log.Printf("Error comparing path %s and %s: %s\n", leftInPath, rightInPath, err) |
|
|
|
return false |
|
|
|
return false |
|
|
|
} |
|
|
|
} |
|
|
|
rightInfo, err := os.Stat(rightInPath) |
|
|
|
return equal |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Printf("Error statting path %s: %s\n", rightInPath, err) |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if leftInfo.Size() != rightInfo.Size() { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
leftFile, err := os.OpenFile(leftInPath, os.O_RDONLY, 0) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Printf("Error opening path %s: %s\n", leftInPath, err) |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
err := leftFile.Close() |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Printf("Error closing %s: %s\n", leftInPath, err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
rightFile, err := os.OpenFile(rightInPath, os.O_RDONLY, 0) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Printf("Error opening path %s: %s\n", rightInPath, err) |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
defer func() { |
|
|
|
|
|
|
|
err := rightFile.Close() |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Printf("Error closing %s: %s\n", rightInPath, err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 4 MB buffers
|
|
|
|
|
|
|
|
var leftData [4194304]byte |
|
|
|
|
|
|
|
var rightData [4194304]byte |
|
|
|
|
|
|
|
for { |
|
|
|
|
|
|
|
leftRead, err := leftFile.Read(leftData[:]) |
|
|
|
|
|
|
|
if err != nil && err != io.EOF { |
|
|
|
|
|
|
|
log.Printf("Error reading %s: %s\n", leftInPath, err) |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
rightRead, err := rightFile.Read(rightData[:]) |
|
|
|
|
|
|
|
if err != nil && err != io.EOF { |
|
|
|
|
|
|
|
log.Printf("Error reading %s: %s\n", rightInPath, err) |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if leftRead != rightRead { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if !bytes.Equal(leftData[:leftRead], rightData[:rightRead]) { |
|
|
|
|
|
|
|
return false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if err == io.EOF { |
|
|
|
|
|
|
|
return true |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (s *Step) Walk() { |
|
|
|
func (s *Step) Walk() { |
|
|
@ -349,7 +294,8 @@ func (s *Step) Walk() { |
|
|
|
|
|
|
|
|
|
|
|
func main() { |
|
|
|
func main() { |
|
|
|
settings := TopLevel{ |
|
|
|
settings := TopLevel{ |
|
|
|
Bar: pb.StartNew(1), |
|
|
|
Bar: pb.StartNew(1), |
|
|
|
|
|
|
|
Comparer: equalfile.New(nil, equalfile.Options{}), |
|
|
|
} |
|
|
|
} |
|
|
|
flag.StringVar(&settings.LeftInput, |
|
|
|
flag.StringVar(&settings.LeftInput, |
|
|
|
"left-input", "./input/left", "The name of the left side of the input.") |
|
|
|
"left-input", "./input/left", "The name of the left side of the input.") |
|
|
|