Skip to content

pull-reprint: stop touching internal Reprint state directly - #4491

Open
fredrikekelund wants to merge 7 commits into
trunkfrom
f26d/pull-reprint-jetpack-remote-file-index-phar
Open

pull-reprint: stop touching internal Reprint state directly#4491
fredrikekelund wants to merge 7 commits into
trunkfrom
f26d/pull-reprint-jetpack-remote-file-index-phar

Conversation

@fredrikekelund

@fredrikekelund fredrikekelund commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Codex wrote the whole thing based on a detailed upfront plan that I drafted with Claude. The process was highly iterative.

Proposed Changes

The pull-reprint command in Studio currently both reads and writes private Reprint state. This was implemented as a temporary measure to make selective sync work, and I'm now working on making the necessary upstream changes and then adapting Studio accordingly.

Here are the specific changes in this PR:

This PR depends on WordPress/reprint#436 and WordPress/reprint#540 being included in the bundled PHAR. To make things easier for testers, I've simply committed the patched PHAR.

Testing Instructions

  1. npm run cli:build
  2. Create a new site for testing and cd into it
  3. STUDIO_ENABLE_PULL_REPRINT=1 studiodev pull-reprint
  4. Ensure that the file picker displays successfully
  5. Deselect the database and ensure that the sync finishes successfully (and that the site works)
  6. Ensure that a second partial file sync also finishes successfully

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@fredrikekelund
fredrikekelund requested review from a team, gavande1 and gcsecsey August 10, 2026 14:11
@fredrikekelund fredrikekelund self-assigned this Aug 10, 2026
@fredrikekelund fredrikekelund changed the title Reprint: first part of cleanup related to reading Reprint private state pull-reprint: stop touching internal Reprint state directly Aug 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

To reiterate: I will remove this file before merging. It's here to make testing easier.

@wpmobilebot

wpmobilebot commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing 746ff2f vs trunk

app-size

Metric trunk 746ff2f Diff Change
App Size (Mac) 1406.61 MB 1405.19 MB 1.42 MB 🟢 -0.1%

site-editor

Metric trunk 746ff2f Diff Change
load 1038 ms 1042 ms +4 ms ⚪ 0.0%

site-startup

Metric trunk 746ff2f Diff Change
siteCreation 7519 ms 7540 ms +21 ms ⚪ 0.0%
siteStartup 2866 ms 2875 ms +9 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

return entries.filter( ( entry ) => entry.isDirectory );
}

export async function fetchJetpackPullTree(

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.

How do the token mapping and parent collapse behave now that values come from buildTreeFromRemote? fetchRemoteFileTree appends a slash to directory paths, so on this branch the values arrive as below, which means the CONTENT_DIR_TOKENS lookup on line 48 and the parent check on line 92 both compare against a key that never matches.

values: [ "plugins/akismet/", "plugins/", "uploads/" ]
only:   [ ".../plugins/akismet/", ".../plugins/", ".../uploads/" ]

Related question: does preserveUnselectedLocalContent still treat a selected directory as covered when the prefix ends in a slash, given its check is absolutePath === prefix || startsWith(prefix + '/')?

Comment thread apps/cli/commands/pull-reprint.ts Outdated

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.

Now that downloadSkippedFiles is gone, what fetches the media library? --filter=essential-files still tells Reprint to exclude :wp-uploads:, and the same filter keeps the remote upload proxy enabled, so I am unsure whether pulled sites are meant to depend on the remote for media permanently. If that is the intent, should the comment above and the uploads entry in the picker be updated to match?

// 4. Flatten the raw download into the site directory. Reprint uses the
// remote URL to locate the pull state, though this step makes no request.
await runStep( __( 'Flattening layout' ), [
'flat-docroot',

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.

With restoreSelectedSymlinks removed, how does a selected plugin that is a symlink on the remote end up at wp-content/plugins/<name>? is_selected_for_pulling still returns false when the remainder under an --only prefix is empty, so the files seem to land under the link target while the link itself is never listed.

savePullSelection( session, selection );
return selection;
}
const tree = await fetchJetpackPullTree( wpComAccessToken, wpComSiteId );

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.

With the raw-scratch reset removed, how does a pull recover when raw/ is non-empty and no cursor exists? Studio does not pass --on-fs-root-nonempty, so Reprint falls back to error and throws "Filesystem root is not empty and no cursor found". Does the move to state/remotes/<md5(url)>/pull/state.json put existing scratches from older builds into exactly that state?

@fredrikekelund

Copy link
Copy Markdown
Contributor Author

Thanks for the review, @gavande1! Several good feedback items 👍 My work is a bit spread out atm. I'll try to consolidate it, but it may be best to inherit one or two of these issues into another PR.

I've pushed fixes related to the buildTreeFromRemote and downloadSkippedFiles issues. For the former, I refined how we generate the --only paths from the selection, and for the latter, I've actually dropped --filter=essential-files altogether for now. We can revisit this later.

No need to review again just yet. I'll revisit all of this tomorrow

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.

3 participants