Merge pull request #494 from efiop/master

dvc: properly check dir
This commit is contained in:
Ruslan Kuprieiev
2018-03-01 09:19:40 +02:00
committed by GitHub
2 changed files with 64 additions and 5 deletions
+37 -5
View File
@@ -171,16 +171,48 @@ class Output(Dependency):
def loads_from(cls, project, s_list, use_cache=False, cwd=os.curdir):
return [cls.loads(project, x, use_cache=use_cache, cwd=cwd) for x in s_list]
def _changed_file(self, path, cache):
if os.path.isfile(path) and \
os.path.isfile(cache) and \
System.samefile(path, cache) and \
os.stat(cache).st_mode & stat.S_IREAD:
return False
return True
def _changed_dir(self):
if not os.path.isdir(self.path) or not os.path.isdir(self.cache):
return True
for root, dirs, files in os.walk(self.path):
for fname in files:
path = os.path.join(root, fname)
mtime = os.path.getmtime(path)
inode = os.stat(path).st_ino
state = self.project.state.get(path)
if state and state.mtime == mtime and state.inode == inode:
md5 = state.md5
else:
md5 = file_md5(path)[0]
cache = self.project.cache.get(md5)
if self._changed_file(path, cache):
return True
return False
def changed(self):
ret = True
if not self.use_cache:
ret = super(Output, self).changed()
elif os.path.exists(self.path) and \
os.path.exists(self.cache) and \
System.samefile(self.path, self.cache) and \
os.stat(self.cache).st_mode & stat.S_IREAD:
ret = False
elif os.path.isfile(self.path) and \
os.path.isfile(self.cache):
ret = self._changed_file(self.path, self.cache)
elif os.path.isdir(self.path) and \
os.path.isdir(self.cache):
ret = self._changed_dir()
msg = "Data {} with cache {} "
if ret:
+27
View File
@@ -104,6 +104,33 @@ class TestReproDataSource(TestReproChangedData):
self.assertEqual(stages[0].outs[0].md5, file_md5(self.BAR)[0])
class TestReproChangedDir(TestDvc):
def test(self):
file_name = 'file'
shutil.copyfile(self.FOO, file_name)
stage_name = 'dir.dvc'
dir_name = 'dir'
dir_code = 'dir.py'
with open(dir_code, 'w+') as fd:
fd.write("import os; import shutil; os.mkdir(\"{}\"); shutil.copyfile(\"{}\", os.path.join(\"{}\", \"{}\"))".format(dir_name, file_name, dir_name, file_name))
self.dvc.run(fname=stage_name,
outs=[dir_name],
deps=[file_name, dir_code],
cmd="python {}".format(dir_code))
stages = self.dvc.reproduce(stage_name)
self.assertEqual(len(stages), 0)
os.unlink(file_name)
shutil.copyfile(self.BAR, file_name)
stages = self.dvc.reproduce(stage_name)
self.assertEqual(len(stages), 1)
class TestCmdRepro(TestRepro):
def test(self):
ret = main(['repro',