patchwork 0.2.0 copy "patchwork: ^0.2.0" to clipboard
patchwork: ^0.2.0 copied to clipboard

Patch management for Dart projects, starting with reviewable dependency patches for pub packages.

Patchwork #

pub package CI license

Patchwork keeps Dart pub dependency fixes in reviewable patch files without editing your shared .pub-cache.

Use it when you need a local dependency fix that should survive fresh checkouts, code review, and CI. Patchwork copies a resolved dependency into .patchwork/<pkg>@<version>/, commits the edit as patches/<pkg>@<version>.patch, and materializes the patch through generated pub path overrides.

Why Patchwork #

Manual .pub-cache edits are fast, but they are local to one machine and easy to lose. Patchwork keeps the durable part of the change in your project so the same patch can be reviewed, committed, and applied by teammates or CI.

Patchwork is a good fit for small dependency fixes while you wait for an upstream release. Prefer a fork or vendored dependency when the change is large, long-lived, security-sensitive, or needs its own release process.

Install #

Add Patchwork as a dev dependency in the project that owns the patch files.

dart pub add dev:patchwork

For local repository development:

dev_dependencies:
  patchwork:
    path: ../path/to/patchwork/pub/patchwork

Run commands with dart run:

dart run patchwork --help

Global activation is optional for users who prefer a standalone executable.

Workflow #

Run Patchwork from the Dart package or workspace you want to patch.

dart pub get
dart run patchwork doctor
dart run patchwork patch collection

Edit the directory printed by patchwork patch, then commit it:

dart run patchwork commit collection

Apply committed patches:

dart run patchwork apply
dart pub get
dart run patchwork status

After a successful apply, Patchwork prints the dart pub get next step so pub refreshes dependency resolution through the generated overrides.

Library API #

The CLI uses the same API that hooks or other Dart tooling can call:

import 'dart:io';

import 'package:patchwork/patchwork.dart';

Future<void> main() async {
  final patchwork = await Patchwork.open(Directory.current);

  await patchwork.patch('collection');
  await patchwork.commit('collection');
  await patchwork.apply('collection');
  await patchwork.undo('collection');

  final state = await patchwork.inspect();
  stdout.writeln('${state.packages.length} patchwork packages');
}

Use PatchRef.version('1.19.0') with patch when carrying an older patch onto a newer dependency source.

What To Commit #

Commit these files in projects that use Patchwork:

  • patchwork.lock
  • patches/*.patch

These files are the reviewable source of truth for your dependency patches.

State Model #

Patchwork uses four project-local locations:

  • .patchwork/<pkg>@<version>/ is the editable work-in-progress copy.
  • patches/<pkg>@<version>.patch is the committed reviewable patch file.
  • patchwork.lock records the selected source, committed patch sha, and applied generated output.
  • .dart_tool/patchwork/<pkg>@<version>/ is generated by patchwork apply and wired into pub through pubspec_overrides.yaml.

The lockfile is intentionally a lockfile, not a patch manifest. A typical entry looks like this:

version: 2
packages:
  collection:
    version: "1.19.1"
    source:
      type: "hosted"
      url: "https://pub.dev"
      sha256: "<source-tree-sha>"
    patch:
      edit-sha256: "<edit-tree-sha>"
      commit-sha256: "<patch-file-sha>"
    patch-history:
      "1.19.0":
        commit-sha256: "<older-patch-file-sha>"
    applied:
      patch-sha256: "<applied-patch-file-sha>"
      path: ".dart_tool/patchwork/collection@1.19.1"

source may describe hosted or custom hosted packages, path dependencies, or git dependencies. Git sources record branch when pub resolves a ref and commit when pub records the resolved commit.

patch-history is only written when a dependency source changes while an older committed patch is still needed for patchwork patch <pkg> --continue <version>. Patchwork uses it to verify the older patch file sha before using it as an edit seed.

source:
  type: "path"
  path: "../packages/foo"
  sha256: "<source-tree-sha>"
source:
  type: "git"
  url: "https://example.com/foo.git"
  branch: "main"
  commit: "<resolved-commit>"
  path: "packages/foo"
  sha256: "<source-tree-sha>"

What Stays Generated #

Do not commit Patchwork's generated integration state:

  • .patchwork/
  • .dart_tool/patchwork/
  • pubspec_overrides.yaml

patchwork apply never mutates the primary pubspec.yaml; it writes pubspec_overrides.yaml so pub resolves patched packages through generated path overrides. pubspec_overrides.yaml is shared with other tools and local workflow, so Patchwork only manages its own patch override entries.

Commands #

patchwork patch <pkg> [--continue [version]]  Create a source-based edit.
patchwork commit [pkg]                        Commit open edits into patches.
patchwork apply [pkg]                         Apply committed patches.
patchwork undo <pkg>                          Remove one applied patch.
patchwork status                              Show patch and override state.
patchwork doctor                              Check local readiness.

Packages are plain pub package names selected by the current pub resolution. Patchwork rejects target syntax such as pub:collection, collection@1.19.1, path:collection, git URLs, filesystem paths, the current project package, and workspace member packages.

Current Limits #

Patchwork 0.2 focuses on pub packages selected by the current pub resolution. It supports hosted, custom hosted, path, and git dependencies as patch sources. It does not support:

  • sdk: targets such as sdk:flutter
  • target syntax other than a plain package name
  • hooks or automatic dart pub get
  • patchwork run

Migrating From Cache Patches #

If you currently use a cache patch tool or manual .pub-cache edits, restore a clean dependency copy before creating a Patchwork edit. Patchwork should diff from the original dependency source, not from a package that already has local cache edits applied.

Patchwork does not import other patch formats yet. Recreate the dependency edit with patchwork patch <package>, then commit it with patchwork commit <package>.

Carrying Patches Across Upgrades #

When an upstream release may contain your fix, undo the generated override before upgrading so pub resolves the real dependency source:

dart run patchwork undo collection
dart pub get
dart pub upgrade collection
dart pub get

If the upstream release contains the fix, create a fresh edit from that source and commit it unchanged. Patchwork removes the obsolete lock entry and the previous patch file recorded in patch-history:

dart run patchwork patch collection
dart run patchwork commit collection

If the upstream release does not contain the fix, explicitly continue from the older patch file:

dart run patchwork patch collection --continue 1.19.0
dart run patchwork commit collection
dart run patchwork apply collection
dart pub get

CI Check #

Run Patchwork in CI after dependencies are installed:

dart run patchwork apply
dart pub get
dart run patchwork status
dart test

Use patchwork doctor when CI should fail on missing, stale, or unapplied patch state.

Example #

The repository contains a runnable example under examples/hello_patch. The package-level example/README.md links to that walkthrough for pub.dev.

4
likes
0
points
673
downloads

Publisher

verified publishermedz.dev

Weekly Downloads

Patch management for Dart projects, starting with reviewable dependency patches for pub packages.

Repository (GitHub)
View/report issues

Topics

#cli #dependencies #patch #pub

Funding

Consider supporting this project:

github.com

License

unknown (license)

Dependencies

crypto, path, yaml

More

Packages that depend on patchwork