Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #5375: add editable install support for svn+ssh URLs with a username #5664

Merged
merged 1 commit into from
Aug 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/reference/pip_install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ Subversion

pip supports the URL schemes ``svn``, ``svn+svn``, ``svn+http``, ``svn+https``, ``svn+ssh``.

Here are some of the supported forms::

[-e] svn+https://svn.example.com/MyProject#egg=MyProject
[-e] svn+ssh://svn.example.com/MyProject#egg=MyProject
[-e] svn+ssh://[email protected]/MyProject#egg=MyProject

You can also give specific revisions to an SVN URL, like so::

[-e] svn+svn://svn.example.com/svn/MyProject#egg=MyProject
Expand Down
1 change: 1 addition & 0 deletions news/5375.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support passing ``svn+ssh`` URLs with a username to ``pip install -e``.
8 changes: 6 additions & 2 deletions src/pip/_internal/vcs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,11 +207,15 @@ def export(self, location):
"""
raise NotImplementedError

def get_netloc_and_auth(self, netloc):
def get_netloc_and_auth(self, netloc, scheme):
"""
Parse the repository URL's netloc, and return the new netloc to use
along with auth information.

Args:
netloc: the original repository URL netloc.
scheme: the repository URL's scheme without the vcs prefix.

This is mainly for the Subversion class to override, so that auth
information can be provided via the --username and --password options
instead of through the URL. For other subclasses like Git without
Expand All @@ -237,7 +241,7 @@ def get_url_rev_and_auth(self, url):
)
# Remove the vcs prefix.
scheme = scheme.split('+', 1)[1]
netloc, user_pass = self.get_netloc_and_auth(netloc)
netloc, user_pass = self.get_netloc_and_auth(netloc, scheme)
rev = None
if '@' in path:
path, rev = path.rsplit('@', 1)
Expand Down
8 changes: 7 additions & 1 deletion src/pip/_internal/vcs/subversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,17 @@ def get_revision(self, location):
revision = max(revision, localrev)
return revision

def get_netloc_and_auth(self, netloc):
def get_netloc_and_auth(self, netloc, scheme):
"""
This override allows the auth information to be passed to svn via the
--username and --password options instead of via the URL.
"""
if scheme == 'ssh':
# The --username and --password options can't be used for
# svn+ssh URLs, so keep the auth information in the URL.
return super(Subversion, self).get_netloc_and_auth(
netloc, scheme)

return split_auth_from_netloc(netloc)

def get_url_rev_and_auth(self, url):
Expand Down
56 changes: 42 additions & 14 deletions tests/unit/test_vcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,33 +124,39 @@ def test_git_is_commit_id_equal(git, rev_name, result):

# The non-SVN backends all use the same get_netloc_and_auth(), so only test
# Git as a representative.
@pytest.mark.parametrize('netloc, expected', [
@pytest.mark.parametrize('args, expected', [
# Test a basic case.
('example.com', ('example.com', (None, None))),
(('example.com', 'https'), ('example.com', (None, None))),
# Test with username and password.
('user:[email protected]', ('user:[email protected]', (None, None))),
(('user:[email protected]', 'https'),
('user:[email protected]', (None, None))),
])
def test_git__get_netloc_and_auth(netloc, expected):
def test_git__get_netloc_and_auth(args, expected):
"""
Test VersionControl.get_netloc_and_auth().
"""
actual = Git().get_netloc_and_auth(netloc)
netloc, scheme = args
actual = Git().get_netloc_and_auth(netloc, scheme)
assert actual == expected


@pytest.mark.parametrize('netloc, expected', [
# Test a basic case.
('example.com', ('example.com', (None, None))),
# Test with username and no password.
('[email protected]', ('example.com', ('user', None))),
# Test with username and password.
('user:[email protected]', ('example.com', ('user', 'pass'))),
@pytest.mark.parametrize('args, expected', [
# Test https.
(('example.com', 'https'), ('example.com', (None, None))),
# Test https with username and no password.
(('[email protected]', 'https'), ('example.com', ('user', None))),
# Test https with username and password.
(('user:[email protected]', 'https'), ('example.com', ('user', 'pass'))),
# Test ssh with username and password.
(('user:[email protected]', 'ssh'),
('user:[email protected]', (None, None))),
])
def test_subversion__get_netloc_and_auth(netloc, expected):
def test_subversion__get_netloc_and_auth(args, expected):
"""
Test Subversion.get_netloc_and_auth().
"""
actual = Subversion().get_netloc_and_auth(netloc)
netloc, scheme = args
actual = Subversion().get_netloc_and_auth(netloc, scheme)
assert actual == expected


Expand Down Expand Up @@ -247,6 +253,28 @@ def test_bazaar__get_url_rev_and_auth():
)


@pytest.mark.parametrize('url, expected', [
# Test an https URL.
('svn+https://svn.example.com/MyProject#egg=MyProject',
('https://svn.example.com/MyProject', None, (None, None))),
# Test an https URL with a username and password.
('svn+https://user:[email protected]/MyProject#egg=MyProject',
('https://svn.example.com/MyProject', None, ('user', 'pass'))),
# Test an ssh URL.
('svn+ssh://svn.example.com/MyProject#egg=MyProject',
('svn+ssh://svn.example.com/MyProject', None, (None, None))),
# Test an ssh URL with a username.
('svn+ssh://[email protected]/MyProject#egg=MyProject',
('svn+ssh://[email protected]/MyProject', None, (None, None))),
])
def test_subversion__get_url_rev_and_auth(url, expected):
"""
Test Subversion.get_url_rev_and_auth().
"""
actual = Subversion().get_url_rev_and_auth(url)
assert actual == expected


# The non-SVN backends all use the same make_rev_args(), so only test
# Git as a representative.
@pytest.mark.parametrize('username, password, expected', [
Expand Down