diff --git a/cmd/db_recover.go b/cmd/db_recover.go index baf599c51..2aa621d21 100644 --- a/cmd/db_recover.go +++ b/cmd/db_recover.go @@ -57,20 +57,37 @@ func checkRepo(repo *deb.LocalRepo) error { err := repos.LoadComplete(repo) if err != nil { - return fmt.Errorf("load complete repo %q: %s", repo.Name, err) + // If we can't load the repo, it might be severely corrupted + // Log the error but continue with other repos + context.Progress().Printf("Warning: Cannot load repo %q: %s\n", repo.Name, err) + return nil } - dangling, err := deb.FindDanglingReferences(repo.RefList(), collectionFactory.PackageCollection()) + // Check if RefList is nil (severe corruption case) + refList := repo.RefList() + if refList == nil { + context.Progress().Printf("Warning: Repo %q has no reference list (severely corrupted), initializing empty list\n", repo.Name) + // Initialize with empty reflist + repo.UpdateRefList(deb.NewPackageRefList()) + if err = repos.Update(repo); err != nil { + return fmt.Errorf("update repo with empty reflist: %w", err) + } + return nil + } + + dangling, err := deb.FindDanglingReferences(refList, collectionFactory.PackageCollection()) if err != nil { - return fmt.Errorf("find dangling references: %w", err) + // If we can't find dangling references, log but continue + context.Progress().Printf("Warning: Cannot check dangling references for repo %q: %s\n", repo.Name, err) + return nil } - if len(dangling.Refs) > 0 { + if dangling != nil && len(dangling.Refs) > 0 { for _, ref := range dangling.Refs { context.Progress().Printf("Removing dangling database reference %q\n", ref) } - repo.UpdateRefList(repo.RefList().Subtract(dangling)) + repo.UpdateRefList(refList.Subtract(dangling)) if err = repos.Update(repo); err != nil { return fmt.Errorf("update repo: %w", err) diff --git a/deb/local.go b/deb/local.go index 4be460769..f4c6e39d8 100644 --- a/deb/local.go +++ b/deb/local.go @@ -160,9 +160,15 @@ func (collection *LocalRepoCollection) Add(repo *LocalRepo) error { func (collection *LocalRepoCollection) Update(repo *LocalRepo) error { batch := collection.db.CreateBatch() _ = batch.Put(repo.Key(), repo.Encode()) + if repo.packageRefs != nil { _ = batch.Put(repo.RefKey(), repo.packageRefs.Encode()) + } else { + // Delete RefKey if packageRefs is nil + // This prevents inconsistent state where RefKey exists but is corrupted + _ = batch.Delete(repo.RefKey()) } + return batch.Write() } diff --git a/deb/remote.go b/deb/remote.go index c6fe595c2..31ac1a2ec 100644 --- a/deb/remote.go +++ b/deb/remote.go @@ -847,11 +847,16 @@ func (collection *RemoteRepoCollection) Add(repo *RemoteRepo) error { // Update stores updated information about repo in DB func (collection *RemoteRepoCollection) Update(repo *RemoteRepo) error { batch := collection.db.CreateBatch() - _ = batch.Put(repo.Key(), repo.Encode()) + if repo.packageRefs != nil { _ = batch.Put(repo.RefKey(), repo.packageRefs.Encode()) + } else { + // Delete RefKey if packageRefs is nil + // This prevents inconsistent state where RefKey exists but is corrupted + _ = batch.Delete(repo.RefKey()) } + return batch.Write() } diff --git a/deb/snapshot.go b/deb/snapshot.go index 74f8865db..b96f3b400 100644 --- a/deb/snapshot.go +++ b/deb/snapshot.go @@ -227,10 +227,14 @@ func (collection *SnapshotCollection) Add(snapshot *Snapshot) error { // Update stores updated information about snapshot in DB func (collection *SnapshotCollection) Update(snapshot *Snapshot) error { batch := collection.db.CreateBatch() - _ = batch.Put(snapshot.Key(), snapshot.Encode()) + if snapshot.packageRefs != nil { _ = batch.Put(snapshot.RefKey(), snapshot.packageRefs.Encode()) + } else { + // Delete RefKey if packageRefs is nil + // This prevents inconsistent state where RefKey exists but is corrupted + _ = batch.Delete(snapshot.RefKey()) } return batch.Write()