Skip to content

Commit c4f6ed8

Browse files
committed
Handling git remotes with different push URLs.
Git remotes (e.g. origin) can have different fetch and push URLs. Before clone() just set the fetch URL for both in the new temporary repo. If the user set a push URL, SCVersioning would effectively not use it at all. Fixing this.
1 parent 0958d81 commit c4f6ed8

File tree

3 files changed

+39
-5
lines changed

3 files changed

+39
-5
lines changed

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ Changelog
4444

4545
This project adheres to `Semantic Versioning <http://semver.org/>`_.
4646

47+
Unreleased
48+
----------
49+
50+
Fixed
51+
* Carrying over to cloned repo the git remote push URL if it's different from fetch URL.
52+
4753
2.1.0 - 2016-08-22
4854
------------------
4955

sphinxcontrib/versioning/git.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
from sphinxcontrib.versioning.lib import TempDir
1313

14+
RE_FETCH_PUSH = re.compile(r'origin\t([A-Za-z0-9@:/._-]+) \((fetch|push)\)\n')
1415
RE_REMOTE = re.compile(r'^(?P<sha>[0-9a-f]{5,40})\trefs/(?P<kind>heads|tags)/(?P<name>[\w./-]+(?:\^\{})?)$',
1516
re.MULTILINE)
1617
RE_UNIX_TIME = re.compile(r'^\d{10}$', re.MULTILINE)
@@ -311,13 +312,15 @@ def clone(local_root, new_root, branch, rel_dest, exclude):
311312
:param iter exclude: List of strings representing relative file paths to exclude from "git rm".
312313
"""
313314
log = logging.getLogger(__name__)
314-
remote_url = run_command(local_root, ['git', 'ls-remote', '--get-url', 'origin']).strip()
315-
if remote_url == 'origin':
316-
raise GitError('Git repo missing remote "origin".', remote_url)
315+
output = run_command(local_root, ['git', 'remote', '-v'])
316+
remote_urls = dict((m[1], m[0]) for m in RE_FETCH_PUSH.findall(output))
317+
if not remote_urls:
318+
raise GitError('Git repo missing remote "origin".', output)
319+
remote_push_url, remote_fetch_url = remote_urls['push'], remote_urls['fetch']
317320

318321
# Clone.
319322
try:
320-
run_command(new_root, ['git', 'clone', remote_url, '--depth=1', '--branch', branch, '.'])
323+
run_command(new_root, ['git', 'clone', remote_fetch_url, '--depth=1', '--branch', branch, '.'])
321324
except CalledProcessError as exc:
322325
raise GitError('Failed to clone from remote repo URL.', exc.output)
323326

@@ -327,6 +330,10 @@ def clone(local_root, new_root, branch, rel_dest, exclude):
327330
except CalledProcessError as exc:
328331
raise GitError('Specified branch is not a real branch.', exc.output)
329332

333+
# Set push URL if different.
334+
if remote_fetch_url != remote_push_url:
335+
run_command(new_root, ['git', 'remote', 'set-url', '--push', 'origin', remote_push_url])
336+
330337
# Done if no exclude.
331338
if not exclude:
332339
return

tests/test_git/test_clone.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,31 @@ def test_bad_branch_rel_dest_exclude(tmpdir, local, run):
151151
run(local, ['git', 'remote', 'rm', 'origin'])
152152
with pytest.raises(GitError) as exc:
153153
clone(str(local), str(tmpdir.ensure_dir('new_root3')), 'master', '.', None)
154-
assert 'origin' in exc.value.output
154+
assert 'Git repo missing remote "origin".' in exc.value.message
155+
assert not exc.value.output
155156

156157
# Bad remote.
157158
run(local, ['git', 'remote', 'add', 'origin', local.join('does_not_exist')])
158159
with pytest.raises(GitError) as exc:
159160
clone(str(local), str(tmpdir.ensure_dir('new_root3')), 'master', '.', None)
160161
assert "repository '{}' does not exist".format(local.join('does_not_exist')) in exc.value.output
162+
163+
164+
def test_fetch_push_remotes(tmpdir, local, remote, run):
165+
"""Test different fetch/push URLs being carried over.
166+
167+
:param tmpdir: pytest fixture.
168+
:param local: conftest fixture.
169+
:param remote: conftest fixture.
170+
:param run: conftest fixture.
171+
"""
172+
remote_push = tmpdir.ensure_dir('remote_push')
173+
run(remote_push, ['git', 'init', '--bare'])
174+
run(local, ['git', 'remote', 'set-url', '--push', 'origin', str(remote_push)])
175+
176+
new_root = tmpdir.ensure_dir('new_root')
177+
clone(str(local), str(new_root), 'master', '', None)
178+
179+
output = run(new_root, ['git', 'remote', '-v'])
180+
expected = 'origin\t{} (fetch)\norigin\t{} (push)\n'.format(remote, remote_push)
181+
assert output == expected

0 commit comments

Comments
 (0)