def compare_commented_files(file1, file2, comment=None, source=None): difference = compare_files(file1, file2, source=source) if comment: if difference is None: difference = Difference(None, file1.name, file2.name) difference.add_comment(comment) return difference
def _compare_using_details(self, other, source): details = [d for d in self.compare_details(other, source) if d is not None] if len(details) == 0: return None difference = Difference(None, self.name, other.name, source=source) difference.add_details(details) return difference
def compare_details(self, other, source=None): differences = [] for field in sorted(set(self.deb822.keys()).union(set(other.deb822.keys()))): if field.startswith('Checksums-') or field == 'Files': continue my_value = '' if field in self.deb822: my_value = self.deb822.get_as_string(field).lstrip() other_value = '' if field in other.deb822: other_value = other.deb822.get_as_string(field).lstrip() differences.append(Difference.from_text( my_value, other_value, self.path, other.path, source=field)) # compare Files as string if self.deb822.get('Files'): differences.append(Difference.from_text(self.deb822.get_as_string('Files'), other.deb822.get_as_string('Files'), self.path, other.path, source='Files')) else: differences.append(Difference.from_text(self.deb822.get_as_string('Checksums-Sha256'), other.deb822.get_as_string('Checksums-Sha256'), self.path, other.path, source='Checksums-Sha256')) return differences
def compare_details(self, other, source=None): differences = [] differences.append(Difference.from_command(SquashfsSuperblock, self.path, other.path)) differences.append(Difference.from_command(SquashfsListing, self.path, other.path)) with SquashfsContainer(self).open() as my_container, \ SquashfsContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def compare_binary_files(file1, file2, source=None): try: with xxd(file1.path) as xxd1, xxd(file2.path) as xxd2: return Difference.from_raw_readers(xxd1, xxd2, file1.name, file2.name, source) except RequiredToolNotFound: hexdump1 = hexdump_fallback(file1.path) hexdump2 = hexdump_fallback(file2.path) comment = 'xxd not available in path. Falling back to Python hexlify.\n' return Difference.from_text(hexdump1, hexdump2, file1.name, file2.name, source, comment)
def compare_binary_files(file1, file2, source=None): import diffoscope.comparators.utils try: return Difference.from_command(diffoscope.comparators.utils.Xxd, file1.path, file2.path, source=[file1.name, file2.name]) except RequiredToolNotFound: hexdump1 = hexdump_fallback(file1.path) hexdump2 = hexdump_fallback(file2.path) comment = 'xxd not available in path. Falling back to Python hexlify.\n' return Difference.from_text(hexdump1, hexdump2, file1.name, file2.name, source, comment)
def compare_details(self, other, source=None): differences = [] # look up differences in metadata zipinfo_difference = Difference.from_command(Zipinfo, self.path, other.path) or \ Difference.from_command(ZipinfoVerbose, self.path, other.path) differences.append(zipinfo_difference) with ZipContainer(self).open() as my_container, \ ZipContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def compare_details(self, other, source=None): differences = [] differences.append(Difference.from_command(ISO9660PVD, self.path, other.path)) differences.append(Difference.from_command(ISO9660Listing, self.path, other.path)) for extension in ('joliet', 'rockridge'): try: differences.append(Difference.from_command(ISO9660Listing, self.path, other.path, command_args=(extension,))) except subprocess.CalledProcessError: pass # probably no joliet or rockridge data return differences
def _compare_using_details(self, other, source): details = [] if hasattr(self, 'compare_details'): details.extend(filter(None, self.compare_details(other, source))) if self.as_container: details.extend(filter(None, self.as_container.compare(other.as_container))) if not details: return None difference = Difference(None, self.name, other.name, source=source) difference.add_details(details) return difference
def compare_details(self, other, source=None): differences = [] differences.append(Difference.from_command(ISO9660PVD, self.path, other.path)) differences.append(Difference.from_command(ISO9660Listing, self.path, other.path)) for extension in ('joliet', 'rockridge'): try: differences.append(Difference.from_command(ISO9660Listing, self.path, other.path, command_args=(extension,))) except subprocess.CalledProcessError: pass # probably no joliet or rockridge data with LibarchiveContainer(self).open() as my_container, \ LibarchiveContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def compare(self, other, source=None): my_encoding = self.encoding or 'utf-8' other_encoding = other.encoding or 'utf-8' try: with codecs.open(self.path, 'r', encoding=my_encoding) as my_content, \ codecs.open(other.path, 'r', encoding=other_encoding) as other_content: difference = Difference.from_text_readers(my_content, other_content, self.name, other.name, source) if my_encoding != other_encoding: if difference is None: difference = Difference(None, self.path, other.path, source) difference.add_details([Difference.from_text(my_encoding, other_encoding, None, None, source='encoding')]) return difference except (LookupError, UnicodeDecodeError): # unknown or misdetected encoding return self.compare_bytes(other, source)
def compare_details(self, other, source=None): differences = [] differences.append(Difference.from_text_readers(list_libarchive(self.path), list_libarchive(other.path), self.path, other.path, source="file list")) differences.extend(_compare_elf_data(self.path, other.path)) return differences
def compare_details(self, other, source=None): return [Difference.from_text( json.dumps(self.parsed, indent=4, sort_keys=True), json.dumps(other.parsed, indent=4, sort_keys=True), self, other, )]
def compare_details(self, other, source=None): differences = [] with TarContainer(self).open() as my_container, \ TarContainer(other).open() as other_container: differences.append(Difference.from_command(TarListing, self.path, other.path)) differences.extend(my_container.compare(other_container)) return differences
def compare_details(self, other, source=None): differences = [] differences.append(Difference.from_command( CpioContent, self.path, other.path, source="file list")) with LibarchiveContainer(self).open() as my_container, \ LibarchiveContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def compare_details(self, other, source=None): differences = [] differences.append(Difference.from_text( self.magic_file_type, other.magic_file_type, self, other, source='metadata')) with GzipContainer(self).open() as my_container, \ GzipContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def compare_details(self, other, source=None): differences = [] ignore_files = self.container.source.container.source.files_with_same_content_in_data with DebTarContainer(self, ignore_files).open() as my_container, \ DebTarContainer(other, ignore_files).open() as other_container: differences.append(Difference.from_command(TarListing, self.path, other.path)) differences.extend(my_container.compare(other_container)) return differences
def compare(self, other, source=None): differences = [] try: find_diff = Difference.from_command(FindAll, self.path, other.path) if find_diff: differences.append(find_diff) except RequiredToolNotFound: logger.info("Unable to find 'getfacl'.") differences.extend(compare_meta(self.name, other.name)) with DirectoryContainer(self).open() as my_container, \ DirectoryContainer(other).open() as other_container: my_names = my_container.get_member_names() other_names = other_container.get_member_names() for name in sorted(set(my_names).intersection(other_names)): my_file = my_container.get_member(name) other_file = other_container.get_member(name) with my_file.get_content(), other_file.get_content(): inner_difference = diffoscope.comparators.compare_files( my_file, other_file, source=name) meta_differences = compare_meta(my_file.name, other_file.name) if meta_differences and not inner_difference: inner_difference = Difference(None, my_file.path, other_file.path) if inner_difference: inner_difference.add_details(meta_differences) differences.append(inner_difference) if not differences: return None difference = Difference(None, self.path, other.path, source) difference.add_details(differences) return difference
def compare(self, other, source=None): differences = [] try: listing_diff = Difference.from_text('\n'.join(list_files(self.path)), '\n'.join(list_files(other.path)), self.path, other.path, source='file list') if listing_diff: differences.append(listing_diff) except RequiredToolNotFound: logger.info("Unable to find 'getfacl'.") differences.extend(compare_meta(self.name, other.name)) my_container = DirectoryContainer(self) other_container = DirectoryContainer(other) my_names = my_container.get_member_names() other_names = other_container.get_member_names() for name in sorted(set(my_names).intersection(other_names)): my_file = my_container.get_member(name) other_file = other_container.get_member(name) inner_difference = diffoscope.comparators.compare_files( my_file, other_file, source=name) meta_differences = compare_meta(my_file.name, other_file.name) if meta_differences and not inner_difference: inner_difference = Difference(None, my_file.path, other_file.path) if inner_difference: inner_difference.add_details(meta_differences) differences.append(inner_difference) if not differences: return None difference = Difference(None, self.path, other.path, source) difference.add_details(differences) return difference
def compare_details(self, other, source=None): differences = [] # look up differences in metadata content1 = get_ar_content(self.path) content2 = get_ar_content(other.path) differences.append(Difference.from_text( content1, content2, self.path, other.path, source="metadata")) differences.extend(_compare_elf_data(self.path, other.path)) return differences
def compare_rpm_headers(path1, path2): # compare headers with get_temporary_directory() as rpmdb_dir: rpm.addMacro("_dbpath", rpmdb_dir) ts = rpm.TransactionSet() ts.setVSFlags(-1) header1 = get_rpm_header(path1, ts) header2 = get_rpm_header(path2, ts) return Difference.from_text(header1, header2, path1, path2, source="header")
def compare_meta(path1, path2): logger.debug('compare_meta(%s, %s)', path1, path2) differences = [] try: differences.append(Difference.from_command(Stat, path1, path2)) except RequiredToolNotFound: logger.warn("'stat' not found! Is PATH wrong?") try: lsattr1 = lsattr(path1) lsattr2 = lsattr(path2) differences.append(Difference.from_text( lsattr1, lsattr2, path1, path2, source="lattr")) except RequiredToolNotFound: logger.info("Unable to find 'lsattr'.") try: differences.append(Difference.from_command(Getfacl, path1, path2)) except RequiredToolNotFound: logger.info("Unable to find 'getfacl'.") return [d for d in differences if d is not None]
def compare_details(self, other, source=None): differences = [] my_content = get_ar_content(self.path) other_content = get_ar_content(other.path) differences.append(Difference.from_text( my_content, other_content, self.path, other.path, source="metadata")) with DebContainer(self).open() as my_container, \ DebContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def test_trim_stderr_in_command(): class FillStderr(Command): def cmdline(self): return ['tee', '/dev/stderr'] def feed_stdin(self, stdin): for dummy in range(0, Command.MAX_STDERR_LINES + 1): stdin.write('error {}\n'.format(self.path).encode('utf-8')) difference = Difference.from_command(FillStderr, 'dummy1', 'dummy2') assert '[ 1 lines ignored ]' in difference.comment
def compare(self, other, source=None): differences = super().compare(other, source) details = None try: details = Difference.from_command(Pstotext, self.path, other.path) except RequiredToolNotFound: logger.debug('ps2ascii not found') if details: differences.add_details([details]) return differences
def compare_details(self, other, source=None): differences = [] # Check for fat binaries, trigger a difference if the architectures differ my_archs = MachoFile.get_arch_from_macho(self.path) other_archs = MachoFile.get_arch_from_macho(other.path) differences.append(Difference.from_text('\n'.join(my_archs), '\n'.join(other_archs), self.name, other.name, source='architectures')) # Compare common architectures for differences for common_arch in set(my_archs) & set(other_archs): differences.append(Difference.from_command(OtoolHeaders, self.path, other.path, command_args=[common_arch], comment="Mach-O headers for architecture %s" % common_arch)) differences.append(Difference.from_command(OtoolLibraries, self.path, other.path, command_args=[common_arch], comment="Mach-O load commands for architecture %s" % common_arch)) differences.append(Difference.from_command(OtoolDisassemble, self.path, other.path, command_args=[common_arch], comment="Code for architecture %s" % common_arch)) return differences
def compare_details(self, other, source=None): differences = [] my_fs = '' other_fs = '' if hasattr(self.as_container, 'fs'): my_fs = self.as_container.fs if hasattr(other.as_container, 'fs'): other_fs = other.as_container.fs if my_fs != other_fs: differences.append(Difference.from_text(my_fs, other_fs, None, None, source="filesystem")) return differences
def compare_details(self, other, source=None): differences = [] with FsImageContainer(self).open() as my_container, \ FsImageContainer(other).open() as other_container: my_fs = '' other_fs = '' if hasattr(my_container, 'fs'): my_fs = my_container.fs if hasattr(other_container, 'fs'): other_fs = other_container.fs if my_fs != other_fs: differences.append(Difference.from_text(my_fs, other_fs, None, None, source="filesystem")) differences.extend(my_container.compare(other_container)) return differences
def compare_details(self, other, source=None): differences = [] for field in sorted(set(self.deb822.keys()).union(set(other.deb822.keys()))): if field.startswith('Checksums-') or field == 'Files': continue my_value = '' if field in self.deb822: my_value = self.deb822.get_as_string(field).lstrip() other_value = '' if field in other.deb822: other_value = other.deb822.get_as_string(field).lstrip() differences.append(Difference.from_text( my_value, other_value, self.path, other.path, source=field)) # compare Files as string differences.append(Difference.from_text(self.deb822.get_as_string('Files'), other.deb822.get_as_string('Files'), self.path, other.path, source='Files')) with DebControlContainer(self).open() as my_container, \ DebControlContainer(other).open() as other_container: differences.extend(my_container.compare(other_container)) return differences
def compare_details(self, other, source=None): return [ Difference.from_command( Odt2txt, self.path, other.path, source='odt2txt' ) ]
def _compare_elf_data(path1, path2): return [Difference.from_command(ReadelfAll, path1, path2), Difference.from_command(ReadelfDebugDump, path1, path2), Difference.from_command(ObjdumpDisassemble, path1, path2)]
def compare_details(self, other, source=None): return [Difference.from_command(ArSymbolTableDumper, self.path, other.path), Difference.from_text_readers(list_libarchive(self.path), list_libarchive(other.path), self.path, other.path, source="file list")]
def compare(self, other, source=None): with open(self.path) as my_content, \ open(other.path) as other_content: return Difference.from_text_readers(my_content, other_content, self.name, other.name, source=source, comment="device")
def compare_details(self, other, source=None): return [ Difference.from_command( Ocamlobjinfo, self.path, other.path, source="ocamlobjinfo" ) ]
def compare_details(self, other, source=None): self_path = ensure_archive_rdx(self) other_path = ensure_archive_rdx(other) return [Difference.from_command(RdbReader, self_path, other_path)]
def compare_details(self, other, source=None): return [ Difference.from_command(LlvmBcAnalyzer, self.path, other.path), Difference.from_command(LlvmBcDisassembler, self.path, other.path), ]
def compare_details(self, other, source=None): return [ Difference.from_command(JavaScriptBeautify, self.path, other.path) ]
def test_traverse_heapq(): d0 = Difference("0", "path1/a", "path2/a") d1 = Difference("012", "path1/b", "path2/b") d2 = Difference("01", "path1/c", "path2/c") d0.add_details([ Difference("012345678", "path1/a/1", "path2/a/1"), Difference("0123", "path1/a/2", "path2/a/2"), Difference("012", "path1/a/3", "path2/a/3"), ]) d1.add_details([ Difference("01234567", "path1/b/1", "path2/b/1"), Difference("01234", "path1/b/2", "path2/b/2"), Difference("012345", "path1/b/3", "path2/b/3"), ]) d2.add_details([ Difference("01", "path1/c/1", "path2/c/1"), Difference("0123456789", "path1/c/2", "path2/c/2"), Difference("0123456", "path1/c/3", "path2/c/3"), ]) diff = Difference("0123456789", "path1", "path2") diff.add_details([d0, d1, d2]) # traverse nodes in depth order, but at a given depth traverse the nodes # there from smallest diff (counted non-recursively) to largest def f(node, parscore): depth = parscore[0] + 1 if parscore else 0 return depth, node.size_self() assert_size(diff, 284) results = [d.source1[6:] for d in diff.traverse_heapq(f)] assert results == [ '', 'a', 'c', 'b', 'c/1', 'a/3', 'a/2', 'b/2', 'b/3', 'c/3', 'b/1', 'a/1', 'c/2', ]
def compare_details(self, other, source=None): return [Difference.from_command(DeviceTreeContents, self.path, other.path)]
def _compare_elf_data(path1, path2): return [ Difference.from_command(x, path1, path2) for x in list(READELF_COMMANDS) + READELF_DEBUG_DUMP_COMMANDS ]
def _compare_elf_data(path1, path2): return [ Difference.from_operation(x, path1, path2, ignore_returncodes={1}) for x in list(READELF_COMMANDS) ]
def compare_details(self, other, source=None): return [ Difference.from_command(SquashfsSuperblock, self.path, other.path), Difference.from_command(SquashfsListing, self.path, other.path), ]
def compare_details(self, other, source=None): zipinfo_difference = Difference.from_command( Zipinfo, self.path, other.path) or Difference.from_command( ZipinfoVerbose, self.path, other.path) return [zipinfo_difference]
def compare(self, other, source=None): return Difference(None, self.path, other.path, source='md5sums', comment="Files in package differs")
def compare_details(self, other, source=None): return [Difference.from_text(self.magic_file_type, other.magic_file_type, self, other, source='metadata')]
def compare(self, other, source=None): return Difference.from_operation(ReadElfSection, self.path, other.path, operation_args=[self._name])
def compare_details(self, other, source=None): return [Difference.from_command(AbootimgInfo, self.path, other.path)]
def compare_details(self, other, source=None): return [Difference.from_command(CbfsListing, self.path, other.path)]
def compare_details(self, other, source=None): return [Difference.from_command(Showttf, self.path, other.path)]
def compare_details(self, other, source=None): return [ Difference.from_command(Pdftotext, self.path, other.path), Difference.from_command(Pdftk, self.path, other.path) ]
def compare_details(self, other, source=None): return [Difference.from_command(CbfsListing, self.path, other.path)]