Skip to content
Snippets Groups Projects
Commit c0587547 authored by Sybren A. Stüvel's avatar Sybren A. Stüvel
Browse files

Move-out-of-way command now uses nicer filenames

The colons in the timestamp are gone, and numerical suffixes (to ensure
new directories are unique) are prefixed with a ~.
parent 515d5b7d
Branches
Tags
No related merge requests found
...@@ -288,6 +288,44 @@ class SleepCommand(AbstractCommand): ...@@ -288,6 +288,44 @@ class SleepCommand(AbstractCommand):
await self.worker.register_log('Done sleeping for %s seconds' % time_in_seconds) await self.worker.register_log('Done sleeping for %s seconds' % time_in_seconds)
def _timestamped_path(path: Path) -> Path:
"""Returns the path with its modification time appended to the name."""
from datetime import datetime
mtime = path.stat().st_mtime
mdatetime = datetime.fromtimestamp(mtime)
# Make the ISO-8601 timestamp a bit more eye- and filename-friendly.
iso = mdatetime.isoformat().replace('T', '_').replace(':', '')
dst = path.with_name('%s-%s' % (path.name, iso))
return dst
def _unique_path(path: Path) -> Path:
"""Returns the path, or if it exists, the path with a unique suffix."""
import re
suf_re = re.compile(r'~([0-9]+)$')
# See which suffixes are in use
max_nr = 0
for altpath in path.parent.glob(path.name + '~*'):
m = suf_re.search(altpath.name)
if not m:
continue
suffix = m.group(1)
try:
suffix = int(suffix)
except ValueError:
continue
max_nr = max(max_nr, suffix)
return path.with_name(path.name + '~%i' % (max_nr + 1))
@command_executor('move_out_of_way') @command_executor('move_out_of_way')
class MoveOutOfWayCommand(AbstractCommand): class MoveOutOfWayCommand(AbstractCommand):
def validate(self, settings: dict): def validate(self, settings: dict):
...@@ -300,9 +338,6 @@ class MoveOutOfWayCommand(AbstractCommand): ...@@ -300,9 +338,6 @@ class MoveOutOfWayCommand(AbstractCommand):
return 'src must be a string' return 'src must be a string'
async def execute(self, settings: dict): async def execute(self, settings: dict):
from pathlib import Path
from datetime import datetime
src = Path(settings['src']) src = Path(settings['src'])
if not src.exists(): if not src.exists():
self._log.info('Render output path %s does not exist, not moving out of way', src) self._log.info('Render output path %s does not exist, not moving out of way', src)
...@@ -310,23 +345,10 @@ class MoveOutOfWayCommand(AbstractCommand): ...@@ -310,23 +345,10 @@ class MoveOutOfWayCommand(AbstractCommand):
'not moving out of way', self.command_name, src) 'not moving out of way', self.command_name, src)
return return
mtime = src.stat().st_mtime dst = _timestamped_path(src)
mdatetime = datetime.fromtimestamp(mtime)
dst = src.with_name('%s-%s' % (src.name, mdatetime.isoformat()))
if dst.exists(): if dst.exists():
self._log.debug('Destination %s exists, finding one that does not', dst) self._log.debug('Destination %s exists, finding one that does not', dst)
# See which suffixes are in use dst = _unique_path(dst)
max_nr = 0
for path in dst.parent.glob(dst.name + '*'):
suffix = path.name.split('-')[-1]
try:
suffix = int(suffix)
except ValueError:
continue
self._log.debug('Found suffix %r', suffix)
max_nr = max(max_nr, suffix)
dst = dst.with_name(dst.name + '-%i' % (max_nr + 1))
self._log.debug('New destination is %s', dst) self._log.debug('New destination is %s', dst)
self._log.info('Moving %s to %s', src, dst) self._log.info('Moving %s to %s', src, dst)
......
from pathlib import Path
import os
from test_runner import AbstractCommandTest from test_runner import AbstractCommandTest
...@@ -20,8 +23,6 @@ class MoveOutOfWayTest(AbstractCommandTest): ...@@ -20,8 +23,6 @@ class MoveOutOfWayTest(AbstractCommandTest):
del self.tmpdir del self.tmpdir
def test_nonexistant_source(self): def test_nonexistant_source(self):
from pathlib import Path
src = Path(self.tmpdir.name) / 'nonexistant-dir' src = Path(self.tmpdir.name) / 'nonexistant-dir'
task = self.cmd.run({'src': str(src)}) task = self.cmd.run({'src': str(src)})
ok = self.loop.run_until_complete(task) ok = self.loop.run_until_complete(task)
...@@ -30,9 +31,6 @@ class MoveOutOfWayTest(AbstractCommandTest): ...@@ -30,9 +31,6 @@ class MoveOutOfWayTest(AbstractCommandTest):
self.assertFalse(src.exists()) self.assertFalse(src.exists())
def test_existing_source(self): def test_existing_source(self):
from pathlib import Path
import os
src = Path(self.tmpdir.name) / 'existing-dir' src = Path(self.tmpdir.name) / 'existing-dir'
src.mkdir() src.mkdir()
(src / 'src-contents').touch() (src / 'src-contents').touch()
...@@ -43,14 +41,11 @@ class MoveOutOfWayTest(AbstractCommandTest): ...@@ -43,14 +41,11 @@ class MoveOutOfWayTest(AbstractCommandTest):
ok = self.loop.run_until_complete(task) ok = self.loop.run_until_complete(task)
self.assertTrue(ok) self.assertTrue(ok)
dst = src.with_name('existing-dir-2012-03-02T19:18:12') dst = src.with_name('existing-dir-2012-03-02_191812')
self.assertTrue(dst.exists()) self.assertTrue(dst.exists())
self.assertFalse(src.exists()) self.assertFalse(src.exists())
def test_source_is_file(self): def test_source_is_file(self):
from pathlib import Path
import os
src = Path(self.tmpdir.name) / 'existing-file' src = Path(self.tmpdir.name) / 'existing-file'
src.touch(exist_ok=False) src.touch(exist_ok=False)
os.utime(str(src), (1330712280, 1330712292)) # fixed (atime, mtime) for testing os.utime(str(src), (1330712280, 1330712292)) # fixed (atime, mtime) for testing
...@@ -59,29 +54,26 @@ class MoveOutOfWayTest(AbstractCommandTest): ...@@ -59,29 +54,26 @@ class MoveOutOfWayTest(AbstractCommandTest):
ok = self.loop.run_until_complete(task) ok = self.loop.run_until_complete(task)
self.assertTrue(ok) self.assertTrue(ok)
dst = src.with_name('existing-file-2012-03-02T19:18:12') dst = src.with_name('existing-file-2012-03-02_191812')
self.assertTrue(dst.exists()) self.assertTrue(dst.exists())
self.assertTrue(dst.is_file()) self.assertTrue(dst.is_file())
self.assertFalse(src.exists()) self.assertFalse(src.exists())
def test_existing_source_and_dest(self): def test_existing_source_and_dest(self):
from pathlib import Path
import os
src = Path(self.tmpdir.name) / 'existing-dir' src = Path(self.tmpdir.name) / 'existing-dir'
src.mkdir() src.mkdir()
(src / 'src-contents').touch() (src / 'src-contents').touch()
os.utime(str(src), (1330712280, 1330712292)) # fixed (atime, mtime) for testing os.utime(str(src), (1330712280, 1330712292)) # fixed (atime, mtime) for testing
existing_dst = src.with_name('existing-dir-2012-03-02T19:18:12') existing_dst = src.with_name('existing-dir-2012-03-02_191812')
existing_dst.mkdir() existing_dst.mkdir()
(existing_dst / 'dst-existing-contents').touch() (existing_dst / 'dst-existing-contents').touch()
existing_dst2 = src.with_name('existing-dir-2012-03-02T19:18:12-2') existing_dst2 = src.with_name('existing-dir-2012-03-02_191812~2')
existing_dst2.mkdir() existing_dst2.mkdir()
(existing_dst2 / 'dst2-existing-contents').touch() (existing_dst2 / 'dst2-existing-contents').touch()
existing_dst4 = src.with_name('existing-dir-2012-03-02T19:18:12-4') existing_dst4 = src.with_name('existing-dir-2012-03-02_191812~4')
existing_dst4.mkdir() existing_dst4.mkdir()
(existing_dst4 / 'dst4-existing-contents').touch() (existing_dst4 / 'dst4-existing-contents').touch()
...@@ -98,7 +90,7 @@ class MoveOutOfWayTest(AbstractCommandTest): ...@@ -98,7 +90,7 @@ class MoveOutOfWayTest(AbstractCommandTest):
self.assertTrue((existing_dst4 / 'dst4-existing-contents').exists()) self.assertTrue((existing_dst4 / 'dst4-existing-contents').exists())
# The source should have been moved to the new destination. # The source should have been moved to the new destination.
new_dst = existing_dst.with_name('existing-dir-2012-03-02T19:18:12-5') new_dst = existing_dst.with_name('existing-dir-2012-03-02_191812~5')
self.assertTrue(new_dst.exists()) self.assertTrue(new_dst.exists())
self.assertTrue((new_dst / 'src-contents').exists()) self.assertTrue((new_dst / 'src-contents').exists())
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment