def patch(self, old_dir, dest_dir, start_callback=None, progress_callback=None): """ Apply the patch to the content of ``old_dir`` and write the results in ``dest_dir``. """ # Read info file self.info = pickle.load(self.tar.extractfile(self.info_path)) # Patch files if start_callback is not None: # Count source files length = 0 for base, dirs, files in os.walk(old_dir): length += len(files) start_callback(stage="patch", length=length) index = 0 for base, dirs, files in os.walk(old_dir): sub_dir = sub_path(base, old_dir) dest_sub_dir = join(dest_dir, sub_dir) # Make directory if it does not exists yet if not isdir(dest_sub_dir): os.makedirs(dest_sub_dir) for file in files: patch_path = self.patch_path(sub_dir, file) src_file = join(base, file) dst_file = join(dest_sub_dir, file) if self.info.is_ext_file(patch_path): # File is not in the patch, copy it to the destination dir shutil.copy(src_file, dst_file) else: self.patch_file(src_file, dst_file, patch_path) if progress_callback is not None: index += 1 progress_callback(index=index) # Extract plain files plain_files = [m for m in self.tar.getmembers() if m.name.startswith(self.plain_prefix) and not m.isdir()] if start_callback is not None: start_callback(stage="plain", length=len(plain_files)) index = 0 for file in plain_files: outpath = join(dest_dir, sub_path(file.name, self.plain_prefix)) outdir = dirname(outpath) if not isdir(outdir): os.makedirs(outdir) infile = self.tar.extractfile(file) outfile = open(outpath, "wb") while True: data = infile.read(2**14) if not data: break outfile.write(data) outfile.close() if progress_callback is not None: index += 1 progress_callback(index=index)
def diff(self, old_dir, new_dir): """ Fill the TarFile with the differences between two directories. """ self.info = PatchInfo() # Write patches and plain files for base, dirs, files in os.walk(old_dir): sub_dir = sub_path(base, old_dir) new_sub_dir = join(new_dir, sub_dir) if not os.path.isdir(new_sub_dir): # Directory not present in the new version, simply don't # include it in the patch continue # Create files diffs for file in files: old_file = join(base, file) new_file = join(new_sub_dir, file) if isfile(new_file): # File is present on both sides, store binary diff self.store_diff(self.patch_path(sub_dir, file), old_file, new_file) # Search for new files and directories for item in os.listdir(new_sub_dir): item_path = join(new_sub_dir, item) if isfile(item_path): if item not in files: self.tar.add(item_path, self.plain_path(sub_dir, item)) elif isdir(item_path): if item not in dirs: self.tar.add(item_path, self.plain_path(sub_dir, item)) # Write info file data = pickle.dumps(self.info) info = tarfile.TarInfo(self.info_path) info.size = len(data) self.tar.addfile(info, StringIO(data))
def append_tree(self, dir, output, files_list): for base, dirs, files in os.walk(dir): sub_dir = sub_path(base, dir) for file in files: files_list.append((os.path.join(output, sub_dir, file), os.path.join(base, file)))