Skip to content

fix(search): keep trashed and live folders at the same path apart - #3602

Merged
aduffeck merged 2 commits into
opencloud-eu:mainfrom
aduffeck:fix/search-trashed-path-collision
Sep 28, 2026
Merged

aduffeck merged 2 commits into
opencloud-eu:mainfrom
aduffeck:fix/search-trashed-path-collision

Conversation

@aduffeck

@aduffeck aduffeck commented Sep 25, 2026 •

Copy link
Copy Markdown
Member

A trashed folder keeps its path in the index, so a live folder can take the same path. Move/delete/restore/purge looked up descendants by path only. As a result, purging the trashed ./a removed the live ./a tree, and moving the live ./a took the trashed tree with it. Both engines now also match the root's trash state.

A trashed folder keeps its path in the index, so a new folder can take
the same one. The descendant lookup behind move, delete, restore and
purge matched on space and path only: purging the trashed folder took
the live folder and its descendants out of the index, and moving the
live folder carried the trashed tree along.

Both engines now also match the root's trash state; purge with
onlyDeleted keeps matching the trashed ones only.
@codacy-production

codacy-production Bot commented Sep 25, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity

Metric Results
Complexity 0

View in Codacy

🟢 Coverage 74.42% diff coverage · +0.01% coverage variation

Metric Results
Coverage variation ✅ +0.01% coverage variation (-1.00%)
Diff coverage ✅ 74.42% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (74462d3) 89037 21582 24.24%
Head commit (b1efb8c) 89056 (+19) 21599 (+17) 24.25% (+0.01%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#3602) 43 32 74.42%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@dschmidt dschmidt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding the deleted / onlyDeleted bools to forEachResourceByPath and forSelfAndDescendants, should the caller pass the query into forEachResourceByPath? It would then only do the paging, and each caller adds the Deleted filter it needs.

Roughly, with three small new helpers:

  • treeQuery(root): the RootID + Path conjunction that forEachResourceByPath builds inline today
  • deletedQuery(deleted): the Deleted bool field query
  • b.pushing(fn): the current apply closure from forSelfAndDescendants, pulled out so Purge can use it too
// forSelfAndDescendants(id, fn): back to the signature from main
q := treeQuery(root)
q.AddQuery(deletedQuery(root.Deleted))
forEachResourceByPath(q, b.index, fn)

// Purge(id, true): doesn't go through forSelfAndDescendants
q := treeQuery(root)
q.AddQuery(deletedQuery(true)) // also leaves out the live root, since the Path term matches the folder itself
forEachResourceByPath(q, b.index, b.pushing(purge))

In forSelfAndDescendants the query has to be built before fn(root) runs, just like rootPath today.

Personally I really dislike boolean parameters as I think it's really hard to reason about what they are doing

Instead of deleted/onlyDeleted bool parameters, the caller now builds
the query and forEachMatch only does the paging.

@dschmidt dschmidt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great, looks much better to me now 👍

@aduffeck

Copy link
Copy Markdown
Member Author

@dschmidt 👍 I hear you about the bool parameter. I wasn't comfortable with the idea of a treeQuery which spans the live tree AND the trash unless amended with another query though, so my treeQuery now consideres the root deleted state and then there's a trashedTreeQuery which only considers the trash instead.

thanks for the review!

@dschmidt

Copy link
Copy Markdown
Contributor

Sounds very good, thanks for taking my review into account 🙂

@aduffeck
aduffeck merged commit eb32a80 into opencloud-eu:main Sep 28, 2026
67 checks passed
@aduffeck
aduffeck deleted the fix/search-trashed-path-collision branch September 28, 2026 11:45
@openclouders openclouders mentioned this pull request Sep 28, 2026
@v-scharf

v-scharf commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

I think we need port it to stable because this case especially bad for opensearch

steps:

  • alan creates foo/alan-file.txt
  • mary creates foo/mary-file.txt
  • mary deletes foo and purge it in trashbin
  • alan search by foo by alan-file

Actual: 7.2.4 - search result is empty. dev (main branch) - alan can see folder and file

@v-scharf v-scharf added this to the next-stable milestone Oct 1, 2026
@v-scharf v-scharf removed this from the next-stable milestone Oct 2, 2026
@v-scharf v-scharf added the backport-required Needs a backport to the current stable branch label Oct 2, 2026
@github-project-automation github-project-automation Bot moved this to Qualification in OpenCloud Team Board Oct 6, 2026
sdwilsh pushed a commit to sdwilsh/ansible-playbooks that referenced this pull request Oct 7, 2026
#1949)

##### [\`8.1.0\`](https://github.com/opencloud-eu/opencloud/blob/HEAD/CHANGELOG.md#810---2026-10-05)

##### ❤️ Thanks to all contributors! ❤️

[@NickWalters](https://github.com/NickWalters), [@aduffeck](https://github.com/aduffeck), [@butonic](https://github.com/butonic), [@dschmidt](https://github.com/dschmidt), [@fschade](https://github.com/fschade), [@maki5](https://github.com/maki5), [@micbar](https://github.com/micbar), [@pascalwengerter](https://github.com/pascalwengerter), [@pbleser-oc](https://github.com/pbleser-oc), [@rhafer](https://github.com/rhafer), [@saw-jan](https://github.com/saw-jan), [@schweigisito](https://github.com/schweigisito), [@v-scharf](https://github.com/v-scharf), [@zerox80](https://github.com/zerox80)

##### 🔒 Security

- feat(proxy): add optional OIDC access token audience validation \[[#3466](opencloud-eu/opencloud#3466)]

##### 🐛 Bug Fixes

- Reindex disabled spaces once they get enabled again \[[#3579](opencloud-eu/opencloud#3579)]
- fix(search): tika key fixes \[[#3651](opencloud-eu/opencloud#3651)]
- fix(search): keep trashed and live folders at the same path apart \[[#3602](opencloud-eu/opencloud#3602)]
- Fix/uploads cli no async consumer \[[#3603](opencloud-eu/opencloud#3603)]
- Remove the timeout when reindexing spaces \[[#3543](opencloud-eu/opencloud#3543)]
- fix(shares): not auto accepting shares created by guest users \[[#3533](opencloud-eu/opencloud#3533)]
- fix(graph): fix PatchMe method to prevent password change \[[#3526](opencloud-eu/opencloud#3526)]

##### 📈 Enhancement

- feat: add new editor roles \[[#3637](opencloud-eu/opencloud#3637)]
- feat(collaboration): let admins disable wopi extensions \[[#3633](opencloud-eu/opencloud#3633)]
- fix(collaboration): send LastModifiedTime and the EuroOffice file size \[[#3636](opencloud-eu/opencloud#3636)]
- feat(collaboration): mobile web view for EuroOffice \[[#3635](opencloud-eu/opencloud#3635)]
- fix(collaboration): harden wopi token handling \[[#3630](opencloud-eu/opencloud#3630)]
- add posixfs index command \[[#3068](opencloud-eu/opencloud#3068)]
- feat(proxy): add per-service metrics to the proxy service \[[#3521](opencloud-eu/opencloud#3521)]

##### ✅ Tests

- fix(search): ellipsize parity matrix labels by runes, not bytes \[[#3643](opencloud-eu/opencloud#3643)]
- fix(collaboration): mint the mobile view test token with the token manager secret \[[#3647](opencloud-eu/opencloud#3647)]
- run cli tests with decomposed nightly \[[#3580](opencloud-eu/opencloud#3580)]
- \[decomposed] test(api): remove passing notification tests from expected failure \[[#3555](opencloud-eu/opencloud#3555)]
- api-test: add CLI test for reindexing all spaces including disabled \[[#3560](opencloud-eu/opencloud#3560)]

##### 📚 Documentation

- \[SKIP CI] fix: add file_read documentation to audit log docu \[[#3503](opencloud-eu/opencloud#3503)]

##### 📦️ Dependencies

- \[full-ci] chore: bump web to v8.1.0 \[[#3656](opencloud-eu/opencloud#3656)]
- chore: bump reva to latest main \[[#3642](opencloud-eu/opencloud#3642)]
- chore: bump libre-graph-api-go to v1.0.8 \[[#3645](opencloud-eu/opencloud#3645)]
- build(deps): bump github.com/nats-io/nats.go from 1.53.1 to 1.54.0 \[[#3584](opencloud-eu/opencloud#3584)]
- build(deps): bump github.com/onsi/gomega from 1.42.1 to 1.43.1 \[[#3582](opencloud-eu/opencloud#3582)]
- build(deps): bump google.golang.org/grpc from 1.83.2 to 1.84.0 \[[#3581](opencloud-eu/opencloud#3581)]
- build(deps): bump github.com/beevik/etree from 1.7.1 to 1.8.0 \[[#3583](opencloud-eu/opencloud#3583)]
- build(deps): bump golang.org/x/image from 0.45.0 to 0.46.0 \[[#3573](opencloud-eu/opencloud#3573)]
- build(deps): bump github.com/nats-io/nats-server/v2 from 2.14.5 to 2.15.0 \[[#3576](opencloud-eu/opencloud#3576)]
- build(deps): bump golang.org/x/text from 0.41.0 to 0.42.0 \[[#3552](opencloud-eu/opencloud#3552)]
- build(deps): bump golang.org/x/sync from 0.22.0 to 0.23.0 \[[#3551](opencloud-eu/opencloud#3551)]
- build(deps): bump go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc from 0.70.0 to 0.71.0 \[[#3427](opencloud-eu/opencloud#3427)]
- build(deps): bump github.com/olekukonko/errors from 1.2.0 to 1.3.0 \[[#3557](opencloud-eu/opencloud#3557)]
- build(deps): bump github.com/prometheus/client_model from 0.6.2 to 0.6.3 \[[#3550](opencloud-eu/opencloud#3550)]
- build(deps): bump github.com/shamaton/msgpack/v2 from 2.4.1 to 2.4.2 \[[#3459](opencloud-eu/opencloud#3459)]
- build(deps): bump go.opentelemetry.io/otel/exporters/stdout/stdouttrace from 1.45.0 to 1.46.0 \[[#3428](opencloud-eu/opencloud#3428)]
- build(deps): bump github.com/sirupsen/logrus from 1.10.1 to 1.10.2 \[[#3492](opencloud-eu/opencloud#3492)]

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-required Needs a backport to the current stable branch Status:Needs-Review Type:Bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants