--- a/goduf.go Sun Oct 14 13:20:09 2018 +0200
+++ b/goduf.go Sun Oct 14 15:21:46 2018 +0200
@@ -51,6 +51,13 @@
partialChecksum
)
+type Options struct {
+ Summary bool
+ OutToJSON bool
+ SkipPartial bool
+ IgnoreEmpty bool
+}
+
// Results contains the results of the duplicates search
type Results struct {
Groups []ResultSet `json:"groups"`
@@ -467,66 +474,25 @@
return fmt.Sprintf("%d bytes (%d %s)", sizeBytes, humanSize, units[n])
}
-// It all starts here.
-func main() {
+func duf(dirs []string, options Options) (Results, error) {
var verbose bool
- var summary bool
- var outToJSON bool
- var skipPartial bool
- var ignoreEmpty bool
-
- // Assertion on constant values
- if minSizePartialChecksum <= 2*medsumBytes {
- myLog.Fatal("Internal error: assert minSizePartialChecksum > 2*medsumBytes")
+ if myLog.verbosity > 0 {
+ verbose = true
}
- // Command line parameters parsingg
- flag.BoolVar(&verbose, "verbose", false, "Be verbose (verbosity=1)")
- flag.BoolVar(&verbose, "v", false, "See --verbose")
- flag.BoolVar(&outToJSON, "json", false, "Use JSON format for output")
- flag.BoolVar(&summary, "summary", false, "Do not display the duplicate list")
- flag.BoolVar(&summary, "s", false, "See --summary")
- flag.BoolVar(&skipPartial, "skip-partial", false, "Skip partial checksums")
- flag.IntVar(&myLog.verbosity, "verbosity", 0,
- "Set verbosity level (1-6)")
- flag.IntVar(&myLog.verbosity, "vl", 0, "See verbosity")
- timings := flag.Bool("timings", false, "Set detailed log timings")
- flag.BoolVar(&ignoreEmpty, "no-empty", false, "Ignore empty files")
-
- flag.Parse()
+ var results Results
+ data.sizeGroups = make(map[int64]*FileObjList)
- // Set verbosity: --verbose=true == --verbosity=1
- if myLog.verbosity > 0 {
- verbose = true
- } else if verbose == true {
- myLog.verbosity = 1
- }
-
- if len(flag.Args()) == 0 {
- // TODO: more helpful usage statement
- myLog.Println(-1, "Usage:", os.Args[0],
- "[options] base_directory|file...")
- os.Exit(0)
- }
-
- // Change log format for benchmarking
- if *timings {
- myLog.SetBenchFlags()
- }
-
- data.sizeGroups = make(map[int64]*FileObjList)
myLog.Println(1, "* Reading file metadata")
- for _, root := range flag.Args() {
+ for _, root := range dirs {
if err := filepath.Walk(root, visit); err != nil {
- myLog.Printf(-1, "* Error: could not read file tree:\n")
- myLog.Printf(-1, "> %v\n", err)
- os.Exit(1)
+ return results, fmt.Errorf("could not read file tree: %v", err)
}
}
// Count empty files and drop them if they should be ignored
- emptyCount := data.dropEmptyFiles(ignoreEmpty)
+ emptyCount := data.dropEmptyFiles(options.IgnoreEmpty)
// Display a small report
if verbose {
@@ -562,12 +528,12 @@
if len(data.emptyFiles) > 0 {
result = append(result, data.emptyFiles)
}
- result = append(result, data.findDupes(skipPartial)...)
+ result = append(result, data.findDupes(options.SkipPartial)...)
myLog.Println(3, "* Number of match groups:", len(result))
// Done! Prepare results data
- if len(result) > 0 && !summary {
+ if len(result) > 0 && !options.Summary {
myLog.Println(1, "* Dupes:")
}
@@ -578,8 +544,6 @@
// Sort groups by increasing size (of the duplicated files)
sort.Sort(byGroupFileSize(result))
- var results Results
-
for _, l := range result {
size := uint64(l[0].Size())
// We do not count the size of the 1st item
@@ -595,6 +559,58 @@
results.RedundantDataSizeH = formatSize(results.RedundantDataSize, true)
results.TotalFileCount = data.cmpt
+ return results, nil
+}
+
+// It all starts here.
+func main() {
+ var verbose bool
+ var options Options
+
+ // Assertion on constant values
+ if minSizePartialChecksum <= 2*medsumBytes {
+ myLog.Fatal("Internal error: assert minSizePartialChecksum > 2*medsumBytes")
+ }
+
+ // Command line parameters parsingg
+ flag.BoolVar(&verbose, "verbose", false, "Be verbose (verbosity=1)")
+ flag.BoolVar(&verbose, "v", false, "See --verbose")
+ flag.BoolVar(&options.OutToJSON, "json", false, "Use JSON format for output")
+ flag.BoolVar(&options.Summary, "summary", false, "Do not display the duplicate list")
+ flag.BoolVar(&options.Summary, "s", false, "See --summary")
+ flag.BoolVar(&options.SkipPartial, "skip-partial", false, "Skip partial checksums")
+ flag.IntVar(&myLog.verbosity, "verbosity", 0,
+ "Set verbosity level (1-6)")
+ flag.IntVar(&myLog.verbosity, "vl", 0, "See verbosity")
+ timings := flag.Bool("timings", false, "Set detailed log timings")
+ flag.BoolVar(&options.IgnoreEmpty, "no-empty", false, "Ignore empty files")
+
+ flag.Parse()
+
+ // Set verbosity: --verbose=true == --verbosity=1
+ if myLog.verbosity > 0 {
+ verbose = true
+ } else if verbose == true {
+ myLog.verbosity = 1
+ }
+
+ if len(flag.Args()) == 0 {
+ // TODO: more helpful usage statement
+ myLog.Println(-1, "Usage:", os.Args[0],
+ "[options] base_directory|file...")
+ os.Exit(0)
+ }
+
+ // Change log format for benchmarking
+ if *timings {
+ myLog.SetBenchFlags()
+ }
+
+ results, err := duf(flag.Args(), options)
+ if err != nil {
+ myLog.Fatal("ERROR: " + err.Error())
+ }
+
// Output the results
- displayResults(results, outToJSON, summary)
+ displayResults(results, options.OutToJSON, options.Summary)
}