Skip to content

Commit f1dcc72

Browse files
Feat/issue #52 (#111)
* feat: add more templates * refactor: update the help section for the scaffold command with new templates * feat: add flags for recursive directory and hidden file / directory support * feat: add symlink and directory support for the add command * feat: add verbose flag for sync and discover commands
1 parent c4cec14 commit f1dcc72

6 files changed

Lines changed: 82 additions & 32 deletions

File tree

cmd/discover.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Example:
8888
}
8989

9090
// Create sync service (with or without RSA)
91-
syncService, err := discover.CreateSyncService(host, vaultMgr, vaultConfig, vaultPath)
91+
syncService, err := discover.CreateSyncService(host, vaultMgr, vaultConfig, vaultPath, verbose)
9292
if err != nil {
9393
return fmt.Errorf("failed to create sync service: %v", err)
9494
}

cmd/sync.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ Examples:
117117
return fmt.Errorf("failed to create sync service: %v", err)
118118
}
119119

120+
// Set verbose flag
121+
verbose, _ := cmd.Flags().GetBool("verbose")
122+
syncService.Verbose = verbose
123+
120124
// Start secure protocol handlers
121125
syncService.RegisterProtocols(ctx)
122126

@@ -339,4 +343,5 @@ func init() {
339343
syncCmd.Flags().IntP("timeout", "t", 60, "Discovery timeout in seconds (for auto-discovery)")
340344
syncCmd.Flags().BoolP("force-trust", "f", false, "Automatically trust new peers without prompting")
341345
syncCmd.Flags().BoolP("read-only", "r", false, "Only receive files, don't send")
346+
syncCmd.Flags().BoolP("verbose", "v", false, "Enable verbose debug output")
342347
}

internal/discover/discovery_util.go

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,33 @@ import (
1414
)
1515

1616
// createSyncService creates a sync service with or without RSA support
17-
func CreateSyncService(h host.Host, vaultMgr *config.Manager, vaultConfig *config.VaultConfig, vaultPath string) (*p2p.SyncService, error) {
17+
func CreateSyncService(h host.Host, vaultMgr *config.Manager, vaultConfig *config.VaultConfig, vaultPath string, verbose bool) (*p2p.SyncService, error) {
18+
var syncService *p2p.SyncService
19+
var err error
20+
1821
if vaultConfig.Sync.Enabled && vaultConfig.Sync.RSA != nil {
1922
privateKey, publicKey, rsaConfig, err := keys.LoadRSAKeys(vaultPath, vaultConfig.Sync.RSA)
2023
if err != nil {
2124
return nil, fmt.Errorf("failed to load RSA keys: %v", err)
2225
}
2326

24-
syncService, err := p2p.NewSecureSyncService(h, vaultMgr, privateKey, publicKey, rsaConfig)
27+
syncService, err = p2p.NewSecureSyncService(h, vaultMgr, privateKey, publicKey, rsaConfig)
2528
if err != nil {
2629
return nil, fmt.Errorf("failed to create sync service: %v", err)
2730
}
2831

2932
fmt.Println("🔐 RSA key exchange enabled with fingerprint:", rsaConfig.Fingerprint)
30-
return syncService, nil
3133
} else {
32-
syncService, err := p2p.NewSyncService(h, vaultMgr)
34+
syncService, err = p2p.NewSyncService(h, vaultMgr)
3335
if err != nil {
3436
return nil, fmt.Errorf("failed to create sync service: %v", err)
3537
}
3638

3739
fmt.Println("⚠️ Warning: RSA key exchange not enabled in vault config")
38-
return syncService, nil
3940
}
41+
42+
syncService.Verbose = verbose
43+
return syncService, nil
4044
}
4145

4246
func SetupDiscovery(ctx context.Context, h host.Host) (*p2p.MDNSDiscovery, <-chan peer.AddrInfo, error) {

internal/discover/discovery_util_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestCreateSyncService_NoRSA(t *testing.T) {
2929
vc := &config.VaultConfig{}
3030
vc.Sync.Enabled = false
3131

32-
svc, err := CreateSyncService(h, vm, vc, ".")
32+
svc, err := CreateSyncService(h, vm, vc, ".", false)
3333
if err != nil {
3434
t.Fatalf("CreateSyncService returned error: %v", err)
3535
}

internal/discover/handle_discovered_peer_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestHandleDiscoveredPeerExercisesPaths(t *testing.T) {
2929

3030
// Create non-RSA sync service
3131
vc := &config.VaultConfig{}
32-
svc, err := CreateSyncService(h, vm, vc, ".")
32+
svc, err := CreateSyncService(h, vm, vc, ".", false)
3333
if err != nil {
3434
t.Fatalf("CreateSyncService failed: %v", err)
3535
}

internal/p2p/sync.go

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type SyncService struct {
4646
trustedPeers map[peer.ID]*PeerInfo
4747
vaultConfig *config.VaultConfig
4848
trustAllPeers bool // New flag to automatically trust all peers
49+
Verbose bool // Enable verbose debug output
4950
}
5051

5152
// PeerInfo contains information about a trusted peer
@@ -426,21 +427,29 @@ func (s *SyncService) handleChunkRequest(stream network.Stream) {
426427

427428
// First try using the primary hash
428429
chunkHash := chunkRequest.Hash
429-
fmt.Printf("Looking for chunk with hash: %s\n", chunkHash)
430+
if s.Verbose {
431+
fmt.Printf("Looking for chunk with hash: %s\n", chunkHash)
432+
}
430433
chunkData, err := s.vaultMgr.GetChunk(chunkHash)
431434

432435
// If that fails and we have an encrypted hash, try that
433436
if err != nil && chunkRequest.EncryptedHash != "" {
434-
fmt.Printf("Chunk not found, trying encrypted hash: %s\n", chunkRequest.EncryptedHash)
437+
if s.Verbose {
438+
fmt.Printf("Chunk not found, trying encrypted hash: %s\n", chunkRequest.EncryptedHash)
439+
}
435440
chunkData, err = s.vaultMgr.GetChunk(chunkRequest.EncryptedHash)
436441
if err == nil {
437-
fmt.Printf("Found chunk using encrypted hash\n")
442+
if s.Verbose {
443+
fmt.Printf("Found chunk using encrypted hash\n")
444+
}
438445
}
439446
}
440447

441448
// If still not found, return error
442449
if err != nil {
443-
fmt.Printf("Chunk not found with either hash\n")
450+
if s.Verbose {
451+
fmt.Printf("Chunk not found with either hash\n")
452+
}
444453
response := struct {
445454
Error string `json:"error"`
446455
}{
@@ -847,7 +856,9 @@ func (s *SyncService) SyncWithPeer(ctx context.Context, peerID peer.ID) (*SyncRe
847856
result := &SyncResult{}
848857

849858
// First verify and exchange keys with peer (will auto-trust if trustAllPeers is true)
850-
fmt.Printf("Starting key verification with peer %s...\n", peerID.String())
859+
if s.Verbose {
860+
fmt.Printf("Starting key verification with peer %s...\n", peerID.String())
861+
}
851862
trusted, err := s.VerifyAndExchangeKeys(timeoutCtx, peerID)
852863
if err != nil {
853864
return nil, fmt.Errorf("key exchange failed: %w", err)
@@ -856,15 +867,21 @@ func (s *SyncService) SyncWithPeer(ctx context.Context, peerID peer.ID) (*SyncRe
856867
if !trusted {
857868
return nil, fmt.Errorf("peer %s is not trusted", peerID.String())
858869
}
859-
fmt.Printf("Peer %s is trusted, proceeding with sync\n", peerID.String())
870+
if s.Verbose {
871+
fmt.Printf("Peer %s is trusted, proceeding with sync\n", peerID.String())
872+
}
860873

861874
// Step 1: Get remote manifest
862-
fmt.Printf("Retrieving manifest from peer %s...\n", peerID.String())
875+
if s.Verbose {
876+
fmt.Printf("Retrieving manifest from peer %s...\n", peerID.String())
877+
}
863878
remoteManifest, err := s.getRemoteManifest(timeoutCtx, peerID)
864879
if err != nil {
865880
return nil, fmt.Errorf("failed to get remote manifest: %v", err)
866881
}
867-
fmt.Printf("Retrieved manifest from peer with %d files\n", len(remoteManifest.Files))
882+
if s.Verbose {
883+
fmt.Printf("Retrieved manifest from peer with %d files\n", len(remoteManifest.Files))
884+
}
868885

869886
// Step 2: Get local manifest
870887
localManifest, err := s.vaultMgr.GetManifest()
@@ -874,11 +891,13 @@ func (s *SyncService) SyncWithPeer(ctx context.Context, peerID peer.ID) (*SyncRe
874891

875892
// Step 3: Find missing chunks
876893
missingChunks := s.findMissingChunks(localManifest, remoteManifest)
877-
fmt.Printf("Found %d missing chunks to fetch\n", len(missingChunks))
894+
if s.Verbose {
895+
fmt.Printf("Found %d missing chunks to fetch\n", len(missingChunks))
896+
}
878897

879898
// Step 4: Fetch missing chunks
880899
for i, chunkHash := range missingChunks {
881-
if i%10 == 0 {
900+
if s.Verbose && i%10 == 0 {
882901
fmt.Printf("Fetching chunk %d of %d...\n", i+1, len(missingChunks))
883902
}
884903

@@ -918,7 +937,9 @@ func (s *SyncService) SyncWithPeer(ctx context.Context, peerID peer.ID) (*SyncRe
918937
}
919938

920939
// Step 5: Save file manifests for synced files
921-
fmt.Println("Saving file manifests...")
940+
if s.Verbose {
941+
fmt.Println("Saving file manifests...")
942+
}
922943
savedCount := 0
923944
for _, remoteFile := range remoteManifest.Files {
924945
// Check if this file already exists locally
@@ -943,11 +964,15 @@ func (s *SyncService) SyncWithPeer(ctx context.Context, peerID peer.ID) (*SyncRe
943964
return nil, fmt.Errorf("failed to save manifest for %s: %v",
944965
fileManifest.FilePath, err)
945966
}
946-
fmt.Printf("Saved manifest for: %s\n", fileManifest.FilePath)
967+
if s.Verbose {
968+
fmt.Printf("Saved manifest for: %s\n", fileManifest.FilePath)
969+
}
947970
savedCount++
948971
}
949972
}
950-
fmt.Printf("Saved %d file manifests\n", savedCount)
973+
if s.Verbose {
974+
fmt.Printf("Saved %d file manifests\n", savedCount)
975+
}
951976
result.FileCount = savedCount
952977

953978
// Step 6: Rebuild references
@@ -956,8 +981,10 @@ func (s *SyncService) SyncWithPeer(ctx context.Context, peerID peer.ID) (*SyncRe
956981
}
957982

958983
result.Duration = time.Since(startTime)
959-
fmt.Printf("Sync completed in %v: %d files, %d chunks transferred, %d chunks reused\n",
960-
result.Duration, result.FileCount, result.ChunksTransferred, result.ChunksDeduplicated)
984+
if s.Verbose {
985+
fmt.Printf("Sync completed in %v: %d files, %d chunks transferred, %d chunks reused\n",
986+
result.Duration, result.FileCount, result.ChunksTransferred, result.ChunksDeduplicated)
987+
}
961988

962989
return result, nil
963990
}
@@ -1018,28 +1045,38 @@ func (s *SyncService) findMissingChunks(local, remote *config.Manifest) []string
10181045
encryptedToRegularHash := make(map[string]string) // Track relationship between hashes
10191046

10201047
// Log all chunk hashes for debugging
1021-
fmt.Println("Local chunks:")
1048+
if s.Verbose {
1049+
fmt.Println("Local chunks:")
1050+
}
10221051
for _, file := range local.Files {
10231052
for _, chunk := range file.Chunks {
10241053
localChunks[chunk.Hash] = true
1025-
fmt.Printf(" - Regular hash: %s\n", chunk.Hash)
1054+
if s.Verbose {
1055+
fmt.Printf(" - Regular hash: %s\n", chunk.Hash)
1056+
}
10261057

10271058
// Also add encrypted hash if available
10281059
if chunk.EncryptedHash != "" {
10291060
localChunks[chunk.EncryptedHash] = true
10301061
encryptedToRegularHash[chunk.EncryptedHash] = chunk.Hash
1031-
fmt.Printf(" Encrypted hash: %s\n", chunk.EncryptedHash)
1062+
if s.Verbose {
1063+
fmt.Printf(" Encrypted hash: %s\n", chunk.EncryptedHash)
1064+
}
10321065
}
10331066
}
10341067
}
10351068

10361069
// Find chunks in remote that don't exist locally
1037-
fmt.Println("Remote chunks:")
1070+
if s.Verbose {
1071+
fmt.Println("Remote chunks:")
1072+
}
10381073
for _, file := range remote.Files {
10391074
for _, chunk := range file.Chunks {
1040-
fmt.Printf(" - Checking remote chunk: %s\n", chunk.Hash)
1041-
if chunk.EncryptedHash != "" {
1042-
fmt.Printf(" With encrypted hash: %s\n", chunk.EncryptedHash)
1075+
if s.Verbose {
1076+
fmt.Printf(" - Checking remote chunk: %s\n", chunk.Hash)
1077+
if chunk.EncryptedHash != "" {
1078+
fmt.Printf(" With encrypted hash: %s\n", chunk.EncryptedHash)
1079+
}
10431080
}
10441081

10451082
// Check if either regular or encrypted hash exists locally
@@ -1051,7 +1088,9 @@ func (s *SyncService) findMissingChunks(local, remote *config.Manifest) []string
10511088
chunkToFetch := chunk.Hash
10521089
alreadyAdded := slices.Contains(missingChunks, chunkToFetch)
10531090
if !alreadyAdded {
1054-
fmt.Printf(" - Adding missing chunk: %s\n", chunkToFetch)
1091+
if s.Verbose {
1092+
fmt.Printf(" - Adding missing chunk: %s\n", chunkToFetch)
1093+
}
10551094
missingChunks = append(missingChunks, chunkToFetch)
10561095
}
10571096
}
@@ -1091,7 +1130,9 @@ func (s *SyncService) fetchChunk(ctx context.Context, peerID peer.ID, hash strin
10911130
IsEncrypted: isEncrypted,
10921131
}
10931132

1094-
fmt.Printf("Requesting chunk with hash: %s, encrypted hash: %s\n", hash, encryptedHash)
1133+
if s.Verbose {
1134+
fmt.Printf("Requesting chunk with hash: %s, encrypted hash: %s\n", hash, encryptedHash)
1135+
}
10951136
if err := json.NewEncoder(stream).Encode(request); err != nil {
10961137
return nil, 0, fmt.Errorf("failed to send chunk request: %w", err)
10971138
}

0 commit comments

Comments
 (0)