def test_create(probe, path): # only as a probe whether this FS is a crippled one ar = AnnexRepo(probe, create=True) ds = Dataset(path) ds.create( description="funny", # custom git init option initopts=dict(shared='world') if not ar.is_managed_branch() else None) ok_(ds.is_installed()) assert_repo_status(ds.path, annex=True) # check default backend (ds.pathobj / "f1").write_text("1") ds.save() eq_(ds.repo.get_file_backend(["f1"]), ['MD5E']) if not ar.is_managed_branch(): eq_(ds.config.get("core.sharedrepository"), '2') # check description in `info` cmlout = ds.repo.call_annex(['info']) assert_in('funny [here]', cmlout) # check dataset ID eq_(ds.config.get_value('datalad.dataset', 'id'), ds.id)
def test_surprise_subds(path): # https://github.com/datalad/datalad/issues/3139 ds = create(path, force=True) # a lonely repo without any commit somerepo = AnnexRepo(path=op.join(path, 'd1', 'subrepo'), create=True) # a proper subdataset subds = create(op.join(path, 'd2', 'subds'), force=True) # If subrepo is an adjusted branch, it would have a commit, making most of # this test irrelevant because it is about the unborn branch edge case. adjusted = somerepo.is_managed_branch() # This edge case goes away with Git v2.22.0. fixed_git = external_versions['cmd:git'] >= '2.22.0' # save non-recursive res = ds.save(recursive=False, on_failure='ignore') if not adjusted and fixed_git: # We get an appropriate error about no commit being checked out. assert_in_results(res, action='add_submodule', status='error') # the content of both subds and subrepo are not added to their # respective parent as no --recursive was given assert_repo_status(subds.path, untracked=['subfile']) assert_repo_status(somerepo.path, untracked=['subfile']) if adjusted or fixed_git: if adjusted: # adjusted branch: #datalad/3178 (that would have a commit) modified = [subds.repo.pathobj, somerepo.pathobj] untracked = [] else: # Newer Git versions refuse to add a sub-repository with no commits # checked out. modified = [subds.repo.pathobj] untracked = ['d1'] assert_repo_status(ds.path, modified=modified, untracked=untracked) assert_not_in(ds.repo.pathobj / 'd1' / 'subrepo' / 'subfile', ds.repo.get_content_info()) else: # however, while the subdataset is added (and reported as modified # because it content is still untracked) the subrepo # cannot be added (it has no commit) # worse: its untracked file add been added to the superdataset assert_repo_status(ds.path, modified=['d2/subds']) assert_in(ds.repo.pathobj / 'd1' / 'subrepo' / 'subfile', ds.repo.get_content_info()) # with proper subdatasets, all evil is gone assert_not_in(ds.repo.pathobj / 'd2' / 'subds' / 'subfile', ds.repo.get_content_info())
def test_create(probe, path): # only as a probe whether this FS is a crippled one ar = AnnexRepo(probe, create=True) ds = Dataset(path) ds.create( description="funny", # custom git init option initopts=dict(shared='world') if not ar.is_managed_branch() else None) ok_(ds.is_installed()) assert_repo_status(ds.path, annex=True) # check default backend eq_(ds.config.get("annex.backends"), 'MD5E') if not ar.is_managed_branch(): eq_(ds.config.get("core.sharedrepository"), '2') runner = Runner() # check description in `info` cmd = ['git', 'annex', 'info'] cmlout = runner.run(cmd, cwd=path) assert_in('funny [here]', cmlout[0]) # check datset ID eq_(ds.config.get_value('datalad.dataset', 'id'), ds.id)
def test_save_amend(dspath): dspath = Path(dspath) file_in_super = dspath / 'somefile' file_in_sub = dspath / 'subds' / 'file_in_sub' # test on a hierarchy including a plain git repo: ds = Dataset(dspath).create(force=True, no_annex=True) subds = ds.create('subds', force=True) ds.save(recursive=True) assert_repo_status(ds.repo) # recursive and amend are mutually exclusive: for d in (ds, subds): assert_raises(ValueError, d.save, recursive=True, amend=True) # in an annex repo the branch we are interested in might not be the active # branch (adjusted): sub_branch = subds.repo.get_corresponding_branch() # amend in subdataset w/ new message; otherwise empty amendment: last_sha = subds.repo.get_hexsha(sub_branch) subds.save(message="new message in sub", amend=True) # we did in fact commit something: neq_(last_sha, subds.repo.get_hexsha(sub_branch)) # repo is clean: assert_repo_status(subds.repo) # message is correct: eq_( subds.repo.format_commit("%B", sub_branch).strip(), "new message in sub") # actually replaced the previous commit: assert_not_in(last_sha, subds.repo.get_branch_commits_(sub_branch)) # amend modifications in subdataset w/o new message if not subds.repo.is_managed_branch(): subds.unlock('file_in_sub') file_in_sub.write_text("modified again") last_sha = subds.repo.get_hexsha(sub_branch) subds.save(amend=True) neq_(last_sha, subds.repo.get_hexsha(sub_branch)) assert_repo_status(subds.repo) # message unchanged: eq_( subds.repo.format_commit("%B", sub_branch).strip(), "new message in sub") # actually replaced the previous commit: assert_not_in(last_sha, subds.repo.get_branch_commits_(sub_branch)) # save --amend with nothing to amend with: res = subds.save(amend=True) assert_result_count(res, 1) assert_result_count(res, 1, status='notneeded', action='save') # amend in superdataset w/ new message; otherwise empty amendment: last_sha = ds.repo.get_hexsha() ds.save(message="new message in super", amend=True) neq_(last_sha, ds.repo.get_hexsha()) assert_repo_status(subds.repo) eq_(ds.repo.format_commit("%B").strip(), "new message in super") assert_not_in(last_sha, ds.repo.get_branch_commits_()) # amend modifications in superdataset w/o new message file_in_super.write_text("changed content") if not subds.repo.is_managed_branch(): subds.unlock('file_in_sub') file_in_sub.write_text("modified once again") last_sha = ds.repo.get_hexsha() last_sha_sub = subds.repo.get_hexsha(sub_branch) ds.save(amend=True) neq_(last_sha, ds.repo.get_hexsha()) eq_(ds.repo.format_commit("%B").strip(), "new message in super") assert_not_in(last_sha, ds.repo.get_branch_commits_()) # we didn't mess with the subds: assert_repo_status(ds.repo, modified=["subds"]) eq_(last_sha_sub, subds.repo.get_hexsha(sub_branch)) eq_( subds.repo.format_commit("%B", sub_branch).strip(), "new message in sub") # save --amend with nothing to amend with: last_sha = ds.repo.get_hexsha() res = ds.save(amend=True) assert_result_count(res, 1) assert_result_count(res, 1, status='notneeded', action='save') eq_(last_sha, ds.repo.get_hexsha()) # we didn't mess with the subds: assert_repo_status(ds.repo, modified=["subds"]) eq_(last_sha_sub, subds.repo.get_hexsha(sub_branch)) eq_( subds.repo.format_commit("%B", sub_branch).strip(), "new message in sub") # amend with different identity: orig_author = ds.repo.format_commit("%an") orig_email = ds.repo.format_commit("%ae") orig_date = ds.repo.format_commit("%ad") orig_committer = ds.repo.format_commit("%cn") orig_committer_mail = ds.repo.format_commit("%ce") eq_(orig_author, orig_committer) eq_(orig_email, orig_committer_mail) with patch.dict( 'os.environ', { 'GIT_COMMITTER_NAME': 'Hopefully Different', 'GIT_COMMITTER_EMAIL': '*****@*****.**' }): ds.config.reload(force=True) ds.save(amend=True, message="amend with hope") # author was kept: eq_(orig_author, ds.repo.format_commit("%an")) eq_(orig_email, ds.repo.format_commit("%ae")) eq_(orig_date, ds.repo.format_commit("%ad")) # committer changed: eq_(ds.repo.format_commit("%cn"), "Hopefully Different") eq_(ds.repo.format_commit("%ce"), "*****@*****.**") # corner case: amend empty commit with no parent: rmtree(str(dspath)) # When adjusted branch is enforced by git-annex detecting a crippled FS, # git-annex produces an empty commit before switching to adjusted branch: # "commit before entering adjusted branch" # The commit by `create` would be the second one already. # Therefore go with plain annex repo and create an (empty) commit only when # not on adjusted branch: repo = AnnexRepo(dspath, create=True) if not repo.is_managed_branch(): repo.commit(msg="initial", options=['--allow-empty']) ds = Dataset(dspath) branch = ds.repo.get_corresponding_branch() or ds.repo.get_active_branch() # test pointless if we start with more than one commit eq_(len(list(ds.repo.get_branch_commits_(branch))), 1, msg="More than on commit '{}': {}".format( branch, ds.repo.call_git(['log', branch]))) last_sha = ds.repo.get_hexsha(branch) ds.save(message="new initial commit", amend=True) assert_repo_status(ds.repo) eq_(len(list(ds.repo.get_branch_commits_(branch))), 1, msg="More than on commit '{}': {}".format( branch, ds.repo.call_git(['log', branch]))) assert_not_in(last_sha, ds.repo.get_branch_commits_(branch)) eq_(ds.repo.format_commit("%B", branch).strip(), "new initial commit")