def test_remove_remote_branch(self, mock_labbook_lfs_disabled): lb = mock_labbook_lfs_disabled[2] with tempfile.TemporaryDirectory() as tempdir: call_subprocess('git init .'.split(), tempdir) call_subprocess('touch FILE_A'.split(), tempdir) call_subprocess('git add FILE_A'.split(), tempdir) call_subprocess('git commit -am "message"'.split(), tempdir) call_subprocess('git checkout -b remote-branch'.split(), cwd=tempdir) call_subprocess('git checkout master'.split(), cwd=tempdir) lb.git.add_remote('origin', tempdir) bm = BranchManager(lb) bm.fetch() assert 'remote-branch' in bm.branches_remote # Get this remote branch locally, but go back to master bm.workon_branch('remote-branch') call_subprocess('git checkout master'.split(), cwd=bm.repository.root_dir) bm.remove_remote_branch('remote-branch') bm.fetch() # Confirm branch exists locally, but is gone on remote. assert 'remote-branch' in bm.branches_local assert 'remote-branch' not in bm.branches_remote
def test_query_mergeable_branches_from_feature_branch( self, mock_create_labbooks): # Per current branch model, can only merge in workspace branch lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) b2 = bm.create_branch(f"tester2") q = f""" {{ labbook(name: "{UT_LBNAME}", owner: "{UT_USERNAME}") {{ workspaceBranchName branches {{ branchName isMergeable }} }} }} """ r = client.execute(q) assert 'errors' not in r assert r['data']['labbook'][ 'workspaceBranchName'] == bm.workspace_branch branches = r['data']['labbook']['branches'] assert branches[0]['branchName'] == 'master' assert branches[0]['isMergeable'] is True assert branches[1]['branchName'] == 'tester1' assert branches[1]['isMergeable'] is True assert branches[2]['branchName'] == 'tester2' assert branches[2]['isMergeable'] is False
def test_create_feature_branch_success(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) q = f""" mutation makeFeatureBranch {{ createExperimentalBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", branchName: "valid-branch-name-working1" }}) {{ labbook{{ name activeBranchName branches {{ branchName }} }} }} }} """ r = client.execute(q) assert 'errors' not in r assert r['data']['createExperimentalBranch']['labbook']['activeBranchName'] \ == 'valid-branch-name-working1' assert set([n['branchName'] for n in r['data']['createExperimentalBranch']['labbook']['branches']]) \ == set(['tester1', 'master', 'valid-branch-name-working1']) assert lb.active_branch == 'valid-branch-name-working1' assert lb.is_repo_clean
def remote_labbook_repo(): # TODO: Remove after integration tests with LFS support are available conf_file, working_dir = _create_temp_work_dir(lfs_enabled=False) im = InventoryManager(conf_file) lb = im.create_labbook('test', 'test', 'sample-repo-lb', description="my first labbook") bm = BranchManager(lb, username='******') bm.create_branch('testing-branch') #with tempfile.TemporaryDirectory() as tmpdirname: with open(os.path.join('/tmp', 'codefile.c'), 'wb') as codef: codef.write(b'// Cody McCodeface ...') FileOperations.insert_file(lb, "code", "/tmp/codefile.c") assert lb.is_repo_clean bm.workon_branch('master') # Location of the repo to push/pull from yield lb.root_dir shutil.rmtree(working_dir) try: os.remove('/tmp/codefile.c') except: pass
def test_delete_feature_branch_success(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) q = f""" mutation makeFeatureBranch {{ deleteExperimentalBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", branchName: "{b1}", deleteLocal: true }}) {{ labbook {{ branches {{ branchName }} }} }} }} """ r = client.execute(q) pprint.pprint(r) # Cannot delete branch when it's the currently active branch assert 'errors' not in r assert bm.active_branch == bm.workspace_branch assert lb.is_repo_clean assert b1 not in bm.branches_local
def test_workon_feature_branch_success(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) assert bm.active_branch == 'master' q = f""" mutation makeFeatureBranch {{ workonExperimentalBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", branchName: "{b1}" }}) {{ labbook{{ name description branches {{ branchName }} activeBranchName }} }} }} """ r = client.execute(q) assert 'errors' not in r assert r['data']['workonExperimentalBranch']['labbook']['activeBranchName'] \ == 'tester1' ab = r['data']['workonExperimentalBranch']['labbook']['branches'] assert set([n['branchName'] for n in ab]) \ == set(['master', 'tester1']) assert bm.active_branch == 'tester1' assert lb.is_repo_clean
def test_conflicted_merge_from_no_force_fail(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] with open('/tmp/s1.txt', 'w') as s1: s1.write('original-file\ndata') FileOperations.insert_file(lb, section='code', src_file=s1.name) bm = BranchManager(lb, username=UT_USERNAME) nb = bm.create_branch(f'new-branch') with open('/tmp/s1.txt', 'w') as s1: s1.write('branch-conflict-data') FileOperations.insert_file(lb, section='code', src_file=s1.name) bm.workon_branch(bm.workspace_branch) with open('/tmp/s1.txt', 'w') as s1: s1.write('mainline-conflict-data') FileOperations.insert_file(lb, section='code', src_file=s1.name) merge_q = f""" mutation x {{ mergeFromBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", otherBranchName: "{nb}" }}) {{ labbook{{ name description activeBranchName }} }} }} """ r = client.execute(merge_q) assert 'errors' in r assert 'Merge conflict' in r['errors'][0]['message']
def test_reflect_deleted_files_on_merge_in(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] with open('/tmp/s1.txt', 'w') as s1: s1.write('original-file\ndata') FileOperations.insert_file(lb, section='code', src_file=s1.name) bm = BranchManager(lb, username=UT_USERNAME) nb = bm.create_branch(f'new-branch') assert os.path.exists(os.path.join(lb.root_dir, 'code', 's1.txt')) FileOperations.delete_files(lb, 'code', ['s1.txt']) assert lb.is_repo_clean assert not os.path.exists(os.path.join(lb.root_dir, 'code', 's1.txt')) bm.workon_branch(bm.workspace_branch) assert os.path.exists(os.path.join(lb.root_dir, 'code', 's1.txt')) merge_q = f""" mutation x {{ mergeFromBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", otherBranchName: "{nb}" }}) {{ labbook{{ name description activeBranchName }} }} }} """ r = client.execute(merge_q) assert 'errors' not in r assert r['data']['mergeFromBranch']['labbook']['activeBranchName'] == 'master' assert not os.path.exists(os.path.join(lb.root_dir, 'code', 's1.txt'))
def test_query_mergeable_branches_from_main(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) b2 = bm.create_branch(f"tester2") bm.workon_branch(bm.workspace_branch) assert bm.active_branch == bm.workspace_branch q = f""" {{ labbook(name: "{UT_LBNAME}", owner: "{UT_USERNAME}") {{ branches {{ branchName isMergeable }} }} }} """ 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]['isMergeable'] == False assert r['data']['labbook']['branches'][1]['branchName'] == 'tester1' assert r['data']['labbook']['branches'][1]['isMergeable'] == True assert r['data']['labbook']['branches'][2]['branchName'] == 'tester2' assert r['data']['labbook']['branches'][2]['isMergeable'] == True
def test_sync___detect_merge_conflict(self, mock_labbook_lfs_disabled, mock_config_file): """ test import_from_remote method """ username = '******' lb = mock_labbook_lfs_disabled[2] wf = LabbookWorkflow(lb) wf.publish(username=username) bm = BranchManager(lb, username='******') bm.create_branch('test-conflict-branch') fpath = os.path.join(lb.root_dir, 'input', 'testfile') with open(fpath, 'w') as f: f.write('filedata') lb.sweep_uncommitted_changes() wf.sync('test') other_user = '******' wf_other = LabbookWorkflow.import_from_remote( wf.remote, username=other_user, config_file=mock_config_file[0]) bm_other = BranchManager(wf_other.labbook, username=other_user) bm_other.workon_branch('test-conflict-branch') with open(os.path.join(wf_other.labbook.root_dir, 'input', 'testfile'), 'w') as f: f.write('conflicting-change-other-user') wf_other.labbook.sweep_uncommitted_changes() wf_other.sync(username=username) with open(fpath, 'w') as f: f.write('conflicting-change-original-user') wf.labbook.sweep_uncommitted_changes() h = wf.labbook.git.commit_hash with pytest.raises(MergeConflict): n = wf.sync(username=username) assert h == wf.labbook.git.commit_hash
def test_sync___override_merge_conflict_ours(self, mock_labbook_lfs_disabled, mock_config_file): """ test sync, with override in case of merge conflict. """ username = '******' lb = mock_labbook_lfs_disabled[2] wf = LabbookWorkflow(lb) wf.publish(username=username) bm = BranchManager(lb, username='******') bm.create_branch('test-conflict-branch') fpath = os.path.join(lb.root_dir, 'input', 'testfile') with open(fpath, 'w') as f: f.write('filedata') lb.sweep_uncommitted_changes() wf.sync('test') other_user = '******' wf_other = LabbookWorkflow.import_from_remote( wf.remote, username=other_user, config_file=mock_config_file[0]) bm_other = BranchManager(wf_other.labbook, username=other_user) bm_other.workon_branch('test-conflict-branch') with open(os.path.join(wf_other.labbook.root_dir, 'input', 'testfile'), 'w') as f: f.write('conflicting-change-other-user') wf_other.labbook.sweep_uncommitted_changes() wf_other.sync(username=username) fpath = os.path.join(wf.labbook.root_dir, 'input', 'testfile') with open(fpath, 'w') as f: f.write('conflicting-change-original-user') wf.labbook.sweep_uncommitted_changes() n = wf.sync(username=username, override=MergeOverride.OURS) flines = open(os.path.join(wf.labbook.root_dir, 'input', 'testfile')).read() assert 'conflicting-change-original-user' == flines
def test_assert_all_remote_branches_can_be_checked_out( self, mock_config_file, remote_labbook_repo, mock_labbook_lfs_disabled): # Make sure all local branches can be checked out lb = mock_labbook_lfs_disabled[2] bm = BranchManager(lb, username=TEST_USER) # There is a remote branch called "testing-branch" lb.add_remote("origin", remote_labbook_repo) for branch_name in bm.branches_remote: bm.workon_branch(branch_name)
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
def test_count_commits_behind_remote_when_no_change(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] bm = BranchManager(lb, username='******') lb.add_remote("origin", remote_labbook_repo) bm.workon_branch('testing-branch') bm.fetch() behind = bm.get_commits_behind() ahead = bm.get_commits_ahead() assert ahead == 0 assert behind == 0
def test_success_remove_branch(self, mock_labbook_lfs_disabled): """ Test that branches can be removed locally """ lb = mock_labbook_lfs_disabled[2] bm = BranchManager(lb, username=TEST_USER) t = 'branch-to-make-and-then-delete' branch_name_to_delete = bm.create_branch(title=t) assert branch_name_to_delete in bm.branches_local bm.workon_branch(bm.workspace_branch) bm.remove_branch(branch_name_to_delete) assert branch_name_to_delete not in bm.branches_local
def test_merge_into_feature_from_workspace_simple_success( self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) og_hash = lb.git.commit_hash b1 = bm.create_branch(f"test-branch") bm.workon_branch(bm.workspace_branch) assert lb.active_branch == bm.workspace_branch og2_hash = lb.git.commit_hash assert lb.git.commit_hash == og_hash FileOperations.makedir(lb, 'code/main-branch-dir1', create_activity_record=True) FileOperations.makedir(lb, 'code/main-branch-dir2', create_activity_record=True) next_main_hash = lb.git.commit_hash assert og_hash != next_main_hash bm.workon_branch(b1) assert not os.path.exists( os.path.join(lb.root_dir, 'code/main-branch-dir1')) merge_q = f""" mutation x {{ mergeFromBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", otherBranchName: "{bm.workspace_branch}" }}) {{ labbook{{ name description activeBranchName }} }} }} """ r = client.execute(merge_q) assert 'errors' not in r assert r['data']['mergeFromBranch']['labbook'][ 'activeBranchName'] == 'test-branch' assert r['data']['mergeFromBranch']['labbook'][ 'name'] == 'unittest-workflow-branch-1' assert lb.active_branch == b1 assert os.path.exists( os.path.join(lb.root_dir, 'code/main-branch-dir1')) assert lb.is_repo_clean
def test_success_create_branch_then_return_to_master(self, mock_labbook_lfs_disabled): """ Test process of creating a new branch, then returning to original and then being in a clean state. """ t = 'my-new-example-feature' lb = mock_labbook_lfs_disabled[2] bm = BranchManager(lb, username=TEST_USER) assert bm.active_branch == 'master' branch_name = bm.create_branch(title=t) assert bm.active_branch == branch_name assert lb.is_repo_clean bm.workon_branch(bm.workspace_branch) assert bm.active_branch == 'master' assert lb.active_branch == 'master' assert lb.is_repo_clean
def test_get_commits_with_local_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") # Do some stuff to make commits locally FileOperations.makedir(lb, 'code/rand_dir', create_activity_record=True) FileOperations.delete_files(lb, 'code', ['rand_dir']) behind = bm.get_commits_behind() ahead = bm.get_commits_ahead() assert ahead == 4 assert behind == 0
def checkout(self, username: str, branch_name: str) -> None: """Workflow method to checkout a branch in a Project, and if a new linked dataset has been introduced, automatically import it. Args: username: Current logged in username branch_name: name of the branch to checkout Returns: None """ # Checkout the branch bm = BranchManager(self.labbook, username=username) bm.workon_branch(branch_name=branch_name) # Update linked datasets inside the Project, clean them out if needed, and schedule auto-imports gitworkflows_utils.process_linked_datasets(self.labbook, username)
def test_objects_to_push_ignore_other_branch(self, mock_dataset_with_manifest): ds, manifest, working_dir = mock_dataset_with_manifest iom = IOManager(ds, manifest) revision = manifest.dataset_revision os.makedirs( os.path.join(manifest.cache_mgr.cache_root, revision, "other_dir")) helper_append_file(manifest.cache_mgr.cache_root, revision, "test1.txt", "test content 1") helper_append_file(manifest.cache_mgr.cache_root, revision, "test2.txt", "fdsfgfd") manifest.sweep_all_changes() obj_to_push = iom.objects_to_push() assert len(obj_to_push) == 2 assert obj_to_push[0].dataset_path == "test1.txt" assert obj_to_push[1].dataset_path == "test2.txt" # Create new branch and add a file there bm = BranchManager(ds, username=USERNAME) starting_branch = bm.active_branch bm.create_branch(title="test-branch") assert bm.active_branch == "test-branch" assert ds.is_repo_clean is True helper_append_file(manifest.cache_mgr.cache_root, iom.manifest.dataset_revision, "test3.txt", "fdsfgfd") manifest.sweep_all_changes() obj_to_push = iom.objects_to_push() assert len(obj_to_push) == 3 assert obj_to_push[0].dataset_path == "test1.txt" assert obj_to_push[1].dataset_path == "test2.txt" assert obj_to_push[2].dataset_path == "test3.txt" # Go back to original branch, you shouldn't have to push file on other branch bm.workon_branch(starting_branch) obj_to_push = iom.objects_to_push() assert len(obj_to_push) == 2 assert obj_to_push[0].dataset_path == "test1.txt" assert obj_to_push[1].dataset_path == "test2.txt"
def mutate_and_get_payload(cls, root, info, owner, labbook_name, branch_name, client_mutation_id=None): username = get_logged_in_username() lb = InventoryManager().load_labbook(username, owner, labbook_name, author=get_logged_in_author()) # TODO - fail fast if already locked. with lb.lock(): bm = BranchManager(lb, username=username) bm.workon_branch(branch_name=branch_name) return WorkonBranch( Labbook(id="{}&{}".format(owner, labbook_name), name=labbook_name, owner=owner))
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
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_create_feature_branch_success_update_description( self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) q = f""" mutation makeFeatureBranch {{ createExperimentalBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", branchName: "valid-branch-name-working1" description: "Updated description" }}) {{ labbook{{ name description branches {{ branchName }} activeBranchName }} }} }} """ r = client.execute(q) assert 'errors' not in r assert r['data']['createExperimentalBranch']['labbook']['activeBranchName'] \ == 'valid-branch-name-working1' assert r['data']['createExperimentalBranch']['labbook']['description'] \ == "Updated description" assert bm.active_branch == 'valid-branch-name-working1' assert lb.is_repo_clean # Make sure activity record was created when description was changed log_data = lb.git.log() assert "_GTM_ACTIVITY_START_**\nmsg:Updated description of Project" in log_data[ 0]['message']
def test_workon_feature_branch_bad_name_fail(self, mock_create_labbooks): lb, client = mock_create_labbooks[0], mock_create_labbooks[1] bm = BranchManager(lb, username=UT_USERNAME) b1 = bm.create_branch(f"tester1") bm.workon_branch(bm.workspace_branch) q = f""" mutation makeFeatureBranch {{ workonExperimentalBranch(input: {{ owner: "{UT_USERNAME}", labbookName: "{UT_LBNAME}", branchName: "{b1.replace('gm', '')}" }}) {{ currentBranchName }} }} """ r = client.execute(q) pprint.pprint(r) # Cannot delete branch when it's the currently active branch assert 'errors' in r assert bm.active_branch == bm.workspace_branch assert lb.is_repo_clean
def test_publish__simple(self, mock_labbook_lfs_disabled): """Test a simple publish and ensuring master is active branch. """ username = '******' lb = mock_labbook_lfs_disabled[2] bm = BranchManager(lb, username) bm.create_branch('test-local-only') assert bm.branches_remote == [] assert bm.branches_local == ['master', 'test-local-only'] wf = LabbookWorkflow(lb) # Test you can only publish on master. with pytest.raises(GitWorkflowException): wf.publish(username=username) assert wf.remote is None # Once we return to master branch, then we can publish. bm.workon_branch(bm.workspace_branch) wf.publish(username=username) assert os.path.exists(wf.remote) # Assert that publish only pushes up the master branch. assert bm.branches_local == ['master', 'test-local-only'] assert bm.branches_remote == ['master']
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
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