When an existing `headRepo` couldn't be detected, it's time to auto-fork
one. Unfortunately, an obscure Go behavior made it seem like `headRepo`
was a non-nil value, where in fact it did contain a nil pointer which
would crash the process.
This avoids ever assigning nil pointers to `var headRepo ghrepo.Interface`.
A branch is considered already pushed if its HEAD commit hash matches
the commit hash of one of the remote tracking branches:
`refs/remotes/<remote>/<branch>`
This mechanism allows the user to:
- Choose a remote as push target for their branch different than the one
that would automatically get chosen for them by `pr create`;
- Avoid a `git push` operation (and its associated git hooks) if a push
was not necessary in the first place.
The 2nd argument now unused since we've determined that, in practice, we
can safely fetch git objects from a freshly created fork on GitHub and
that we don't need the remote URL-swapping workaround.
Before: the default push target for the current branch in `pr create`
was the first repository found among git remotes that has write access.
Now: the default push target is the fork the base repo, if said fork
exists and has write access, falling back to old behavior otherwise.
This change in the default is to facilitate contributions to projects
that have a hard requirement that all pull requests (even those opened
by people with write access to that project) come from forks.
- Only check for existing PRs if `--web` wasn't given
- Fix detecting PRs from forks
- Improve order of error handling: local validation errors are handled
earlier than the ones that have to consult the API
Since we cannot pass the "draft" option as query parameter, this raises
an error instead of proceeding to open the browser and potentially
confuse the user as to why `--draft` wasn't respected.
This avoids fork or push operation if there were errors processing the
input arguments or if the operation has been cancelled during
interactive survey.
When the user has just created a fork, it might not yet be ready for
writing. This ensures that the wait period between retries is
communicated to the user on stderr.
Turns out the "standard" way of wrapping errors in Go is via
`fmt.Errorf("%w")`, which doesn't require an external package and also allows a
finer control of error sentence formatting.
Also define a handful of utility methods:
- `New(owner, repo)`
- `FullName`: the name slash owner pair
- `FromFullName`: parse the name slash owner pair
- `FromURL`: parse a GitHub.com URL
- `IsSame(r1, r2)`: compare two repositories
- The local git remotes are scanned and resolved to GitHub repositories
- The "base" repo is the first result resolved to its parent repo (if a fork)
- The name of the default branch is read from the base repo
- The "head" repo is the first repo that has push access
If multiple templates are found, the user is prompted to select one.
The templates are searched for, in order of preference:
- issues:
1. `.github/ISSUE_TEMPLATE/*.md`
2. `.github/ISSUE_TEMPLATE.md`
3. `ISSUE_TEMPLATE/*.md`
4. `ISSUE_TEMPLATE.md`
5. `docs/ISSUE_TEMPLATE/*.md`
6. `docs/ISSUE_TEMPLATE.md`
- pull requests:
1. `.github/PULL_REQUEST_TEMPLATE/*.md`
2. `.github/PULL_REQUEST_TEMPLATE.md`
3. `PULL_REQUEST_TEMPLATE/*.md`
4. `PULL_REQUEST_TEMPLATE.md`
5. `docs/PULL_REQUEST_TEMPLATE/*.md`
6. `docs/PULL_REQUEST_TEMPLATE.md`
The filename matches are case-insensitive.