Skip to content

Commit

Permalink
feat: Add folder diff command for comparing with 0gStorage
Browse files Browse the repository at this point in the history
  • Loading branch information
wanliqun committed Sep 11, 2024
1 parent 08282b6 commit e7b3a69
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 1 deletion.
59 changes: 59 additions & 0 deletions cmd/diff_dir.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"context"

"github.com/0glabs/0g-storage-client/transfer"
"github.com/0glabs/0g-storage-client/transfer/dir"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

var (
diffDirArgs downloadArgument

diffDirCmd = &cobra.Command{
Use: "diff-dir",
Short: "Diff directory from ZeroGStorage network",
Run: diffDir,
}
)

func init() {
bindDownloadFlags(diffDirCmd, &diffDirArgs)

rootCmd.AddCommand(diffDirCmd)
}

func diffDir(*cobra.Command, []string) {
ctx := context.Background()
var cancel context.CancelFunc
if diffDirArgs.timeout > 0 {
ctx, cancel = context.WithTimeout(ctx, diffDirArgs.timeout)
defer cancel()
}

localRoot, err := dir.BuildFileTree(diffDirArgs.file)
if err != nil {
logrus.WithError(err).Fatal("Failed to build local file tree")
}

downloader, closer, err := newDownloader(diffDirArgs)
if err != nil {
logrus.WithError(err).Fatal("Failed to initialize downloader")
}
defer closer()

zgRoot, err := transfer.BuildFileTree(ctx, downloader, diffDirArgs.root, diffDirArgs.proof)
if err != nil {
logrus.WithError(err).Fatal("Failed to build file tree from ZeroGStorage network")
}

diffRoot, err := dir.Diff(zgRoot, localRoot)
if err != nil {
logrus.WithError(err).Fatal("Failed to diff directory")
}

// Print the diff result
dir.PrettyPrint(diffRoot)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.21.5

require (
github.com/ethereum/go-ethereum v1.14.7
github.com/fatih/color v1.16.0
github.com/gin-contrib/cors v1.7.2
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.22.0
Expand Down Expand Up @@ -54,7 +55,6 @@ require (
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240306133620-7d920df305f0 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fjl/memsize v0.0.2 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.4 // indirect
Expand Down
74 changes: 74 additions & 0 deletions transfer/dir/diff.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package dir

import (
"fmt"
"strings"

"github.com/fatih/color"
"github.com/google/btree"
"github.com/pkg/errors"
)
Expand Down Expand Up @@ -84,3 +88,73 @@ func diff(current, next *FsNode) *DiffNode {

return root
}

// PrettyPrint prints the DiffNode tree in a human-readable format with a tree skeleton structure.
func PrettyPrint(root *DiffNode) {
prettyPrint(root, 0, false, nil)
}

func prettyPrint(node *DiffNode, depth int, isLast bool, prefixes []string) {
if depth == 0 { // Root directory case
fmt.Println(node.Node.Name)
printChildEntries(node, 1, nil)
return
}

// Create prefix and branch for current node
prefix := strings.Join(prefixes, "")
branch := "├─"
if isLast {
branch = "└─"
}

// Print node with optional status
coloredStatus := colorStringForDiffStatus(node.Status)
fmt.Printf("%s%s %s %s\n", prefix, branch, node.Node.Name, coloredStatus)

// Update prefixes for children
newPrefixes := append(prefixes, "│ ")
if isLast {
newPrefixes[len(newPrefixes)-1] = " "
}

// Recursively print children if it's a directory
if node.Node.Type == FileTypeDirectory {
printChildEntries(node, depth+1, newPrefixes)
}
}

func printChildEntries(node *DiffNode, depth int, prefixes []string) {
if node.Entries == nil || node.Entries.Len() == 0 {
return
}

// Get the last node in a BTree efficiently by descending to the last element.
var last *DiffNode
node.Entries.Descend(func(item *DiffNode) bool {
last = item
return false // Stop the iteration as soon as we get the last node.
})

// Print all child entries of the current node
node.Entries.Ascend(func(item *DiffNode) bool {
// Check if this is the last entry in the directory
isLast := item == last
prettyPrint(item, depth, isLast, prefixes)
return true
})
}

// colorStringForDiffStatus returns a color string based on the diff status.
func colorStringForDiffStatus(status DiffStatus) string {
switch status {
case DiffStatusAdded:
return color.GreenString("[+]")
case DiffStatusRemoved:
return color.RedString("[-]")
case DiffStatusModified:
return color.YellowString("[*]")
default:
return ""
}
}

0 comments on commit e7b3a69

Please sign in to comment.