Repository navigation
Implement lossless RVT write and save-as foundation - #188
AndreyStartsev wants to merge 3 commits into
Conversation
mahach666
left a comment
There was a problem hiding this comment.
Requesting changes for three independently reproduced defects in the new writer: unavailable sharing/hosting metadata bypasses the capability gate; unchanged SaveAs loses opaque storage metadata; and an incompatible replacement schema can be published successfully even though the writer then rejects its own output.
The merge preview against current main builds and passes the default suites (10,402 tests on .NET 8 and 10,406 on .NET 10; 439 skipped on each). These passing tests do not cover the failures described inline. Unchanged SaveAs stream/identity checks on two real release samples also passed; native Revit Audit validation was not independently performed.
|
Addressed all three review items in f0e4050 with regression tests:
|
mahach666
left a comment
There was a problem hiding this comment.
Re-reviewed f0e4050 and its merge preview against current main (cd243be). All three previously reported defects are fixed and independently verified; the corresponding threads are resolved. No additional blocking findings.
Validation:
- Release solution builds pass on the PR head and merge preview.
- Default merge-preview suites: 10,406 passed on .NET 8 and 10,410 passed on .NET 10; zero failures, 439 skipped on each.
- Independent checks confirm refusal of missing/incomplete metadata, preservation of root/child storage metadata, and rejection of incompatible replacement schemas without publishing output.
- SaveAs copies of two real samples (releases 2022 and 2027) preserve all stream bytes, storage metadata and element identities; source hashes are unchanged.
- Both private writer sample tests pass on these samples on .NET 10.
- Package creation and DocFX with warnings-as-errors pass.
Limits: the hosted CI and Docs runs remain action_required and are not counted as passing. Native Revit Audit and the full private fixture corpus were not independently run. No merge performed.
mahach666
left a comment
There was a problem hiding this comment.
Requesting changes after native acceptance of f0e4050. This review supersedes my earlier approval: SaveAs and Rewrite can report success while breaking a valid relative RVT link when the destination directory changes. This fails the external-reference preservation criterion in #20.
The issue was independently reproduced in Revit 2022, with a same-directory SaveAs as a passing control. Native checks also exercised Audit opening and length-changing record writes in Revit 2020, 2022, 2025 and 2027. Source hashes remained unchanged. The three previously reported defects remain fixed; the new destination-dependent reference failure still blocks acceptance.
Preserve the resolved reference targets, or explicitly refuse the unsupported relocation before publishing output, and add a regression covering both destination cases.
| var containerResult = ContainerRewriter.Rewrite( | ||
| sourcePath, | ||
| fullOutput, | ||
| replacements ?? NoStreamReplacements, | ||
| verifyEditedOutput); |
There was a problem hiding this comment.
[P2] Preserve relative reference targets when changing directories
This copies the container to a new location without checking whether relative external references still resolve to the same files. For example, a host in input/host.rvt referencing ../links/linked.rvt resolves that reference differently after saving to output/nested/host.rvt. In a controlled Revit 2022 project, both SaveAs and Rewrite return success, but the previously valid RVT link changes from Loaded to NotFound, and RevitLinkInstance.GetLinkDocument() returns null. The original linked file still exists. Saving into the source directory keeps the link loaded, confirming that relocation causes the failure.
Preserve the resolved targets of supported relative references, or refuse destination changes that cannot preserve them before publishing the file. Add a regression with a valid relative link and both same-directory and different-directory destinations; checking stored reference bytes alone misses this failure.
|
@AndreyStartsev could you fix this? |
- Add RvtWriter, RvtWriteCapabilities, RvtWriteRequest, RvtWriteResult, RvtWriteRefusedException, and RvtDocument.SaveAs for local 2020-2027 .rvt and .rfa files - Add PagedStreamCodec for Formats/* and Global/* paged gzip streams and PartitionStreamEditor for targeted Partitions/<n> record rewrites with Adler-32 checksums, 128 KB segment bounds, and untouched block, chain, and opaque payload preservation - Add rvtio save-as CLI command (--check and --report) and DocFX documentation (docs/writing.md) - Add synthetic and optional fixture tests across net8.0 and net10.0 Closes IOExtend#20
- Refuse writes with missing-metadata when BasicFileInfo is missing, unreadable, or lacks recognised Worksharing, IsSingleUserCloudModel, or saving-release fields; expose IsWorkshared and IsCloudModel as nullable bool? and classify Worksharing: Enabled as workshared. - Preserve and verify root and child storage directory-entry metadata (CLSID, StateBits, CreationFileTime, ModifiedFileTime, HeaderCLSID) in ContainerRewriter across SaveAs and Rewrite. - Validate replacement Formats/Latest payloads against SavedRelease, supported release bounds, ElementIdWidth, and existing partition framing marker class IDs, and re-inspect edited temporary containers before publishing. - Add regression tests covering missing/incomplete BasicFileInfo, opaque storage metadata preservation and tampering detection, and valid-but-incompatible replacement schemas.
f0e4050 to
e6c624f
Compare
|
Rebased onto
|
What changes and why
Implements the lossless .rvt / .rfa write and save-as foundation (RvtWriter, RvtDocument.SaveAs, PagedStreamCodec, PartitionStreamEditor, and
vtio save-as).
Closes #20
Summary
vtio save-as <source.rvt|source.rfa> [<output.rvt|output.rfa>] [--check] [--report <report.json>] (exit codes , 1, 2, and 5 when refused by the matrix).
How it was checked
et8.0 and
et10.0
et8.0 and
et10.0, including synthetic 2020-2027 .rvt/.rfa round-trips, multi-chain/multi-segment >128 KB rewrites, unknown class preservation, refusal codes, CLI exit codes, and RvtWriterSampleTests when RVTIO_TEST_FILES is configured)