def read_config(mandatory_opts):
    loader = KeyValuePairFileLoader(
        '/etc/dispatch-conf.conf', None)
    opts, errors = loader.load()
    if not opts:
        print(_('dispatch-conf: Error reading /etc/dispatch-conf.conf; fatal'), 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)

    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
Beispiel #2
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
Beispiel #3
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 /etc/dispatch-conf.conf; fatal'), 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
Beispiel #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['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')
	manifest_required_hashes = layout_data.get('manifest-required-hashes')

	if manifest_required_hashes is not None and manifest_hashes is None:
		repo_name = _get_repo_name(repo_location, cached=repo_name)
		warnings.warn((_("Repository named '%(repo_name)s' specifies "
			"'manifest-required-hashes' setting without corresponding "
			"'manifest-hashes'. Portage will default it to match "
			"the required set but please add the missing entry "
			"to: %(layout_filename)s") %
			{"repo_name": repo_name or 'unspecified',
			"layout_filename":layout_filename}),
			SyntaxWarning)
		manifest_hashes = manifest_required_hashes

	if manifest_hashes is not None:
		# require all the hashes unless specified otherwise
		if manifest_required_hashes is None:
			manifest_required_hashes = manifest_hashes

		manifest_required_hashes = frozenset(manifest_required_hashes.upper().split())
		manifest_hashes = frozenset(manifest_hashes.upper().split())
		missing_required_hashes = manifest_required_hashes.difference(
			manifest_hashes)
		if missing_required_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' hashes which are listed in "
				"'manifest-required-hashes'. Please fix that file "
				"if you want to generate valid manifests for this "
				"repository: %(layout_filename)s") %
				{"repo_name": repo_name or 'unspecified',
				"hash": ' '.join(missing_required_hashes),
				"layout_filename":layout_filename}),
				SyntaxWarning)
		unsupported_hashes = manifest_hashes.difference(
			get_valid_checksum_keys())
		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['manifest-required-hashes'] = manifest_required_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
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)
Beispiel #6
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
Beispiel #7
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', '').lower().split()
	if not cache_formats:
		# Auto-detect cache formats, and prefer md5-cache if available.
		# After this behavior is deployed in stable portage, the default
		# egencache format can be changed to md5-dict.
		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

	return data, layout_errors
Beispiel #8
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
Beispiel #9
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
Beispiel #10
0
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)