A Transparent and Verifiable Way to Sync the AT Protocol's PLC Directory

better diff

Changed files
+40 -19
cmd
plcbundle
commands
+40 -19
cmd/plcbundle/commands/diff.go
··· 288 288 remoteCIDs[op.CID] = i 289 289 } 290 290 291 - // Find differences 292 - var missingInLocal []string 293 - var missingInRemote []string 294 - var positionMismatches []string 291 + // Find differences - store as position+CID pairs 292 + type cidWithPos struct { 293 + cid string 294 + pos int 295 + } 296 + 297 + var missingInLocal []cidWithPos 298 + var missingInRemote []cidWithPos 299 + var positionMismatches []cidWithPos 295 300 296 301 for cid, remotePos := range remoteCIDs { 297 302 if localPos, exists := localCIDs[cid]; !exists { 298 - missingInLocal = append(missingInLocal, cid) 303 + missingInLocal = append(missingInLocal, cidWithPos{cid, remotePos}) 299 304 } else if localPos != remotePos { 300 - positionMismatches = append(positionMismatches, cid) 305 + positionMismatches = append(positionMismatches, cidWithPos{cid, localPos}) 301 306 } 302 307 } 303 308 304 - for cid := range localCIDs { 309 + for cid, localPos := range localCIDs { 305 310 if _, exists := remoteCIDs[cid]; !exists { 306 - missingInRemote = append(missingInRemote, cid) 311 + missingInRemote = append(missingInRemote, cidWithPos{cid, localPos}) 307 312 } 308 313 } 309 314 315 + // Sort by position 316 + sort.Slice(missingInLocal, func(i, j int) bool { 317 + return missingInLocal[i].pos < missingInLocal[j].pos 318 + }) 319 + sort.Slice(missingInRemote, func(i, j int) bool { 320 + return missingInRemote[i].pos < missingInRemote[j].pos 321 + }) 322 + sort.Slice(positionMismatches, func(i, j int) bool { 323 + return positionMismatches[i].pos < positionMismatches[j].pos 324 + }) 325 + 310 326 // Display differences 311 327 if len(missingInLocal) > 0 { 312 328 fmt.Printf(" Missing in Local (%d operations):\n", len(missingInLocal)) 313 329 displaySample := min(sampleSize, len(missingInLocal)) 314 330 for i := 0; i < displaySample; i++ { 315 - cid := missingInLocal[i] 316 - pos := remoteCIDs[cid] 317 - fmt.Printf(" - [%04d] %s\n", pos, cid) 331 + item := missingInLocal[i] 332 + fmt.Printf(" - [%04d] %s\n", item.pos, item.cid) 318 333 } 319 334 if len(missingInLocal) > displaySample { 320 335 fmt.Printf(" ... and %d more\n", len(missingInLocal)-displaySample) ··· 326 341 fmt.Printf(" Missing in Remote (%d operations):\n", len(missingInRemote)) 327 342 displaySample := min(sampleSize, len(missingInRemote)) 328 343 for i := 0; i < displaySample; i++ { 329 - cid := missingInRemote[i] 330 - pos := localCIDs[cid] 331 - fmt.Printf(" + [%04d] %s\n", pos, cid) 344 + item := missingInRemote[i] 345 + fmt.Printf(" + [%04d] %s\n", item.pos, item.cid) 332 346 } 333 347 if len(missingInRemote) > displaySample { 334 348 fmt.Printf(" ... and %d more\n", len(missingInRemote)-displaySample) ··· 340 354 fmt.Printf(" Position Mismatches (%d operations):\n", len(positionMismatches)) 341 355 displaySample := min(sampleSize, len(positionMismatches)) 342 356 for i := 0; i < displaySample; i++ { 343 - cid := positionMismatches[i] 344 - localPos := localCIDs[cid] 345 - remotePos := remoteCIDs[cid] 346 - fmt.Printf(" ~ %s\n", cid) 347 - fmt.Printf(" Local: position %04d\n", localPos) 357 + item := positionMismatches[i] 358 + remotePos := remoteCIDs[item.cid] 359 + fmt.Printf(" ~ %s\n", item.cid) 360 + fmt.Printf(" Local: position %04d\n", item.pos) 348 361 fmt.Printf(" Remote: position %04d\n", remotePos) 349 362 } 350 363 if len(positionMismatches) > displaySample { ··· 541 554 } 542 555 } 543 556 } 557 + 558 + // ADD THIS: Sort mismatches by bundle number 559 + sort.Slice(comparison.HashMismatches, func(i, j int) bool { 560 + return comparison.HashMismatches[i].BundleNumber < comparison.HashMismatches[j].BundleNumber 561 + }) 562 + sort.Slice(comparison.ContentMismatches, func(i, j int) bool { 563 + return comparison.ContentMismatches[i].BundleNumber < comparison.ContentMismatches[j].BundleNumber 564 + }) 544 565 545 566 return comparison 546 567 }