Commit 1e0c53e5 authored by Sebastien Luttringer's avatar Sebastien Luttringer
Browse files

Image are not searched in search path

Image are not crawled anymore in all repositories by default
You needs to specify a list of repo to look in
parent 9e8fc553
Loading
Loading
Loading
Loading
+59 −23
Original line number Diff line number Diff line
@@ -24,6 +24,10 @@ from installsystems.repository import RepositoryConfig
from installsystems.image import PackageImage, SourceImage
from installsystems.config import MainConfigFile, RepoConfigFile

################################################################################
# Common functions
################################################################################

def load_repositories(args):
    '''
    Load repositories on a repository manager
@@ -31,6 +35,10 @@ def load_repositories(args):
    # remove cache is asked
    if hasattr(args, "no_cache") and args.no_cache:
        args.cache = None
    # split filter in list
    if args.repo_filter is not None:
        args.repo_filter = [f for f in  re.split("[ ,\n\t\v]+", args.repo_filter)
                            if f != ""]
    # init repo cache object
    repoman = RepositoryManager(args.cache, timeout=args.timeout, filter=args.repo_filter)
    # register repositories (order matter)
@@ -56,19 +64,37 @@ def select_image(name, repoman, best=False):

    Return the repository as second argument
    '''
    # image is a local file
    if istools.isfile(name) and os.path.isfile(name):
        return PackageImage(name), None
    # we need to find image in a repository
    else:
        x = re.match("^(([-_\w]+)/)?([-_\w]+)(:v?(\d+))?$", name)
        if x is None:
            raise Exception("%s is not a valid image" % name)
        (repo, image, version) = x.group(2,3,5)
        debug("Selected image is %s v%s in %s" % (image, version, repo))
        if len(repoman.onlines) == 0:
            raise Exception('No online repository')
        (repo, image, version) = istools.split_image_path(name)
        debug("Requested image: %s v%s in %s" % (image, version, repo))
        # repo is not specified, we need to crawl in path
        if repo is None:
            return repoman.get(image, version, best)
            # split search path as a list
            if args.repo_search is not None:
                args.repo_search = [s for s in re.split("[ ,\n\t\v]+", args.repo_search)
                                    if s in repoman.onlines]
            else:
                args.repo_search = []
            # if we have only one repo, search in it
            if len(args.repo_search) == 0 and len(repoman.onlines) == 1:
                args.repo_search = repoman.onlines
            elif len(args.repo_search) == 0 and len(repoman.onlines) > 1:
                raise Exception('You must use a full image path or set a valid search path')
            return repoman.get(image, version, search=args.repo_search, best=best)
        # we can ask directly repository about image
        else:
            return repoman[repo].get(image, version), repoman[repo]

################################################################################
# Commands functions
################################################################################

def c_add(parser, args):
    '''
    Add an image package into a repository
@@ -328,6 +354,10 @@ def c_version(parser, args):
    '''
    out(installsystems.version)

################################################################################
# Parser definition
################################################################################

# Top level argument parsing
p_main = argparse.ArgumentParser()
p_main.add_argument("-V", "--version", action="version",
@@ -340,22 +370,24 @@ ex_group.add_argument("-d", "--debug", action="store_true", default=None,
ex_group.add_argument("-q", "--quiet", action="store_true", default=None,
                      help="active quiet mode")
# common options
p_main.add_argument("-c", "--config", default="installsystems",
p_main.add_argument("-c", "--config", default="installsystems", metavar="PATH",
                    help="config file path")
p_main.add_argument("-R", "--repo-config", default="repository",
p_main.add_argument("-R", "--repo-config", default="repository", metavar="REPO",
                    help="repository config file path")
p_main.add_argument("-f", "--repo-filter", default=None,
                    help="select repository by name in config files")
p_main.add_argument("-r", "--repo-path", default=None,
                    help="repository path")
p_main.add_argument("-C", "--cache", default=None,
p_main.add_argument("-s", "--repo-search", metavar="REPO,REPO,...",
                    help="search for images inside those repositories")
p_main.add_argument("-f", "--repo-filter", metavar="REPO,REPO,...",
                    help="filter repositories by name")
p_main.add_argument("-r", "--repo-path", metavar="PATH",
                    help="define a temporary repository")
p_main.add_argument("-C", "--cache", metavar="PATH",
                    help="path of the repository cache")
p_main.add_argument("--no-cache", action="store_true", default=None,
                    help="not use persistent db caching")
p_main.add_argument("--no-color", action="store_true", default=None,
                    help="dot not display colored output")
p_main.add_argument("-t", "--timeout", dest="timeout", type=int, default=None,
                    help="download timeout (default 3)")
                    metavar="SECONDS", help="download timeout (default 3)")

# create a subparsers for each command
subparsers = p_main.add_subparsers()
@@ -382,7 +414,7 @@ p_build.set_defaults(func=c_build)
# cat command parser
p_cat = subparsers.add_parser("cat", help=c_cat.__doc__.lower())
p_cat.add_argument("-b", "--best", action="store_true", default=False,
                   help="in best mode, image is the most recent in all repositories")
                   help="take the most recent image in all searchable repositories")
p_cat.add_argument("image", help="<path|[repository/]image[:version]>")
p_cat.add_argument("file", nargs="+",
                   help="file inside image to cat (globbing allowed)")
@@ -391,7 +423,7 @@ p_cat.set_defaults(func=c_cat)
# changelog command parser
p_changelog = subparsers.add_parser("changelog", help=c_changelog.__doc__.lower())
p_changelog.add_argument("-b", "--best", action="store_true", default=False,
                         help="in best mode, image is the most recent in all repositories")
                         help="take the most recent image in all searchable repositories")
p_changelog.add_argument("-v", "--all-version",  action="store_true", default=False,
                         help="display changelog for all versions")
p_changelog.add_argument("image", help="<path|[repository/]image[:version]>")
@@ -419,7 +451,7 @@ p_clean.set_defaults(func=c_clean)
# copy command parser
p_copy = subparsers.add_parser("copy", help=c_copy.__doc__.lower())
p_copy.add_argument("-b", "--best", action="store_true", default=False,
                   help="in best mode, image is the most recent in all repositories")
                   help="take the most recent image in all searchable repositories")
p_copy.add_argument("image", nargs="+",
                    help="image syntax is <path|[repository/]image[:version]>")
p_copy.add_argument("repository", help="destination repository")
@@ -430,7 +462,7 @@ p_del = subparsers.add_parser("del", help=c_del.__doc__.lower())
p_del.add_argument("image", nargs="+",
                   help="image syntax is <path|[repository/]image[:version]>")
p_del.add_argument("-b", "--best", action="store_true", default=False,
                   help="in best mode, image is the most recent in all repositories")
                   help="take the most recent image in all searchable repositories")
p_del.add_argument("-f", "--force", action="store_true", default=False,
                   help="delete image without confirmation")
p_del.add_argument("-p", "--preserve", action="store_true", default=False,
@@ -442,13 +474,13 @@ p_diff = subparsers.add_parser("diff", help=c_diff.__doc__.lower())
p_diff.add_argument("object", nargs=2,
                    help="object syntax is <path|repository|[repository/]image[:version]>")
p_diff.add_argument("-b", "--best", action="store_true", default=False,
                    help="in best mode, image is the most recent in all repositories")
                    help="take the most recent image in all searchable repositories")
p_diff.set_defaults(func=c_diff)

# extract command parser
p_extract = subparsers.add_parser("extract", help=c_extract.__doc__.lower())
p_extract.add_argument("-b", "--best", action="store_true", default=False,
                       help="in best mode, image is the most recent in all repositories")
                       help="take the most recent image in all searchable repositories")
p_extract.add_argument("-f", "--force", action="store_true", default=False,
                       help="overwrite existing destinations")
p_extract.add_argument("-g", "--gen-description", action="store_true", default=False,
@@ -463,7 +495,7 @@ p_extract.set_defaults(func=c_extract)
# get command parser
p_get = subparsers.add_parser("get", help=c_get.__doc__.lower())
p_get.add_argument("-b", "--best", action="store_true", default=False,
                   help="in best mode, image is the most recent in all repositories")
                   help="take the most recent image in all searchable repositories")
p_get.add_argument("-f", "--force", action="store_true", default=False,
                   help="overwrite existing destinations")
p_get.add_argument("-I", "--no-image", action="store_true", default=False,
@@ -482,7 +514,7 @@ p_help.set_defaults(func=c_help, subparser=subparsers)
# info command parser
p_info = subparsers.add_parser("info", help=c_info.__doc__.lower())
p_info.add_argument("-b", "--best", action="store_true", default=False,
                    help="in best mode, image is the most recent in all repositories")
                    help="take the most recent image in all searchable repositories")
p_info.add_argument("-c", "--changelog", action="store_true", default=False,
                    help="display image changelog")
p_info.add_argument("-v", "--verbose", action="store_true", default=False,
@@ -535,7 +567,7 @@ p_list.set_defaults(func=c_list)
# move command parser
p_move = subparsers.add_parser("move", help=c_move.__doc__.lower())
p_move.add_argument("-b", "--best", action="store_true", default=False,
                    help="in best mode, image is the most recent in all repositories")
                    help="take the most recent image in all searchable repositories")
p_move.add_argument("-f", "--force", action="store_true", default=False,
                    help="move image without confirmation")
p_move.add_argument("image", nargs="+",
@@ -594,6 +626,10 @@ p_unprepare_chroot.set_defaults(func=c_unprepare_chroot)
p_version = subparsers.add_parser("version", help=c_version.__doc__.lower())
p_version.set_defaults(func=c_version)

################################################################################
# Main
################################################################################

try:
    # first (partial) parsing
    args = p_main.parse_known_args()[0]
+13 −4
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@ class MainConfigFile(ConfigFile):
    Program configuration file
    '''

    valid_options = ("debug", "quiet", "no_cache", "no_color", "timeout", "cache", "repo_search", "repo_filter", "repo_config")

    def __init__(self, filename, prefix=os.path.basename(sys.argv[0])):
        self.prefix = prefix
        ConfigFile.__init__(self, filename)
@@ -81,8 +83,14 @@ class MainConfigFile(ConfigFile):
        Merge current loaded option with a namespace from argparse
        '''
        for option, value in self._config.items():
            # check option is valid
            if option not in self.valid_options:
                warn("Invalid option %s in %s, skipped" % (option, self.path))
                continue
            # no option is specified in command line, set it
            if not hasattr(namespace, option):
                setattr(namespace, option, value)
            # handle by default none options
            elif getattr(namespace, option) == None:
                # we need to handle boolean differently
                if option in ("debug", "quiet", "no_cache", "no_color"):
@@ -94,11 +102,12 @@ class MainConfigFile(ConfigFile):
                    except ValueError:
                        raise Exception("Invalid %s: Not a number" % option)
                    setattr(namespace, option, n)
                # we can handle string more carefuly
                elif option in ("cache", "repo_filter", "repo_config"):
                # handle strings
                elif option in ("cache", "repo_search", "repo_filter"):
                    setattr(namespace, option, value)
            # repo_config is a special parameter, default value is repository
            elif option == "repo_config" and option.repo_config == "repository":
                setattr(namespace, option, value)
                else:
                    warn("Invalid option %s in %s, skipped" % (option, self.path))

    def _cache_paths(self):
        '''
+20 −17
Original line number Diff line number Diff line
@@ -391,7 +391,8 @@ class Repository(object):
        r = self.db.ask("select md5 from image where name = ? and version = ? limit 1",
                        (name, version)).fetchone()
        if r is None:
            raise Exception("Unable to find image %s v%s" % (name, version))
            raise Exception("Unable to find image %s v%s in %s" % (name, version,
                                                                   self.config.name))
        path = os.path.join(self.config.path, r[0])
        # getting the file
        arrow("Loading image %s v%s from repository %s" % (name,
@@ -436,7 +437,7 @@ class RepositoryManager(object):
        self.timeout = 3 if timeout is None else timeout
        self.repos = []
        self.tempfiles = []
        self.filter = filter
        self.filter = [] if filter is None else filter
        if cache_path is None:
            self.cache_path = None
            debug("No repository cache")
@@ -500,8 +501,9 @@ class RepositoryManager(object):
        offline: repository is marked offline
        '''
        # check filter on name
        if self.filter is not None:
            if not fnmatch.fnmatch(config.name, self.filter):
        if len(self.filter) > 0:
            if config.name not in self.filter:
                debug("Filtering repository %s" % config.name)
                return
        # repository is offline
        if config.offline or offline:
@@ -622,19 +624,20 @@ class RepositoryManager(object):
                        del images["%s/%s:%s" % (repo, img, rmv)]
        return images

    def get(self, name, version=None, best=False):
    def get(self, name, version=None, search=None, best=False):
        '''
        Crawl repositories to get an image
        Crawl searchable repositories to get an image

        best mode search the most recent version accross all repo
        else it search the first match
        '''
        if search is None:
            search = []
        # search last version if needed
        if version is None:
            version = -1
            for repo in self.repos:
                if repo.config.offline: continue
                current = repo.last(name)
            for repo in search:
                current = self[repo].last(name)
                # if not best mode, we found our version
                if not best and current > 0:
                    version = current
@@ -642,13 +645,14 @@ class RepositoryManager(object):
                version = max(version, current)
            # if version < 0, il n'y a pas d'image
            if version < 0:
                raise Exception("Unable to find image %s" % name)
                raise Exception("Unable to find image %s in %s" % (
                        name, search))
        # search image in repos
        for repo in self.repos:
            if repo.config.offline:  continue
            if repo.has(name, version):
                return repo.get(name, version), repo
        raise Exception("Unable to find image %s v%s" % (name, version))
        for repo in search:
            if self[repo].has(name, version):
                return self[repo].get(name, version), repo
        raise Exception("No image %s v%s in %s" % (
                name, version, search))

    def show_repos(self, pattern, local=None, online=None, url=False, state=True):
        '''
@@ -722,8 +726,7 @@ class RepositoryManager(object):
        '''
        Search pattern accross all registered repositories
        '''
        for repo in self.repos:
            if repo.config.offline:  continue
        for repo in self.onlines:
            arrow(repo.config.name)
            repo.search(pattern)

+10 −0
Original line number Diff line number Diff line
@@ -493,3 +493,13 @@ def compare_versions(v1, v2):
    fv1 = get_ver(v1)
    fv2 = get_ver(v2)
    return fv1 - fv2

def split_image_path(path):
    '''
    Split an image path (repo/image:version)
    in a tuple (repo, image, version)
    '''
    x = re.match(u"^(?:([-_\w]+)/)?([-_\w]+)(?::v?(\d+))?$", path)
    if x is None:
        raise Exception("invalid image path: %s" % path)
    return x.group(1,2,3)
+5 −2
Original line number Diff line number Diff line
@@ -23,8 +23,11 @@
# define connection timeout
#timeout = 30

# default repository name
#repo_filter = local
# search images inside repositories
#repo_search = stable testing

# filter repository list
#repo_filter = stable testing

# custom repository config file
#repo_config =