Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # courg_dpatch.py
- # Generate a delta of two directories using Google's Courgette
- #
- # Copyright (C) 2007 National Fitness Financial Systems
- # Written by Steven Willoughby (stevenw _at_ nffs _dot_ com)
- # Adapted with some script modifications by
- # Puligheddu Karsten Sascha (fwiffo _at_ ircom _dot_ net)
- # Conversion from Perl to Python with some additional changes
- # by nBurn
- #
- # This program is free software; you can redistribute it and/or
- # modify it under the terms of the GNU General Public License
- # as published by the Free Software Foundation; either version 2
- # of the License, or (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program; if not, write to the Free Software
- # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- import os, re, sys, shutil, subprocess
- from timeit import default_timer
- patch_error = False
- verbose = False
- courgette = r"path\\to\\courgette.executable" # replace with local path
- success_marker = "courgette_completed"
- deleted_files = "DELETED"
- total_size = 0
- delta_size = 0
- file2pat = ''
- def print_usage_and_exit():
- print("Usage:\n" +
- " courg_dpatch [-v] delta old new patch_to_make\n" +
- " courg_dpatch [-v] patch patch_location old patch_output\n")
- sys.exit()
- def main():
- global verbose, patch_error, success_marker
- global total_size, delta_size
- start = default_timer()
- if len(sys.argv) == 6:
- if sys.argv[1] in ('-v', '--v', '-verbose', '--verbose'):
- verbose = True
- else:
- print_usage_and_exit()
- elif len(sys.argv) != 5:
- print_usage_and_exit()
- mode = sys.argv[-4]
- if mode == 'delta':
- old_dir = sys.argv[-3]
- new_dir = sys.argv[-2]
- patch_dir = sys.argv[-1]
- print("mode:", mode) # debug
- print("old_dir:", old_dir) # debug
- print("new_dir:", new_dir) # debug
- print("patch_dir:", patch_dir) # debug
- if os.path.exists(patch_dir):
- print("Patch directory '%s' exists, delete it!" % patch_dir)
- sys.exit()
- dir_delta(old_dir, new_dir, patch_dir)
- with open(os.path.join(patch_dir, success_marker), 'w') as wf:
- wf.write("1")
- info("xdelta completed!\n\n")
- #print("xdelta completed! total_size: %s\n\n" % total_size) # debug
- if total_size != 0:
- '''
- #info("original size: %5i MB delta: %4i MB reduction: %4.2f%%\n" % (
- total_size / 1024 / 1024,
- delta_size / 1024 / 1024,
- delta_size / total_size * 100))
- '''
- print("original size: %5i B delta: %4i B reduction: %4.2f%%\n" % (
- total_size,
- delta_size,
- delta_size / total_size * 100))
- elif mode == 'patch':
- patch_dir = sys.argv[-3]
- old_dir = sys.argv[-2]
- new_dir = sys.argv[-1]
- print("mode:", mode) # debug
- print("patch_dir:", patch_dir) # debug
- print("old_dir:", old_dir) # debug
- print("new_dir:", new_dir) # debug
- if not os.path.exists(os.path.join(patch_dir, success_marker)):
- # No 'success_marker' found in patch directory
- print("File '%s' missing, the directory '%s' does not contain correct data..." %
- (success_marker, patch_dir))
- sys.exit()
- if os.path.exists(new_dir):
- #print("Warning: The destination directory already exists!", file=sys.stderr)
- print("Destination directory '%s' exists, delete it!" % new_dir)
- sys.exit()
- dir_patch(patch_dir, old_dir, new_dir)
- if not patch_error:
- print("Patch completed!\n")
- else:
- print("Patch completed with ERRORS!\n")
- else:
- print("Unknown mode '%s'" % mode)
- sys.exit()
- print("Total time: %4.2f seconds" % (default_timer() - start))
- sys.exit()
- def info(message):
- global verbose
- if verbose:
- print(message, file=sys.stderr)
- def call(cmds):
- subprocess.call(cmds) # popen ?
- '''
- if(defined wantarray): # if call run in SCALER context (or list?)
- # bitshift 8 unless system failed to execute or child died with signal
- return $? >> 8 unless $? == -1 || $? & 127
- global patch_error, file2pat
- if ($?): # if system status not zero or undefined
- if $?: print("Can not apply patch: %s\n" % file2pat)
- patch_error = True
- '''
- def dir_delta(old_dir, new_dir, patch_dir):
- global deleted_files, success_marker, total_size, delta_size, courgette
- info("Directory: %s\n" % new_dir)
- os.mkdir(patch_dir)
- # To avoid missing dir in old causing xdelta to quit in unexpected manner...
- if not os.path.isdir(old_dir):
- os.mkdir(old_dir)
- old_files = {i:1 for i in os.listdir(old_dir)}
- new_files = {i:1 for i in os.listdir(new_dir)}
- with open(os.path.join(patch_dir, success_marker), 'w') as wf:
- wf.write("1")
- # just note deleted files and dirs and write a file where we keep this note...
- for i in sorted(old_files.keys()):
- # Note deleted dirs or files
- if i in new_files:
- continue
- elif os.path.isdir(os.path.join(old_dir, i)):
- info("Directory deleted: %s\n" % os.path.join(old_dir, i))
- else:
- info("File deleted: %s\n" % os.path.join(old_dir, i))
- with open(deleted_files, 'a') as df:
- df.write(os.path.join(old_dir, i) + "\n")
- for i in sorted(new_files.keys()):
- old = os.path.join(old_dir, i)
- new = os.path.join(new_dir, i)
- patch = os.path.join(patch_dir, i)
- # directories
- if os.path.isdir(new):
- dir_delta(old, new, patch)
- continue
- patch += ".courgette"
- #cmd = ['xdelta3', '-0', '-D', '-R', '-q']
- # created files
- if i in old_files and os.path.getsize(old) > 0 and \
- os.path.getsize(new) > 0:
- #call(['courgette64.exe', '-gen', old, new, patch])
- call([courgette, '-gen', old, new, patch])
- # cmd.extend(('-s', old))
- #print("Changed file: %s\n" % new) # debug
- info("Changed file: %s\n" % new)
- else:
- shutil.copy2(new, patch)
- #print("New file: %s\n" % new) # debug
- info("New file: %s\n" % new)
- #cmd.extend((new, patch))
- #call(cmd)
- total_size += os.path.getsize(new)
- delta_size += os.path.getsize(patch)
- #print("total_size: %s delta_size: %s\n" % (total_size, delta_size)) # debug
- def dir_patch(patch_dir, old_dir, new_dir):
- global success_marker, file2pat, courgette
- os.mkdir(new_dir)
- info("Directory: %s\n" % new_dir)
- for i in sorted(os.listdir(patch_dir)):
- if i == success_marker:
- continue
- patch = os.path.join(patch_dir, i)
- old = os.path.join(old_dir, i)
- new = os.path.join(new_dir, i)
- # directories
- if os.path.isdir(patch):
- dir_patch(patch, old, new)
- # changed and new files
- elif i.endswith(".courgette"):
- old = old[:-len('.courgette')]
- new = new[:-len('.courgette')]
- file2pat = old
- #cmd = ['xdelta3', '-d', '-q', '-D', '-R']
- if os.path.exists(old) and os.path.getsize(old) > 0 and \
- os.path.getsize(patch) > 0:
- call([courgette, '-apply', old, patch, new])
- info("Changed file: %s\n" % new)
- else:
- shutil.copy2(patch, new)
- info("New file: %s\n" % new)
- #cmd.extend((patch, new))
- #call(cmd)
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement