From c0ea60e5aea477cadaaba0f793d7631e98fe77d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Torbjo=CC=88rn=20Einarsson?=
 <torbjorn.einarsson@edgeware.tv>
Date: Mon, 11 Mar 2019 12:28:17 +0100
Subject: [PATCH] Factored backup of files to be changed to separate module

---
 python/dash_tools/backup_handler.py         | 24 +++++++++++++++++++++
 python/dash_tools/initcleaner.py            | 12 +++++++----
 python/dash_tools/mediacleaner.py           | 10 +++++----
 python/dash_tools/ondemand_creator.py       | 14 ++++++------
 python/dash_tools/restore_from_bup.py       |  7 ++++--
 python/dash_tools/shift_composition_time.py |  7 +++++-
 python/dash_tools/stppfixer.py              |  9 +++++---
 python/dash_tools/track_resegmenter.py      | 15 ++++++-------
 8 files changed, 69 insertions(+), 29 deletions(-)
 create mode 100644 python/dash_tools/backup_handler.py

diff --git a/python/dash_tools/backup_handler.py b/python/dash_tools/backup_handler.py
new file mode 100644
index 0000000..528e645
--- /dev/null
+++ b/python/dash_tools/backup_handler.py
@@ -0,0 +1,24 @@
+"""Simple handling of backup of media files.
+
+Creates a file with _bup ending if not already avaliable.
+"""
+import os
+from shutil import copy2
+
+BACKUP_FILE_SUFFIX = "_bup"
+
+
+class BackupError(Exception):
+    "Problem in moving file to backup location."
+
+
+def make_backup(filepath):
+    "Copy filepath to backuppath. Raise BackupError if not possible."
+    backup_path = filepath + BACKUP_FILE_SUFFIX
+    if os.path.exists(backup_path):
+        raise BackupError("Backup file %s already exists" %
+                          backup_path)
+    try:
+        copy2(filepath, backup_path)
+    except IOError as err:
+        raise BackupError("IOError %s" % err)
diff --git a/python/dash_tools/initcleaner.py b/python/dash_tools/initcleaner.py
index c61b70b..a245747 100644
--- a/python/dash_tools/initcleaner.py
+++ b/python/dash_tools/initcleaner.py
@@ -32,9 +32,10 @@
 
 import sys
 import os
+
 from structops import uint32_to_str, str_to_uint32
 from mp4filter import MP4Filter
-
+from backup_handler import make_backup, BackupError
 
 class InitCleanFilter(MP4Filter):
     """Process an init file and clean it.
@@ -130,6 +131,7 @@ def process_tkhd(self, data):
         output += data[pos:]
         return output
 
+
 def main():
     "Command-line function."
     from optparse import OptionParser
@@ -142,9 +144,10 @@ def main():
         parser.error("Wrong number of arguments")
         sys.exit(1)
     for file_name in args:
-        bup_name = file_name + "_bup"
-        if os.path.exists(bup_name):
-            print "Backup-file %s already exists. Skipping file %s" % (bup_name, file_name)
+        try:
+            make_backup(file_name)
+        except BackupError:
+            print "Backup-file already exists. Skipping file %s" % file_name)
             continue
         init_cleaner = InitCleanFilter(file_name, new_track_id=options.track_id)
         print "Processing %s" % file_name
@@ -153,5 +156,6 @@ def main():
         with open(file_name, "wb") as ofh:
             ofh.write(output)
 
+
 if __name__ == "__main__":
     main()
diff --git a/python/dash_tools/mediacleaner.py b/python/dash_tools/mediacleaner.py
index c57e8d6..ffe2a5d 100644
--- a/python/dash_tools/mediacleaner.py
+++ b/python/dash_tools/mediacleaner.py
@@ -34,6 +34,7 @@
 import os
 from structops import uint32_to_str, str_to_uint32
 from mp4filter import MP4Filter
+from backup_handler import make_backup, BackupError
 
 
 class MediaCleanFilter(MP4Filter):
@@ -92,6 +93,7 @@ def process_tfhd(self, data):
         output += data[16:]
         return output
 
+
 def main():
     "Command-line function."
     from optparse import OptionParser
@@ -105,14 +107,14 @@ def main():
         parser.error("Wrong number of arguments")
         sys.exit(1)
     for file_name in args:
-        bup_name = file_name + "_bup"
-        if os.path.exists(bup_name):
-            print "Backup-file %s already exists. Skipping file %s" % (bup_name, file_name)
+        try:
+            make_backup(file_name)
+        except BackupError:
+            print "Backup-file already exists. Skipping file %s" % file_name)
             continue
         init_cleaner = MediaCleanFilter(file_name, new_track_id=options.track_id)
         print "Processing %s" % file_name
         output = init_cleaner.filter_top_boxes()
-        os.rename(file_name, bup_name)
         with open(file_name, "wb") as ofh:
             ofh.write(output)
 
diff --git a/python/dash_tools/ondemand_creator.py b/python/dash_tools/ondemand_creator.py
index e19dd1f..fa8a7cc 100644
--- a/python/dash_tools/ondemand_creator.py
+++ b/python/dash_tools/ondemand_creator.py
@@ -38,8 +38,8 @@
 from argparse import ArgumentParser
 
 from track_resegmenter import TrackResegmenter
+from backup_handler import make_backup, BackupError
 
-BACKUP_FILE_SUFFIX = "_bup"
 MP4BOX = "MP4Box"  # path to MP4Box of late-enough version.
 
 
@@ -170,16 +170,16 @@ def fix_sidx_ranges_in_mpd(self, mpd_file, sidx_ranges):
         output = StringIO()
         with open(mpd_file, 'rb') as ifh:
             self._fix_sidx_ranges(ifh, output, sidx_ranges)
-        move_file_to_backup(mpd_file)
+        try:
+            make_backup(mpd_file)
+        except BackupError:
+            print("Backupfile already exists. Will not overwrite %s" %
+                  mpd_file)
+            return
         with open(mpd_file, 'wb') as ofh:
             ofh.write(output.getvalue())
 
 
-def move_file_to_backup(file_path):
-    backup_file = file_path + BACKUP_FILE_SUFFIX
-    os.rename(file_path, backup_file)
-
-
 def main():
     parser = ArgumentParser(usage="usage: %(prog)s [options]")
 
diff --git a/python/dash_tools/restore_from_bup.py b/python/dash_tools/restore_from_bup.py
index ef3f0f0..675790d 100644
--- a/python/dash_tools/restore_from_bup.py
+++ b/python/dash_tools/restore_from_bup.py
@@ -32,7 +32,9 @@
 
 import os
 import sys
-BACKUP_ENDING = "_bup"
+
+from backup_handler import BACKUP_ENDING
+
 
 def main():
     "Command-line function."
@@ -48,11 +50,12 @@ def main():
     for file_name in args:
         if file_name.endswith(BACKUP_ENDING):
             old_name = file_name[:-len(BACKUP_ENDING)]
-            print "moving %s to %s" % (file_name, old_name)
+            print("moving %s to %s" % (file_name, old_name))
             if os.path.exists(old_name):
                 os.unlink(old_name)
             os.rename(file_name, old_name)
             continue
 
+
 if __name__ == "__main__":
     main()
diff --git a/python/dash_tools/shift_composition_time.py b/python/dash_tools/shift_composition_time.py
index c5ef11d..c0e3e5a 100644
--- a/python/dash_tools/shift_composition_time.py
+++ b/python/dash_tools/shift_composition_time.py
@@ -35,6 +35,7 @@
 from argparse import ArgumentParser
 
 from mp4filter import ShiftCompositionTimeOffset
+from backup_handler import make_backup, BackupError
 
 
 def process_files(files):
@@ -50,7 +51,11 @@ def process_files(files):
         if output != input:
             assert len(output) == len(input)
             print("Change in file %s. Make backup %s" % (f, f_backup))
-            os.rename(f, f_backup)
+            try:
+                make_backup(f)
+            except BackupError:
+                print("Cannot make backup for %s. Skipping it" % f)
+                return
             with open(f, 'wb') as ofh:
                 ofh.write(output)
 
diff --git a/python/dash_tools/stppfixer.py b/python/dash_tools/stppfixer.py
index 4f61e7e..9369996 100644
--- a/python/dash_tools/stppfixer.py
+++ b/python/dash_tools/stppfixer.py
@@ -34,6 +34,7 @@
 import os
 from structops import uint32_to_str, str_to_uint32
 from mp4filter import MP4Filter
+from backup_handler import make_backup, BackupError
 
 REPLACE_STRING = """</div>
  </body>
@@ -197,9 +198,10 @@ def main():
         parser.error("Wrong number of arguments")
         sys.exit(1)
     for file_name in args:
-        bup_name = file_name + "_bup"
-        if os.path.exists(bup_name):
-            print "Backup-file %s already exists. Skipping file %s" % (bup_name, file_name)
+        try:
+            make_backup(file_name)
+        except BackupError:
+            print("Backup-file already exists. Skipping file %s" % file_name)
             continue
         stpp_cleaner = STPPFixerFilter(file_name, new_track_id=options.track_id,
                                        new_default_sample_duration=options.dur)
@@ -209,5 +211,6 @@ def main():
         with open(file_name, "wb") as ofh:
             ofh.write(output)
 
+
 if __name__ == "__main__":
     main()
diff --git a/python/dash_tools/track_resegmenter.py b/python/dash_tools/track_resegmenter.py
index d1c0b9f..636f578 100644
--- a/python/dash_tools/track_resegmenter.py
+++ b/python/dash_tools/track_resegmenter.py
@@ -39,8 +39,7 @@
 from structops import str_to_uint16, uint16_to_str, uint32_to_str, sint32_to_str
 from structops import str_to_uint32, str_to_uint64, uint64_to_str
 from track_data_extractor import TrackDataExtractor
-
-BACKUP_FILE_SUFFIX = "_bup"
+from backup_handler import make_backup, BackupError
 
 SegmentData = namedtuple("SegmentData", "nr start dur size data")
 SegmentInfo = namedtuple("SegmentInfo", "start_nr end_nr start_time dur")
@@ -89,7 +88,12 @@ def resegment(self):
             segment_sizes.append(len(output_segment))
         if self.output_file:
             if self.output_file == self.input_file:
-                move_file_to_backup(self.input_file)
+                try:
+                    make_backup(self.input_file)
+                except BackupError:
+                    print("Backup file for %s already exists" %
+                          self.input_file)
+                    return
             with open(self.output_file, "wb") as ofh:
                 input_header_end = self.input_parser.find_header_end()
                 ofh.write(ip.data[:input_header_end])
@@ -271,11 +275,6 @@ def nr_sample_bytes(sample_flags):
         return output
 
 
-def move_file_to_backup(file_path):
-    backup_file = file_path + BACKUP_FILE_SUFFIX
-    os.rename(file_path, backup_file)
-
-
 def main():
     parser = ArgumentParser(usage="usage: %(prog)s [options]")