test_install_vcs_git.py 15.6 KB
Newer Older
1
import pytest
2

P
Pradyun S. Gedam 已提交
3
from tests.lib import (
4 5 6
    _change_test_package_version,
    _create_test_package,
    _test_path_to_file_url,
C
Chris Jerdonek 已提交
7
    pyversion,
P
Pradyun S. Gedam 已提交
8
)
9
from tests.lib.git_submodule_helpers import (
10 11
    _change_test_package_submodule,
    _create_test_package_with_submodule,
12 13
    _pull_in_submodule_changes_to_module,
)
14
from tests.lib.local_repos import local_checkout
15

16

C
Chris Jerdonek 已提交
17 18 19 20 21 22 23
def _get_editable_repo_dir(script, package_name):
    """
    Return the repository directory for an editable install.
    """
    return script.venv_path / 'src' / package_name


24 25 26 27
def _get_editable_branch(script, package_name):
    """
    Return the current branch of an editable install.
    """
C
Chris Jerdonek 已提交
28
    repo_dir = _get_editable_repo_dir(script, package_name)
29 30 31
    result = script.run(
        'git', 'rev-parse', '--abbrev-ref', 'HEAD', cwd=repo_dir
    )
C
Chris Jerdonek 已提交
32 33
    return result.stdout.strip()

34

C
Chris Jerdonek 已提交
35 36 37 38 39 40 41 42
def _get_branch_remote(script, package_name, branch):
    """

    """
    repo_dir = _get_editable_repo_dir(script, package_name)
    result = script.run(
        'git', 'config', 'branch.{}.remote'.format(branch), cwd=repo_dir
    )
43 44 45
    return result.stdout.strip()


46
def _github_checkout(url_path, temp_dir, rev=None, egg=None, scheme=None):
47
    """
48
    Call local_checkout() with a GitHub URL, and return the resulting URL.
49 50

    Args:
51 52
      url_path: the string used to create the package URL by filling in the
        format string "git+{scheme}://github.com/{url_path}".
53 54 55
      temp_dir: the pytest tmpdir value.
      egg: an optional project name to append to the URL as the egg fragment,
        prior to returning.
56
      scheme: the scheme without the "git+" prefix. Defaults to "https".
57
    """
58 59
    if scheme is None:
        scheme = 'https'
60
    url = 'git+{}://github.com/{}'.format(scheme, url_path)
61
    local_url = local_checkout(url, temp_dir)
62 63
    if rev is not None:
        local_url += '@{}'.format(rev)
64
    if egg is not None:
65
        local_url += '#egg={}'.format(egg)
66

67
    return local_url
68 69


70 71 72 73 74 75 76 77 78
def _make_version_pkg_url(path, rev=None):
    """
    Return a "git+file://" URL to the version_pkg test package.

    Args:
      path: a tests.lib.path.Path object pointing to a Git repository
        containing the version_pkg package.
      rev: an optional revision to install like a branch name, tag, or SHA.
    """
C
Chris Jerdonek 已提交
79
    file_url = _test_path_to_file_url(path)
80
    url_rev = '' if rev is None else '@{}'.format(rev)
C
Chris Jerdonek 已提交
81
    url = 'git+{}{}#egg=version_pkg'.format(file_url, url_rev)
82 83 84 85

    return url


86
def _install_version_pkg_only(script, path, rev=None, expect_stderr=False):
87
    """
88 89
    Install the version_pkg package in editable mode (without returning
    the version).
90 91 92 93

    Args:
      path: a tests.lib.path.Path object pointing to a Git repository
        containing the package.
94
      rev: an optional revision to install like a branch name or tag.
95
    """
96
    version_pkg_url = _make_version_pkg_url(path, rev=rev)
97
    script.pip('install', '-e', version_pkg_url, expect_stderr=expect_stderr)
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112


def _install_version_pkg(script, path, rev=None, expect_stderr=False):
    """
    Install the version_pkg package in editable mode, and return the version
    installed.

    Args:
      path: a tests.lib.path.Path object pointing to a Git repository
        containing the package.
      rev: an optional revision to install like a branch name or tag.
    """
    _install_version_pkg_only(
        script, path, rev=rev, expect_stderr=expect_stderr,
    )
113 114 115 116 117 118
    result = script.run('version_pkg')
    version = result.stdout.strip()

    return version


119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
def test_git_install_again_after_changes(script):
    """
    Test installing a repository a second time without specifying a revision,
    and after updates to the remote repository.

    This test also checks that no warning message like the following gets
    logged on the update: "Did not find branch or tag ..., assuming ref or
    revision."
    """
    version_pkg_path = _create_test_package(script)
    version = _install_version_pkg(script, version_pkg_path)
    assert version == '0.1'

    _change_test_package_version(script, version_pkg_path)
    version = _install_version_pkg(script, version_pkg_path)
    assert version == 'some different version'


137 138 139 140 141 142
def test_git_install_branch_again_after_branch_changes(script):
    """
    Test installing a branch again after the branch is updated in the remote
    repository.
    """
    version_pkg_path = _create_test_package(script)
143
    version = _install_version_pkg(script, version_pkg_path, rev='master')
144 145 146
    assert version == '0.1'

    _change_test_package_version(script, version_pkg_path)
147
    version = _install_version_pkg(script, version_pkg_path, rev='master')
148 149 150
    assert version == 'some different version'


151
@pytest.mark.network
152
def test_install_editable_from_git_with_https(script, tmpdir):
J
Jannis Leidel 已提交
153 154 155
    """
    Test cloning from Git with https.
    """
156 157
    url_path = 'pypa/pip-test-package.git'
    local_url = _github_checkout(url_path, tmpdir, egg='pip-test-package')
158
    result = script.pip('install', '-e', local_url)
159
    result.assert_installed('pip-test-package', with_files=['.git'])
J
Jannis Leidel 已提交
160

H
Hugo Lopes Tavares 已提交
161

162
@pytest.mark.network
163 164 165 166 167 168
def test_install_noneditable_git(script, tmpdir):
    """
    Test installing from a non-editable git URL with a given tag.
    """
    result = script.pip(
        'install',
M
Marcus Smith 已提交
169 170 171
        'git+https://github.com/pypa/pip-test-package.git'
        '@0.1.1#egg=pip-test-package'
    )
172
    egg_info_folder = (
M
Marcus Smith 已提交
173 174 175 176 177 178
        script.site_packages /
        'pip_test_package-0.1.1-py%s.egg-info' % pyversion
    )
    result.assert_installed('piptestpackage',
                            without_egg_link=True,
                            editable=False)
179 180 181
    assert egg_info_folder in result.files_created, str(result)


182
def test_git_with_sha1_revisions(script):
H
Hugo Lopes Tavares 已提交
183 184 185
    """
    Git backend should be able to install from SHA1 revisions
    """
D
Donald Stufft 已提交
186 187
    version_pkg_path = _create_test_package(script)
    _change_test_package_version(script, version_pkg_path)
188 189 190 191
    sha1 = script.run(
        'git', 'rev-parse', 'HEAD~1',
        cwd=version_pkg_path,
    ).stdout.strip()
192
    version = _install_version_pkg(script, version_pkg_path, rev=sha1)
193
    assert '0.1' == version
194 195 196 197 198 199 200 201 202 203 204 205


def test_git_with_short_sha1_revisions(script):
    """
    Git backend should be able to install from SHA1 revisions
    """
    version_pkg_path = _create_test_package(script)
    _change_test_package_version(script, version_pkg_path)
    sha1 = script.run(
        'git', 'rev-parse', 'HEAD~1',
        cwd=version_pkg_path,
    ).stdout.strip()[:7]
206
    version = _install_version_pkg(script, version_pkg_path, rev=sha1)
207
    assert '0.1' == version
H
Hugo Lopes Tavares 已提交
208

209

210
def test_git_with_branch_name_as_revision(script):
211 212 213
    """
    Git backend should be able to install from branch names
    """
D
Donald Stufft 已提交
214
    version_pkg_path = _create_test_package(script)
215
    branch = 'test_branch'
216
    script.run('git', 'checkout', '-b', branch, cwd=version_pkg_path)
D
Donald Stufft 已提交
217
    _change_test_package_version(script, version_pkg_path)
218 219
    version = _install_version_pkg(script, version_pkg_path, rev=branch)
    assert 'some different version' == version
220

221

222
def test_git_with_tag_name_as_revision(script):
223 224 225
    """
    Git backend should be able to install from tag names
    """
D
Donald Stufft 已提交
226
    version_pkg_path = _create_test_package(script)
227
    script.run('git', 'tag', 'test_tag', cwd=version_pkg_path)
D
Donald Stufft 已提交
228
    _change_test_package_version(script, version_pkg_path)
229 230
    version = _install_version_pkg(script, version_pkg_path, rev='test_tag')
    assert '0.1' == version
231

232

C
Chris Jerdonek 已提交
233
def _add_ref(script, path, ref):
234
    """
C
Chris Jerdonek 已提交
235
    Add a new ref to a repository at the given path.
236
    """
237
    script.run('git', 'update-ref', ref, 'HEAD', cwd=path)
C
Chris Jerdonek 已提交
238 239 240 241 242 243


def test_git_install_ref(script):
    """
    The Git backend should be able to install a ref with the first install.
    """
244 245 246
    version_pkg_path = _create_test_package(script)
    _add_ref(script, version_pkg_path, 'refs/foo/bar')
    _change_test_package_version(script, version_pkg_path)
C
Chris Jerdonek 已提交
247

248
    version = _install_version_pkg(
249
        script, version_pkg_path, rev='refs/foo/bar',
250 251
    )
    assert '0.1' == version
C
Chris Jerdonek 已提交
252 253 254 255 256 257 258


def test_git_install_then_install_ref(script):
    """
    The Git backend should be able to install a ref after a package has
    already been installed.
    """
259 260 261
    version_pkg_path = _create_test_package(script)
    _add_ref(script, version_pkg_path, 'refs/foo/bar')
    _change_test_package_version(script, version_pkg_path)
C
Chris Jerdonek 已提交
262

263
    version = _install_version_pkg(script, version_pkg_path)
264
    assert 'some different version' == version
C
Chris Jerdonek 已提交
265 266

    # Now install the ref.
267
    version = _install_version_pkg(
268
        script, version_pkg_path, rev='refs/foo/bar',
269 270
    )
    assert '0.1' == version
271 272


273
@pytest.mark.network
274
def test_git_with_tag_name_and_update(script, tmpdir):
275 276 277
    """
    Test cloning a git repository and updating to a different version.
    """
278
    url_path = 'pypa/pip-test-package.git'
279 280 281
    base_local_url = _github_checkout(url_path, tmpdir)

    local_url = '{}#egg=pip-test-package'.format(base_local_url)
282
    result = script.pip('install', '-e', local_url)
283
    result.assert_installed('pip-test-package', with_files=['.git'])
284

285
    new_local_url = '{}@0.1.2#egg=pip-test-package'.format(base_local_url)
286
    result = script.pip(
287
        'install', '--global-option=--version', '-e', new_local_url,
288
    )
289
    assert '0.1.2' in result.stdout
290

291

292
@pytest.mark.network
293
def test_git_branch_should_not_be_changed(script, tmpdir):
294 295 296 297
    """
    Editable installations should not change branch
    related to issue #32 and #161
    """
298 299
    url_path = 'pypa/pip-test-package.git'
    local_url = _github_checkout(url_path, tmpdir, egg='pip-test-package')
300
    script.pip('install', '-e', local_url)
301 302
    branch = _get_editable_branch(script, 'pip-test-package')
    assert 'master' == branch
303

304

305
@pytest.mark.network
306
def test_git_with_non_editable_unpacking(script, tmpdir):
307 308 309
    """
    Test cloning a git repository from a non-editable URL with a given tag.
    """
310 311 312
    url_path = 'pypa/pip-test-package.git'
    local_url = _github_checkout(
        url_path, tmpdir, rev='0.1.2', egg='pip-test-package',
313
    )
314
    result = script.pip('install', '--global-option=--version', local_url)
315
    assert '0.1.2' in result.stdout
316

317

318
@pytest.mark.network
319
def test_git_with_editable_where_egg_contains_dev_string(script, tmpdir):
320
    """
321 322
    Test cloning a git repository from an editable url which contains "dev"
    string
323
    """
324 325 326 327
    url_path = 'dcramer/django-devserver.git'
    local_url = _github_checkout(
        url_path, tmpdir, egg='django-devserver', scheme='git',
    )
328
    result = script.pip('install', '-e', local_url)
329 330
    result.assert_installed('django-devserver', with_files=['.git'])

331

332
@pytest.mark.network
333
def test_git_with_non_editable_where_egg_contains_dev_string(script, tmpdir):
334
    """
335 336
    Test cloning a git repository from a non-editable url which contains "dev"
    string
337
    """
338 339 340 341
    url_path = 'dcramer/django-devserver.git'
    local_url = _github_checkout(
        url_path, tmpdir, egg='django-devserver', scheme='git',
    )
342
    result = script.pip('install', local_url)
D
Donald Stufft 已提交
343
    devserver_folder = script.site_packages / 'devserver'
344
    assert devserver_folder in result.files_created, str(result)
345 346


347
def test_git_with_ambiguous_revs(script):
348 349 350
    """
    Test git with two "names" (tag/branch) pointing to the same commit
    """
D
Donald Stufft 已提交
351
    version_pkg_path = _create_test_package(script)
352
    version_pkg_url = _make_version_pkg_url(version_pkg_path, rev='0.1')
D
Donald Stufft 已提交
353
    script.run('git', 'tag', '0.1', cwd=version_pkg_path)
354
    result = script.pip('install', '-e', version_pkg_url)
355 356 357 358
    assert 'Could not find a tag or branch' not in result.stdout
    # it is 'version-pkg' instead of 'version_pkg' because
    # egg-link name is version-pkg.egg-link because it is a single .py module
    result.assert_installed('version-pkg', with_files=['.git'])
R
test  
Rory McCann 已提交
359

360

C
Chris Jerdonek 已提交
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
def test_editable__no_revision(script):
    """
    Test a basic install in editable mode specifying no revision.
    """
    version_pkg_path = _create_test_package(script)
    _install_version_pkg_only(script, version_pkg_path)

    branch = _get_editable_branch(script, 'version-pkg')
    assert branch == 'master'

    remote = _get_branch_remote(script, 'version-pkg', 'master')
    assert remote == 'origin'


def test_editable__branch_with_sha_same_as_default(script):
    """
    Test installing in editable mode a branch whose sha matches the sha
378
    of the default branch, but is different from the default branch.
C
Chris Jerdonek 已提交
379 380 381
    """
    version_pkg_path = _create_test_package(script)
    # Create a second branch with the same SHA.
382 383
    script.run('git', 'branch', 'develop', cwd=version_pkg_path)
    _install_version_pkg_only(script, version_pkg_path, rev='develop')
C
Chris Jerdonek 已提交
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398

    branch = _get_editable_branch(script, 'version-pkg')
    assert branch == 'develop'

    remote = _get_branch_remote(script, 'version-pkg', 'develop')
    assert remote == 'origin'


def test_editable__branch_with_sha_different_from_default(script):
    """
    Test installing in editable mode a branch whose sha is different from
    the sha of the default branch.
    """
    version_pkg_path = _create_test_package(script)
    # Create a second branch.
399
    script.run('git', 'branch', 'develop', cwd=version_pkg_path)
C
Chris Jerdonek 已提交
400 401 402
    # Add another commit to the master branch to give it a different sha.
    _change_test_package_version(script, version_pkg_path)

403
    version = _install_version_pkg(script, version_pkg_path, rev='develop')
C
Chris Jerdonek 已提交
404 405 406 407 408 409 410 411 412 413
    assert version == '0.1'

    branch = _get_editable_branch(script, 'version-pkg')
    assert branch == 'develop'

    remote = _get_branch_remote(script, 'version-pkg', 'develop')
    assert remote == 'origin'


def test_editable__non_master_default_branch(script):
414 415 416 417 418 419 420
    """
    Test the branch you get after an editable install from a remote repo
    with a non-master default branch.
    """
    version_pkg_path = _create_test_package(script)
    # Change the default branch of the remote repo to a name that is
    # alphabetically after "master".
421
    script.run('git', 'checkout', '-b', 'release', cwd=version_pkg_path)
422
    _install_version_pkg_only(script, version_pkg_path)
C
Chris Jerdonek 已提交
423

424
    branch = _get_editable_branch(script, 'version-pkg')
C
Chris Jerdonek 已提交
425
    assert branch == 'release'
426 427 428


def test_reinstalling_works_with_editable_non_master_branch(script):
429 430 431 432 433 434 435 436 437
    """
    Reinstalling an editable installation should not assume that the "master"
    branch exists. See https://github.com/pypa/pip/issues/4448.
    """
    version_pkg_path = _create_test_package(script)

    # Switch the default branch to something other than 'master'
    script.run('git', 'branch', '-m', 'foobar', cwd=version_pkg_path)

438 439
    version = _install_version_pkg(script, version_pkg_path)
    assert '0.1' == version
440 441

    _change_test_package_version(script, version_pkg_path)
442 443
    version = _install_version_pkg(script, version_pkg_path)
    assert 'some different version' == version
444 445 446 447 448 449 450 451


# TODO(pnasrat) fix all helpers to do right things with paths on windows.
@pytest.mark.skipif("sys.platform == 'win32'")
def test_check_submodule_addition(script):
    """
    Submodules are pulled in on install and updated on upgrade.
    """
452 453 454
    module_path, submodule_path = (
        _create_test_package_with_submodule(script, rel_path='testpkg/static')
    )
455 456 457 458 459 460 461 462 463 464

    install_result = script.pip(
        'install', '-e', 'git+' + module_path + '#egg=version_pkg'
    )
    assert (
        script.venv / 'src/version-pkg/testpkg/static/testfile'
        in install_result.files_created
    )

    _change_test_package_submodule(script, submodule_path)
465 466 467
    _pull_in_submodule_changes_to_module(
        script, module_path, rel_path='testpkg/static',
    )
468 469 470 471 472 473 474 475 476 477 478

    # expect error because git may write to stderr
    update_result = script.pip(
        'install', '-e', 'git+' + module_path + '#egg=version_pkg',
        '--upgrade',
    )

    assert (
        script.venv / 'src/version-pkg/testpkg/static/testfile2'
        in update_result.files_created
    )