Skip to content

remote: add url=/token= to fetch/push/pull, plus dest_ref for fetch#2182

Open
cumulus13 wants to merge 1 commit into
gitpython-developers:mainfrom
cumulus13:feature/remote-fetch-url-token
Open

remote: add url=/token= to fetch/push/pull, plus dest_ref for fetch#2182
cumulus13 wants to merge 1 commit into
gitpython-developers:mainfrom
cumulus13:feature/remote-fetch-url-token

Conversation

@cumulus13

Copy link
Copy Markdown

Remote.fetch(), Remote.push(), and Remote.pull() could previously only operate against the remote's configured name/URL, forcing anyone who wanted to use an alternate URL (e.g. with an embedded credential) to first rewrite the remote's permanent config via set_url() -- persisting a token to .git/config as a side effect just to do a single operation. All three shell out to the underlying git transport command with the remote's name hardcoded as the target; git remote update/rename/set-url/prune etc. are not affected since those are config-only commands that don't accept an arbitrary URL to begin with.

Add to Remote.fetch(), Remote.push(), and Remote.pull():

  • url: use this URL for this call only. The remote's stored config is never read or written for the transport target when given; it takes precedence over the remote's name/configured url.

  • token: optional credential embedded into url's authority component for this call only (http/https only). Never written to config or logged, and scrubbed from GitCommandError text if the call fails, so a failure can't leak the token via an exception/log message.

Additionally, Remote.fetch() gets dest_ref (fetch-only -- push writes directly to the named destination ref regardless of url=, and pull's merge target is the checked-out branch, so neither has fetch's FETCH_HEAD-only footgun): a bare refspec entry (no ':dst') only updates FETCH_HEAD when fetching from an anonymous url, because unlike a named/configured remote, git has no remote..fetch pattern to complete a destination from. dest_ref lets a caller ask for a normal tracking ref instead:

  • True -> refs/remotes//
  • '...{branch}...' -> templated destination, applied per-entry
    when refspec is a list
  • plain string -> used verbatim (single bare entry only)
    Entries that already contain ':' are left untouched. Raises
    ValueError if given without url=, or if a plain-string dest_ref is
    combined with more than one bare refspec entry; raises TypeError
    for any other dest_ref type.

Existing calls (no url=/token=/dest_ref=) are unaffected on all three methods; behavior and the 'no refspec configured' assertion are unchanged for that path on fetch/pull.

Adds test coverage for: one-off URL fetch/push/pull (each confirming the configured remote url/config is untouched afterwards and, for push/pull, that the operation actually took effect against the alternate target), skipping the refspec-assertion when url= is given, token= rejecting non-http(s) urls on all three methods, token redaction in the raised GitCommandError on failure for all three, dest_ref=True creating a real tracking ref, a '{branch}' template applied across a list of refspecs, a plain-string dest_ref, explicit 'src:dst' refspecs being left untouched by dest_ref, and the ValueError/TypeError validation paths.

Remote.fetch(), Remote.push(), and Remote.pull() could previously
only operate against the remote's configured name/URL, forcing
anyone who wanted to use an alternate URL (e.g. with an embedded
credential) to first rewrite the remote's permanent config via
set_url() -- persisting a token to .git/config as a side effect
just to do a single operation. All three shell out to the
underlying git transport command with the remote's name hardcoded
as the target; git remote update/rename/set-url/prune etc. are not
affected since those are config-only commands that don't accept an
arbitrary URL to begin with.

Add to Remote.fetch(), Remote.push(), and Remote.pull():

- url: use this URL for this call only. The remote's stored config
  is never read or written for the transport target when given; it
  takes precedence over the remote's name/configured url.

- token: optional credential embedded into url's authority
  component for this call only (http/https only). Never written to
  config or logged, and scrubbed from GitCommandError text if the
  call fails, so a failure can't leak the token via an
  exception/log message.

Additionally, Remote.fetch() gets dest_ref (fetch-only -- push
writes directly to the named destination ref regardless of url=,
and pull's merge target is the checked-out branch, so neither has
fetch's FETCH_HEAD-only footgun): a *bare* refspec entry (no
':dst') only updates FETCH_HEAD when fetching from an anonymous
url, because unlike a named/configured remote, git has no
remote.<name>.fetch pattern to complete a destination from.
dest_ref lets a caller ask for a normal tracking ref instead:
  * True             -> refs/remotes/<this-remote-name>/<branch>
  * '...{branch}...' -> templated destination, applied per-entry
                        when refspec is a list
  * plain string      -> used verbatim (single bare entry only)
Entries that already contain ':' are left untouched. Raises
ValueError if given without url=, or if a plain-string dest_ref is
combined with more than one bare refspec entry; raises TypeError
for any other dest_ref type.

Existing calls (no url=/token=/dest_ref=) are unaffected on all
three methods; behavior and the 'no refspec configured' assertion
are unchanged for that path on fetch/pull.

Adds test coverage for: one-off URL fetch/push/pull (each
confirming the configured remote url/config is untouched
afterwards and, for push/pull, that the operation actually took
effect against the alternate target), skipping the
refspec-assertion when url= is given, token= rejecting non-http(s)
urls on all three methods, token redaction in the raised
GitCommandError on failure for all three, dest_ref=True creating a
real tracking ref, a '{branch}' template applied across a list of
refspecs, a plain-string dest_ref, explicit 'src:dst' refspecs
being left untouched by dest_ref, and the ValueError/TypeError
validation paths.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant