feat(update): move a page to its declared parent, refuse another space - #202
Merged
Merged
Conversation
Plan for #10: update refuses a page in another space and moves a page to its declared parent.
update published the body, title, width, labels and status but ignored
space and parent, which left the two coordinates outside L9.
A declared parent is now asserted by moving the page: an id or a .md
path moves it under that page or folder, parent: null (or ~, or an empty
value) moves it to the top of the space, and an absent parent leaves it
alone. A moved page goes last among its new siblings; markfluence does
not manage sibling order. Every move uses the v1 move route, which
leaves the page version alone where a v2 parentId change bumps it, so a
move stays out of the moved-page check and the unchanged-body skip, and
v1 is the only route that reaches the top of a space.
Every read the move needs happens before any write, so --dry-run reports
a move that would fail: the parent resolves, is a page or folder in the
page's space, and is not the page itself or below it. The loop check
walks the target's parentId chain, since v2's ancestors route needs a
scope nothing else here needs. The move is the first write, and a
failed move fails the file.
A space is a refusal, never a move: a page outside the file's space, or
outside markfluence.yaml's space: default when the file names none,
fails before any write.
--json gains moved on update results, null or {from, to}; a new key is
compatible since #200. diff compares parent: null and the project
default space, to match. The ".md parent -> page id" code create and
diff each had is now internal/parentref, which update uses too.
Fixes #10.
- moved is set only once the move has happened (or under --dry-run), so a failure after planning no longer claims a move; a move made before a later failure is reported in human output too. - A blank parent is a value when frontmatter and a pages: entry are compared, so parent: null against an id is a coordinate disagreement instead of the id winning silently. - A parent that is neither digits nor a .md path is refused before any request, and so is a .md parent whose page_id is not a number. - The already-in-place check also compares the id the server returned, so 0100 does not move a page onto its own parent; the move targets that id. - Space keys compare without regard to case, which is how Confluence resolves them (measured: sre, Sre and SRE all name SRE). A page whose space cannot be told is refused with that reason, and a move to the top of the space refuses rather than requesting a malformed route. - Among top-level pages sharing a position, the last one listed is last. - Within's comment says what an unreadable ancestor costs: only the preview, since Confluence still refuses a real loop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #10.
updatepublished the body, title, width, labels and status but ignoredspaceandparent, which left the two coordinates outside L9. Plan:_plans/053_update-moves-pages.md(amended with what implementation and review changed).Upgrade note:
updatenow moves pages. Every filecreatewrote carries aparent:line (an id, ornullfor a top-level page). So the firstupdateafter upgrading moves any page that someone moved by hand in Confluence back to the parent its file records, subtree included. That is L9 working as written, and it is how labels already behave, but it is a quiet change for anyone who rearranged a tree in the UI. Runupdate --dry-run(ordiff) first to see which pages would move, and editparent:in those files to keep the new places. This belongs in the release notes.Parent.
.mdpath moves the page under that page or folder.parent: null(or~, or an empty value) moves it to the top of the space.parentleaves the page where it is.parentIdchange bumps it, so a move stays out of the moved-page check and the unchanged-body skip. v1 is also the only route that reaches the top of a space: v2 silently ignores a nullparentId. The measurements are indocs/confluence/api.md.Checks before any write. Every read the move needs happens first, so
--dry-runreports a move that would fail. The parent must resolve, be a number or a.mdpath, be a page or folder in the page's space, and not be the page itself or below it. The loop check walks the target'sparentIdchain, since v2's ancestors route needs a scope nothing else here needs. The move is the first write, and a failed move fails the file.Space. A space is a refusal, never a move. A page outside the file's
space, or outsidemarkfluence.yaml'sspace:default when the file names none, fails with nothing written. Keys compare without regard to case, which is how Confluence resolves them.Frontmatter against
pages:entry. A blankparentis now a value when the two locations are compared, soparent: nullin one against an id in the other is a coordinate disagreement and fails the file.Output.
moved under "Runbooks" (placed last; reorder in Confluence if needed), shown even when a later step fails.--jsongainsmoved: null | {from, to}on update results. A new key is compatible since json-output: make adding a key a compatible schema change #200, soschema_versionstays 1.Also:
diffcomparesparent: nulland the project's space default, to match.createanddiffeach had is nowinternal/parentref, whichupdateuses too.pagemeta.ResolvedgainedSpace(root)andParent().Verified end to end against a personal space with the built binary:
.mdparent each left the page at the same version with the bodyPUTskipped;diffreported the project-default space.