def compare_root_paths(path1, path2): from ..directory import ( FilesystemDirectory, FilesystemFile, compare_directories, compare_meta, ) if not Config().new_file: bail_if_non_existing(path1, path2) if any_excluded(path1, path2): return None if os.path.isdir(path1) and os.path.isdir(path2): return compare_directories(path1, path2) container1 = FilesystemDirectory(os.path.dirname(path1)).as_container file1 = specialize(FilesystemFile(path1, container=container1)) container2 = FilesystemDirectory(os.path.dirname(path2)).as_container file2 = specialize(FilesystemFile(path2, container=container2)) difference = compare_files(file1, file2) if Config().exclude_directory_metadata in ('no', 'recursive'): meta = compare_meta(path1, path2) if meta: # Create an "empty" difference so we have something to attach file # metadata to. if difference is None: difference = Difference(None, file1.name, file2.name) difference.add_details(meta) return difference
def compare_files(file1, file2, source=None, diff_content_only=False): logger.debug( "Comparing %s (%s) and %s (%s)", file1.name, file1.__class__.__name__, file2.name, file2.__class__.__name__, ) if any_excluded(file1.name, file2.name): return None with profile('has_same_content_as', file1): if file1.has_same_content_as(file2): logger.debug( "has_same_content_as returned True; skipping further comparisons" ) return None if diff_content_only: difference = Difference(None, file1.name, file2.name) difference.add_comment("Files differ") return difference specialize(file1) specialize(file2) if isinstance(file1, MissingFile): file1.other_file = file2 elif isinstance(file2, MissingFile): file2.other_file = file1 elif file1.__class__.__name__ != file2.__class__.__name__: return file1.compare_bytes(file2, source) with profile('compare_files (cumulative)', file1): return file1.compare(file2, source)
def get_filtered_members(self): try: with libarchive.file_reader(self.source.path) as archive: for entry in archive: if any_excluded(entry.pathname): continue yield entry.pathname, self.get_subclass(entry) except libarchive.exception.ArchiveError: pass
def compare_root_paths(path1, path2): from ..directory import FilesystemDirectory, FilesystemFile, compare_directories if not Config().new_file: bail_if_non_existing(path1, path2) if any_excluded(path1, path2): return None if os.path.isdir(path1) and os.path.isdir(path2): return compare_directories(path1, path2) container1 = FilesystemDirectory(os.path.dirname(path1)).as_container file1 = specialize(FilesystemFile(path1, container=container1)) container2 = FilesystemDirectory(os.path.dirname(path2)).as_container file2 = specialize(FilesystemFile(path2, container=container2)) return compare_files(file1, file2)
def ensure_unpacked(self): if hasattr(self, '_members'): return tmpdir = get_temporary_directory().name self._members = collections.OrderedDict() logger.debug("Extracting %s to %s", self.source.path, tmpdir) with libarchive.file_reader(self.source.path) as archive: for idx, entry in enumerate(archive): # Always skip directories if entry.isdir: continue # Save extracting excluded files if any_excluded(entry.pathname): continue # Keep directory sizes small. could be improved but should be # good enough for "ordinary" large archives. dst = os.path.join(tmpdir, str(idx // 4096), str(idx % 4096)) root, ext = os.path.splitext(entry.pathname) dst += ext # Maintain a mapping of archive path to the extracted path, # avoiding the need to sanitise filenames. self._members[entry.pathname] = dst logger.debug("Extracting %s to %s", entry.pathname, dst) os.makedirs(os.path.dirname(dst), exist_ok=True) try: with open(dst, 'wb') as f: for block in entry.get_blocks(): f.write(block) except Exception as exc: raise ContainerExtractionError(entry.pathname, exc) logger.debug( "Extracted %d entries from %s to %s", len(self._members), self.source.path, tmpdir, )
def compare_files(file1, file2, source=None, diff_content_only=False): logger.debug( "Comparing %s (%s) and %s (%s)", file1.name, file1.__class__.__name__, file2.name, file2.__class__.__name__, ) if any_excluded(file1.name, file2.name): return None force_details = Config().force_details with profile('has_same_content_as', file1): has_same_content = file1.has_same_content_as(file2) if has_same_content: if not force_details: logger.debug( "has_same_content_as returned True; skipping further comparisons" ) return None if diff_content_only: return None elif diff_content_only: assert not has_same_content return Difference(None, file1.name, file2.name, comment="Files differ") specialize(file1) specialize(file2) if isinstance(file1, MissingFile): file1.other_file = file2 elif isinstance(file2, MissingFile): file2.other_file = file1 elif (file1.__class__.__name__ != file2.__class__.__name__) and ( file1.as_container is None or file2.as_container is None): return file1.compare_bytes(file2, source) with profile('compare_files (cumulative)', file1): return file1.compare(file2, source)