def test_merge_conflict_basic(self, mock_labbook_lfs_disabled):
        """ Test a basic merge-conflict scenario with a conflict on one file.
            First, assert that a MergeConflict is raised when the conflict is detected
            Second, test the force flag to overwrite the conflict using the incoming branch."""
        lb = mock_labbook_lfs_disabled[2]

        # Insert a text file into the master branch of lb
        with open('/tmp/s1.txt', 'w') as s1:
            s1.write('original-file\ndata')
        FileOperations.insert_file(lb, section='code', src_file=s1.name)

        # Create a new branch from this point and make a change to s1.txt
        bm = BranchManager(lb, username=TEST_USER)
        feature_name = bm.create_branch("example-feature-branch")
        with open('/tmp/s1.txt', 'w') as s1:
            s1.write('new-changes-in\nfeature-branch')
        FileOperations.insert_file(lb, section='code', src_file=s1.name)

        # Switch back to the main branch and make a new, conflicting change.
        bm.workon_branch(bm.workspace_branch)
        assert lb.is_repo_clean
        assert not os.path.exists(os.path.join(lb.root_dir, 'output/sample'))
        with open('/tmp/s1.txt', 'w') as s1:
            s1.write('upstream-changes-from-workspace')
        FileOperations.insert_file(lb,
                                   section='code',
                                   src_file=s1.name,
                                   dst_path='')

        # Switch back to feature branch -- make sure that failed merges rollback to state before merge.
        bm.workon_branch(feature_name)
        cp = bm.repository.git.commit_hash
        try:
            bm.merge_from(bm.workspace_branch)
            assert False, "merge_from should have thrown conflict"
        except MergeConflict as m:
            # Assert that the conflicted file(s) are as expected
            assert m.file_conflicts == ['code/s1.txt']
        assert lb.is_repo_clean

        # Now try to force merge, and changes are taken from the workspace-branch
        bm.merge_use_ours(bm.workspace_branch)
        assert open(os.path.join(lb.root_dir, 'code', 's1.txt')).read(1000) == \
            'new-changes-in\nfeature-branch'
        assert lb.is_repo_clean

        # Reset this branch
        call_subprocess(f'git reset --hard {cp}'.split(),
                        cwd=bm.repository.root_dir)
        bm.merge_use_theirs(bm.workspace_branch)
        assert open(os.path.join(lb.root_dir, 'code', 's1.txt')).read(1000) == \
               'upstream-changes-from-workspace'
        assert lb.is_repo_clean
示例#2
0
 def resolve_is_local(self, info):
     lb = InventoryManager().load_labbook(get_logged_in_username(),
                                          self.owner,
                                          self.name)
     return self.branch_name in BranchManager(lb).branches_local
    def test_success_merge_from(self, mock_labbook_lfs_disabled):
        """ Test merging with nonconflicting changes. """
        lb = mock_labbook_lfs_disabled[2]
        bm = BranchManager(lb, username=TEST_USER)

        t = 'my-new-example-feature'
        feature_branch_name = bm.create_branch(title=t)
        assert bm.active_branch == feature_branch_name

        bm.workon_branch(bm.workspace_branch)
        FileOperations.makedir(lb,
                               'code/sillyfolder',
                               create_activity_record=True)
        FileOperations.makedir(lb,
                               'input/newfolder',
                               create_activity_record=True)

        bm.workon_branch(feature_branch_name)
        FileOperations.makedir(lb,
                               'output/otherdir',
                               create_activity_record=True)
        bm.merge_from(bm.workspace_branch)

        # Assert repo state is as we expect
        assert os.path.isdir(os.path.join(lb.root_dir, 'code/sillyfolder'))
        assert os.path.isdir(os.path.join(lb.root_dir, 'input/newfolder'))
        assert os.path.isdir(os.path.join(lb.root_dir, 'output/otherdir'))
        assert lb.is_repo_clean

        # Return to original branch and check proper state
        bm.workon_branch(bm.workspace_branch)
        assert os.path.isdir(os.path.join(lb.root_dir, 'code/sillyfolder'))
        assert os.path.isdir(os.path.join(lb.root_dir, 'input/newfolder'))
        assert not os.path.isdir(os.path.join(lb.root_dir, 'output/otherdir'))
        assert lb.is_repo_clean
    def test_link_unlink_dataset_across_branches(self, mock_labbook):
        """Test to verify linked Dataset initialization works across branching in Projects

        - Create a project
        - Create a dataset
        - Link dataset on master
        - Switch to another branch
        - Unlink dataset: dataset is gone
        - Switch to master: dataset is available
        - Switch to other branch: dataset is gone
        - Switch to master: dataset is available
        """
        inv_manager = InventoryManager(mock_labbook[0])
        lb = mock_labbook[2]
        ds = inv_manager.create_dataset("test",
                                        "test",
                                        "dataset100",
                                        "gigantum_object_v1",
                                        description="my dataset")

        # Fake publish to a local bare repo
        _MOCK_create_remote_repo2(ds, 'test', None, None)

        assert os.path.exists(os.path.join(lb.root_dir,
                                           '.gitmodules')) is False

        # link dataset and make sure it's there
        inv_manager.link_dataset_to_labbook(ds.remote, 'test', 'dataset100',
                                            lb)

        assert os.path.exists(os.path.join(lb.root_dir, '.gitmodules')) is True
        dataset_submodule_dir = os.path.join(lb.root_dir, '.gigantum',
                                             'datasets', 'test', 'dataset100')
        assert os.path.exists(dataset_submodule_dir) is True
        assert os.path.exists(os.path.join(dataset_submodule_dir,
                                           '.gigantum')) is True

        # Create a branch
        bm = BranchManager(lb, username="******")
        assert bm.active_branch == 'master'
        branch_name = bm.create_branch(title="test-branch")
        assert bm.active_branch == branch_name
        assert lb.is_repo_clean

        # Dataset still there
        assert os.path.exists(os.path.join(lb.root_dir, '.gitmodules')) is True
        dataset_submodule_dir = os.path.join(lb.root_dir, '.gigantum',
                                             'datasets', 'test', 'dataset100')
        assert os.path.exists(dataset_submodule_dir) is True
        assert os.path.exists(os.path.join(dataset_submodule_dir,
                                           '.gigantum')) is True

        # Unlink dataset in branch
        inv_manager.unlink_dataset_from_labbook('test', 'dataset100', lb)

        # Dataset gone
        dataset_submodule_dir = os.path.join(lb.root_dir, '.gigantum',
                                             'datasets', 'test', 'dataset100')
        assert os.path.exists(dataset_submodule_dir) is False
        assert os.path.exists(os.path.join(dataset_submodule_dir,
                                           '.gigantum')) is False
        with open(os.path.join(lb.root_dir, '.gitmodules'), 'rt') as mf:
            data = mf.read()

        assert len(data) == 0

        # Switch back to master
        bm.workon_branch('master')
        assert bm.active_branch == 'master'
        assert lb.active_branch == 'master'
        assert lb.is_repo_clean

        # Dataset is back!
        assert os.path.exists(os.path.join(lb.root_dir, '.gitmodules')) is True
        dataset_submodule_dir = os.path.join(lb.root_dir, '.gigantum',
                                             'datasets', 'test', 'dataset100')
        assert os.path.exists(dataset_submodule_dir) is True
        assert os.path.exists(os.path.join(dataset_submodule_dir,
                                           '.gigantum')) is True
        with open(os.path.join(lb.root_dir, '.gitmodules'), 'rt') as mf:
            data = mf.read()

        assert len(data) > 0

        # Switch back to branch
        bm.workon_branch('test-branch')
        assert bm.active_branch == 'test-branch'
        assert lb.active_branch == 'test-branch'
        assert lb.is_repo_clean

        dataset_submodule_dir = os.path.join(lb.root_dir, '.gigantum',
                                             'datasets', 'test', 'dataset100')
        assert os.path.exists(dataset_submodule_dir) is False
        assert os.path.exists(os.path.join(dataset_submodule_dir,
                                           '.gigantum')) is False
        with open(os.path.join(lb.root_dir, '.gitmodules'), 'rt') as mf:
            data = mf.read()

        assert len(data) == 0

        # Switch back to master
        bm.workon_branch('master')
        assert bm.active_branch == 'master'
        assert lb.active_branch == 'master'
        assert lb.is_repo_clean

        # Dataset is back!
        assert os.path.exists(os.path.join(lb.root_dir, '.gitmodules')) is True
        dataset_submodule_dir = os.path.join(lb.root_dir, '.gigantum',
                                             'datasets', 'test', 'dataset100')
        assert os.path.exists(dataset_submodule_dir) is True
        assert os.path.exists(os.path.join(dataset_submodule_dir,
                                           '.gigantum')) is True
        with open(os.path.join(lb.root_dir, '.gitmodules'), 'rt') as mf:
            data = mf.read()

        assert len(data) > 0
示例#5
0
 def resolve_is_active(self, info):
     lb = InventoryManager().load_labbook(get_logged_in_username(),
                                          self.owner,
                                          self.name)
     return BranchManager(lb).active_branch == self.branch_name
示例#6
0
 def helper_resolve_commits_behind(dataset):
     """Temporary Helper to get the commits behind for a dataset. Used for linked datasets to see if
     they are out of date"""
     bm = BranchManager(dataset)
     bm.fetch()
     return bm.get_commits_behind(branch_name='master')
示例#7
0
 def helper_resolve_active_branch(self, labbook):
     active_branch_name = BranchManager(labbook, username=get_logged_in_username()).active_branch
     return LabbookRef(id=f"{self.owner}&{self.name}&None&{active_branch_name}",
                       owner=self.owner, name=self.name, prefix=None,
                       ref_name=active_branch_name)
示例#8
0
 def resolve_workspace_branch_name(self, info):
     return info.context.labbook_loader.load(f"{get_logged_in_username()}&{self.owner}&{self.name}").then(
         lambda labbook: BranchManager(labbook, username=get_logged_in_username()).workspace_branch)
示例#9
0
 def resolve_remote_branch_names(self, info):
     fltr = lambda labbook: \
         BranchManager(labbook, username=get_logged_in_username()).branches_remote
     return info.context.labbook_loader.load(f"{get_logged_in_username()}&{self.owner}&{self.name}").then(
         fltr)
示例#10
0
 def test_fail_remove_branch_not_exist(self, mock_labbook_lfs_disabled):
     """ Test remove branch does raises exception when deleting nonexisting branch """
     lb = mock_labbook_lfs_disabled[2]
     bm = BranchManager(lb, username=TEST_USER)
     with pytest.raises(InvalidBranchName):
         bm.remove_branch('branch-that-does-not-exist')
示例#11
0
 def test_fail_remove_branch_on_active_branch(self, mock_labbook_lfs_disabled):
     """ Test remove branch does raises exception when deleting current branch """
     lb = mock_labbook_lfs_disabled[2]
     bm = BranchManager(lb, username=TEST_USER)
     with pytest.raises(BranchException):
         bm.remove_branch(bm.active_branch)
示例#12
0
    def test_success_init_and_active_branch(self, mock_labbook_lfs_disabled):
        """ All newly-created repos should be on master branch. """

        bm = BranchManager(mock_labbook_lfs_disabled[2], username=TEST_USER)
        assert bm.active_branch == 'master'
        assert bm.workspace_branch == 'master'
示例#13
0
 def test_fail_create_rollback_to_invalid_revision(self, mock_labbook_lfs_disabled):
     """ Fail when provided with an invalid Git revision """
     test_user_lb = mock_labbook_lfs_disabled[2]
     bm = BranchManager(test_user_lb, username=TEST_USER)
     with pytest.raises(InvalidBranchName):
         bm.create_branch('should-fail', revision='invalidrevision')
示例#14
0
    def test_commits_ahead_behind(self, fixture_working_dir_lfs_disabled):
        with responses.RequestsMock() as rsps:
            rsps.add(responses.GET,
                     'https://usersrv.gigantum.io/key',
                     json={'key': 'afaketoken'},
                     status=200)

            config_file, client = fixture_working_dir_lfs_disabled[0], \
                                     fixture_working_dir_lfs_disabled[2]

            im = InventoryManager(config_file)
            lb = im.create_labbook(UT_USERNAME,
                                   UT_USERNAME,
                                   UT_LBNAME,
                                   description="tester")
            bm = BranchManager(lb, username=UT_USERNAME)
            bm.create_branch('new-branch-1')
            bm.create_branch('new-branch-2')
            bm.workon_branch('master')

            q = f"""
            {{
                labbook(name: "{UT_LBNAME}", owner: "{UT_USERNAME}") {{
                    branches {{
                        branchName
                        isLocal
                        isRemote
                        isActive
                        commitsAhead
                        commitsBehind
                    }}
                }}
            }}
            """

            r = client.execute(q)
            assert 'errors' not in r
            assert len(r['data']['labbook']['branches']) == 3
            assert r['data']['labbook']['branches'][0][
                'branchName'] == 'master'
            assert r['data']['labbook']['branches'][0][
                'isLocal'] is True, "Should be local"
            assert r['data']['labbook']['branches'][0][
                'isRemote'] is False, "not published yet"
            assert r['data']['labbook']['branches'][0]['isActive'] is True
            assert r['data']['labbook']['branches'][0]['commitsAhead'] == 0
            assert r['data']['labbook']['branches'][0]['commitsBehind'] == 0

            # Make a remote change!
            username = '******'
            wf = LabbookWorkflow(lb)
            wf.publish(username=username)

            other_user = '******'
            wf_other = LabbookWorkflow.import_from_remote(
                remote_url=wf.remote,
                username=other_user,
                config_file=lb.client_config.config_file)
            with open(os.path.join(wf_other.repository.root_dir, 'testfile'),
                      'w') as f:
                f.write('filedata')
            wf_other.repository.sweep_uncommitted_changes()

            wf_other.sync(username=other_user)

            r = client.execute(q)
            assert 'errors' not in r
            assert len(r['data']['labbook']['branches']) == 3
            assert r['data']['labbook']['branches'][0][
                'branchName'] == 'master'
            assert r['data']['labbook']['branches'][0][
                'isLocal'] is True, "Should be local"
            assert r['data']['labbook']['branches'][0][
                'isRemote'] is True, "There should be a remote"
            assert r['data']['labbook']['branches'][0]['isActive'] is True
            assert r['data']['labbook']['branches'][0]['commitsAhead'] == 0
            assert r['data']['labbook']['branches'][0]['commitsBehind'] == 1

            # Make a local change!
            lb.write_readme("blah")

            r = client.execute(q)
            assert 'errors' not in r
            assert len(r['data']['labbook']['branches']) == 3
            assert r['data']['labbook']['branches'][0][
                'branchName'] == 'master'
            assert r['data']['labbook']['branches'][0][
                'isLocal'] is True, "Should be local"
            assert r['data']['labbook']['branches'][0][
                'isRemote'] is True, "There should be a remote"
            assert r['data']['labbook']['branches'][0]['isActive'] is True
            assert r['data']['labbook']['branches'][0]['commitsAhead'] == 1
            assert r['data']['labbook']['branches'][0]['commitsBehind'] == 1

            # Sync
            wf.sync(username=username)
            r = client.execute(q)
            assert 'errors' not in r
            assert len(r['data']['labbook']['branches']) == 3
            assert r['data']['labbook']['branches'][0][
                'branchName'] == 'master'
            assert r['data']['labbook']['branches'][0][
                'isLocal'] is True, "Should be local"
            assert r['data']['labbook']['branches'][0][
                'isRemote'] is True, "There should be a remote"
            assert r['data']['labbook']['branches'][0]['isActive'] is True
            assert r['data']['labbook']['branches'][0]['commitsAhead'] == 0
            assert r['data']['labbook']['branches'][0]['commitsBehind'] == 0
 def test_no_remote_branches_when_no_remote(self,
                                            mock_labbook_lfs_disabled):
     test_user_lb = mock_labbook_lfs_disabled[2]
     bm = BranchManager(test_user_lb, username=TEST_USER)
     assert bm.branches_remote == []
示例#16
0
 def _mergeable(lb):
     # TODO(billvb) - Refactor for new branch model.
     username = get_logged_in_username()
     bm = BranchManager(lb, username=username)
     return [b for b in bm.branches_local if bm.active_branch != b]
    def test_get_commits_with_remote_changes(self, mock_config_file,
                                             remote_labbook_repo,
                                             mock_labbook_lfs_disabled):
        # When the branch is up to date, ensure it doesn't report being behind.
        lb = mock_labbook_lfs_disabled[2]
        lb.add_remote("origin", remote_labbook_repo)
        bm = BranchManager(lb, username='******')
        bm.workon_branch("testing-branch")

        from gtmcore.inventory.inventory import InventoryManager
        remote_lb = InventoryManager(
            mock_config_file[0]).load_labbook_from_directory(
                remote_labbook_repo)
        remote_bm = BranchManager(remote_lb, 'test')
        remote_bm.workon_branch("testing-branch")
        FileOperations.makedir(remote_lb,
                               'code/xyzdir',
                               create_activity_record=True)

        bm.fetch()
        behind = bm.get_commits_behind()
        ahead = bm.get_commits_ahead()
        assert ahead == 0
        assert behind == 2
示例#18
0
 def helper_resolve_branches(self, lb, kwargs):
     bm = BranchManager(lb)
     return [Branch(owner=self.owner, name=self.name, branch_name=b)
             for b in sorted(set(bm.branches_local + bm.branches_remote))]