fix: collision prevent

This commit is contained in:
2026-06-09 20:20:34 +02:00
parent dd7c13fc5f
commit ff264f0d7c
+55 -2
View File
@@ -760,8 +760,16 @@ func shouldCheckRemoteTopicTitle(previous wikiDeployManifestPage, pageTitle, des
func recoverCreateCollision(plan wikiDeployPlan, manifest wikiDeployManifest, client *nodeBBClient, summary string) (bool, error) {
entry, ok, err := findExistingNodeBBPage(plan.Page, plan.Entry.CID, client)
if err != nil || !ok {
return ok, err
if err != nil {
return false, err
}
if !ok {
// Search-based lookup failed. NodeBB confirmed the collision, so the page definitely
// exists — fall back to listing the category and matching by title.
entry, ok, err = findCollisionPageByTitle(plan.Page, plan.Entry.CID, client)
if err != nil || !ok {
return false, err
}
}
remote, err := client.getPost(entry.PID)
if err != nil {
@@ -801,6 +809,15 @@ func adoptExistingNodeBBPage(page wikiDeployPage, cid int, remotePagesByCID map[
if err := nestedCanonicalAdoptionFallbackError(page, remotePages); err != nil {
return wikiDeployManifestPage{}, false, err
}
// For nested-path pages: nestedCanonicalAdoptionFallbackError only examined pages
// without WikiPath/CanonicalPath. Pages that have those fields set but whose stored
// path doesn't normalize to match the local PublicPath (e.g. different slug format)
// still need to be adopted. Try an unambiguous title match across all remote pages.
if isNestedCanonicalWikiPath(page.PublicPath) {
if remotePage, ok := matchByTitle(page, remotePages); ok && remotePage.TID != 0 {
return fetchNodeBBWikiPageMapping(page, cid, remotePage, client)
}
}
return wikiDeployManifestPage{}, false, nil
}
return fetchNodeBBWikiPageMapping(page, cid, remotePage, client)
@@ -834,6 +851,42 @@ func findExistingNodeBBPage(page wikiDeployPage, cid int, client *nodeBBClient)
return wikiDeployManifestPage{}, false, nil
}
func findCollisionPageByTitle(page wikiDeployPage, cid int, client *nodeBBClient) (wikiDeployManifestPage, bool, error) {
remotePages, err := client.listNamespacePages(cid)
if err != nil {
return wikiDeployManifestPage{}, false, err
}
remotePage, ok := matchByTitle(page, remotePages)
if !ok || remotePage.TID == 0 {
return wikiDeployManifestPage{}, false, nil
}
return fetchNodeBBWikiPageMapping(page, cid, remotePage, client)
}
func matchByTitle(page wikiDeployPage, remotePages []nodeBBWikiPage) (nodeBBWikiPage, bool) {
desiredTitle := normalizeWikiTitle(page.Title)
if desiredTitle == "" {
return nodeBBWikiPage{}, false
}
var match *nodeBBWikiPage
for i, candidate := range remotePages {
for _, title := range []string{candidate.TitleLeaf, candidate.Title} {
if normalizeWikiTitle(title) == desiredTitle {
if match != nil {
return nodeBBWikiPage{}, false // ambiguous — refuse to guess
}
cp := remotePages[i]
match = &cp
break
}
}
}
if match == nil {
return nodeBBWikiPage{}, false
}
return *match, true
}
func uniqueNodeBBPageSearchQueries(values ...string) []string {
queries := []string{}
seen := map[string]struct{}{}