Example #1
0
def read_config(mandatory_opts):
    eprefix = portage.settings["EPREFIX"]
    if portage._not_installed:
        config_path = os.path.join(portage.PORTAGE_BASE_PATH, "cnf",
                                   "dispatch-conf.conf")
    else:
        config_path = os.path.join(eprefix or os.sep, "etc/dispatch-conf.conf")
    loader = KeyValuePairFileLoader(config_path, None)
    opts, _errors = loader.load()
    if not opts:
        print(
            _("dispatch-conf: Error reading {}; fatal").format(config_path),
            file=sys.stderr,
        )
        sys.exit(1)

    # Handle quote removal here, since KeyValuePairFileLoader doesn't do that.
    quotes = "\"'"
    for k, v in opts.items():
        if v[:1] in quotes and v[:1] == v[-1:]:
            opts[k] = v[1:-1]

    for key in mandatory_opts:
        if key not in opts:
            if key == "merge":
                opts[
                    "merge"] = "sdiff --suppress-common-lines --output='%s' '%s' '%s'"
            else:
                print(
                    _('dispatch-conf: Missing option "%s" in /etc/dispatch-conf.conf; fatal'
                      ) % (key, ),
                    file=sys.stderr,
                )

    # archive-dir supports ${EPREFIX} expansion, in order to avoid hardcoding
    variables = {"EPREFIX": eprefix}
    opts["archive-dir"] = varexpand(opts["archive-dir"], mydict=variables)

    if not os.path.exists(opts["archive-dir"]):
        os.mkdir(opts["archive-dir"])
        # Use restrictive permissions by default, in order to protect
        # against vulnerabilities (like bug #315603 involving rcs).
        os.chmod(opts["archive-dir"], 0o700)
    elif not os.path.isdir(opts["archive-dir"]):
        print(
            _("dispatch-conf: Config archive dir [%s] must exist; fatal") %
            (opts["archive-dir"], ),
            file=sys.stderr,
        )
        sys.exit(1)

    return opts
def ExtractKernelVersion(base_dir):
    """
	Try to figure out what kernel version we are running
	@param base_dir: Path to sources (usually /usr/src/linux)
	@type base_dir: string
	@rtype: tuple( version[string], error[string])
	@return:
	1. tuple( version[string], error[string])
	Either version or error is populated (but never both)

	"""
    lines = []
    pathname = os.path.join(base_dir, 'Makefile')
    try:
        f = io.open(_unicode_encode(pathname,
                                    encoding=_encodings['fs'],
                                    errors='strict'),
                    mode='r',
                    encoding=_encodings['content'],
                    errors='replace')
    except OSError as details:
        return (None, str(details))
    except IOError as details:
        return (None, str(details))

    try:
        for i in range(4):
            lines.append(f.readline())
    except OSError as details:
        return (None, str(details))
    except IOError as details:
        return (None, str(details))
    finally:
        f.close()

    lines = [l.strip() for l in lines]

    version = ''

    #XXX: The following code relies on the ordering of vars within the Makefile
    for line in lines:
        # split on the '=' then remove annoying whitespace
        items = line.split("=")
        items = [i.strip() for i in items]
        if items[0] == 'VERSION' or \
         items[0] == 'PATCHLEVEL':
            version += items[1]
            version += "."
        elif items[0] == 'SUBLEVEL':
            version += items[1]
        elif items[0] == 'EXTRAVERSION' and \
         items[-1] != items[0]:
            version += items[1]

    # Grab a list of files named localversion* and sort them
    localversions = os.listdir(base_dir)
    for x in range(len(localversions) - 1, -1, -1):
        if localversions[x][:12] != "localversion":
            del localversions[x]
    localversions.sort()

    # Append the contents of each to the version string, stripping ALL whitespace
    for lv in localversions:
        version += "".join(" ".join(grabfile(base_dir + "/" + lv)).split())

    # Check the .config for a CONFIG_LOCALVERSION and append that too, also stripping whitespace
    loader = KeyValuePairFileLoader(os.path.join(base_dir, ".config"), None)
    kernelconfig, loader_errors = loader.load()
    if loader_errors:
        for file_path, file_errors in loader_errors.items():
            for error_str in file_errors:
                writemsg_level("%s: %s\n" % (file_path, error_str),
                               level=logging.ERROR,
                               noiselevel=-1)

    if kernelconfig and "CONFIG_LOCALVERSION" in kernelconfig:
        version += "".join(shlex_split(kernelconfig["CONFIG_LOCALVERSION"]))

    return (version, None)
Example #3
0
def parse_layout_conf(repo_location, repo_name=None):
    eapi = read_corresponding_eapi_file(
        os.path.join(repo_location, REPO_NAME_LOC))

    layout_filename = os.path.join(repo_location, "metadata", "layout.conf")
    layout_file = KeyValuePairFileLoader(layout_filename, None, None)
    layout_data, layout_errors = layout_file.load()

    data = {}

    # None indicates abscence of a masters setting, which later code uses
    # to trigger a backward compatibility fallback that sets an implicit
    # master. In order to avoid this fallback behavior, layout.conf can
    # explicitly set masters to an empty value, which will result in an
    # empty tuple here instead of None.
    masters = layout_data.get('masters')
    if masters is not None:
        masters = tuple(masters.split())
    data['masters'] = masters
    data['aliases'] = tuple(layout_data.get('aliases', '').split())

    data['allow-provide-virtual'] = \
     layout_data.get('allow-provide-virtuals', 'false').lower() == 'true'

    data['eapis-banned'] = tuple(layout_data.get('eapis-banned', '').split())
    data['eapis-deprecated'] = tuple(
        layout_data.get('eapis-deprecated', '').split())

    data['sign-commit'] = layout_data.get('sign-commits', 'false').lower() \
     == 'true'

    data['sign-manifest'] = layout_data.get('sign-manifests', 'true').lower() \
     == 'true'

    data['thin-manifest'] = layout_data.get('thin-manifests', 'false').lower() \
     == 'true'

    data['repo-name'] = _gen_valid_repo(layout_data.get('repo-name', ''))

    manifest_policy = layout_data.get('use-manifests', 'strict').lower()
    data['allow-missing-manifest'] = manifest_policy != 'strict'
    data['create-manifest'] = manifest_policy != 'false'
    data['disable-manifest'] = manifest_policy == 'false'

    # for compatibility w/ PMS, fallback to pms; but also check if the
    # cache exists or not.
    cache_formats = layout_data.get('cache-formats', '').lower().split()
    if not cache_formats:
        # Auto-detect cache formats, and prefer md5-cache if available.
        # This behavior was deployed in portage-2.1.11.14, so that the
        # default egencache format could eventually be changed to md5-dict
        # in portage-2.1.11.32. WARNING: Versions prior to portage-2.1.11.14
        # will NOT recognize md5-dict format unless it is explicitly
        # listed in layout.conf.
        cache_formats = []
        if os.path.isdir(os.path.join(repo_location, 'metadata', 'md5-cache')):
            cache_formats.append('md5-dict')
        if os.path.isdir(os.path.join(repo_location, 'metadata', 'cache')):
            cache_formats.append('pms')
    data['cache-formats'] = tuple(cache_formats)

    manifest_hashes = layout_data.get('manifest-hashes')
    if manifest_hashes is not None:
        manifest_hashes = frozenset(manifest_hashes.upper().split())
        if MANIFEST2_REQUIRED_HASH not in manifest_hashes:
            repo_name = _get_repo_name(repo_location, cached=repo_name)
            warnings.warn(
                (_("Repository named '%(repo_name)s' has a "
                   "'manifest-hashes' setting that does not contain "
                   "the '%(hash)s' hash which is required by this "
                   "portage version. You will have to upgrade portage "
                   "if you want to generate valid manifests for this "
                   "repository: %(layout_filename)s") % {
                       "repo_name": repo_name or 'unspecified',
                       "hash": MANIFEST2_REQUIRED_HASH,
                       "layout_filename": layout_filename
                   }), DeprecationWarning)
        unsupported_hashes = manifest_hashes.difference(
            MANIFEST2_HASH_FUNCTIONS)
        if unsupported_hashes:
            repo_name = _get_repo_name(repo_location, cached=repo_name)
            warnings.warn((
                _("Repository named '%(repo_name)s' has a "
                  "'manifest-hashes' setting that contains one "
                  "or more hash types '%(hashes)s' which are not supported by "
                  "this portage version. You will have to upgrade "
                  "portage if you want to generate valid manifests for "
                  "this repository: %(layout_filename)s") % {
                      "repo_name": repo_name or 'unspecified',
                      "hashes": " ".join(sorted(unsupported_hashes)),
                      "layout_filename": layout_filename
                  }), DeprecationWarning)
    data['manifest-hashes'] = manifest_hashes

    data['update-changelog'] = layout_data.get('update-changelog', 'false').lower() \
     == 'true'

    raw_formats = layout_data.get('profile-formats')
    if raw_formats is None:
        if eapi_allows_directories_on_profile_level_and_repository_level(eapi):
            raw_formats = ('portage-1', )
        else:
            raw_formats = ('portage-1-compat', )
    else:
        raw_formats = set(raw_formats.split())
        unknown = raw_formats.difference(_valid_profile_formats)
        if unknown:
            repo_name = _get_repo_name(repo_location, cached=repo_name)
            warnings.warn((_(
                "Repository named '%(repo_name)s' has unsupported "
                "profiles in use ('profile-formats = %(unknown_fmts)s' setting in "
                "'%(layout_filename)s; please upgrade portage.") %
                           dict(repo_name=repo_name or 'unspecified',
                                layout_filename=layout_filename,
                                unknown_fmts=" ".join(unknown))),
                          DeprecationWarning)
        raw_formats = tuple(raw_formats.intersection(_valid_profile_formats))
    data['profile-formats'] = raw_formats

    try:
        eapi = layout_data['profile_eapi_when_unspecified']
    except KeyError:
        pass
    else:
        if 'profile-default-eapi' not in raw_formats:
            warnings.warn(
                (_("Repository named '%(repo_name)s' has "
                   "profile_eapi_when_unspecified setting in "
                   "'%(layout_filename)s', but 'profile-default-eapi' is "
                   "not listed in the profile-formats field. Please "
                   "report this issue to the repository maintainer.") %
                 dict(repo_name=repo_name or 'unspecified',
                      layout_filename=layout_filename)), SyntaxWarning)
        elif not portage.eapi_is_supported(eapi):
            warnings.warn(
                (_("Repository named '%(repo_name)s' has "
                   "unsupported EAPI '%(eapi)s' setting in "
                   "'%(layout_filename)s'; please upgrade portage.") %
                 dict(repo_name=repo_name or 'unspecified',
                      eapi=eapi,
                      layout_filename=layout_filename)), SyntaxWarning)
        else:
            data['profile_eapi_when_unspecified'] = eapi

    return data, layout_errors
Example #4
0
def parse_layout_conf(repo_location, repo_name=None):
	eapi = read_corresponding_eapi_file(os.path.join(repo_location, REPO_NAME_LOC))

	layout_filename = os.path.join(repo_location, "metadata", "layout.conf")
	layout_file = KeyValuePairFileLoader(layout_filename, None, None)
	layout_data, layout_errors = layout_file.load()

	data = {}

	# None indicates abscence of a masters setting, which later code uses
	# to trigger a backward compatibility fallback that sets an implicit
	# master. In order to avoid this fallback behavior, layout.conf can
	# explicitly set masters to an empty value, which will result in an
	# empty tuple here instead of None.
	masters = layout_data.get('masters')
	if masters is not None:
		masters = tuple(masters.split())
	data['masters'] = masters
	data['aliases'] = tuple(layout_data.get('aliases', '').split())

	data['allow-provide-virtual'] = \
		layout_data.get('allow-provide-virtuals', 'false').lower() == 'true'

	data['sign-commit'] = layout_data.get('sign-commits', 'false').lower() \
		== 'true'

	data['sign-manifest'] = layout_data.get('sign-manifests', 'true').lower() \
		== 'true'

	data['thin-manifest'] = layout_data.get('thin-manifests', 'false').lower() \
		== 'true'

	manifest_policy = layout_data.get('use-manifests', 'strict').lower()
	data['allow-missing-manifest'] = manifest_policy != 'strict'
	data['create-manifest'] = manifest_policy != 'false'
	data['disable-manifest'] = manifest_policy == 'false'

	# for compatibility w/ PMS, fallback to pms; but also check if the
	# cache exists or not.
	cache_formats = layout_data.get('cache-formats', 'pms').lower().split()
	if 'pms' in cache_formats and not os.path.isdir(
		os.path.join(repo_location, 'metadata', 'cache')):
		cache_formats.remove('pms')
	data['cache-formats'] = tuple(cache_formats)

	manifest_hashes = layout_data.get('manifest-hashes')
	if manifest_hashes is not None:
		manifest_hashes = frozenset(manifest_hashes.upper().split())
		if MANIFEST2_REQUIRED_HASH not in manifest_hashes:
			repo_name = _get_repo_name(repo_location, cached=repo_name)
			warnings.warn((_("Repository named '%(repo_name)s' has a "
				"'manifest-hashes' setting that does not contain "
				"the '%(hash)s' hash which is required by this "
				"portage version. You will have to upgrade portage "
				"if you want to generate valid manifests for this "
				"repository: %(layout_filename)s") %
				{"repo_name": repo_name or 'unspecified',
				"hash":MANIFEST2_REQUIRED_HASH,
				"layout_filename":layout_filename}),
				DeprecationWarning)
		unsupported_hashes = manifest_hashes.difference(
			MANIFEST2_HASH_FUNCTIONS)
		if unsupported_hashes:
			repo_name = _get_repo_name(repo_location, cached=repo_name)
			warnings.warn((_("Repository named '%(repo_name)s' has a "
				"'manifest-hashes' setting that contains one "
				"or more hash types '%(hashes)s' which are not supported by "
				"this portage version. You will have to upgrade "
				"portage if you want to generate valid manifests for "
				"this repository: %(layout_filename)s") %
				{"repo_name": repo_name or 'unspecified',
				"hashes":" ".join(sorted(unsupported_hashes)),
				"layout_filename":layout_filename}),
				DeprecationWarning)
	data['manifest-hashes'] = manifest_hashes

	data['update-changelog'] = layout_data.get('update-changelog', 'false').lower() \
		== 'true'

	raw_formats = layout_data.get('profile-formats')
	if raw_formats is None:
		if eapi in ('4-python',):
			raw_formats = ('portage-1',)
		else:
			raw_formats = ('portage-1-compat',)
	else:
		raw_formats = set(raw_formats.split())
		unknown = raw_formats.difference(['pms', 'portage-1'])
		if unknown:
			repo_name = _get_repo_name(repo_location, cached=repo_name)
			warnings.warn((_("Repository named '%(repo_name)s' has unsupported "
				"profiles in use ('profile-formats = %(unknown_fmts)s' setting in "
				"'%(layout_filename)s; please upgrade portage.") %
				dict(repo_name=repo_name or 'unspecified',
				layout_filename=layout_filename,
				unknown_fmts=" ".join(unknown))),
				DeprecationWarning)
		raw_formats = tuple(raw_formats.intersection(['pms', 'portage-1']))
	data['profile-formats'] = raw_formats

	return data, layout_errors