def search_for_files(self, files): # Make a set of all the requested files requested = dict((f.path, f) for f in self.filter_files(files)) found = {} # {path: pkgname} # Request a few files at a time so we don't hit the command-line size # limit iter_batch = iter(requested) while True: batch = list(itertools.islice(iter_batch, MAX_ARGV)) if not batch: break proc = subprocess.Popen(['dpkg-query', '-S'] + [path.path for path in batch], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = proc.communicate() for l in out.splitlines(): pkgname, path = l.split(b': ', 1) path = Path(path.strip()) # 8-bit safe encoding, because this might be a localized error # message (that we don't care about) pkgname = pkgname.decode('iso-8859-1') if ', ' in pkgname: # Multiple packages found[path] = None continue pkgname = pkgname.split(':', 1)[0] # Remove :arch if path in requested: if ' ' not in pkgname: # If we had assigned it to a package already, undo if path in found: found[path] = None # Else assign to the package else: found[path] = pkgname # Remaining files are not from packages self.unknown_files.update( f for f in files if f.path in requested and found.get(f.path) is None) nb_pkg_files = 0 for path, pkgname in iteritems(found): if pkgname is None: continue if pkgname in self.packages: package = self.packages[pkgname] else: package = self._create_package(pkgname) self.packages[pkgname] = package package.add_file(requested.pop(path)) nb_pkg_files += 1 logger.info("%d packages with %d files, and %d other files", len(self.packages), nb_pkg_files, len(self.unknown_files))
def _get_package_for_file(self, filename): p = subprocess.Popen(['dpkg', '-S', filename.path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() for l in out.splitlines(): pkgname, f = l.split(b': ', 1) f = Path(f.strip()) # 8-bit safe encoding, because this might be a localized error # message (that we don't care about) pkgname = (pkgname.decode('iso-8859-1') .split(':', 1)[0]) # Removes :arch self.package_files[f] = pkgname if f == filename: if ' ' not in pkgname: return pkgname return None