mirror of
https://github.com/minio/mc.git
synced 2025-11-12 01:02:26 +03:00
Refacture structure proposal. (#1793)
This commit is contained in:
committed by
Harshavardhana
parent
c9ecd023fa
commit
b51fb32054
191
command/difference.go
Normal file
191
command/difference.go
Normal file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* Minio Client (C) 2015 Minio, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package command
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// differType difference in type.
|
||||
type differType int
|
||||
|
||||
const (
|
||||
differInNone differType = iota // does not differ
|
||||
differInSize // differs in size
|
||||
differInType // only in source
|
||||
differInFirst // only in target
|
||||
differInSecond // differs in type, exfile/directory
|
||||
)
|
||||
|
||||
func (d differType) String() string {
|
||||
switch d {
|
||||
case differInNone:
|
||||
return ""
|
||||
case differInSize:
|
||||
return "size"
|
||||
case differInType:
|
||||
return "type"
|
||||
case differInFirst:
|
||||
return "only-in-first"
|
||||
case differInSecond:
|
||||
return "only-in-second"
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
// objectDifference function finds the difference between all objects
|
||||
// recursively in sorted order from source and target.
|
||||
func objectDifference(sourceClnt, targetClnt Client, sourceURL, targetURL string) (diffCh chan diffMessage) {
|
||||
var (
|
||||
srcEOF, tgtEOF bool
|
||||
srcOk, tgtOk bool
|
||||
srcCtnt, tgtCtnt *clientContent
|
||||
srcSuffix, tgtSuffix string
|
||||
)
|
||||
|
||||
// Set default values for listing.
|
||||
isRecursive := true // recursive is always true for diff.
|
||||
isIncomplete := false // we will not compare any incomplete objects.
|
||||
srcCh := sourceClnt.List(isRecursive, isIncomplete)
|
||||
tgtCh := targetClnt.List(isRecursive, isIncomplete)
|
||||
|
||||
diffCh = make(chan diffMessage, 1000)
|
||||
|
||||
go func() {
|
||||
|
||||
srcCtnt, srcOk = <-srcCh
|
||||
tgtCtnt, tgtOk = <-tgtCh
|
||||
|
||||
for {
|
||||
srcEOF = !srcOk
|
||||
tgtEOF = !tgtOk
|
||||
|
||||
// No objects from source AND target: Finish
|
||||
if srcEOF && tgtEOF {
|
||||
close(diffCh)
|
||||
break
|
||||
}
|
||||
|
||||
if !srcEOF && srcCtnt.Err != nil {
|
||||
switch srcCtnt.Err.ToGoError().(type) {
|
||||
// Handle this specifically for filesystem related errors.
|
||||
case BrokenSymlink, TooManyLevelsSymlink, PathNotFound, PathInsufficientPermission:
|
||||
errorIf(srcCtnt.Err.Trace(sourceURL, targetURL), fmt.Sprintf("Failed on '%s'", sourceURL))
|
||||
// Handle these specifically for object storage related errors.
|
||||
case BucketNameEmpty, ObjectMissing, ObjectAlreadyExists, BucketDoesNotExist, BucketInvalid, ObjectOnGlacier:
|
||||
errorIf(srcCtnt.Err.Trace(sourceURL, targetURL), fmt.Sprintf("Failed on '%s'", sourceURL))
|
||||
default:
|
||||
fatalIf(srcCtnt.Err.Trace(sourceURL, targetURL), fmt.Sprintf("Failed on '%s'", sourceURL))
|
||||
}
|
||||
srcCtnt, srcOk = <-srcCh
|
||||
continue
|
||||
}
|
||||
|
||||
if !tgtEOF && tgtCtnt.Err != nil {
|
||||
switch tgtCtnt.Err.ToGoError().(type) {
|
||||
// Handle this specifically for filesystem related errors.
|
||||
case BrokenSymlink, TooManyLevelsSymlink, PathNotFound, PathInsufficientPermission:
|
||||
errorIf(tgtCtnt.Err.Trace(sourceURL, targetURL), fmt.Sprintf("Failed on '%s'", targetURL))
|
||||
// Handle these specifically for object storage related errors.
|
||||
case BucketNameEmpty, ObjectMissing, ObjectAlreadyExists, BucketDoesNotExist, BucketInvalid, ObjectOnGlacier:
|
||||
errorIf(tgtCtnt.Err.Trace(sourceURL, targetURL), fmt.Sprintf("Failed on '%s'", targetURL))
|
||||
default:
|
||||
fatalIf(tgtCtnt.Err.Trace(sourceURL, targetURL), fmt.Sprintf("Failed on '%s'", targetURL))
|
||||
}
|
||||
tgtCtnt, tgtOk = <-tgtCh
|
||||
continue
|
||||
}
|
||||
|
||||
// If source doesn't have objects anymore, comparison becomes obvious
|
||||
if srcEOF {
|
||||
diffCh <- diffMessage{
|
||||
SecondURL: tgtCtnt.URL.String(),
|
||||
Diff: differInSecond,
|
||||
secondContent: tgtCtnt,
|
||||
}
|
||||
tgtCtnt, tgtOk = <-tgtCh
|
||||
continue
|
||||
}
|
||||
|
||||
// The same for target
|
||||
if tgtEOF {
|
||||
diffCh <- diffMessage{
|
||||
FirstURL: srcCtnt.URL.String(),
|
||||
Diff: differInFirst,
|
||||
firstContent: srcCtnt,
|
||||
}
|
||||
srcCtnt, srcOk = <-srcCh
|
||||
continue
|
||||
}
|
||||
|
||||
srcSuffix = strings.TrimPrefix(srcCtnt.URL.String(), sourceURL)
|
||||
tgtSuffix = strings.TrimPrefix(tgtCtnt.URL.String(), targetURL)
|
||||
|
||||
current := urlJoinPath(targetURL, srcSuffix)
|
||||
expected := urlJoinPath(targetURL, tgtSuffix)
|
||||
|
||||
if expected > current {
|
||||
diffCh <- diffMessage{
|
||||
FirstURL: srcCtnt.URL.String(),
|
||||
Diff: differInFirst,
|
||||
firstContent: srcCtnt,
|
||||
}
|
||||
srcCtnt, srcOk = <-srcCh
|
||||
continue
|
||||
}
|
||||
if expected == current {
|
||||
srcType, tgtType := srcCtnt.Type, tgtCtnt.Type
|
||||
srcSize, tgtSize := srcCtnt.Size, tgtCtnt.Size
|
||||
if srcType.IsRegular() && !tgtType.IsRegular() ||
|
||||
!srcType.IsRegular() && tgtType.IsRegular() {
|
||||
// Type differes. Source is never a directory.
|
||||
diffCh <- diffMessage{
|
||||
FirstURL: srcCtnt.URL.String(),
|
||||
SecondURL: tgtCtnt.URL.String(),
|
||||
Diff: differInType,
|
||||
firstContent: srcCtnt,
|
||||
secondContent: tgtCtnt,
|
||||
}
|
||||
} else if (srcType.IsRegular() && tgtType.IsRegular()) && srcSize != tgtSize {
|
||||
// Regular files differing in size.
|
||||
diffCh <- diffMessage{
|
||||
FirstURL: srcCtnt.URL.String(),
|
||||
SecondURL: tgtCtnt.URL.String(),
|
||||
Diff: differInSize,
|
||||
firstContent: srcCtnt,
|
||||
secondContent: tgtCtnt,
|
||||
}
|
||||
}
|
||||
// No differ
|
||||
srcCtnt, srcOk = <-srcCh
|
||||
tgtCtnt, tgtOk = <-tgtCh
|
||||
continue
|
||||
}
|
||||
// Differ in second
|
||||
diffCh <- diffMessage{
|
||||
SecondURL: tgtCtnt.URL.String(),
|
||||
Diff: differInSecond,
|
||||
secondContent: tgtCtnt,
|
||||
}
|
||||
tgtCtnt, tgtOk = <-tgtCh
|
||||
continue
|
||||
}
|
||||
}()
|
||||
|
||||
return diffCh
|
||||
}
|
||||
Reference in New Issue
Block a user