ds300 / patch-package

Fix broken node modules instantly 🏃🏽‍♀️💨
MIT License
10.31k stars 288 forks source link

Add guide for importing module instead of editing files #197

Open christianbundy opened 4 years ago

christianbundy commented 4 years ago

Background: I have a pull request into a repository where the npm module isn't up-to-date with master, and I'd like to test out my branch in a module that depends on it through a bunch of different deep dependencies. It seems like patch-package would be a great solution for this.

Problem: When I append .patch to my GitHub URL it gives me a patch, but when I pass it to patch -p1 it fails because the diff between my branch and master is not the same as the diff between my branch and the latest published npm module. I tried to instead use the diff between my branch and the corresponding tag, but it turns out that the npm module and the Git tag aren't 100% in sync. My guess is that the "import a diff from a pull request" isn't documented in the readme because all of the solutions are fraught with errors like the ones I've encountered, but it would be great to have a recommendation of how to import code rather than hand-editing files with Vim.

Proposal: Let's document how to import an entire module! After trying a bunch of different solutions for a few hours, the best I can come up with is simple [albeit primitive]:

# Delete the currently installed module.
rm -rf ./node_modules/foo
# Import your code directly into `node_modules`
cp -r ~/src/foo ./node_modules
# Generate a diff for patch-package
patch-package foo

This feels wasteful, since Git already provides a diff for us, but since the npm registry is divorced from the Git history it seems like the only robust solution. I'd be very happy to hear improvements to this workflow. Thanks for your work on this module!

christianbundy commented 4 years ago

Unfortunately my previous solution doesn't respect .npmignore, and includes directories like .git that we don't want. I wrote a small shell function and it's working much better for me:

patch_package_install () {
  # Only take one argument, like "~/src/foo" or "../foo" or "/over/the/rainbow/foo".
  module_path="$1"

  # Change to module directory.
  cd "$module_path"
  # Get the module name.
  name="$(jq -r .name < package.json)"
  # Create a tarball and remember its path.
  tarball="$1/$(npm pack)"

  # Return to previous directory.
  cd -
  # Install the tarball without touching `package*.json`
  npm install --no-save "$tarball"
  # Create a diff between our tarball and the official tarball.
  patch-package "$name"
  # Delete the tarball
  rm -f "$tarball"
}

This works fine with a Bourne shell (/bin/sh) and Zsh with set -k, so I'd imagine it probably works with Bash as well?

christianbundy commented 4 years ago

I think I must be doing something wrong, because the above function isn't noticing changes to package.json.

christianbundy commented 4 years ago

Oh, I just saw in a comment (oops I closed the tab) that this module excludes package.json because it can't manage changes to the dependency graph. :cry: