move: Take into account suffix

🔨 Refactor

Fix #1491
This commit is contained in:
Mr. Outis
2019-01-11 12:57:42 -06:00
parent 471029cc6d
commit 0372e1d87d
2 changed files with 60 additions and 29 deletions
+41 -29
View File
@@ -261,49 +261,61 @@ class Project(object):
return stage
def move(self, from_path, to_path):
"""
Renames an output file and modifies the stage associated
to reflect the change on the pipeline.
If the output has the same name as its stage, it would
also rename the corresponding stage file.
E.g.
Having: (hello, hello.dvc)
$ dvc move hello greetings
Result: (greeting, greeting.dvc)
It only works with outputs generated by `add` or `import`,
also known as data sources.
"""
import dvc.output as Output
from dvc.stage import Stage
from_out = Output.loads_from(Stage(self, cwd=os.curdir),
[from_path])[0]
found = False
self._files_to_git_add = []
try:
stage, out = next((stage, out)
for stage in self.stages()
for out in stage.outs
if from_out.path == out.path)
except StopIteration:
raise DvcException("unable to find stage file with output '{path}'"
.format(path=from_path))
if not stage.is_data_source:
raise MoveNotDataSourceError(stage.relpath)
to_out = Output.loads_from(stage, [to_path], out.cache, out.metric)[0]
with self.state:
for stage in self.stages():
for out in stage.outs:
if out.path != from_out.path:
continue
out.move(to_out)
if not stage.is_data_source:
raise MoveNotDataSourceError(stage.relpath)
stage_name = os.path.splitext(os.path.basename(stage.path))[0]
from_name = os.path.basename(from_out.path)
found = True
to_out = Output.loads_from(out.stage,
[to_path],
out.cache,
out.metric)[0]
out.move(to_out)
if stage_name == from_name:
os.unlink(stage.path)
stage_base = os.path.basename(stage.path)
stage_base = stage_base.rstrip(Stage.STAGE_FILE_SUFFIX)
stage.path = os.path.join(
os.path.dirname(stage.path),
os.path.basename(to_path) + Stage.STAGE_FILE_SUFFIX
)
stage_dir = os.path.dirname(stage.path)
from_base = os.path.basename(from_path)
to_base = os.path.basename(to_path)
if stage_base == from_base:
os.unlink(stage.path)
path = to_base + Stage.STAGE_FILE_SUFFIX
stage.path = os.path.join(stage_dir, path)
stage.dump()
stage.dump()
self._remind_to_git_add()
if not found:
msg = "unable to find dvcfile with output '{}'"
raise DvcException(msg.format(from_path))
def _unprotect_file(self, path):
import stat
import uuid
+19
View File
@@ -57,3 +57,22 @@ class TestMoveNotDataSource(TestRepro):
ret = main(['move', self.file1, 'dst'])
self.assertNotEqual(ret, 0)
class TestMoveFileWithExtension(TestDvc):
def test(self):
with open(os.path.join(self.dvc.root_dir, 'file.csv'), 'w') as fd:
fd.write('1,2,3\n')
self.dvc.add('file.csv')
self.assertTrue(os.path.exists('file.csv'))
self.assertTrue(os.path.exists('file.csv.dvc'))
ret = main(['move', 'file.csv', 'other_name.csv'])
self.assertEqual(ret, 0)
self.assertFalse(os.path.exists('file.csv'))
self.assertFalse(os.path.exists('file.csv.dvc'))
self.assertTrue(os.path.exists('other_name.csv'))
self.assertTrue(os.path.exists('other_name.csv.dvc'))