Skip to content

Commit b366d3f

Browse files
committed
Adding support for git remote set-url/get-url API to Remote
Both commands enable handling of a little known feature of git, which is to support multiple URL for one remote. You can add multiple url using the `set_url` subcommand of `git remote`. As listing them is also handy, there's a nice method to do it, using `get_url`. * adding set_url method that maps to the git remote set-url command¶ * can be used to set an URL, or replace an URL with optional positional arg¶ * can be used to add, delete URL with kwargs (matching set-url options)¶ * adding add_url, delete_url methods that wraps around set_url for conveniency¶ * adding urls property that yields an iterator over the setup urls for a remote¶ * adding a test suite that checks all use case scenarii of this added API.¶ Signed-off-by: Guyzmo <guyzmo+github@m0g.net>
1 parent 902679c commit b366d3f

File tree

2 files changed

+95
-2
lines changed

2 files changed

+95
-2
lines changed

git/remote.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,54 @@ def iter_items(cls, repo):
434434
yield Remote(repo, section[lbound + 1:rbound])
435435
# END for each configuration section
436436

437+
def set_url(self, new_url, old_url=None, **kwargs):
438+
"""Configure URLs on current remote (cf command git remote set_url)
439+
440+
This command manages URLs on the remote.
441+
442+
:param new_url: string being the URL to add as an extra remote URL
443+
:param old_url: when set, replaces this URL with new_url for the remote
444+
:return: self
445+
"""
446+
scmd = 'set-url'
447+
kwargs['insert_kwargs_after'] = scmd
448+
if old_url:
449+
self.repo.git.remote(scmd, self.name, old_url, new_url, **kwargs)
450+
else:
451+
self.repo.git.remote(scmd, self.name, new_url, **kwargs)
452+
return self
453+
454+
def add_url(self, url, **kwargs):
455+
"""Adds a new url on current remote (special case of git remote set_url)
456+
457+
This command adds new URLs to a given remote, making it possible to have
458+
multiple URLs for a single remote.
459+
460+
:param url: string being the URL to add as an extra remote URL
461+
:return: self
462+
"""
463+
return self.set_url(url, add=True)
464+
465+
def delete_url(self, url, **kwargs):
466+
"""Deletes a new url on current remote (special case of git remote set_url)
467+
468+
This command deletes new URLs to a given remote, making it possible to have
469+
multiple URLs for a single remote.
470+
471+
:param url: string being the URL to delete from the remote
472+
:return: self
473+
"""
474+
return self.set_url(url, delete=True)
475+
476+
@property
477+
def urls(self):
478+
""":return: Iterator yielding all configured URL targets on a remote
479+
as strings"""
480+
scmd = 'get-url'
481+
kwargs = {'insert_kwargs_after': scmd}
482+
for url in self.repo.git.remote(scmd, self.name, all=True, **kwargs).split('\n'):
483+
yield url
484+
437485
@property
438486
def refs(self):
439487
"""

git/test/test_remote.py

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
with_rw_repo,
1010
with_rw_and_rw_remote_repo,
1111
fixture,
12-
GIT_DAEMON_PORT
12+
GIT_DAEMON_PORT,
13+
assert_raises
1314
)
1415
from git import (
1516
RemoteProgress,
@@ -62,7 +63,7 @@ def update(self, op_code, cur_count, max_count=None, message=''):
6263
# check each stage only comes once
6364
op_id = op_code & self.OP_MASK
6465
assert op_id in (self.COUNTING, self.COMPRESSING, self.WRITING)
65-
66+
6667
if op_code & self.WRITING > 0:
6768
if op_code & self.BEGIN > 0:
6869
assert not message, 'should not have message when remote begins writing'
@@ -568,3 +569,47 @@ def test_uncommon_branch_names(self):
568569
assert res[0].remote_ref_path == 'refs/pull/1/head'
569570
assert res[0].ref.path == 'refs/heads/pull/1/head'
570571
assert isinstance(res[0].ref, Head)
572+
573+
@with_rw_repo('HEAD', bare=False)
574+
def test_multiple_urls(self, rw_repo):
575+
# test addresses
576+
test1 = 'https://github.com/gitpython-developers/GitPython'
577+
test2 = 'https://github.com/gitpython-developers/gitdb'
578+
test3 = 'https://github.com/gitpython-developers/smmap'
579+
580+
remote = rw_repo.remotes[0]
581+
# Testing setting a single URL
582+
remote.set_url(test1)
583+
assert list(remote.urls) == [test1]
584+
585+
# Testing replacing that single URL
586+
remote.set_url(test1)
587+
assert list(remote.urls) == [test1]
588+
# Testing adding new URLs
589+
remote.set_url(test2, add=True)
590+
assert list(remote.urls) == [test1, test2]
591+
remote.set_url(test3, add=True)
592+
assert list(remote.urls) == [test1, test2, test3]
593+
# Testing removing an URL
594+
remote.set_url(test2, delete=True)
595+
assert list(remote.urls) == [test1, test3]
596+
# Testing changing an URL
597+
remote.set_url(test3, test2)
598+
assert list(remote.urls) == [test1, test2]
599+
600+
# will raise: fatal: --add --delete doesn't make sense
601+
assert_raises(GitCommandError, remote.set_url, test2, add=True, delete=True)
602+
603+
# Testing on another remote, with the add/delete URL
604+
remote = rw_repo.create_remote('another', url=test1)
605+
remote.add_url(test2)
606+
assert list(remote.urls) == [test1, test2]
607+
remote.add_url(test3)
608+
assert list(remote.urls) == [test1, test2, test3]
609+
# Testing removing all the URLs
610+
remote.delete_url(test2)
611+
assert list(remote.urls) == [test1, test3]
612+
remote.delete_url(test1)
613+
assert list(remote.urls) == [test3]
614+
# will raise fatal: Will not delete all non-push URLs
615+
assert_raises(GitCommandError, remote.delete_url, test3)

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy