checkout: Remove selectively on directory files when changed (#1320)

Fix: #1220
This commit is contained in:
Mr. Outis
2018-11-13 13:30:19 -06:00
committed by GitHub
parent 7d069d2210
commit fc7545b6cf
3 changed files with 61 additions and 11 deletions
+2 -4
View File
@@ -465,12 +465,10 @@ class Project(object):
def checkout(self, target=None, with_deps=False):
all_stages = self.active_stages()
stages = all_stages
if target:
stages = self._collect(target,
with_deps=with_deps)
else:
stages = all_stages
stages = self._collect(target, with_deps=with_deps)
with self.state:
self._cleanup_unused_links(all_stages)
+20 -7
View File
@@ -270,7 +270,7 @@ class RemoteLOCAL(RemoteBase):
def checkout(self, path_info, checksum_info):
path = path_info['path']
md5 = checksum_info.get(self.PARAM_MD5, None)
md5 = checksum_info.get(self.PARAM_MD5)
cache = self.get(md5)
if not cache:
@@ -289,15 +289,16 @@ class RemoteLOCAL(RemoteBase):
remove(path)
return
if os.path.exists(path):
msg = u'Data \'{}\' exists. Removing before checkout.'
Logger.warn(msg.format(os.path.relpath(path)))
remove(path)
msg = u'Checking out \'{}\' with cache \'{}\'.'
Logger.info(msg.format(os.path.relpath(path), md5))
if not self.is_dir_cache(cache):
if os.path.exists(path):
msg = u'File \'{}\' exists. Removing before checkout.'
Logger.warn(msg.format(os.path.relpath(path)))
remove(path)
self.link(cache, path)
self.state.update_link(path)
return
@@ -319,7 +320,19 @@ class RemoteLOCAL(RemoteBase):
m = entry[self.PARAM_MD5]
p = os.path.join(path, relpath)
c = self.get(m)
self.link(c, p)
entry_info = {
'scheme': path_info['scheme'],
self.PARAM_PATH: p,
}
entry_checksum_info = {
self.PARAM_MD5: m,
}
if self.changed(entry_info, entry_checksum_info):
remove(p)
self.link(c, p)
if bar:
progress.update_target(dir_relpath, processed, dir_size)
+39
View File
@@ -4,9 +4,11 @@ import time
import stat
import shutil
import filecmp
import collections
from dvc.main import main
from dvc.project import Project
from dvc.system import System
from tests.basic_env import TestDvc
from tests.test_repro import TestRepro
from dvc.stage import Stage
@@ -116,6 +118,20 @@ class CheckoutBase(TestDvc):
def read_ignored(self):
return list(map(lambda s: s.strip('\n'), open(self.GIT_IGNORE).readlines()))
def outs_info(self, stage):
FileInfo = collections.namedtuple('FileInfo', 'path inode')
paths = [
os.path.join(root, file)
for output in stage.outs
for root, _, files in os.walk(output.path)
for file in files
]
return [
FileInfo(path=path, inode=System.inode(path))
for path in paths
]
class TestRemoveFilesWhenCheckout(CheckoutBase):
def test(self):
@@ -143,6 +159,29 @@ class TestRemoveFilesWhenCheckout(CheckoutBase):
self.assertFalse(os.path.exists(fname))
class TestCheckoutSelectiveRemove(CheckoutBase):
def test(self):
# Use copy to test for changes in the inodes
ret = main(['config', 'cache.type', 'copy'])
self.assertEqual(ret, 0)
stages = self.dvc.add(self.DATA_DIR)
self.assertEqual(len(stages), 1)
stage = stages[0]
staged_files = self.outs_info(stage)
os.remove(staged_files[0].path)
ret = main(['checkout', stage.relpath])
self.assertEqual(ret, 0)
checkedout_files = self.outs_info(stage)
self.assertEqual(len(staged_files), len(checkedout_files))
self.assertEqual(staged_files[0].path, checkedout_files[0].path)
self.assertNotEqual(staged_files[0].inode, checkedout_files[0].inode)
self.assertEqual(staged_files[1].inode, checkedout_files[1].inode)
class TestGitIgnoreBasic(CheckoutBase):
def test(self):
fname1 = 'file_1'