Skip to content

Commit

Permalink
BF: annexrepo: Avoid typechange when using temporary index
Browse files Browse the repository at this point in the history
git-annex's pre-commit hook throws the following error if an unlocked
file is given in a 'git commit PATH ...' call:

  Cannot make a partial commit with unlocked annexed files. You should
  `git annex add` the files you want to commit, and then run git
  commit.

The motivation for this is explained in git-annex's
adc5ca70a (pre-commit: Block partial commit of unlocked annexed file,
since that left a typechange staged in index, 2014-11-10)

In the typical case, we could fix this by running 'git annex add'
before the 'git commit PATH' call.  (And 'datalad save' already does
this, so this is an issue only when directly calling
AnnexRepo.commit().)  *But* a complication is introduced when 'git
annex add' adds the file to index as a regular file while the file in
HEAD is an annex symbolic link (e.g., the common case would be the
file size shrinking below the threshold specified via
annex.largefiles).  git-annex can't distinguish the typechange of the
added file from that of an unlocked file, so 'git commit PATH' fails
with the partial commit error [*].

To work around this, dataladgh-3009 taught AnnexRepo.commit() to stage the
specified paths in a temporary index and then call 'git commit'
without the pathspec.  After the commit, we need to reset the main
index to the state in HEAD to reflect changes that git-annex might
have made in the pre-commit hook (e.g., changing the regular file to
an annex symlink).  dataladgh-3009 did this for the specified paths that had
unstaged changes, but we need to do the same thing for paths with
staged changes.  Otherwise, calling 'datalad save PATH' with a path
moved below the annex.largefiles cutoff will show a typechange after
the save call.

[*]: https://git-annex.branchable.com/bugs/cannot_commit___34__annex_add__34__ed_modified_file_which_switched_its_largefile_status_to_be_committed_to_git_now/
  • Loading branch information
kyleam committed Apr 30, 2019
1 parent 514545a commit 1a609d4
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
16 changes: 15 additions & 1 deletion datalad/interface/tests/test_save.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,4 +481,18 @@ def test_save_directory(path):

with chpwd(opj(path, 'sdir3')):
save(path='sdir')
ok_clean_git(ds.path)
ok_clean_git(ds.path)


@with_tree({'.gitattributes': "* annex.largefiles=(largerthan=4b)",
"foo": "in annex"})
def test_save_partial_index(path):
ds = Dataset(path).create(force=True)
ds.add("foo")
ok_clean_git(ds.path)
ds.unlock(path="foo")
create_tree(ds.path, tree={"foo": "a", "staged": ""},
remove_existing=True)
ds.repo.add("staged", git=True)
ds.save(path="foo")
ok_clean_git(ds.path, head_modified=["staged"])
12 changes: 6 additions & 6 deletions datalad/support/annexrepo.py
Original file line number Diff line number Diff line change
Expand Up @@ -2964,12 +2964,12 @@ def commit(self, msg=None, options=None, _datalad_msg=False,
careless=careless,
index_file=alt_index_file)

if files_changed_notstaged:
# reset current index to reflect the changes annex might have done
self._git_custom_command(
list(files_changed_notstaged),
['git', 'reset']
)
# reset current index to reflect the changes annex might have done
self._git_custom_command(
list(files_changed_notstaged |
files_changed_staged),
['git', 'reset']
)

# in any case we will not specify files explicitly
files_to_commit = None
Expand Down

0 comments on commit 1a609d4

Please sign in to comment.