From 62bf675736cb5f13d9395d229f9a76299104a64e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= <sybren@stuvel.eu>
Date: Fri, 27 Jan 2017 12:57:31 +0100
Subject: [PATCH] Worker: move_out_of_way cmd now handles existing destination
 dirs

When 'src' needs to be moved to 'dst', but 'dst' already exists, the
command finds a suffix that doesn't exist yet.
---
 .../flamenco_worker/runner.py                 | 15 +++++++
 .../tests/test_runner_move_out_of_way.py      | 42 +++++++++++++++++++
 2 files changed, 57 insertions(+)

diff --git a/packages/flamenco-worker-python/flamenco_worker/runner.py b/packages/flamenco-worker-python/flamenco_worker/runner.py
index 194a152b..5c5bd549 100644
--- a/packages/flamenco-worker-python/flamenco_worker/runner.py
+++ b/packages/flamenco-worker-python/flamenco_worker/runner.py
@@ -274,6 +274,21 @@ class MoveOutOfWayCommand(AbstractCommand):
         mdatetime = datetime.fromtimestamp(mtime)
         dst = src.with_name('%s-%s' % (src.name, mdatetime.isoformat()))
 
+        if dst.exists():
+            self._log.debug('Destination %s exists, finding one that does not', dst)
+            # See which suffixes are in use
+            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.info('Moving %s to %s', src, dst)
         await self.worker.register_log('%s: Moving %s to %s', self.command_name, src, dst)
         src.rename(dst)
diff --git a/packages/flamenco-worker-python/tests/test_runner_move_out_of_way.py b/packages/flamenco-worker-python/tests/test_runner_move_out_of_way.py
index 59cba3f5..9b2d4ed6 100644
--- a/packages/flamenco-worker-python/tests/test_runner_move_out_of_way.py
+++ b/packages/flamenco-worker-python/tests/test_runner_move_out_of_way.py
@@ -34,6 +34,8 @@ class MoveOutOfWayTest(AbstractCommandTest):
 
         src = Path(self.tmpdir.name) / 'existing-dir'
         src.mkdir()
+        (src / 'src-contents').touch()
+
         os.utime(str(src), (1330712280, 1330712292))  # fixed (atime, mtime) for testing
 
         task = self.cmd.run({'src': str(src)})
@@ -60,3 +62,43 @@ class MoveOutOfWayTest(AbstractCommandTest):
         self.assertTrue(dst.exists())
         self.assertTrue(dst.is_file())
         self.assertFalse(src.exists())
+
+    def test_existing_source_and_dest(self):
+        from pathlib import Path
+        import os
+
+        src = Path(self.tmpdir.name) / 'existing-dir'
+        src.mkdir()
+        (src / 'src-contents').touch()
+        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.mkdir()
+        (existing_dst / 'dst-existing-contents').touch()
+
+        existing_dst2 = src.with_name('existing-dir-2012-03-02T19:18:12-2')
+        existing_dst2.mkdir()
+        (existing_dst2 / 'dst2-existing-contents').touch()
+
+        existing_dst4 = src.with_name('existing-dir-2012-03-02T19:18:12-4')
+        existing_dst4.mkdir()
+        (existing_dst4 / 'dst4-existing-contents').touch()
+
+        task = self.cmd.run({'src': str(src)})
+        ok = self.loop.run_until_complete(task)
+        self.assertTrue(ok)
+
+        # The existing destination directories should not have been touched.
+        self.assertTrue(existing_dst.exists())
+        self.assertTrue(existing_dst2.exists())
+        self.assertTrue(existing_dst4.exists())
+        self.assertTrue((existing_dst / 'dst-existing-contents').exists())
+        self.assertTrue((existing_dst2 / 'dst2-existing-contents').exists())
+        self.assertTrue((existing_dst4 / 'dst4-existing-contents').exists())
+
+        # The source should have been moved to the new destination.
+        new_dst = existing_dst.with_name('existing-dir-2012-03-02T19:18:12-5')
+        self.assertTrue(new_dst.exists())
+        self.assertTrue((new_dst / 'src-contents').exists())
+
+        self.assertFalse(src.exists())
-- 
GitLab