diff --git a/library/packaging/apt b/library/packaging/apt index 27c0ca4f920..acc61b6c67b 100644 --- a/library/packaging/apt +++ b/library/packaging/apt @@ -29,7 +29,7 @@ version_added: "0.0.2" options: pkg: description: - - A package name or package specifier with version, like C(foo) or C(foo=1.0) + - A package name or package specifier with version, like C(foo) or C(foo=1.0). Shell like wildcards (fnmatch) like apt* are also supported. required: false default: null state: @@ -169,8 +169,30 @@ def package_status(m, pkgname, version, cache, state): #assume older version of python-apt is installed return pkg.isInstalled, pkg.isUpgradable, has_files +def expand_pkgspec_from_fnmatches(m, pkgspec, cache): + new_pkgspec = [] + for pkgname_or_fnmatch_pattern in pkgspec: + # note that any of these chars is not allowed in a (debian) pkgname + if [c for c in pkgname_or_fnmatch_pattern if c in "*?[]!"]: + if "=" in pkgname_or_fnmatch_pattern: + m.fail_json(msg="pkgname wildcard and version can not be mixed") + # handle multiarch pkgnames, the idea is that "apt*" should + # only select native packages. But "apt*:i386" should still work + if not ":" in pkgname_or_fnmatch_pattern: + matches = fnmatch.filter( + [pkg.name for pkg in cache + if not ":" in pkg.name], pkgname_or_fnmatch_pattern) + else: + matches = fnmatch.filter( + [pkg.name for pkg in cache], pkgname_or_fnmatch_pattern) + new_pkgspec.extend(matches) + else: + new_pkgspec.append(pkgname_or_fnmatch_pattern) + return new_pkgspec + def install(m, pkgspec, cache, upgrade=False, default_release=None, install_recommends=True, force=False): packages = "" + pkgspec = expand_pkgspec_from_fnmatches(m, pkgspec, cache) for package in pkgspec: name, version = package_split(package) installed, upgradable, has_files = package_status(m, name, version, cache, state='install')