def test_workspace_recovery(server, tmpdir):
    """Test that we can detect and recover from various workspace snafus"""
    repo = P4Repo(
        root=tmpdir,
        # allow unit test to delete otherwise readonly files from workspace
        client_options='allwrite')

    # clobber writeable file
    # partially synced writeable files may be left in the workspace if a machine was shutdown mid-sync
    with open(os.path.join(tmpdir, "file.txt"), 'w') as depotfile:
        depotfile.write("Overwrite this file")
    repo.sync()  # By default, would raise 'cannot clobber writable file'
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"

    # p4 clean
    os.remove(os.path.join(tmpdir, "file.txt"))
    open(os.path.join(tmpdir, "added.txt"), 'a').close()
    repo.clean()
    assert sorted(os.listdir(tmpdir)) == sorted(
        ["file.txt",
         "p4config"]), "Failed to restore workspace file with repo.clean()"

    os.remove(os.path.join(tmpdir, "file.txt"))
    os.remove(os.path.join(tmpdir, "p4config"))
    repo = P4Repo(
        root=tmpdir)  # Open a fresh tmpdir, as if this was a different job
    repo.sync(
    )  # Normally: "You already have file.txt", but since p4config is missing it will restore the workspace
    assert sorted(os.listdir(tmpdir)) == sorted([
        "file.txt", "p4config"
    ]), "Failed to restore corrupt workspace due to missing p4config"
def test_modify_client_type(server, tmpdir):
    """Test modifying a clients type"""
    repo = P4Repo(root=tmpdir, client_type='writeable')
    repo.sync()

    with pytest.raises(
            Exception,
            match=
            r'Client storage type cannot be changed after client is created'):
        repo = P4Repo(root=tmpdir, client_type='readonly')
        repo.sync()
def test_head(server, tmpdir):
    """Test resolve of HEAD changelist"""
    repo = P4Repo(root=tmpdir)
    assert repo.head() == "@6", "Unexpected global HEAD revision"

    repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
    assert repo.head() == "@2", "Unexpected HEAD revision for stream"

    repo = P4Repo(root=tmpdir, stream='//stream-depot/idontexist')
    with pytest.raises(
            Exception,
            match=r"Stream '//stream-depot/idontexist' doesn't exist."):
        repo.head()
def test_client_migration(server, tmpdir):
    """Test re-use of workspace data when moved to another host"""
    repo = P4Repo(root=tmpdir)

    assert os.listdir(tmpdir) == [], "Workspace should be empty"
    synced = repo.sync()
    assert len(synced) > 0, "Didn't sync any files"

    with tempfile.TemporaryDirectory(prefix="bk-p4-test-") as second_client:
        copytree(tmpdir, second_client)
        # Client names include path on disk, so this creates a new unique client
        repo = P4Repo(root=second_client)
        synced = repo.sync(
        )  # Flushes to match previous client, since p4config is there on disk
        assert synced == [], "Should not have synced any files in second client"
def test_fingerprint_changed(server, tmpdir):
    """Test updating a fingerprint"""
    os.environ['P4TRUST'] = os.path.join(tmpdir, 'trust.txt')

    repo = P4Repo(
        root=tmpdir,
        fingerprint=
        'FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF')
    with pytest.raises(Exception,
                       match=r"The authenticity of '.*' can't be established"):
        repo.sync()

    repo = P4Repo(root=tmpdir, fingerprint=__LEGIT_P4_FINGERPRINT__)
    synced = repo.sync()
    assert len(synced) > 0, "Didn't sync any files"
def main():
    """Main"""
    os.environ.update(get_env())
    config = get_config()

    repo = P4Repo(**config)

    revision = get_build_revision()
    if revision == 'HEAD':
        # Resolve HEAD to a concrete revision
        revision = repo.head()
        set_build_revision(revision)

    # Convert changelist number to revision specifier
    if re.match(r'^\d*$', revision):
        revision = '@%s' % revision

    repo.sync(revision=revision)

    user_changelist = get_users_changelist()
    if user_changelist:
        # Use existing or make a copy of the users changelist for this build
        changelist = get_build_changelist()
        if not changelist:
            changelist = user_changelist
            if should_backup_changelists():
                changelist = repo.backup(user_changelist)
            set_build_changelist(changelist)

        repo.p4print_unshelve(changelist)

    revision = get_build_revision()
    description = repo.description(get_users_changelist()
                                   or revision.strip('@'))
    set_build_info(revision, description)
def test_stream_switching(server, tmpdir):
    """Test stream-switching within the same depot"""
    repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
    synced = repo.sync()
    assert len(synced) > 0, "Didn't sync any files"
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello Stream World\n", "Unexpected content in workspace file"

    # Re-use the same checkout directory, but switch streams
    repo = P4Repo(root=tmpdir, stream='//stream-depot/dev')
    repo.sync()
    assert len(synced) > 0, "Didn't sync any files"
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello Stream World (dev)\n", "Unexpected content in workspace file"
def test_unshelve(server, tmpdir):
    """Test unshelving a pending changelist"""
    repo = P4Repo(root=tmpdir)
    repo.sync()
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"

    repo.unshelve('3')  # Modify a file
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Goodbye World\n", "Unexpected content in workspace file"
    repo.sync()

    repo.unshelve('4')  # Delete a file
    assert not os.path.exists(os.path.join(tmpdir, "file.txt"))
    repo.sync()

    repo.unshelve('5')  # Add a file
    assert os.path.exists(os.path.join(tmpdir, "newfile.txt"))
    repo.sync()

    with pytest.raises(
            Exception,
            match=r'Changelist 999 does not contain any shelved files.'):
        repo.unshelve('999')

    # Unshelved changes are removed in following syncs
    repo.sync()
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"
    assert not os.path.exists(os.path.join(
        tmpdir, "newfile.txt")), "File unshelved for add was not deleted"
def test_fingerprint_good(server, tmpdir):
    """Test supplying the correct fingerprint"""
    os.environ['P4TRUST'] = os.path.join(tmpdir, 'trust.txt')

    repo = P4Repo(root=tmpdir, fingerprint=__LEGIT_P4_FINGERPRINT__)
    synced = repo.sync()
    assert len(synced) > 0, "Didn't sync any files"
def test_client_migration():
    """Test re-use of workspace data when moved to another host"""
    with setup_server_and_client() as client_root:
        repo = P4Repo(root=client_root)

        assert os.listdir(client_root) == [], "Workspace should be empty"
        synced = repo.sync()
        assert len(synced) > 0, "Didn't sync any files"

        with tempfile.TemporaryDirectory(
                prefix="bk-p4-test-") as second_client_root:
            copytree(client_root, second_client_root)
            repo = P4Repo(root=second_client_root)
            synced = repo.sync(
            )  # Flushes to match previous client, since p4config is there on disk
            assert synced == [], "Should not have synced any files in second client"
Esempio n. 11
0
def main():
    """Main"""
    os.environ.update(get_env())
    config = get_config()

    repo = P4Repo(**config)

    revision = get_build_revision()
    if revision is None:
        revision = repo.head()
        set_build_revision(revision)

    repo.sync(revision=revision)

    user_changelist = get_users_changelist()
    if user_changelist:
        # Use existing or make a copy of the users changelist for this build
        changelist = get_build_changelist()
        if not changelist:
            changelist = user_changelist
            if should_backup_changelists():
                changelist = repo.backup(user_changelist)
            set_build_changelist(changelist)

        repo.p4print_unshelve(changelist)

    description = repo.description(
        # Prefer users change description over latest submitted change
        get_users_changelist() or repo.head_at_revision(revision))
    set_build_info(revision, description)
def test_head(server, tmpdir):
    """Test resolve of HEAD changelist"""
    # workspace with no changes in view defaults to global view
    repo = P4Repo(root=tmpdir, view="//depot/empty_dir/... empty_dir/...")
    assert repo.head() == "@9", "Unexpected global HEAD revision"

    repo = P4Repo(root=tmpdir, stream='//stream-depot/dev')
    assert repo.head() == "@8", "Unexpected HEAD revision for stream"

    repo = P4Repo(root=tmpdir, stream='//stream-depot/idontexist')
    with pytest.raises(
            Exception,
            match=r"Stream '//stream-depot/idontexist' doesn't exist."):
        repo.head()

    assert repo.head_at_revision(
        "@my-label") == "2", "Unexpected HEAD revision for label"
def main():
    """Perform any last-second cleanup regardless of success or failure"""
    os.environ.update(get_env())
    config = get_config()

    repo = P4Repo(**config)

    repo.revert()
def test_checkout_stream(server, tmpdir):
    """Test checking out a stream depot"""
    repo = P4Repo(root=tmpdir, stream='//stream-depot/main')

    assert os.listdir(tmpdir) == [], "Workspace should be empty"
    repo.sync()
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello Stream World\n", "Unexpected content in workspace file"
def test_p4print_unshelve(server, tmpdir):
    """Test unshelving a pending changelist by p4printing content into a file"""
    repo = P4Repo(root=tmpdir)
    repo.sync()
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"

    repo.p4print_unshelve('3')  # Modify a file
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Goodbye World\n", "Unexpected content in workspace file"

    repo.p4print_unshelve('4')  # Delete a file
    assert not os.path.exists(os.path.join(tmpdir, "file.txt"))

    repo.p4print_unshelve('5')  # Add a file
    assert os.path.exists(os.path.join(tmpdir, "newfile.txt"))

    with pytest.raises(
            Exception,
            match=r'Changelist 999 does not contain any shelved files.'):
        repo.p4print_unshelve('999')

    assert len(
        repo._read_patched()) == 2  # changes to file.txt and newfile.txt

    # Unshelved changes are removed in following syncs
    repo.sync()
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"
    assert not os.path.exists(os.path.join(
        tmpdir, "newfile.txt")), "File unshelved for add was not deleted"

    # Shelved changes containing files not selected for sync are skipped
    repo = P4Repo(root=tmpdir, sync=['//depot/fake-dir/...'])
    repo.sync()
    repo.p4print_unshelve('3')  # Modify file.txt
    assert not os.path.exists(os.path.join(tmpdir, "file.txt"))

    # Shelved changes containing files not mapped into this workspace do not throw an exception
    repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
    repo.p4print_unshelve('3')  # Modify a file
def test_checkout_stream():
    """Test checking out a stream depot"""
    with setup_server_and_client() as client_root:
        repo = P4Repo(root=client_root, stream='//stream-depot/main')

        assert os.listdir(client_root) == [], "Workspace should be empty"
        repo.sync()
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Hello Stream World\n", "Unexpected content in workspace file"
def test_backup_shelve(server, tmpdir):
    """Test making a copy of a shelved changelist"""
    repo = P4Repo(root=tmpdir)

    backup_changelist = repo.backup('3')
    assert backup_changelist != '3', "Backup changelist number must be new"
    repo.revert()
    repo.unshelve(backup_changelist)
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Goodbye World\n", "Unexpected content in workspace file"
def test_fingerprint_bad(server, tmpdir):
    """Test supplying an incorrect fingerprint"""
    os.environ['P4TRUST'] = os.path.join(tmpdir, 'trust.txt')

    repo = P4Repo(
        root=tmpdir,
        fingerprint=
        'FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF:FF')
    with pytest.raises(Exception,
                       match=r"The authenticity of '.+' can't be established"):
        repo.sync()
def test_checkout_label(server, tmpdir):
    """Test checking out at a specific label"""
    repo = P4Repo(root=tmpdir)

    with pytest.raises(Exception,
                       match=r'Invalid changelist/client/label/date'):
        repo.sync(revision="@nonexistent-label")

    repo.sync(revision="@my-label")
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"
def test_p4print_unshelve():
    """Test unshelving a pending changelist by p4printing content into a file"""
    with setup_server_and_client() as client_root:
        repo = P4Repo(root=client_root)
        repo.sync()
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Hello World\n", "Unexpected content in workspace file"

        repo.p4print_unshelve('3')  # Modify a file
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Goodbye World\n", "Unexpected content in workspace file"

        repo.p4print_unshelve('4')  # Delete a file
        assert not os.path.exists(os.path.join(client_root, "file.txt"))

        repo.p4print_unshelve('5')  # Add a file
        assert os.path.exists(os.path.join(client_root, "newfile.txt"))

        with pytest.raises(
                Exception,
                match=r'Changelist 999 does not contain any shelved files.'):
            repo.p4print_unshelve('999')

        assert len(
            repo._read_patched()) == 2  # changes to file.txt and newfile.txt

        # Unshelved changes are removed in following syncs
        repo.sync()
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Hello World\n", "Unexpected content in workspace file"
        assert not os.path.exists(os.path.join(client_root, "newfile.txt"))

        # Shelved changes containing files not mapped into this workspace do not throw an exception
        repo = P4Repo(root=client_root, stream='//stream-depot/main')
        repo.p4print_unshelve('3')  # Modify a file
def test_stream_switching_migration(server, tmpdir):
    """Test stream-switching and client migration simultaneously"""
    repo = P4Repo(root=tmpdir, stream='//stream-depot/main')
    synced = repo.sync()
    assert len(synced) > 0, "Didn't sync any files"
    assert set(os.listdir(tmpdir)) == set(
        ["file.txt", "file_2.txt", "p4config"])
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello Stream World\n", "Unexpected content in workspace file"

    with tempfile.TemporaryDirectory(prefix="bk-p4-test-") as second_client:
        copytree(tmpdir, second_client)
        # Client names include path on disk, so this creates a new unique client
        # Re-use the same checkout directory and switch streams at the same time
        repo = P4Repo(root=second_client, stream='//stream-depot/dev')
        repo.sync()
        assert len(synced) > 0, "Didn't sync any files"
        assert set(os.listdir(second_client)) == set(
            ["file.txt", "p4config"])  # file_2.txt was de-synced
        with open(os.path.join(second_client, "file.txt")) as content:
            assert content.read(
            ) == "Hello Stream World (dev)\n", "Unexpected content in workspace file"
def test_fixture(capsys):
    """Check that tests can start and connect to a local perforce server"""
    port = setup_server(from_zip='server.zip')
    with capsys.disabled():
        print('port:', port, 'user: carl')
    repo = P4Repo()
    assert repo.info()['serverAddress'] == port

    # There should be a sample file checked into the fixture server
    # Returns [metadata, contents]
    content = repo.perforce.run_print("//depot/file.txt")[1]
    assert content == "Hello World\n"
    assert repo.head() == "2", "Unexpected head revision"

    shelved_change = repo.perforce.run_describe('-sS', '3')
    assert len(shelved_change) > 0, "Shelved changelist was missing"
    assert shelved_change[0]['depotFile'] == [
        '//depot/file.txt'
    ], "Unexpected files in shelved changelist"
def test_checkout(server, tmpdir):
    """Test normal flow of checking out files"""
    repo = P4Repo(root=tmpdir)

    assert os.listdir(tmpdir) == [], "Workspace should be empty"
    repo.sync()
    assert sorted(os.listdir(tmpdir)) == sorted(
        ["file.txt", "p4config"]), "Workspace sync not as expected"
    with open(os.path.join(tmpdir, "file.txt")) as content:
        assert content.read(
        ) == "Hello World\n", "Unexpected content in workspace file"

    repo.sync(revision='@0')
    assert "file.txt" not in os.listdir(
        tmpdir), "Workspace file wasn't de-synced"

    # Validate p4config
    with open(os.path.join(tmpdir, "p4config")) as content:
        assert "P4PORT=%s\n" % repo.perforce.port in content.readlines(
        ), "Unexpected p4config content"
def main():
    """Main"""
    os.environ.update(get_env())
    config = get_config()

    repo = P4Repo(**config)

    revision = get_build_revision()
    if revision is None:
        revision = repo.head()
        set_build_revision(revision)

    repo.sync(revision=revision)

    user_changelist = get_users_changelist()
    if user_changelist:
        repo.p4print_unshelve(user_changelist)

    description = repo.description(
        # Prefer users change description over latest submitted change
        user_changelist or repo.head_at_revision(revision))
    set_build_info(revision, description)
def test_unshelve():
    """Test unshelving a pending changelist"""
    with setup_server_and_client() as client_root:
        repo = P4Repo(root=client_root)
        repo.sync()
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Hello World\n", "Unexpected content in workspace file"

        repo.unshelve('3')
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Goodbye World\n", "Unexpected content in workspace file"

        with pytest.raises(
                Exception,
                match=r'Changelist 999 does not contain any shelved files.'):
            repo.unshelve('999')

        # Unshelved changes are removed in following syncs
        repo.sync()
        with open(os.path.join(client_root, "file.txt")) as content:
            assert content.read(
            ) == "Hello World\n", "Unexpected content in workspace file"
def test_checkout_partial_multiple(server, tmpdir):
    """Test checking out a subset of view with multiple paths"""
    repo = P4Repo(root=tmpdir,
                  sync=['//depot/fake-dir/...', '//depot/file.txt'])
    repo.sync()
    assert 'file.txt' in os.listdir(tmpdir)
def test_server_fixture(capsys, server):
    """Check that tests can start and connect to a local perforce server"""
    with capsys.disabled():
        print('port:', server, 'user: carl')
    repo = P4Repo()

    # To change the fixture server, uncomment the line below with 'store_server' and put a breakpoint on it
    # Run unit tests in the debugger and hit the breakpoint
    # Log in using details printed to stdout (port/user) via p4v or the command line
    # Make changes to the p4 server
    # Continue execution so that the 'store_server' line executes
    # Replace server.zip with new_server.zip
    # Update validation code below to document the new server contents

    # store_server(repo, 'new_server.zip')

    # Validate contents of server fixture @HEAD
    depotfiles = [
        info['depotFile'] for info in repo.perforce.run_files('//...')
    ]
    depotfile_to_content = {
        depotfile: repo.perforce.run_print(depotfile)[1]
        for depotfile in depotfiles
    }
    assert depotfile_to_content == {
        "//depot/file.txt": "Hello World\n",
        "//stream-depot/main/file.txt": "Hello Stream World\n",
        "//stream-depot/main/file_2.txt": "file_2\n",
        "//stream-depot/dev/file.txt": "Hello Stream World (dev)\n",
    }

    # Check submitted changes
    submitted_changes = repo.perforce.run_changes('-s', 'submitted')
    submitted_changeinfo = {
        change["change"]: repo.perforce.run_describe(change["change"])[0]
        for change in submitted_changes
    }
    # Filter info to only contain relevant keys for submitted changes
    submitted_changeinfo = {
        change:
        {key: info.get(key)
         for key in ['depotFile', 'desc', 'action']}
        for change, info in submitted_changeinfo.items()
    }
    assert submitted_changeinfo == {
        '1': {
            'action': ['add'],
            'depotFile': ['//depot/file.txt'],
            'desc': 'Initial Commit'
        },
        '2': {
            'action': ['add'],
            'depotFile': ['//stream-depot/main/file.txt'],
            'desc': 'Initial Commit to Stream\n'
        },
        '6': {
            'action': ['edit'],
            'depotFile': ['//depot/file.txt'],
            'desc': 'modify //depot/file.txt\n'
        },
        '7': {
            'action': ['branch'],
            'depotFile': ['//stream-depot/dev/file.txt'],
            'desc':
            'Copy files from //stream-depot/main to //stream-depot/dev\n'
        },
        '8': {
            'action': ['edit'],
            'depotFile': ['//stream-depot/dev/file.txt'],
            'desc': 'Update contents of //stream-depot/dev/file.txt\n'
        },
        '9': {
            'action': ['add'],
            'depotFile': ['//stream-depot/main/file_2.txt'],
            'desc': 'file_2.txt - exists in main but not dev\n'
        }
    }

    # Check shelved changes
    shelved_changes = repo.perforce.run_changes('-s', 'pending')
    shelved_changeinfo = {
        change["change"]: repo.perforce.run_describe('-S', change["change"])[0]
        for change in shelved_changes
    }
    # Filter info to only contain relevant keys for submitted changes
    shelved_changeinfo = {
        change:
        {key: info.get(key)
         for key in ['depotFile', 'desc', 'action']}
        for change, info in shelved_changeinfo.items()
    }
    assert shelved_changeinfo == {
        '3': {
            'action': ['edit'],
            'depotFile': ['//depot/file.txt'],
            'desc': 'Modify file in shelved change\n',
            # Change content from 'Hello World\n' to 'Goodbye World\n'
        },
        '4': {
            'action': ['delete'],
            'depotFile': ['//depot/file.txt'],
            'desc': 'Delete file in shelved change\n',
        },
        '5': {
            'action': ['add'],
            'depotFile': ['//depot/newfile.txt'],
            'desc': 'Add file in shelved change\n',
        },
    }

    labels = repo.perforce.run_labels()
    # Filter info to only contain relevant keys
    labelinfo = {
        label.get('label'): {key: label.get(key)
                             for key in ['Revision']}
        for label in labels
    }
    assert labelinfo == {'my-label': {'Revision': '@2'}}
def test_checkout_partial_dir(server, tmpdir):
    """Test checking out a subset of view with one directory"""
    repo = P4Repo(root=tmpdir, sync=['//depot/...'])
    repo.sync()
    assert 'file.txt' in os.listdir(tmpdir)
def test_partitioned_client(server, tmpdir):
    """Test creation of a partitioned client"""
    repo = P4Repo(root=tmpdir, client_type='partitioned')
    repo.sync()
    assert "file.txt" in os.listdir(tmpdir), "Workspace file was not synced"
def test_readonly_client(server, tmpdir):
    """Test creation of a readonly client"""
    repo = P4Repo(root=tmpdir, client_type='readonly')
    repo.sync()
    assert "file.txt" in os.listdir(tmpdir), "Workspace file was not synced"