GithubHelp home page GithubHelp logo

bluekeyes / patch2pr Goto Github PK

View Code? Open in Web Editor NEW
37.0 4.0 4.0 276 KB

Create pull requests from patches without cloning the repository

License: MIT License

Go 100.00%
github golang pullrequest git patch

patch2pr's Introduction

patch2pr

PkgGoDev

Create GitHub pull requests from Git patches without cloning the repository.

Why?

As a command line tool, it's mostly a curiosity and test for the library, but might have some use for exceptionally large repositories or in environments where cloning is not feasible.

As a library, however, it enables tools to make automated code changes without giving every part of system write access or requiring extra logic for managing clones. One part of the system can generate a patch and send it to another part that uses this library to apply it and create a pull request.

Usage: CLI

Pre-built binaries for common platforms are available on the releases page.

You can also install from source using go install:

go install github.com/bluekeyes/patch2pr/cmd/patch2pr@latest

The CLI takes a path to a patch file as the only argument or reads a patch from stdin if no file is given.

The other required arguments are:

  • The -repository flag to specify the repository in owner/name format
  • A GitHub token, set with the -token flag or in the GITHUB_TOKEN environment variable.
    • Classic tokens must have repo scope
    • Fine-grained tokens must have read and write access to administration (for creating forks), contents (for committing changes), and pull requests

For example:

$ export GITHUB_TOKEN="token"
$ patch2pr -repository bluekeyes/patch2pr /path/to/file.patch

See the CLI help (-h or -help) or below for full details.

Full Usage

Usage: patch2pr [options] [patch...]

  Create a GitHub pull request from a patch file

  This command parses one or more patches, applies them, and creates a pull
  request with the result. It does not clone the repository. If no patch files
  are given, the command reads the patches from standard input. Each file can
  contain a single patch or multiple patches in the mbox format produced by 'git
  format-patch --stdout' or GitHub's patch view.

  By default, patch2pr uses the patch header for author and committer
  information, falling back to the authenticated GitHub user if the headers are
  missing or invalid. Callers can override these values using the standard Git
  environment variables:

    GIT_AUTHOR_NAME
    GIT_AUTHOR_EMAIL
    GIT_AUTHOR_DATE
    GIT_COMMITTER_NAME
    GIT_COMMITER_EMAIL
    GIT_COMMITER_DATE

  Override the commit message by using the -message flag.

  With the -fork and -fork-repository flags, the command can submit the pull
  request from a fork repository. If an existing fork does not exist, the
  command creates a new fork, which may take up to five minutes.

Options:

  -base-branch=branch    The branch to target with the pull request. If unset,
                         use the repository's default branch.

  -draft                 Create a draft pull request.

  -force                 Update the head branch even if it exists and is not a
                         fast-forward.

  -fork                  Submit the pull request from a fork instead of pushing
                         directly to the repository. With no other flags, use a
                         fork in the current account with the same name as the
                         target repository, creating the fork if it does not exist.

  -fork-repository=repo  Submit the pull request from the named fork instead of
                         pushing directly to the repository, creating the fork
                         if it does not exist. Implies the -fork flag.

  -head-branch=branch    The branch to create or update with the new commit. If
                         unset, use 'patch2pr'.

  -json                  Output information about the new commit and pull request
                         in JSON format.

  -message=message       Message for the commit. Overrides the patch header.

  -no-pull-request       Do not create a pull request after creating a commit.

  -patch-base=base       Base commit to apply the patch to. Can be a SHA1, a
                         branch, or a tag. Branches and tags must start with
                         'refs/heads/' or 'refs/tags/' respectively. If unset,
                         use the repository's default branch.

  -pull-body=body        The body for the pull request. If unset, use the body of
                         the commit message.

  -pull-title=title      The title for the pull request. If unset, use the title
                         of the commit message.

  -repository=repo       Repository to apply the patch to in 'owner/name' format.
                         Required.

  -token=token           GitHub API token with 'repo' scope for authentication.
                         If unset, use the value of the GITHUB_TOKEN environment
                         variable.

  -url=url               GitHub API URL. If unset, use https://api.github.com.

  -v/-version            Print the version and exit.

Usage: Library

The CLI is built on the patch2pr library, which can be used to build other tools that apply patches directly to GitHub. See the documentation for full details.

The library uses google/go-github to interact with GitHub and exposes types from that package in the API.

Stability

Beta. The library is used in a production application that applies thousands of patches every day, but the interface for both the CLI and the library may change.

While the underlying patch library (bluekeyes/go-gitdiff) has good test coverage and real-world usage, the space of all possible patches is large, so there are likely undiscovered bugs.

Contributing

Contributions are welcome. If reporting an issue with applying a patch, please include the patch file and the base commit or file content if possible. A link to a public repository is most helpful.

At this time, I don't intend to support services other than GitHub. If you'd like support for another service, please file an issue with a link to the relevant API documentation so I can estimate the work involved in adding the necessary abstractions.

License

MIT

patch2pr's People

Contributors

arunsathiya avatar asvoboda avatar bluekeyes avatar dependabot[bot] avatar jamestoyer avatar katrinafyi avatar pankaj-a avatar pospelove avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

patch2pr's Issues

Publish binary CLI distributions

Since more people seem to use the CLI than I expected, it would be nice to make binaries available so you don't have to have Go installed. I think using GoReleaser in GitHub Actions will be the easiest way to do this.

Allow multiple changes to same file in one patch

patch2pr/applier.go

Lines 58 to 65 in da87617

// Because of the tree cache, files must be part of a remote (i.e. created)
// tree before they are modifiable. This could be fixed by refactoring the
// apply logic but doesn't seem like an onerous restriction.
for _, e := range a.entries {
if e.GetPath() == f.NewName {
return nil, errors.New("cannot apply with pending changes to file")
}
}

This check prevents applying multiple changes to the same file in a single path, assuming callers do the obvious thing and call Apply for each file entry in the patch.

I don't really remember what I meant by this comment (shame on me), but I think that getEntry could be modified to return either a pending entry from the list or the entry from a tree to resolve this. The entry needs to be removed from the pending list or the apply helpers need to not add it again, but otherwise, I think it will work. Entries in the pending list are all valid, so code shouldn't see any difference between a new entry and one from a persisted tree.

This problem came up with a patch that deleted a file and replaced it with a symlink. I think Git generated a patch with a deletion and then an addition at the same path, rather than a mode change and content modification. Theoretically, this same problem happens with any other patch that does the same "delete and add instead of modify" thing.

Add support for forks in the CLI

Follow-up from #70. It would be nice if the CLI provided a -fork flag to create (or use) a fork to submit the pull request, instead of requiring that you have write access to the target repository. Right now, I believe you have to manually create a fork, target your fork with the -no-pull-request flag, and then manually create the PR to the upstream repository.

Multiple commits in one patch file are not supported

In a file with multiple commits (e.g. Github PR patches), only the first commit is parsed from the git format-patch output.

Additional commits can be detected by the "From" headers when the parser is looking for further "diff --git" lines. Fortunately, this is not ambiguous with diff context lines since those always start with +, -, or space.

Edit: I should mention I noticed this via patch2pr. If this is better filed there, feel free to move!

Skip or fix integration tests on fork PRs

Both fork PRs and Dependabot PRs fail the integration tests, because the GitHub token must have write permissions. I don't think there's a good way around this (short of using mocks for all the test), so probably best to add a way to skip these tests in builds that don't have permissions.

Unable to create commits on my forked repository

patch2pr sounds really handy! I am having some troubles getting started though.

This is the command that I am running:

patch2pr -repository replit/pyright-extended -fork -no-pull-request changes.patch

My understanding is that:

  • It creates a fork of replit/pyright-extended on my account arunsathiya
  • Commits the patch

And without the -no-pull-request flag, it submits a PR too, to upstream replit/pyright-extended.

But the command's failing with this error:

error: commit failed: create tree failed: POST https://api.github.com/repos/arunsathiya/pyright-extended/git/trees: 404 Not Found []

This may be because the repository does not exist or the token you are using
does not have write permission. If submitting a patch to a repository where you
do not have write access, consider using the -fork flag to submit the patch
from a fork.

I have tried the following command too, but it fails with the same error after creating the fork:

patch2pr -repository replit/pyright-extended -fork-repository arunsathiya/pyright-extended -no-pull-request changes.patch

I see the same behavior with the following types of tokens:

Add CLI flag to clean format-patch titles and messages

Applying a patch created by git format-patch works, but leaves a kind of messy result:

  • The title of the commit and the PR title contain a [PATCH] prefix
  • The body of the commit and the PR body contain a summary of the changed files (content that appears after the --- in the patch message)

It would be nice to have a flag that attempted to strip this stuff out of the title and body. If I remember correctly, the -k flag for format-patch and am does something similar.

Can't apply patch

Tried to create a PR for a patch generated by nodejs patch-package module. This tool checks out a clean copy of the module to be patched and diffs it with the changes in the modules node_modules folder hirarchy. The resulting patch is saved to patches/module.name.patch

I used this patch to run patch2pr and got this error:

patch2pr -repository mrousavy/react-native-vision-camera patches/react-native-vision-camera+2.15.4.patch
error: apply failed: node_modules/react-native-vision-camera/android/src/main/java/com/mrousavy/camera/CameraViewModule.kt: no entry for modified file

getting 404 on POST repository/git/blobs (outdated github api?)

is this project up to date? i've tried to create a pr from a patch and i've been unable to because i receive a 404 response from the api
error: apply failed: path/to/file: create blob failed: POST https://api.github.com/repos/owner/repo/git/blobs: 404 Not Found []

Draft PRs

First off, this tool is awesome. Thank you to all that created it!

Secondly, I'm curious if it supports the ability to create draft PRs? If not, that's a feature I might (eventually) add.

Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.