def get_version_info(packages): try: raw_info = utils.xcmd('dpkg-query', '-Wf', '${db:Status-Abbrev}\t${Package}\t${Version}\n', *set(packages)) except subprocess.CalledProcessError as exc: raw_info = exc.output raw_info = raw_info.decode('ASCII') info = {} for line in raw_info.splitlines(): status, package, version = line.split('\t') info[package] = (status, version) return info
def pkginfo_for_deb(path): info = utils.xcmd('dpkg-deb', '-f', path, 'Package', 'Version', 'Architecture') info = info.decode('UTF-8') match = re.match( r'\A' r'Package:\s*(\S+)\n' r'Version:\s*(\S+)\n' r'Architecture:\s*(\S+)\n' r'\Z', info) if match is None: raise ValueError (package, version, architecture) = match.groups() if not deblogic.is_package_name(package): raise ValueError if not deblogic.is_package_version(version): raise ValueError if not deblogic.is_architecture(architecture): raise ValueError return (package, version, architecture)
def run(options): package = options.package source = None version = None architecture = None installed = False if utils.looks_like_path(package): path = package package = None try: os.stat(path) except OSError: options.error('{0!r} is not a package'.format(path)) if os.path.isdir(path + '/debian'): (source, version) = pkginfo_for_unpacked(path) elif path.endswith('.dsc'): (source, version) = pkginfo_for_dsc(path) elif path.endswith('.deb'): (package, version, architecture) = pkginfo_for_deb(path) else: options.error('{0!r} is not a package'.format(path)) elif package.startswith(('src:', 'source:')): (prefix, source) = package.split(':', 1) package = None elif package.endswith(':source'): (source, suffix) = package.rsplit(':', 1) package = None else: try: info = utils.xcmd( 'dpkg-query', '-Wf', '${Package}\x1F${Architecture}\x1F${Version}\x1F${Pre-Depends}\x1F${Depends}\x1F${Recommends}\x1F${Suggests}\n', package) except subprocess.CalledProcessError: pass else: info = info.decode('ASCII') info = info.splitlines() if len(info) != 1: options.error('ambiguous package name: {0!r}'.format(package)) [package, architecture, version, *dep_lists] = info[0].split('\x1F') if version: dep_lists = [list(flatten_depends(d)) for d in dep_lists] dep_lists[0][:0] = dep_lists.pop( 0) # merge Depends + Pre-Depends dverbs = ['depends on', 'recommends', 'suggests'] installed = True else: del dep_lists body = [] def a(s=''): body.append(s) if package: a('Package: {pkg}'.format(pkg=package)) if source: a('Source: {src}'.format(src=source)) if version: a('Version: {ver}'.format(ver=version)) if options.severity is not None: a('Severity: {sev}'.format(sev=options.severity)) a() a() if installed or architecture: a('-- System Information:') if installed and architecture == 'all': architecture = dpkg_get_architecture() a('Architecture: {arch}'.format(arch=architecture)) a() if installed: seen = set() version_info = get_version_info(itertools.chain(*dep_lists)) for deps, dverb in zip(dep_lists, dverbs): deptable = Table() for dep in deps: if dep not in seen: try: (status, version) = version_info[dep] except KeyError: status = 'un' version = None version = version or '<none>' deptable.add(status, dep, version) seen.add(dep) if deptable: a('Versions of packages {pkg} {verb}:'.format(pkg=package, verb=dverb)) a(str(deptable)) a() body = '\n'.join(body) subject = '{pkg}:'.format(pkg=(package or source)) url = 'mailto:[email protected]?' + urlencode(subject=subject, body=body) cmdline = [ 'neomutt', '-e', 'my_hdr X-Debbugs-No-Ack: please', '-e', 'my_hdr X-Debbugs-Cc: $from', ] if options.attach: print(repr(options.attach)) cmdline += ['-a'] cmdline += options.attach cmdline += ['--', url] os.execvp(cmdline[0], cmdline)
def dpkg_get_architecture(): info = utils.xcmd('dpkg', '--print-architecture') info = info.decode('ASCII') return info.rstrip()
def select_for_deb(path): pkg = utils.xcmd('dpkg-deb', '-f', path, 'Package') pkg = pkg.decode('ASCII').strip() return [{'package': pkg}]