Cache keys are hashed absolute paths, so the cache can never be reused across checkouts (CI → local, git worktrees)

Open
#8,488 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
55/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
php
Domain
tooling

Research direction

Start with ChangedFilesDetector, especially getFilePathCacheKey() and resolvePath(), then trace how cache entries are written and read. Decide how the project root is supplied and how paths outside it behave, using the issue's PHPStan comparison as context. Done means cache entries can be reused across equivalent checkouts without breaking existing cache reads.

Written by the indexing model from the issue text.

Description

Subject Details
Rector version 2.6.6
Installed as composer dependency

ChangedFilesDetector keys every cache entry on the absolute path of the file:

private function getFilePathCacheKey(string $filePath): string
{
    return $this->fileHasher->hash($this->resolvePath($filePath) . $this->scopeSuffix);
}

private function resolvePath(string $filePath): string
{
    $realPath = realpath($filePath);
    // ...
    return $realPath;
}

The path is hashed into the cache file's name, so the cache is bound to one location on disk. Move the project - a second git worktree, a CI checkout, a container mount - and the cache is 100% misses while containing nothing that could be rewritten to fix it.

Measurements

A 12 762-file project, 14 cores, PHP 8.5.10.

Scenario Wall time
fresh checkout, empty cache 224 s
same checkout, warm cache 5 s
fresh checkout, cache copied from another checkout of the same commit 247 s (291 MB copied for nothing)

For comparison, the same experiment with the other two tools in the same toolchain, copying their caches into the same fresh checkout:

Tool cold seeded from another checkout
Pint (PHP-CS-Fixer) 105 s 2.7 s
PHPStan 43 s 4.4 s
Rector 224 s 247 s

Rector's cache records nothing about the environment. Grepping all 12 761 entries of a populated tmp/rector finds zero references to a PHP version, an extension list or an OS - each entry is just a content hash. The absolute path is the only thing standing between that cache and reuse somewhere else.

Proposal

Key on the path relative to the project root and re-absolutize on read, as PHPStan does.
Two honest caveats:

  1. Existing caches invalidate once on upgrade.
  2. Files outside the project root (if any can reach the detector) need a defined behaviour - PHPStan's transformer leaves an already-absolute path untouched, which also keeps old-format caches readable.

I am happy to send a PR if you agree with the direction. I would rather hear which shape you want (anchor directory as a constructor dependency vs resolving it from the config) than guess and have it rewritten.

Dominant language
PHP
Stars
137
Forks
451
Avg merge
7h 11m
Merged PRs (30d)
129

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from rectorphp/rector-src

All issues in rectorphp/rector-src

Similar issues

More PHP issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.