Skip to content

fix: normalise trashbin-original-location PROPFIND response (full-ci)#41649

Open
phil-davis wants to merge 1 commit into
masterfrom
fix/trashbin-original-location
Open

fix: normalise trashbin-original-location PROPFIND response (full-ci)#41649
phil-davis wants to merge 1 commit into
masterfrom
fix/trashbin-original-location

Conversation

@phil-davis

@phil-davis phil-davis commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

In certain situations the trashbin original-location in a PROPFIND response
contained a leading slash. This change ensures that a relative path (without
a leading slash) is always returned.

#39337
#41649

Fixes #39337

The test code changes related to this issue from old PR #39336 have also been reverted in this PR.
The test code checks for an exact match to the original-location specified in the test steps.
For test steps that check that an element does NOT exist in the trashbin, the test steps check the trashbin for both forms of original-location (relative and absolute path). That is a double-check to make sure that no unexpected stuff is left in the trashbin.

@phil-davis phil-davis changed the title fix: normalise trashbin-original-location PROPFIND response fix: normalise trashbin-original-location PROPFIND response (full-ci) Jun 23, 2026
@phil-davis

Copy link
Copy Markdown
Contributor Author

I have run full-ci because we want to know that all the API acceptance tests still pass.

@DeepDiver1975 DeepDiver1975 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Automated review by Claude Code review agent.

Thanks for tackling this — it targets the exact inconsistency the triage flagged in #39337 (the oc:trashbin-original-location leading-slash mismatch: the deleter's entry was stored relative/no-slash via move()+pathinfo()['dirname'], while the owner's copy used dirname()/absolute, and getOriginalLocation() reflected that verbatim). Normalising the PROPFIND output to a single, stable leading-slash form is the right direction.

Verdict: changes-requested — the fix is incomplete and CI proves it.

Root-cause coverage

The change in AbstractTrashBinNode::getOriginalLocation():

-    $originalPath = $location . '/' . $originalPath;
+    $originalPath = '/' . ltrim($location, '/') . '/' . $originalPath;

correctly normalises the non-root case: regardless of whether $location arrives with a leading slash (owner copy) or without (deleter copy), the output now gets exactly one leading slash. Good.

But the normalisation only runs inside the if ($location !== '.') branch. For a file deleted from the root ($location === '.'), that branch is skipped and the method returns the bare $originalPath (e.g. textfile0.txt) with no leading slash. So the root-level case — the most common one — is still un-normalised.

CI failure (directly caused by this PR)

Two required API Smoke Test shards are failing, with 8 trashbin scenarios failing:

Failed step: But as "Alice" the file with original path "/textfile0.txt" should exist in the trashbin
File previously located at /textfile0.txt wasn't found in the trashbin of user Alice

This PR also tightens the test helper TrashbinContext::isInTrash() to an exact comparison by removing the ltrim() tolerance on both sides:

-        $originalPath = \ltrim($originalPath, '/');
-        if (... \ltrim($entry['original-location'], '/') === $originalPath) {
+        if (... $entry['original-location'] === $originalPath) {

The feature files now assert against /textfile0.txt (leading slash), but for root-deleted files the PROPFIND value is still textfile0.txt (no slash) because of the $location === '.' gap above — so the exact match fails. The test tightening and the production fix are out of sync for the root case.

Suggested fix

Apply the leading slash unconditionally (or handle the . case), e.g.:

$originalPath = '/' . \ltrim($originalPath, '/');
if ($location !== '.') {
    $originalPath = '/' . \ltrim($location, '/') . \rtrim($originalPath, '/') ... ;
}

or simply normalise the final return value once: return '/' . ltrim($originalPath, '/');. Then re-run the trashbin smoke suites until green.

Changelog

changelog/unreleased/41649 is present and well-formed (Bugfix: type, present-tense summary <80 chars, descriptive body, issue + PR URLs including the #39337 link).

Summary

  • Resolves #39337's intent, but the fix misses the $location === '.' (root-deleted file) path.
  • Required checks are failing (8 trashbin acceptance scenarios) as a direct result.
  • Please slash the root case and get CI green; happy to re-review.

phil-davis added a commit that referenced this pull request Jun 23, 2026
In certain situations the trashbin original-location in a PROPFIND response
contained a leading slash. This change ensures that a relative path (without
a leading slash) is always returned.

#39337
#41649

fix
@phil-davis phil-davis force-pushed the fix/trashbin-original-location branch from 9197b14 to 4ccdb8f Compare June 23, 2026 09:13
In certain situations the trashbin original-location in a PROPFIND response
contained a leading slash. This change ensures that a relative path (without
a leading slash) is always returned.

#39337
#41649

fix
@phil-davis phil-davis force-pushed the fix/trashbin-original-location branch from 4ccdb8f to b7558ee Compare June 23, 2026 09:21
@phil-davis

Copy link
Copy Markdown
Contributor Author

I have revised the code in this PR to use the solution discussed in #39337 (comment)

@DeepDiver1975 DeepDiver1975 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🤖 Automated review by Claude Code review agent.

Re-review of the updated HEAD (9197b14b7558ee). The previous pass flagged that the leading-slash normalisation only ran in the non-root branch, leaving root-deleted files ($location === '.') un-normalised — and the PR's own tightened test helper would have failed for those. This revision fixes exactly that gap.

Root-case gap — fixed ✅

In apps/dav/lib/TrashBin/AbstractTrashBinNode.php, getOriginalLocation() now normalises at the single return point, after the if ($location \!== '.') block:

if ($location \!== '.') {
    $originalPath = $location . '/' . $originalPath;
}
return ltrim($originalPath, '/');

Because ltrim is applied to the final value regardless of which branch ran, the canonical form (relative, no leading slash) is now returned consistently for both root-deleted files and files deleted from a subfolder. This matches the PR description ("a relative path without a leading slash is always returned") and resolves the inconsistency triaged in #39337. The storage side (apps/files_trashbin/lib/Trashbin.php) is intentionally untouched — the fix lives entirely in the DAV presentation layer, which is the right, minimal place.

Test helper / feature files — consistent

TrashbinContext::isInTrash() now does an exact match against the relative form, with an opt-in $checkRelativeAndAbsolutePath flag that additionally accepts the absolute form. That flag is set true only for the negative checks ("should not exist") and the restore check — a sensible belt-and-braces double-check that nothing is left under either path form, while positive-existence assertions pin the exact relative canonical form. The feature files were updated to drop the leading slashes from positive-existence rows accordingly. Coherent with the source change.

Changelog

changelog/unreleased/41649 present and well-formed (Bugfix: prefix, body, cites #39337 and the PR). Changelog-lint check is green.

Checks — currently PENDING

The CI run for this HEAD (run 28015959486) is still in progress. PHP Unit (all DBs), PHP Code Style, Changelog lint, CodeQL, semantic-commit and JS unit are green. However every acceptance shard — including the decisive apiTrashbin,apiTrashbinRestore and cliTrashbin shards that must validate the previously-failing scenarios — is still pending. I can't yet confirm the 8 trashbin scenarios pass; the source+test logic looks correct, but the acceptance result is the real proof. mergeStateStatus is BLOCKED (waiting on required checks/review).

Verdict

The code change is correct and minimal, and it directly closes the root-case gap from the last review. Holding short of approve only because the trashbin acceptance shards have not yet reported — once apiTrashbin,apiTrashbinRestore goes green this is good to go.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Minor difference in oc:trashbin-original-location PROPFIND response

2 participants