From 49baf38871ea36207e9b24b61b45bba11eb41c00 Mon Sep 17 00:00:00 2001 From: Ruslan Kuprieiev Date: Wed, 29 Aug 2018 13:40:50 +0300 Subject: [PATCH] dvc: properly compute mtime for the directory Fixes #1067 Signed-off-by: Ruslan Kuprieiev --- dvc/state.py | 15 ++++++++++++++- tests/test_repro.py | 25 +++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/dvc/state.py b/dvc/state.py index 1e668d031..efcf142d8 100644 --- a/dvc/state.py +++ b/dvc/state.py @@ -96,7 +96,20 @@ class State(object): @staticmethod def mtime(path): - return str(int(nanotime.timestamp(os.path.getmtime(path)))) + if os.path.isdir(path): + mtime = -1 + for root, dirs, files in os.walk(path): + for fname in files: + f = os.path.join(root, fname) + m = os.path.getmtime(f) + if m > mtime: + mtime = m + if mtime == -1: + mtime = os.path.getmtime(path) + else: + mtime = os.path.getmtime(path) + + return str(int(nanotime.timestamp(mtime))) @staticmethod def inode(path): diff --git a/tests/test_repro.py b/tests/test_repro.py index 1e1441ad1..94ff02dd7 100644 --- a/tests/test_repro.py +++ b/tests/test_repro.py @@ -255,6 +255,31 @@ class TestReproChangedDir(TestDvc): self.assertEqual(len(stages), 1) +class TestReproChangedDirData(TestDvc): + def test(self): + dir_name = 'dir' + dir_code = 'dir_code.py' + with open(dir_code, 'w+') as fd: + fd.write("import os; import sys; import shutil; shutil.copytree(sys.argv[1], sys.argv[2])") + + stage = self.dvc.run(outs=[dir_name], + deps=[self.DATA_DIR, dir_code], + cmd="python {} {} {}".format(dir_code, + self.DATA_DIR, + dir_name)) + self.assertTrue(stage is not None) + + stages = self.dvc.reproduce(stage.path) + self.assertEqual(len(stages), 0) + + with open(self.DATA_SUB, 'a') as fd: + fd.write('add') + + stages = self.dvc.reproduce(stage.path) + self.assertEqual(len(stages), 1) + self.assertTrue(stages[0] is not None) + + class TestReproMissingMd5InStageFile(TestRepro): def test(self): with open(self.file1_stage, 'r') as fd: