Show package and other improvements
Change-Id: I449a32a68be7d9c87c874c641b353866030297ae
Related-PROD: PROD-28199
diff --git a/cfg_checker/modules/packages/__init__.py b/cfg_checker/modules/packages/__init__.py
index f88ce51..77c1654 100644
--- a/cfg_checker/modules/packages/__init__.py
+++ b/cfg_checker/modules/packages/__init__.py
@@ -60,6 +60,16 @@
action="store_true", default=False,
help="Save pkg descriptions while parsing"
)
+ pkg_show = pkg_subparsers.add_parser(
+ 'show',
+ help="Show package history from the map"
+ )
+ pkg_show.add_argument(
+ 'args',
+ nargs='+',
+ help="Package names separated by space"
+ )
+
return _parser
@@ -89,6 +99,9 @@
"""
# Get the list of tags for the url
r = RepoManager()
+ if args.list_tags:
+ r.action_for_tag(args.url, args.tag, action="list")
+ return
if args.build_repos:
# if tag is supplied, use it
if args.tag:
@@ -96,7 +109,6 @@
else:
r.build_repos(args.url)
- # if tag is supplied, use it
if args.tag:
# Process only this tag
r.action_for_tag(
@@ -108,3 +120,13 @@
else:
# All of them
r.parse_repos()
+
+
+def do_show(args):
+ """Shows package (or multiple) history across parsed tags
+ """
+ # Init manager
+ r = RepoManager()
+ # show packages
+ for p in args.args:
+ r.show_package(p)
diff --git a/cfg_checker/modules/packages/repos.py b/cfg_checker/modules/packages/repos.py
index 2a91ed5..e592915 100644
--- a/cfg_checker/modules/packages/repos.py
+++ b/cfg_checker/modules/packages/repos.py
@@ -2,7 +2,7 @@
import os
from copy import deepcopy
-from cfg_checker.common import logger, logger_cli
+from cfg_checker.common import logger, logger_cli, nested_set
from cfg_checker.common.const import _pkg_desc_archive
from cfg_checker.common.const import _repos_index_filename
from cfg_checker.common.const import _repos_info_archive
@@ -20,6 +20,18 @@
ext = ".json"
+def get_tag_label(_tag):
+ # prettify the tag for printing
+ _label = ""
+ if _tag.endswith(".update"):
+ _label += "[updates] " + _tag.rsplit('.', 1)[0]
+ elif _tag.endswith(".hotfix"):
+ _label += " [hotfix] " + _tag.rsplit('.', 1)[0]
+ else:
+ _label += " "*10 + _tag
+ return _label
+
+
def _n_url(url):
if url[-1] == '/':
return url
@@ -236,21 +248,37 @@
return
- def list_tags(self):
+ def list_tags(self, splitted=False):
_files = TGZFile(self._repofile).list_files()
# all files in archive with no '.json' part
_all = set([f.rsplit('.', 1)[0] for f in _files])
- # files that ends with '.update'
- _updates = set([f for f in _all if f.find('update') >= 0])
- # files that ends with '.hotfix'
- _hotfix = set([f for f in _all if f.find('hotfix') >= 0])
- # remove updates and hotfix tags from all. The true magic of SETs
- _all = _all - _updates - _hotfix
- # cut updates and hotfix endings
- _updates = [f.rsplit('.', 1)[0] for f in _updates]
- _hotfix = [f.rsplit('.', 1)[0] for f in _hotfix]
+ if splitted:
+ # files that ends with '.update'
+ _updates = set([f for f in _all if f.find('update') >= 0])
+ # files that ends with '.hotfix'
+ _hotfix = set([f for f in _all if f.find('hotfix') >= 0])
+ # remove updates and hotfix tags from all. The true magic of SETs
+ _all = _all - _updates - _hotfix
+ # cut updates and hotfix endings
+ _updates = [f.rsplit('.', 1)[0] for f in _updates]
+ _hotfix = [f.rsplit('.', 1)[0] for f in _hotfix]
- return _all, _updates, _hotfix
+ return _all, _updates, _hotfix
+ else:
+ # dynamic import
+ import re
+ _all = list(_all)
+ # lexical tags
+ _lex = [s for s in _all if not s[0].isdigit()]
+ _lex.sort()
+ # tags with digits
+ _dig = [s for s in _all if s[0].isdigit()]
+ _dig = sorted(
+ _dig,
+ key=lambda x: tuple(int(i) for i in re.findall('\\d+', x)[:3])
+ )
+
+ return _dig + _lex
def get_repoinfo(self, tag):
_tgz = TGZFile(self._repofile)
@@ -489,7 +517,6 @@
_name = _desc['package']
_md5 = _desc['md5sum']
_version = _desc['version']
- _pkg['md5'] = _md5
# update version for a package
if self._update_pkg_version(
_name,
@@ -557,6 +584,16 @@
# and gather all of the repos for 'tag' or all of the tags
_repos.fetch_repos(url, tag=tag)
+ def _build_action(self, url, tags):
+ for t in tags:
+ logger_cli.info(
+ "# Building repo info for '{}/{}'".format(
+ url,
+ t
+ )
+ )
+ self.build_repos(url, tag=t)
+
def action_for_tag(
self,
url,
@@ -568,57 +605,124 @@
"""
if not action:
logger_cli.info("# No action set, nothing to do")
- # get all tags
- major, updates, hotfix = ReposInfo().list_tags()
+ # See if this is a list action
if action == "list":
+ _all = ReposInfo().list_tags()
+ # Print pretty list and exit
logger_cli.info("# Tags available at '{}':".format(url))
- for t in major:
- logger_cli.info("\t{}".format(t))
- for t in updates:
- logger_cli.info("\t{} [updates]".format(t))
- for t in hotfix:
- logger_cli.info("\t{} [hotfix]".format(t))
+ for t in _all:
+ logger_cli.info(get_tag_label(t))
+ # exit
return
+
# Pupulate action tags
+ major, updates, hotfix = ReposInfo().list_tags(splitted=True)
_action_tags = []
if tag in major:
_action_tags.append(tag)
- elif tag in updates:
+ if tag in updates:
_action_tags.append(tag + ".update")
- elif tag in hotfix:
+ if tag in hotfix:
_action_tags.append(tag + ".hotfix")
-
+ # Check if any tags collected
if not _action_tags:
logger_cli.info(
"# Tag of '{}' not found. "
"Consider rebuilding repos info.".format(tag)
)
- elif action == "build":
+ else:
logger_cli.info(
- "-> tags to build {}".format(", ".join(_action_tags))
- )
- for t in _action_tags:
- logger_cli.info(
- "# Building repo info for '{}/{}'".format(
- url,
- tag
- )
- )
- self.build_repos(url, tag=tag)
- elif action == "fetch":
- logger_cli.info(
- "-> fetching versions for tags {}".format(
+ "-> tags to process: {}".format(
", ".join(_action_tags)
)
)
+ # Execute actions
+ if action == "build":
+ self._build_action(url, _action_tags)
+ elif action == "fetch":
for t in _action_tags:
self.fetch_versions(t, descriptions=descriptions)
logger_cli.info("# Done.")
+ def show_package(self, name):
+ # get the package data
+ _p = self.get_package_versions(name)
+ if not _p:
+ logger_cli.warning(
+ "# WARNING: Package '{}' not found".format(name)
+ )
+ else:
+ # print package info using sorted tags from headers
+ # Package: name
+ # [u/h] tag \t <version>
+ # \t <version>
+ # <10symbols> \t <md5> \t sorted headers with no tag
+ # ...
+ logger_cli.info("\n# Package: {}".format(name))
+ _o = ""
+ # get and sort tags
+ _vs = _p.keys()
+ _vs.sort()
+ for _v in _vs:
+ _o += "\n" + " "*8 + _v + ':\n'
+ # get and sort tags
+ _mds = _p[_v].keys()
+ _mds.sort()
+ for _md5 in _mds:
+ _o += " "*16 + _md5 + "\n"
+ # get and sort repo headers
+ _rr = _p[_v][_md5].keys()
+ _rr.sort()
+ for _r in _rr:
+ _o += " "*24 + _r.replace('_', ' ') + "\n"
+
+ logger_cli.info(_o)
+
+ def get_package_versions(self, name, tagged=False):
+ """Method builds package version structure
+ with repository properties included
+ """
+ # get data
+ if name in self._versions:
+ _vs = self._versions[name]
+ else:
+ return {}
+ # insert repo data, insert props into headers place
+ _package = {}
+ if tagged:
+ for _v, _d1 in _vs.iteritems():
+ # use tag as a next step
+ for _md5, _repos in _d1.iteritems():
+ for _index in _repos:
+ # extract props for a repo
+ _repo_props = self._repo_index[_index]
+ # get tag
+ _tag = _repo_props["props"]["tag"]
+ # cut tag from the header
+ _cut_head = _repo_props["header"].split("_", 1)[1]
+ # populate dict
+ nested_set(
+ _package,
+ [_tag, _v, _cut_head, _md5],
+ _repo_props["props"]
+ )
+ else:
+ for _v, _d1 in _vs.iteritems():
+ for _md5, _repos in _d1.iteritems():
+ for _index in _repos:
+ _repo_props = self._repo_index[_index]
+ nested_set(
+ _package,
+ [_v, _md5, _repo_props["header"]],
+ _repo_props["props"]
+ )
+
+ return _package
+
def parse_repos(self):
# all tags to check
- major, updates, hotfix = ReposInfo().list_tags()
+ major, updates, hotfix = ReposInfo().list_tags(splitted=True)
# major tags
logger_cli.info("# Processing major tags")