-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Tooling for the Future of Forked Files #4104
Comments
Somewhat off-topic, but just want to mention the existence of https://github.com/ds300/patch-package, which is a fairly popular JS tool to patch packages in |
Note that @jonthysell is going to help drive the resolution of react-native-community/discussions-and-proposals#182, which is related - whatever solution we come up with will need to work with the tooling proposed here. |
Add a foundation for new override tooling described in microsoft#4104. This includes: - Build scripts, lint scripts, config files, etc - Logic for parsing and checking validity of an override manifest - Unit tests for override manifest logic - Abstractions to allow fetching React Native files of arbtrary versions A lot of this is foundational. The override logic has been well-tested, and the Git logic has been manually tested, but we don't have much end-to-end set up yet.
* Initial commit of override tooling Add a foundation for new override tooling described in #4104. This includes: - Build scripts, lint scripts, config files, etc - Logic for parsing and checking validity of an override manifest - Unit tests for override manifest logic - Abstractions to allow fetching React Native files of arbtrary versions A lot of this is foundational. The override logic has been well-tested, and the Git logic has been manually tested, but we don't have much end-to-end set up yet. * Address comments and deuplicate lockfile * Add more dependencies for WebDriverIO We hardcode an old version of WebderiverIO beacuse of #3019. These seem to have loose dependency requirements, because the change to deuplicate packages broke this (see webdriverio/webdriverio#4104). Hardcode resolutions in E2ETest for existing versions of wdio packages in the meantime.
Summary
While React Native Windows has moved off the microsoft/react-native fork, mechanisms still exist to modify upstream React Native code. Our C++ code is mostly clean of changes, but we still have significant changes to upstream JavaScript. These changes, and the mechanisms we use to apply them increase fragility and lead to slow merges. Some of our problems can be mitigated by investment in tooling.
Our Current System
Platform-specific JavaScript is a necessity. Metro (the React Native bundler) accomplishes this by allowing per-platform implementations of a JavaScript module. E.g. We could have
Widget.android.js
andWidget.ios.js
, with Metro resolving the correct module if a code asks to import from./Widget
. React Native Windows makes extensive use of this capability, with 175 files shared between.windows
,.win32
, and.windesktop
. Apart from providing platform-unique code, we abuse this system to override existing shared JavaScript. This accounts for 60% of overrides. Other overrides for non-shared JavaScript are often just copies of Android or iOS implementations with minor changes. These files are kept together in a structure that’s merged with React Native source code during the JavaScript build.While changing code internal to component boundaries is inherently fragile, this system adds additional unnecessary pain:
Some of these pains can be eliminated by changing how we record and represent overrides.
Adding the Override Manifest
Overrides can be divided into three rough categories:
These different categories have different ideal representations, and require different knowledge to achieve tool-based merging. Patches can be kept as a diff, derived overrides require knowing the file they derive from. Abstraction logic doesn't require much attention.
We can embed this extra information into a manifest, associating metadata with overrides. The addition of structured metadata opens new opportunities around merge tooling, version checking, and system enforced issue tracking.
The manifest will initially contain the following:
Override Validation and Generation in the JS Build
During
yarn build
we will copy override files to a shared directory cohabitated with React Native source. This build step can be expanded to work with the manifest, adding integrity checking and patching. A just task could be added toyarn lint
to check all files insrc
against the manifest, verifying the override has metadata, and that its base file hasn't changed since creation. This task should create an actionable error pointing to the faulty or outdated override. Doing this check during the lint phase allowsyarn build
to work with unregistered overrides during local development.Patching can also be implemented as a simple just task during build time, using the patch file to create an override in the target file structure.
The Override CLI
CLI based tools should be added to manage overrides and upgrades. We need a few commands for different scenarios:
yarn override --add
Present a wizard style series of prompts to the developer to add an override to the manifest. E.g. asking type, asking for the creation of a Github issue with a plan, and doing generation of hashes or patch files.
yarn override --verify
Validate the the all files are correctly described in the manifest.
yarn override --remove
Removes an override from the manifest 👍
yarn override --patchify
andyarn override --unpatchify
Convert a file to or from a diff based representation. This is needed to allow editing of a file while still storing changes as diffs. Since we have full knowledge of original vs new sources, this step can programmatically add comments around changed areas.
yarn override --update
andyarn override --finalize
Used to upadte patches to a new base version. The
yarn override --update
step does two thingsThis allows simple three-way merging using standard Git tools (e.g. VSCode) to compare current vs staged. Eg:
Once everything is updated, you can run
yarn override --finalize
to convert files back to patches and update the manifest.The text was updated successfully, but these errors were encountered: