Exemplo n.º 1
0
def test_destroy_and_multiple_remotes(mock_repo, monkeypatch):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN destroy_and_reclone is called
    AND the repo has multiple remotes
    THEN Repo.clone_from is called
    AND create_remote is called
    """
    monkeypatch.setattr(shutil, 'rmtree', Mock())
    clone = GitRepo(repo=mock_repo)
    local_dir = '/tmp/8f697668fgitwrappertest'
    clone.repo.working_dir = local_dir

    remote = Mock(spec=git.Remote)
    remote.configure_mock(name="otherremote", url="http://example.com/another")
    clone.repo.remotes.append(remote)

    with patch('git.repo.base.Repo.clone_from') as mock_clone:
        new_repo_mock = Mock()
        mock_clone.return_value = new_repo_mock
        clone.destroy_and_reclone()
        assert mock_clone.called is True
        mock_clone.assert_called_with('http://example.com',
                                      local_dir,
                                      bare=False)
        new_repo_mock.create_remote.assert_called_with(
            "otherremote",
            "http://example.com/another"
        )
Exemplo n.º 2
0
def test_bare_clone():
    """
    GIVEN GitRepo without a path or repo
    WHEN clone is called with valid parameters and bare set to True
    THEN Repo.clone_from is called with bare=True
    """
    with patch('git.repo.base.Repo.clone_from') as mock_clone:
        GitRepo.clone('./', './testclone', True)
        mock_clone.assert_called_with('./', ANY, bare=True)
Exemplo n.º 3
0
def test_branch_setter_wrong_type(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN the branch setter is called with the wrong type
    THEN a TypeError is raised
    """
    repo = GitRepo('./', mock_repo)
    with pytest.raises(TypeError):
        repo.branch = repo
Exemplo n.º 4
0
def test_destroy_no_path_no_repo(monkeypatch):
    """
    GIVEN GitRepo initialized with no path or repo object
    WHEN destroy_and_reclone is called
    THEN an exception is raised
    """
    monkeypatch.setattr(shutil, 'rmtree', Mock())
    with pytest.raises(Exception):
        clone = GitRepo('', None)
        clone.destroy_and_reclone()
Exemplo n.º 5
0
def test_tag_setter(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN the tag setter is called
    THEN the tag is set as expected
    """
    repo = GitRepo('./', mock_repo)
    new_tag = GitTag(git_repo=repo, logger=None)
    repo.tag = new_tag
    assert repo.tag == new_tag
Exemplo n.º 6
0
def test_commit_setter(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN the commit setter is called
    THEN the commit is set as expected
    """
    repo = GitRepo('./', mock_repo)
    new_commit = GitCommit(git_repo=repo, logger=None)
    repo.commit = new_commit
    assert repo.commit == new_commit
Exemplo n.º 7
0
def test_remote_setter(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN the remote setter is called
    THEN the remote is set as expected
    """
    repo = GitRepo('./', mock_repo)
    new_remote = GitRemote(git_repo=repo, logger=None)
    repo.remote = new_remote
    assert repo.remote == new_remote
Exemplo n.º 8
0
def test_branch_setter(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN the branch setter is called
    THEN the branch is set as expected
    """
    repo = GitRepo('./', mock_repo)
    new_branch = GitBranch(git_repo=repo, logger=None)
    repo.branch = new_branch
    assert repo.branch == new_branch
Exemplo n.º 9
0
def test_clone_failed():
    """
    GIVEN GitRepo without a path or repo
    WHEN clone is called with a valid clone_from URL and clone_to path
    AND Repo.clone_from fails with an exception
    THEN a RepoCreationException is raised
    """
    with patch('git.repo.base.Repo.clone_from') as mock_clone:
        mock_clone.side_effect = git.GitCommandError('clone', '')
        with pytest.raises(exceptions.RepoCreationException):
            GitRepo.clone('./', './testclone')
Exemplo n.º 10
0
def test_destroy_no_remotes(mock_repo, monkeypatch):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN destroy_and_reclone is called
    AND the repo does not have any remotes configured
    THEN an exception is raised
    """
    monkeypatch.setattr(shutil, 'rmtree', Mock())
    clone = GitRepo(repo=mock_repo)

    with pytest.raises(exceptions.RepoCreationException):
        clone.repo.remotes = {}
        clone.destroy_and_reclone()
Exemplo n.º 11
0
def test_rebase_doesnt_push_in_dev_mode(local_repo, patches_repo_root):
    """
    GIVEN a local repository initialized with origin and upstream remotes
    WHEN running Rebaser.rebase_and_update_remote
    WITH dev_mode set to True
    THEN the local repo is rebased
    AND the origin remote is not updated with the rebase results
    """
    patches_repo = GitRepo(patches_repo_root)
    commit_to_rebase_to = "61a18a2a"

    # confirm we are the same as the patches repo
    orig_local_repo_head = local_repo.repo.head.object.hexsha
    assert patches_repo.repo.head.object.hexsha == orig_local_repo_head

    # Rebase with dev_mode on
    rebaser = Rebaser(local_repo, "master", commit_to_rebase_to, "origin",
                      "0000", True)
    rebaser.rebase_and_update_remote()

    # assert local repo was updated
    assert local_repo.repo.head.object.hexsha != orig_local_repo_head

    # assert remote repo was not updated
    assert patches_repo.repo.head.object.hexsha == orig_local_repo_head
Exemplo n.º 12
0
def test_rebase_avoid_pushing_unnecessary_tags(local_repo, patches_repo_root):
    """
    GIVEN a local repository initialized with origin and upstream remotes
    WHEN running Rebaser.rebase_and_update_remote
    AND the rebase history doesn't change
    THEN the newly created tag doesn't get pushed to the remote
    """
    patches_repo = GitRepo(patches_repo_root)
    commit_to_rebase_to = "61a18a2a"

    # Rebase
    rebaser = Rebaser(local_repo, "master", commit_to_rebase_to, "origin",
                      "0000", False)
    rebaser.rebase_and_update_remote()

    # Assert remote repo was updated with the rebase result
    rebased_head = local_repo.repo.head.commit.hexsha
    assert patches_repo.repo.head.commit.hexsha == rebased_head

    # Run another rebase - no changes but new timestamp
    rebaser = Rebaser(local_repo, "master", commit_to_rebase_to, "origin",
                      "0001", False)
    rebaser.rebase_and_update_remote()

    # Check the first tag was pushed, but not the second one
    patches_repo.commit.describe("private-rebaser-0000-previous")
    try:
        patches_repo.commit.describe("private-rebaser-0001-previous")
        pytest.fail("Tag was pushed when it shouldn't have")
    except gw_exceptions.ReferenceNotFoundException:
        pass
Exemplo n.º 13
0
def main():
    # These variables are set up by DLRN
    user = os.environ['DLRN_USER']
    local_repo = os.environ['DLRN_SOURCEDIR']
    commit = os.environ['DLRN_SOURCE_COMMIT']
    distroinfo_repo = os.environ['DLRN_DISTROINFO_REPO']
    pkg_name = os.environ['DLRN_PACKAGE_NAME']

    # The next variables come from patch_rebaser.ini
    rebaser_config = get_rebaser_config()
    remote = rebaser_config.get('DEFAULT', 'remote_name')
    git_name = rebaser_config.get('DEFAULT', 'git_name')
    git_email = rebaser_config.get('DEFAULT', 'git_email')
    patches_repo_key = rebaser_config.get('distroinfo', 'patches_repo_key')
    pkg_to_process = rebaser_config.get('DEFAULT', 'packages_to_process')

    if pkg_to_process:
        if "," in pkg_to_process:
            pkg_to_process = pkg_to_process.split(",")
        else:
            pkg_to_process = [pkg_to_process]

        if pkg_name not in pkg_to_process:
            LOGGER.info(
                "Skipping %s, as package not in list of packages_to_process",
                pkg_name)
            return

    set_up_git_config(git_name, git_email)

    repo = GitRepo(local_repo)

    # Create a remote for the patches branch
    patches_repo = get_patches_repo(distroinfo_repo, pkg_name,
                                    patches_repo_key)
    if not patches_repo:
        return

    if remote not in repo.remote.names():
        if not repo.remote.add(remote, patches_repo):
            raise Exception("Could not add remote {0} ({1})".format(
                remote, patches_repo))
    repo.remote.fetch_all()

    # Create local patches branch
    branch = get_patches_branch(repo, remote, user)

    # Not every project has a -patches branch for every release
    if not branch:
        # TODO: (future) Create and set up patches branch
        return

    remote_branch = "{remote}/{branch}".format(remote=remote, branch=branch)
    repo.branch.create(branch, remote_branch, reset_if_exists=True)

    # Rebase
    LOGGER.info("Rebasing %s to %s", branch, commit)
    repo.branch.rebase_to_hash(branch, commit)
    LOGGER.info("Rebasing %s to %s", branch, remote_branch)
    repo.branch.rebase_to_hash(branch, remote_branch)
Exemplo n.º 14
0
def test_log_grep(repo_root):
    repo = GitRepo(repo_root)

    commits = repo.log.grep_for_commits('master', "Initial commit")

    assert len(commits) == 1
    assert commits[0] == "ba82064c5fea1fc40270fb2748d5d8a783397609"
Exemplo n.º 15
0
def test_fetch_all_with_errors(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN remote.fetch_all is called
    AND one remote fails
    THEN the other remotes still fetch
    AND an exception is raised
    """
    mock_remoteA, mock_remoteB, mock_remoteC = Mock(), Mock(), Mock()
    mock_remoteA.fetch.side_effect = git.GitCommandError("fetch", "")
    mock_remotes = {
        "origin": mock_remoteA,
        "a_remote": mock_remoteB,
        "other": mock_remoteC
    }
    mock_repo.remote = lambda r: mock_remotes[r]

    repo = GitRepo(repo=mock_repo)
    repo.remote.names = Mock(return_value=["origin", "a_remote", "other"])

    with pytest.raises(exceptions.RemoteException) as exc_info:
        repo.remote.fetch_all()

    assert 'origin' in str(exc_info.value)
    assert mock_remoteA.fetch.called is True
    assert mock_remoteB.fetch.called is True
    assert mock_remoteC.fetch.called is True
Exemplo n.º 16
0
def test_reset(repo_root):
    repo = GitRepo(repo_root)
    branch_name = "test_reset"

    # Exercise repo refresh
    repo.remote.fetch("origin")

    # Save the current reference to origin/master
    reset_to_commit = git.repo.fun.name_to_object(repo.repo, "origin/master")

    # Create a new branch based on an old commit
    repo.git.branch(branch_name, "0.0.1")

    # Ensure branch head is different from the one we saved
    branch_commit = repo.repo.branches[branch_name].commit
    assert branch_commit.hexsha != reset_to_commit.hexsha

    # Reset the branch to origin/master
    repo.branch.hard_reset(
        refresh=False,  # Avoid race condition if something new merged
        branch=branch_name,
        remote="origin",
        remote_branch="master")

    # Ensure the new head matches the origin/master we saved
    branch_commit = repo.repo.branches[branch_name].commit
    assert branch_commit.hexsha == reset_to_commit.hexsha
Exemplo n.º 17
0
def test_log_grep_empty(repo_root):
    repo = GitRepo(repo_root)

    commits = repo.log.grep_for_commits('master', "somethingthatcannotbefound",
                                        True)

    assert len(commits) == 0
Exemplo n.º 18
0
def test_log_grep_with_path(repo_root):
    repo = GitRepo(repo_root)

    commits = repo.log.grep_for_commits('master',
                                        "structure",
                                        path=".gitignore")

    assert len(commits) == 1
Exemplo n.º 19
0
def test_not_path_no_repo():
    """
    GIVEN GitRepo initialized with no path or repo object
    WHEN the object is created
    THEN an exception is raised
    """
    with pytest.raises(Exception):
        GitRepo('', None)
Exemplo n.º 20
0
def test_log_diff_wrong_hash(repo_root):
    repo = GitRepo(repo_root)

    with pytest.raises(exceptions.ReferenceNotFoundException):
        repo.branch.log_diff("0.1.0", "123456789z")

    with pytest.raises(exceptions.ReferenceNotFoundException):
        repo.branch.log_diff("123456789z", "0.1.0")
Exemplo n.º 21
0
def test_log_show_commit(repo_root):
    repo = GitRepo(repo_root)
    commit = repo.log.log_show_commit(
        'ba82064c5fea1fc40270fb2748d5d8a783397609')
    assert commit == ('commit ba82064c5fea1fc40270fb2748d5d8a783397609\n'
                      'Author: Jason Joyce <*****@*****.**>\n'
                      'Date: Tue Jun 12 14:21:45 2018 -0400\n\n'
                      'Initial commit of README.rst\n')
Exemplo n.º 22
0
 def apply_inflight_patch():
     tmp_repo_root = "/tmp/test_retry"
     if os.path.exists(tmp_repo_root):
         # We already applied the inflight patch
         return
     else:
         tmp_repo = GitRepo.clone(patches_repo_root, tmp_repo_root)
         tmp_repo.branch.apply_patch("master", (datadir / "inflight.patch"))
         tmp_repo.git.push("origin", "master")
Exemplo n.º 23
0
def test_destroy_and_reclone(mock_repo, monkeypatch):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN destroy_and_reclone is called
    THEN Repo.clone_from is called
    WITH the expected remote url and local working dir
    """
    monkeypatch.setattr(shutil, 'rmtree', Mock())
    clone = GitRepo(repo=mock_repo)
    local_dir = '/tmp/8f697668fgitwrappertest'
    clone.repo.working_dir = local_dir

    with patch('git.repo.base.Repo.clone_from') as mock_clone:
        clone.destroy_and_reclone()
        assert mock_clone.called is True
        mock_clone.assert_called_with('http://example.com',
                                      local_dir,
                                      bare=False)
Exemplo n.º 24
0
def test_git_command(mock_repo):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN the git property is called
    THEN a git object is returned
    """
    git_util = GitRepo('./', mock_repo)

    assert mock_repo.git is git_util.git
Exemplo n.º 25
0
def test_branch_exists_with_invalid_remote(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN branch.exists is called with a valid branch and invalid remote
    THEN a RemoteException is raised
    """
    repo = GitRepo(repo=mock_repo)

    with pytest.raises(exceptions.RemoteException):
        assert repo.branch.exists("another", "doesntexist")
Exemplo n.º 26
0
def test_local_branch_doesnt_exist(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN branch.exists is called with an invalid branch and None remote
    THEN False is returned
    """
    repo = GitRepo(repo=mock_repo)
    mock_repo.branches = ["master", "test"]

    assert repo.branch.exists("another-test") is False
Exemplo n.º 27
0
def test_local_branch_exists(mock_repo):
    """
    GIVEN GitRepo is initialized with a path and repo
    WHEN branch.exists is called with a valid branch and None remote
    THEN True is returned
    """
    repo = GitRepo(repo=mock_repo)
    mock_repo.branches = ["master", "test"]

    assert repo.branch.exists("test") is True
Exemplo n.º 28
0
def test_reverse_diff(mock_repo):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN reverse_diff is called with a valid diff_path
    THEN git.am called
    """
    repo = GitRepo('./', mock_repo)

    repo.branch.reverse_diff('./requirements.txt')
    assert repo.git.apply.called is True
Exemplo n.º 29
0
def test_abort_patch_apply(mock_repo):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN abort_patch_apply is called
    THEN git.am called
    """
    repo = GitRepo('./', mock_repo)

    repo.branch.abort_patch_apply()
    assert repo.git.am.called is True
Exemplo n.º 30
0
def test_abort_rebase(mock_repo):
    """
    GIVEN GitRepo initialized with a path and repo
    WHEN branch.abort_rebase is called
    THEN git.rebase called
    """
    repo = GitRepo('./', mock_repo)

    repo.branch.abort_rebase()
    assert repo.repo.git.rebase.called is True