Example #1
0
	def _parse_repository_usealiases(self, repositories):
		ret = {}
		for repo in repositories.repos_with_profiles():
			file_name = os.path.join(repo.location, "profiles", "use.aliases")
			eapi = read_corresponding_eapi_file(
				file_name, default=repo.eapi)
			useflag_re = _get_useflag_re(eapi)
			raw_file_dict = grabdict(file_name, recursive=True)
			file_dict = {}
			for real_flag, aliases in raw_file_dict.items():
				if useflag_re.match(real_flag) is None:
					writemsg(_("--- Invalid real USE flag in '%s': '%s'\n") % (file_name, real_flag), noiselevel=-1)
				else:
					for alias in aliases:
						if useflag_re.match(alias) is None:
							writemsg(_("--- Invalid USE flag alias for '%s' real USE flag in '%s': '%s'\n") %
								(real_flag, file_name, alias), noiselevel=-1)
						else:
							if any(alias in v for k, v in file_dict.items() if k != real_flag):
								writemsg(_("--- Duplicated USE flag alias in '%s': '%s'\n") %
									(file_name, alias), noiselevel=-1)
							else:
								file_dict.setdefault(real_flag, []).append(alias)
			ret[repo.name] = file_dict
		return ret
Example #2
0
	def _parse_file_to_dict(self, file_name, juststrings=False, recursive=True, eapi_filter=None):
		ret = {}
		location_dict = {}
		file_dict = grabdict_package(file_name, recursive=recursive, verify_eapi=True)
		eapi = read_corresponding_eapi_file(file_name)
		if eapi_filter is not None and not eapi_filter(eapi):
			if file_dict:
				writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
					(eapi, os.path.basename(file_name), file_name),
					noiselevel=-1)
			return ret
		useflag_re = _get_useflag_re(eapi)
		for k, v in file_dict.items():
			useflags = []
			for prefixed_useflag in v:
				if prefixed_useflag[:1] == "-":
					useflag = prefixed_useflag[1:]
				else:
					useflag = prefixed_useflag
				if useflag_re.match(useflag) is None:
					writemsg(_("--- Invalid USE flag for '%s' in '%s': '%s'\n") %
						(k, file_name, prefixed_useflag), noiselevel=-1)
				else:
					useflags.append(prefixed_useflag)
			location_dict.setdefault(k, []).extend(useflags)
		for k, v in location_dict.items():
			if juststrings:
				v = " ".join(v)
			else:
				v = tuple(v)
			ret.setdefault(k.cp, {})[k] = v
		return ret
Example #3
0
 def _parse_repository_packageusealiases(self, repositories):
     ret = {}
     for repo in repositories.repos_with_profiles():
         file_name = os.path.join(repo.location, "profiles",
                                  "package.use.aliases")
         eapi = read_corresponding_eapi_file(file_name, default=repo.eapi)
         useflag_re = _get_useflag_re(eapi)
         lines = grabfile(file_name, recursive=True)
         file_dict = {}
         for line in lines:
             elements = line.split()
             atom = elements[0]
             try:
                 atom = Atom(atom, eapi=eapi)
             except InvalidAtom:
                 writemsg(
                     _("--- Invalid atom in '%s': '%s'\n") %
                     (file_name, atom))
                 continue
             if len(elements) == 1:
                 writemsg(
                     _("--- Missing real USE flag for '%s' in '%s'\n") %
                     (atom, file_name),
                     noiselevel=-1)
                 continue
             real_flag = elements[1]
             if useflag_re.match(real_flag) is None:
                 writemsg(
                     _("--- Invalid real USE flag for '%s' in '%s': '%s'\n")
                     % (atom, file_name, real_flag),
                     noiselevel=-1)
             else:
                 for alias in elements[2:]:
                     if useflag_re.match(alias) is None:
                         writemsg(_(
                             "--- Invalid USE flag alias for '%s' real USE flag for '%s' in '%s': '%s'\n"
                         ) % (real_flag, atom, file_name, alias),
                                  noiselevel=-1)
                     else:
                         # Duplicated USE flag aliases in entries for different atoms
                         # matching the same package version are detected in getUseAliases().
                         if any(alias in v for k, v in file_dict.get(
                                 atom.cp, {}).get(atom, {}).items()
                                if k != real_flag):
                             writemsg(_(
                                 "--- Duplicated USE flag alias for '%s' in '%s': '%s'\n"
                             ) % (atom, file_name, alias),
                                      noiselevel=-1)
                         else:
                             file_dict.setdefault(atom.cp, {}).setdefault(
                                 atom, {}).setdefault(real_flag,
                                                      []).append(alias)
         ret[repo.name] = file_dict
     return ret
Example #4
0
 def _parse_file_to_tuple(self,
                          file_name,
                          recursive=True,
                          eapi_filter=None,
                          eapi=None,
                          eapi_default="0"):
     """
     @param file_name: input file name
     @type file_name: str
     @param recursive: triggers recursion if the input file is a
             directory
     @type recursive: bool
     @param eapi_filter: a function that accepts a single eapi
             argument, and returns true if the current file type
             is supported by the given EAPI
     @type eapi_filter: callable
     @param eapi: the EAPI of the current profile node, which allows
             a call to read_corresponding_eapi_file to be skipped
     @type eapi: str
     @param eapi_default: the default EAPI which applies if the
             current profile node does not define a local EAPI
     @type eapi_default: str
     @rtype: tuple
     @return: collection of USE flags
     """
     ret = []
     lines = grabfile(file_name, recursive=recursive)
     if eapi is None:
         eapi = read_corresponding_eapi_file(file_name,
                                             default=eapi_default)
     if eapi_filter is not None and not eapi_filter(eapi):
         if lines:
             writemsg(
                 _("--- EAPI '%s' does not support '%s': '%s'\n") %
                 (eapi, os.path.basename(file_name), file_name),
                 noiselevel=-1,
             )
         return ()
     useflag_re = _get_useflag_re(eapi)
     for prefixed_useflag in lines:
         if prefixed_useflag[:1] == "-":
             useflag = prefixed_useflag[1:]
         else:
             useflag = prefixed_useflag
         if useflag_re.match(useflag) is None:
             writemsg(
                 _("--- Invalid USE flag in '%s': '%s'\n") %
                 (file_name, prefixed_useflag),
                 noiselevel=-1,
             )
         else:
             ret.append(prefixed_useflag)
     return tuple(ret)
Example #5
0
 def _parse_repository_packageusealiases(self, repositories):
     ret = {}
     for repo in repositories.repos_with_profiles():
         file_name = os.path.join(repo.location, "profiles", "package.use.aliases")
         eapi = read_corresponding_eapi_file(file_name)
         useflag_re = _get_useflag_re(eapi)
         lines = grabfile(file_name, recursive=True)
         file_dict = {}
         for line in lines:
             elements = line.split()
             atom = elements[0]
             try:
                 atom = Atom(atom, eapi=eapi)
             except InvalidAtom:
                 writemsg(_("--- Invalid atom in '%s': '%s'\n") % (file_name, atom))
                 continue
             if len(elements) == 1:
                 writemsg(_("--- Missing real USE flag for '%s' in '%s'\n") % (atom, file_name), noiselevel=-1)
                 continue
             real_flag = elements[1]
             if useflag_re.match(real_flag) is None:
                 writemsg(
                     _("--- Invalid real USE flag for '%s' in '%s': '%s'\n") % (atom, file_name, real_flag),
                     noiselevel=-1,
                 )
             else:
                 for alias in elements[2:]:
                     if useflag_re.match(alias) is None:
                         writemsg(
                             _("--- Invalid USE flag alias for '%s' real USE flag for '%s' in '%s': '%s'\n")
                             % (real_flag, atom, file_name, alias),
                             noiselevel=-1,
                         )
                     else:
                         # Duplicated USE flag aliases in entries for different atoms
                         # matching the same package version are detected in getUseAliases().
                         if any(
                             alias in v
                             for k, v in file_dict.get(atom.cp, {}).get(atom, {}).items()
                             if k != real_flag
                         ):
                             writemsg(
                                 _("--- Duplicated USE flag alias for '%s' in '%s': '%s'\n")
                                 % (atom, file_name, alias),
                                 noiselevel=-1,
                             )
                         else:
                             file_dict.setdefault(atom.cp, {}).setdefault(atom, {}).setdefault(real_flag, []).append(
                                 alias
                             )
         ret[repo.name] = file_dict
     return ret
Example #6
0
 def _parse_file_to_dict(self,
                         file_name,
                         juststrings=False,
                         recursive=True,
                         eapi_filter=None,
                         user_config=False):
     ret = {}
     location_dict = {}
     eapi = read_corresponding_eapi_file(file_name, default=None)
     if eapi is None and not user_config:
         eapi = "0"
     if eapi is None:
         ret = ExtendedAtomDict(dict)
     else:
         ret = {}
     file_dict = grabdict_package(file_name,
                                  recursive=recursive,
                                  allow_wildcard=(eapi is None),
                                  allow_repo=(eapi is None),
                                  verify_eapi=(eapi is not None))
     if eapi is not None and eapi_filter is not None and not eapi_filter(
             eapi):
         if file_dict:
             writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
                      (eapi, os.path.basename(file_name), file_name),
                      noiselevel=-1)
         return ret
     useflag_re = _get_useflag_re(eapi)
     for k, v in file_dict.items():
         useflags = []
         for prefixed_useflag in v:
             if prefixed_useflag[:1] == "-":
                 useflag = prefixed_useflag[1:]
             else:
                 useflag = prefixed_useflag
             if useflag_re.match(useflag) is None:
                 writemsg(
                     _("--- Invalid USE flag for '%s' in '%s': '%s'\n") %
                     (k, file_name, prefixed_useflag),
                     noiselevel=-1)
             else:
                 useflags.append(prefixed_useflag)
         location_dict.setdefault(k, []).extend(useflags)
     for k, v in location_dict.items():
         if juststrings:
             v = " ".join(v)
         else:
             v = tuple(v)
         ret.setdefault(k.cp, {})[k] = v
     return ret
Example #7
0
	def _parse_file_to_tuple(self, file_name, recursive=True):
		ret = []
		lines = grabfile(file_name, recursive=recursive)
		eapi = read_corresponding_eapi_file(file_name)
		useflag_re = _get_useflag_re(eapi)
		for prefixed_useflag in lines:
			if prefixed_useflag[:1] == "-":
				useflag = prefixed_useflag[1:]
			else:
				useflag = prefixed_useflag
			if useflag_re.match(useflag) is None:
				writemsg(_("--- Invalid USE flag in '%s': '%s'\n") %
					(file_name, prefixed_useflag), noiselevel=-1)
			else:
				ret.append(prefixed_useflag)
		return tuple(ret)
Example #8
0
	def _parse_file_to_tuple(self, file_name, recursive=True,
		eapi_filter=None, eapi=None, eapi_default="0"):
		"""
		@param file_name: input file name
		@type file_name: str
		@param recursive: triggers recursion if the input file is a
			directory
		@type recursive: bool
		@param eapi_filter: a function that accepts a single eapi
			argument, and returns true if the the current file type
			is supported by the given EAPI
		@type eapi_filter: callable
		@param eapi: the EAPI of the current profile node, which allows
			a call to read_corresponding_eapi_file to be skipped
		@type eapi: str
		@param eapi_default: the default EAPI which applies if the
			current profile node does not define a local EAPI
		@type eapi_default: str
		@rtype: tuple
		@return: collection of USE flags
		"""
		ret = []
		lines = grabfile(file_name, recursive=recursive)
		if eapi is None:
			eapi = read_corresponding_eapi_file(
				file_name, default=eapi_default)
		if eapi_filter is not None and not eapi_filter(eapi):
			if lines:
				writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
					(eapi, os.path.basename(file_name), file_name),
					noiselevel=-1)
			return ()
		useflag_re = _get_useflag_re(eapi)
		for prefixed_useflag in lines:
			if prefixed_useflag[:1] == "-":
				useflag = prefixed_useflag[1:]
			else:
				useflag = prefixed_useflag
			if useflag_re.match(useflag) is None:
				writemsg(_("--- Invalid USE flag in '%s': '%s'\n") %
					(file_name, prefixed_useflag), noiselevel=-1)
			else:
				ret.append(prefixed_useflag)
		return tuple(ret)
Example #9
0
	def _parse_file_to_tuple(self, file_name, recursive=True, eapi_filter=None):
		ret = []
		lines = grabfile(file_name, recursive=recursive)
		eapi = read_corresponding_eapi_file(file_name)
		if eapi_filter is not None and not eapi_filter(eapi):
			if lines:
				writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
					(eapi, os.path.basename(file_name), file_name),
					noiselevel=-1)
			return ()
		useflag_re = _get_useflag_re(eapi)
		for prefixed_useflag in lines:
			if prefixed_useflag[:1] == "-":
				useflag = prefixed_useflag[1:]
			else:
				useflag = prefixed_useflag
			if useflag_re.match(useflag) is None:
				writemsg(_("--- Invalid USE flag in '%s': '%s'\n") %
					(file_name, prefixed_useflag), noiselevel=-1)
			else:
				ret.append(prefixed_useflag)
		return tuple(ret)
Example #10
0
 def _parse_repository_usealiases(self, repositories):
     ret = {}
     for repo in repositories.repos_with_profiles():
         file_name = os.path.join(repo.location, "profiles", "use.aliases")
         eapi = read_corresponding_eapi_file(file_name, default=repo.eapi)
         useflag_re = _get_useflag_re(eapi)
         raw_file_dict = grabdict(file_name, recursive=True)
         file_dict = {}
         for real_flag, aliases in raw_file_dict.items():
             if useflag_re.match(real_flag) is None:
                 writemsg(
                     _("--- Invalid real USE flag in '%s': '%s'\n") %
                     (file_name, real_flag),
                     noiselevel=-1,
                 )
             else:
                 for alias in aliases:
                     if useflag_re.match(alias) is None:
                         writemsg(
                             _("--- Invalid USE flag alias for '%s' real USE flag in '%s': '%s'\n"
                               ) % (real_flag, file_name, alias),
                             noiselevel=-1,
                         )
                     else:
                         if any(alias in v for k, v in file_dict.items()
                                if k != real_flag):
                             writemsg(
                                 _("--- Duplicated USE flag alias in '%s': '%s'\n"
                                   ) % (file_name, alias),
                                 noiselevel=-1,
                             )
                         else:
                             file_dict.setdefault(real_flag,
                                                  []).append(alias)
         ret[repo.name] = file_dict
     return ret
Example #11
0
	def __init__(self, name, repo_opts, local_config=True):
		"""Build a RepoConfig with options in repo_opts
		   Try to read repo_name in repository location, but if
		   it is not found use variable name as repository name"""

		force = repo_opts.get('force')
		if force is not None:
			force = tuple(force.split())
		self.force = force
		if force is None:
			force = ()

		self.local_config = local_config

		if local_config or 'aliases' in force:
			aliases = repo_opts.get('aliases')
			if aliases is not None:
				aliases = tuple(aliases.split())
		else:
			aliases = None

		self.aliases = aliases

		if local_config or 'eclass-overrides' in force:
			eclass_overrides = repo_opts.get('eclass-overrides')
			if eclass_overrides is not None:
				eclass_overrides = tuple(eclass_overrides.split())
		else:
			eclass_overrides = None

		self.eclass_overrides = eclass_overrides
		# Eclass databases and locations are computed later.
		self.eclass_db = None
		self.eclass_locations = None

		if local_config or 'masters' in force:
			# Masters from repos.conf override layout.conf.
			masters = repo_opts.get('masters')
			if masters is not None:
				masters = tuple(masters.split())
		else:
			masters = None

		self.masters = masters

		#The main-repo key makes only sense for the 'DEFAULT' section.
		self.main_repo = repo_opts.get('main-repo')

		priority = repo_opts.get('priority')
		if priority is not None:
			try:
				priority = int(priority)
			except ValueError:
				priority = None
		self.priority = priority

		sync_cvs_repo = repo_opts.get('sync-cvs-repo')
		if sync_cvs_repo is not None:
			sync_cvs_repo = sync_cvs_repo.strip()
		self.sync_cvs_repo = sync_cvs_repo or None

		sync_type = repo_opts.get('sync-type')
		if sync_type is not None:
			sync_type = sync_type.strip()
		self.sync_type = sync_type or None

		sync_uri = repo_opts.get('sync-uri')
		if sync_uri is not None:
			sync_uri = sync_uri.strip()
		self.sync_uri = sync_uri or None

		# Not implemented.
		format = repo_opts.get('format')
		if format is not None:
			format = format.strip()
		self.format = format

		location = repo_opts.get('location')
		self.user_location = location
		if location is not None and location.strip():
			if os.path.isdir(location) or portage._sync_mode:
				location = os.path.realpath(location)
		else:
			location = None
		self.location = location

		eapi = None
		missing = True
		self.name = name
		if self.location is not None:
			eapi = read_corresponding_eapi_file(os.path.join(self.location, REPO_NAME_LOC))
			self.name, missing = self._read_valid_repo_name(self.location)
			if missing:
				# The name from repos.conf has to be used here for
				# things like emerge-webrsync to work when the repo
				# is empty (bug #484950).
				if name is not None:
					self.name = name
				if portage._sync_mode:
					missing = False

		elif name == "DEFAULT":
			missing = False

		self.eapi = eapi
		self.missing_repo_name = missing
		# sign_commit is disabled by default, since it requires Git >=1.7.9,
		# and key_id configured by `git config user.signingkey key_id`
		self.sign_commit = False
		self.sign_manifest = True
		self.thin_manifest = False
		self.allow_missing_manifest = False
		self.allow_provide_virtual = False
		self.create_manifest = True
		self.disable_manifest = False
		self.manifest_hashes = None
		self.update_changelog = False
		self.cache_formats = None
		self.portage1_profiles = True
		self.portage1_profiles_compat = False
		self.find_invalid_path_char = _find_invalid_path_char
		self._masters_orig = None

		# Parse layout.conf.
		if self.location:
			layout_data = parse_layout_conf(self.location, self.name)[0]
			self._masters_orig = layout_data['masters']

			# layout.conf masters may be overridden here if we have a masters
			# setting from the user's repos.conf
			if self.masters is None:
				self.masters = layout_data['masters']

			if (local_config or 'aliases' in force) and layout_data['aliases']:
				aliases = self.aliases
				if aliases is None:
					aliases = ()
				# repos.conf aliases come after layout.conf aliases, giving
				# them the ability to do incremental overrides
				self.aliases = layout_data['aliases'] + tuple(aliases)

			if layout_data['repo-name']:
				# allow layout.conf to override repository name
				# useful when having two copies of the same repo enabled
				# to avoid modifying profiles/repo_name in one of them
				self.name = layout_data['repo-name']

			for value in ('allow-missing-manifest',
				'allow-provide-virtual', 'cache-formats',
				'create-manifest', 'disable-manifest', 'manifest-hashes',
				'profile-formats',
				'sign-commit', 'sign-manifest', 'thin-manifest', 'update-changelog'):
				setattr(self, value.lower().replace("-", "_"), layout_data[value])

			self.portage1_profiles = eapi_allows_directories_on_profile_level_and_repository_level(eapi) or \
				any(x in _portage1_profiles_allow_directories for x in layout_data['profile-formats'])
			self.portage1_profiles_compat = not eapi_allows_directories_on_profile_level_and_repository_level(eapi) and \
				layout_data['profile-formats'] == ('portage-1-compat',)

			self._eapis_banned = frozenset(layout_data['eapis-banned'])
			self._eapis_deprecated = frozenset(layout_data['eapis-deprecated'])
Example #12
0
    def load_profiles(self, repositories, known_repository_paths):
        known_repository_paths = set(
            os.path.realpath(x) for x in known_repository_paths)

        known_repos = []
        for x in known_repository_paths:
            try:
                repo = repositories.get_repo_for_location(x)
            except KeyError:
                layout_data = parse_layout_conf(x)[0]
            else:
                layout_data = {
                    "profile-formats": repo.profile_formats,
                    "profile_eapi_when_unspecified": repo.eapi
                }
            # force a trailing '/' for ease of doing startswith checks
            known_repos.append((x + '/', layout_data))
        known_repos = tuple(known_repos)

        if self.config_profile_path is None:
            deprecated_profile_path = os.path.join(self.config_root, 'etc',
                                                   'make.profile')
            self.config_profile_path = \
             os.path.join(self.config_root, PROFILE_PATH)
            if isdir_raise_eaccess(self.config_profile_path):
                self.profile_path = self.config_profile_path
                if isdir_raise_eaccess(deprecated_profile_path) and not \
                 os.path.samefile(self.profile_path,
                 deprecated_profile_path):
                    # Don't warn if they refer to the same path, since
                    # that can be used for backward compatibility with
                    # old software.
                    writemsg("!!! %s\n" % _("Found 2 make.profile dirs: "
                                            "using '%s', ignoring '%s'") %
                             (self.profile_path, deprecated_profile_path),
                             noiselevel=-1)
            else:
                self.config_profile_path = deprecated_profile_path
                if isdir_raise_eaccess(self.config_profile_path):
                    self.profile_path = self.config_profile_path
                else:
                    self.profile_path = None
        else:
            # NOTE: repoman may pass in an empty string
            # here, in order to create an empty profile
            # for checking dependencies of packages with
            # empty KEYWORDS.
            self.profile_path = self.config_profile_path

        # The symlink might not exist or might not be a symlink.
        self.profiles = []
        self.profiles_complex = []
        if self.profile_path:
            try:
                self._addProfile(os.path.realpath(self.profile_path),
                                 repositories, known_repos)
            except ParseError as e:
                if not portage._sync_mode:
                    writemsg(_("!!! Unable to parse profile: '%s'\n") %
                             self.profile_path,
                             noiselevel=-1)
                    writemsg("!!! ParseError: %s\n" % str(e), noiselevel=-1)
                self.profiles = []
                self.profiles_complex = []

        if self._user_config and self.profiles:
            custom_prof = os.path.join(self.config_root, CUSTOM_PROFILE_PATH)
            if os.path.exists(custom_prof):
                # For read_corresponding_eapi_file, specify default=None
                # in order to allow things like wildcard atoms when
                # is no explicit EAPI setting.
                self.user_profile_dir = custom_prof
                self.profiles.append(custom_prof)
                self.profiles_complex.append(
                    _profile_node(
                        custom_prof, True, True,
                        ('profile-bashrcs', 'profile-set'),
                        read_corresponding_eapi_file(custom_prof + os.sep,
                                                     default=None), True))
            del custom_prof

        self.profiles = tuple(self.profiles)
        self.profiles_complex = tuple(self.profiles_complex)
Example #13
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 #14
0
    def __init__(self, name, repo_opts, local_config=True):
        """Build a RepoConfig with options in repo_opts
		   Try to read repo_name in repository location, but if
		   it is not found use variable name as repository name"""

        force = repo_opts.get('force')
        if force is not None:
            force = tuple(force.split())
        self.force = force
        if force is None:
            force = ()

        self.local_config = local_config

        if local_config or 'aliases' in force:
            aliases = repo_opts.get('aliases')
            if aliases is not None:
                aliases = tuple(aliases.split())
        else:
            aliases = None

        self.aliases = aliases

        if local_config or 'eclass-overrides' in force:
            eclass_overrides = repo_opts.get('eclass-overrides')
            if eclass_overrides is not None:
                eclass_overrides = tuple(eclass_overrides.split())
        else:
            eclass_overrides = None

        self.eclass_overrides = eclass_overrides
        # Eclass databases and locations are computed later.
        self.eclass_db = None
        self.eclass_locations = None

        if local_config or 'masters' in force:
            # Masters from repos.conf override layout.conf.
            masters = repo_opts.get('masters')
            if masters is not None:
                masters = tuple(masters.split())
        else:
            masters = None

        self.masters = masters

        #The main-repo key makes only sense for the 'DEFAULT' section.
        self.main_repo = repo_opts.get('main-repo')

        priority = repo_opts.get('priority')
        if priority is not None:
            try:
                priority = int(priority)
            except ValueError:
                priority = None
        self.priority = priority

        sync_type = repo_opts.get('sync-type')
        if sync_type is not None:
            sync_type = sync_type.strip()
        self.sync_type = sync_type or None

        sync_umask = repo_opts.get('sync-umask')
        if sync_umask is not None:
            sync_umask = sync_umask.strip()
        self.sync_umask = sync_umask or None

        sync_uri = repo_opts.get('sync-uri')
        if sync_uri is not None:
            sync_uri = sync_uri.strip()
        self.sync_uri = sync_uri or None

        sync_user = repo_opts.get('sync-user')
        if sync_user is not None:
            sync_user = sync_user.strip()
        self.sync_user = sync_user or None

        auto_sync = repo_opts.get('auto-sync', 'yes')
        if auto_sync is not None:
            auto_sync = auto_sync.strip().lower()
        self.auto_sync = auto_sync

        self.sync_depth = repo_opts.get('sync-depth')
        self.sync_hooks_only_on_change = repo_opts.get(
            'sync-hooks-only-on-change', 'false').lower() == 'true'

        self.module_specific_options = {}

        # Not implemented.
        format = repo_opts.get('format')
        if format is not None:
            format = format.strip()
        self.format = format

        location = repo_opts.get('location')
        if location is not None and location.strip():
            if os.path.isdir(location) or portage._sync_mode:
                location = os.path.realpath(location)
        else:
            location = None
        self.location = location

        missing = True
        self.name = name
        if self.location is not None:
            self.name, missing = self._read_valid_repo_name(self.location)
            if missing:
                # The name from repos.conf has to be used here for
                # things like emerge-webrsync to work when the repo
                # is empty (bug #484950).
                if name is not None:
                    self.name = name
                if portage._sync_mode:
                    missing = False

        elif name == "DEFAULT":
            missing = False

        self.eapi = None
        self.missing_repo_name = missing
        # sign_commit is disabled by default, since it requires Git >=1.7.9,
        # and key_id configured by `git config user.signingkey key_id`
        self.sign_commit = False
        self.sign_manifest = True
        self.thin_manifest = False
        self.allow_missing_manifest = False
        self.allow_provide_virtual = False
        self.create_manifest = True
        self.disable_manifest = False
        self.manifest_hashes = None
        self.update_changelog = False
        self.cache_formats = None
        self.portage1_profiles = True
        self.portage1_profiles_compat = False
        self.find_invalid_path_char = _find_invalid_path_char
        self._masters_orig = None

        # Parse layout.conf.
        if self.location:
            layout_data = parse_layout_conf(self.location, self.name)[0]
            self._masters_orig = layout_data['masters']

            # layout.conf masters may be overridden here if we have a masters
            # setting from the user's repos.conf
            if self.masters is None:
                self.masters = layout_data['masters']

            if (local_config or 'aliases' in force) and layout_data['aliases']:
                aliases = self.aliases
                if aliases is None:
                    aliases = ()
                # repos.conf aliases come after layout.conf aliases, giving
                # them the ability to do incremental overrides
                self.aliases = layout_data['aliases'] + tuple(aliases)

            if layout_data['repo-name']:
                # allow layout.conf to override repository name
                # useful when having two copies of the same repo enabled
                # to avoid modifying profiles/repo_name in one of them
                self.name = layout_data['repo-name']
                self.missing_repo_name = False

            for value in ('allow-missing-manifest', 'allow-provide-virtual',
                          'cache-formats', 'create-manifest',
                          'disable-manifest', 'manifest-hashes',
                          'profile-formats', 'sign-commit', 'sign-manifest',
                          'thin-manifest', 'update-changelog'):
                setattr(self,
                        value.lower().replace("-", "_"), layout_data[value])

            # If profile-formats specifies a default EAPI, then set
            # self.eapi to that, otherwise set it to "0" as specified
            # by PMS.
            self.eapi = layout_data.get('profile_eapi_when_unspecified', '0')

            eapi = read_corresponding_eapi_file(os.path.join(
                self.location, REPO_NAME_LOC),
                                                default=self.eapi)

            self.portage1_profiles = eapi_allows_directories_on_profile_level_and_repository_level(eapi) or \
             any(x in _portage1_profiles_allow_directories for x in layout_data['profile-formats'])
            self.portage1_profiles_compat = not eapi_allows_directories_on_profile_level_and_repository_level(eapi) and \
             layout_data['profile-formats'] == ('portage-1-compat',)

            self._eapis_banned = frozenset(layout_data['eapis-banned'])
            self._eapis_deprecated = frozenset(layout_data['eapis-deprecated'])
Example #15
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 #16
0
	def load_profiles(self, repositories, known_repository_paths):
		known_repository_paths = set(os.path.realpath(x)
			for x in known_repository_paths)

		known_repos = []
		for x in known_repository_paths:
			try:
				repo = repositories.get_repo_for_location(x)
			except KeyError:
				layout_data = parse_layout_conf(x)[0]
			else:
				layout_data = {
					"profile-formats": repo.profile_formats,
					"profile_eapi_when_unspecified": repo.eapi
				}
			# force a trailing '/' for ease of doing startswith checks
			known_repos.append((x + '/', layout_data))
		known_repos = tuple(known_repos)

		if self.config_profile_path is None:
			deprecated_profile_path = os.path.join(
				self.config_root, 'etc', 'make.profile')
			self.config_profile_path = \
				os.path.join(self.config_root, PROFILE_PATH)
			if isdir_raise_eaccess(self.config_profile_path):
				self.profile_path = self.config_profile_path
				if isdir_raise_eaccess(deprecated_profile_path) and not \
					os.path.samefile(self.profile_path,
					deprecated_profile_path):
					# Don't warn if they refer to the same path, since
					# that can be used for backward compatibility with
					# old software.
					writemsg("!!! %s\n" %
						_("Found 2 make.profile dirs: "
						"using '%s', ignoring '%s'") %
						(self.profile_path, deprecated_profile_path),
						noiselevel=-1)
			else:
				self.config_profile_path = deprecated_profile_path
				if isdir_raise_eaccess(self.config_profile_path):
					self.profile_path = self.config_profile_path
				else:
					self.profile_path = None
		else:
			# NOTE: repoman may pass in an empty string
			# here, in order to create an empty profile
			# for checking dependencies of packages with
			# empty KEYWORDS.
			self.profile_path = self.config_profile_path


		# The symlink might not exist or might not be a symlink.
		self.profiles = []
		self.profiles_complex = []
		if self.profile_path:
			try:
				self._addProfile(os.path.realpath(self.profile_path),
					repositories, known_repos)
			except ParseError as e:
				if not portage._sync_mode:
					writemsg(_("!!! Unable to parse profile: '%s'\n") % self.profile_path, noiselevel=-1)
					writemsg("!!! ParseError: %s\n" % str(e), noiselevel=-1)
				self.profiles = []
				self.profiles_complex = []

		if self._user_config and self.profiles:
			custom_prof = os.path.join(
				self.config_root, CUSTOM_PROFILE_PATH)
			if os.path.exists(custom_prof):
				# For read_corresponding_eapi_file, specify default=None
				# in order to allow things like wildcard atoms when
				# is no explicit EAPI setting.
				self.user_profile_dir = custom_prof
				self.profiles.append(custom_prof)
				self.profiles_complex.append(
					_profile_node(custom_prof, True, True,
					('profile-bashrcs', 'profile-set'),
					read_corresponding_eapi_file(
					custom_prof + os.sep, default=None)))
			del custom_prof

		self.profiles = tuple(self.profiles)
		self.profiles_complex = tuple(self.profiles_complex)
Example #17
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
Example #18
0
	def __init__(self, name, repo_opts, local_config=True):
		"""Build a RepoConfig with options in repo_opts
		   Try to read repo_name in repository location, but if
		   it is not found use variable name as repository name"""

		force = repo_opts.get('force')
		if force is not None:
			force = tuple(force.split())
		self.force = force
		if force is None:
			force = ()

		self.local_config = local_config

		if local_config or 'aliases' in force:
			aliases = repo_opts.get('aliases')
			if aliases is not None:
				aliases = tuple(aliases.split())
		else:
			aliases = None

		self.aliases = aliases

		if local_config or 'eclass-overrides' in force:
			eclass_overrides = repo_opts.get('eclass-overrides')
			if eclass_overrides is not None:
				eclass_overrides = tuple(eclass_overrides.split())
		else:
			eclass_overrides = None

		self.eclass_overrides = eclass_overrides
		# Eclass databases and locations are computed later.
		self.eclass_db = None
		self.eclass_locations = None

		if local_config or 'masters' in force:
			# Masters from repos.conf override layout.conf.
			masters = repo_opts.get('masters')
			if masters is not None:
				masters = tuple(masters.split())
		else:
			masters = None

		self.masters = masters

		#The main-repo key makes only sense for the 'DEFAULT' section.
		self.main_repo = repo_opts.get('main-repo')

		priority = repo_opts.get('priority')
		if priority is not None:
			try:
				priority = int(priority)
			except ValueError:
				priority = None
		self.priority = priority

		sync_type = repo_opts.get('sync-type')
		if sync_type is not None:
			sync_type = sync_type.strip()
		self.sync_type = sync_type or None

		sync_umask = repo_opts.get('sync-umask')
		if sync_umask is not None:
			sync_umask = sync_umask.strip()
		self.sync_umask = sync_umask or None

		sync_uri = repo_opts.get('sync-uri')
		if sync_uri is not None:
			sync_uri = sync_uri.strip()
		self.sync_uri = sync_uri or None

		sync_user = repo_opts.get('sync-user')
		if sync_user is not None:
			sync_user = sync_user.strip()
		self.sync_user = sync_user or None

		auto_sync = repo_opts.get('auto-sync', 'yes')
		if auto_sync is not None:
			auto_sync = auto_sync.strip().lower()
		self.auto_sync = auto_sync

		self.clone_depth = repo_opts.get('clone-depth')
		self.sync_depth = repo_opts.get('sync-depth')

		if self.sync_depth is not None:
			warnings.warn(_("repos.conf: sync-depth is deprecated,"
				" use clone-depth instead"))

		self.sync_hooks_only_on_change = repo_opts.get(
			'sync-hooks-only-on-change', 'false').lower() == 'true'

		self.strict_misc_digests = repo_opts.get(
			'strict-misc-digests', 'true').lower() == 'true'

		self.sync_openpgp_key_path = repo_opts.get(
			'sync-openpgp-key-path', None)

		for k in ('sync_openpgp_key_refresh_retry_count',
			'sync_openpgp_key_refresh_retry_delay_max',
			'sync_openpgp_key_refresh_retry_delay_exp_base',
			'sync_openpgp_key_refresh_retry_delay_mult',
			'sync_openpgp_key_refresh_retry_overall_timeout'):
			setattr(self, k, repo_opts.get(k.replace('_', '-'), None))

		self.module_specific_options = {}

		# Not implemented.
		format = repo_opts.get('format')
		if format is not None:
			format = format.strip()
		self.format = format

		location = repo_opts.get('location')
		if location is not None and location.strip():
			if os.path.isdir(location) or portage._sync_mode:
				location = os.path.realpath(location)
		else:
			location = None
		self.location = location

		missing = True
		self.name = name
		if self.location is not None:
			self.name, missing = self._read_valid_repo_name(self.location)
			if missing:
				# The name from repos.conf has to be used here for
				# things like emerge-webrsync to work when the repo
				# is empty (bug #484950).
				if name is not None:
					self.name = name
				if portage._sync_mode:
					missing = False

		elif name == "DEFAULT":
			missing = False

		self.eapi = None
		self.missing_repo_name = missing
		# sign_commit is disabled by default, since it requires Git >=1.7.9,
		# and key_id configured by `git config user.signingkey key_id`
		self.sign_commit = False
		self.sign_manifest = True
		self.thin_manifest = False
		self.allow_missing_manifest = False
		self.allow_provide_virtual = False
		self.create_manifest = True
		self.disable_manifest = False
		self.manifest_hashes = None
		self.manifest_required_hashes = None
		self.update_changelog = False
		self.cache_formats = None
		self.portage1_profiles = True
		self.portage1_profiles_compat = False
		self.find_invalid_path_char = _find_invalid_path_char
		self._masters_orig = None

		# Parse layout.conf.
		if self.location:
			layout_data = parse_layout_conf(self.location, self.name)[0]
			self._masters_orig = layout_data['masters']

			# layout.conf masters may be overridden here if we have a masters
			# setting from the user's repos.conf
			if self.masters is None:
				self.masters = layout_data['masters']

			if (local_config or 'aliases' in force) and layout_data['aliases']:
				aliases = self.aliases
				if aliases is None:
					aliases = ()
				# repos.conf aliases come after layout.conf aliases, giving
				# them the ability to do incremental overrides
				self.aliases = layout_data['aliases'] + tuple(aliases)

			if layout_data['repo-name']:
				# allow layout.conf to override repository name
				# useful when having two copies of the same repo enabled
				# to avoid modifying profiles/repo_name in one of them
				self.name = layout_data['repo-name']
				self.missing_repo_name = False

			for value in ('allow-missing-manifest',
				'cache-formats',
				'create-manifest', 'disable-manifest', 'manifest-hashes',
				'manifest-required-hashes', 'profile-formats',
				'sign-commit', 'sign-manifest', 'thin-manifest', 'update-changelog'):
				setattr(self, value.lower().replace("-", "_"), layout_data[value])

			# If profile-formats specifies a default EAPI, then set
			# self.eapi to that, otherwise set it to "0" as specified
			# by PMS.
			self.eapi = layout_data.get(
				'profile_eapi_when_unspecified', '0')

			eapi = read_corresponding_eapi_file(
				os.path.join(self.location, REPO_NAME_LOC),
				default=self.eapi)

			self.portage1_profiles = eapi_allows_directories_on_profile_level_and_repository_level(eapi) or \
				any(x in _portage1_profiles_allow_directories for x in layout_data['profile-formats'])
			self.portage1_profiles_compat = not eapi_allows_directories_on_profile_level_and_repository_level(eapi) and \
				layout_data['profile-formats'] == ('portage-1-compat',)

			self._eapis_banned = frozenset(layout_data['eapis-banned'])
			self._eapis_deprecated = frozenset(layout_data['eapis-deprecated'])
Example #19
0
	def __init__(self, name, repo_opts):
		"""Build a RepoConfig with options in repo_opts
		   Try to read repo_name in repository location, but if
		   it is not found use variable name as repository name"""
		aliases = repo_opts.get('aliases')
		if aliases is not None:
			aliases = tuple(aliases.split())
		self.aliases = aliases

		eclass_overrides = repo_opts.get('eclass-overrides')
		if eclass_overrides is not None:
			eclass_overrides = tuple(eclass_overrides.split())
		self.eclass_overrides = eclass_overrides
		# Eclass databases and locations are computed later.
		self.eclass_db = None
		self.eclass_locations = None

		# Masters from repos.conf override layout.conf.
		masters = repo_opts.get('masters')
		if masters is not None:
			masters = tuple(masters.split())
		self.masters = masters

		#The main-repo key makes only sense for the 'DEFAULT' section.
		self.main_repo = repo_opts.get('main-repo')

		priority = repo_opts.get('priority')
		if priority is not None:
			try:
				priority = int(priority)
			except ValueError:
				priority = None
		self.priority = priority

		sync = repo_opts.get('sync')
		if sync is not None:
			sync = sync.strip()
		self.sync = sync

		format = repo_opts.get('format')
		if format is not None:
			format = format.strip()
		self.format = format

		location = repo_opts.get('location')
		self.user_location = location
		if location is not None and location.strip():
			if os.path.isdir(location):
				location = os.path.realpath(location)
		else:
			location = None
		self.location = location

		eapi = None
		missing = True
		if self.location is not None:
			eapi = read_corresponding_eapi_file(os.path.join(self.location, REPO_NAME_LOC))
			name, missing = self._read_valid_repo_name(self.location)
		elif name == "DEFAULT": 
			missing = False

		self.eapi = eapi
		self.name = name
		self.missing_repo_name = missing
		# sign_commit is disabled by default, since it requires Git >=1.7.9,
		# and key_id configured by `git config user.signingkey key_id`
		self.sign_commit = False
		self.sign_manifest = True
		self.thin_manifest = False
		self.allow_missing_manifest = False
		self.allow_provide_virtual = False
		self.create_manifest = True
		self.disable_manifest = False
		self.manifest_hashes = None
		self.update_changelog = False
		self.cache_formats = None
		self.portage1_profiles = True
		self.portage1_profiles_compat = False
		self.find_invalid_path_char = _find_invalid_path_char

		# Parse layout.conf.
		if self.location:
			layout_filename = os.path.join(self.location, "metadata", "layout.conf")
			layout_data = parse_layout_conf(self.location, self.name)[0]

			# layout.conf masters may be overridden here if we have a masters
			# setting from the user's repos.conf
			if self.masters is None:
				self.masters = layout_data['masters']

			if layout_data['aliases']:
				aliases = self.aliases
				if aliases is None:
					aliases = ()
				# repos.conf aliases come after layout.conf aliases, giving
				# them the ability to do incremental overrides
				self.aliases = layout_data['aliases'] + tuple(aliases)

			for value in ('allow-missing-manifest',
				'allow-provide-virtual', 'cache-formats',
				'create-manifest', 'disable-manifest', 'manifest-hashes',
				'profile-formats',
				'sign-commit', 'sign-manifest', 'thin-manifest', 'update-changelog'):
				setattr(self, value.lower().replace("-", "_"), layout_data[value])

			self.portage1_profiles = eapi_allows_directories_on_profile_level_and_repository_level(eapi) or \
				any(x in _portage1_profiles_allow_directories for x in layout_data['profile-formats'])
			self.portage1_profiles_compat = not eapi_allows_directories_on_profile_level_and_repository_level(eapi) and \
				layout_data['profile-formats'] == ('portage-1-compat',)
Example #20
0
	def _parse_file_to_dict(self, file_name, juststrings=False, recursive=True,
		eapi_filter=None, user_config=False, eapi=None, eapi_default="0"):
		"""
		@param file_name: input file name
		@type file_name: str
		@param juststrings: store dict values as space-delimited strings
			instead of tuples
		@type juststrings: bool
		@param recursive: triggers recursion if the input file is a
			directory
		@type recursive: bool
		@param eapi_filter: a function that accepts a single eapi
			argument, and returns true if the the current file type
			is supported by the given EAPI
		@type eapi_filter: callable
		@param user_config: current file is part of the local
			configuration (not repository content)
		@type user_config: bool
		@param eapi: the EAPI of the current profile node, which allows
			a call to read_corresponding_eapi_file to be skipped
		@type eapi: str
		@param eapi_default: the default EAPI which applies if the
			current profile node does not define a local EAPI
		@type eapi_default: str
		@rtype: tuple
		@return: collection of USE flags
		"""
		ret = {}
		location_dict = {}
		if eapi is None:
			eapi = read_corresponding_eapi_file(file_name,
				default=eapi_default)
		extended_syntax = eapi is None and user_config
		if extended_syntax:
			ret = ExtendedAtomDict(dict)
		else:
			ret = {}
		file_dict = grabdict_package(file_name, recursive=recursive,
			allow_wildcard=extended_syntax, allow_repo=extended_syntax,
			verify_eapi=(not extended_syntax), eapi=eapi,
			eapi_default=eapi_default)
		if eapi is not None and eapi_filter is not None and not eapi_filter(eapi):
			if file_dict:
				writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
					(eapi, os.path.basename(file_name), file_name),
					noiselevel=-1)
			return ret
		useflag_re = _get_useflag_re(eapi)
		for k, v in file_dict.items():
			useflags = []
			for prefixed_useflag in v:
				if prefixed_useflag[:1] == "-":
					useflag = prefixed_useflag[1:]
				else:
					useflag = prefixed_useflag
				if useflag_re.match(useflag) is None:
					writemsg(_("--- Invalid USE flag for '%s' in '%s': '%s'\n") %
						(k, file_name, prefixed_useflag), noiselevel=-1)
				else:
					useflags.append(prefixed_useflag)
			location_dict.setdefault(k, []).extend(useflags)
		for k, v in location_dict.items():
			if juststrings:
				v = " ".join(v)
			else:
				v = tuple(v)
			ret.setdefault(k.cp, {})[k] = v
		return ret
Example #21
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
Example #22
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
Example #23
0
    def _parse_file_to_dict(self,
                            file_name,
                            juststrings=False,
                            recursive=True,
                            eapi_filter=None,
                            user_config=False,
                            eapi=None,
                            eapi_default="0",
                            allow_build_id=False):
        """
		@param file_name: input file name
		@type file_name: str
		@param juststrings: store dict values as space-delimited strings
			instead of tuples
		@type juststrings: bool
		@param recursive: triggers recursion if the input file is a
			directory
		@type recursive: bool
		@param eapi_filter: a function that accepts a single eapi
			argument, and returns true if the the current file type
			is supported by the given EAPI
		@type eapi_filter: callable
		@param user_config: current file is part of the local
			configuration (not repository content)
		@type user_config: bool
		@param eapi: the EAPI of the current profile node, which allows
			a call to read_corresponding_eapi_file to be skipped
		@type eapi: str
		@param eapi_default: the default EAPI which applies if the
			current profile node does not define a local EAPI
		@type eapi_default: str
		@param allow_build_id: allow atoms to specify a particular
			build-id
		@type allow_build_id: bool
		@rtype: tuple
		@return: collection of USE flags
		"""
        ret = {}
        location_dict = {}
        if eapi is None:
            eapi = read_corresponding_eapi_file(file_name,
                                                default=eapi_default)
        extended_syntax = eapi is None and user_config
        if extended_syntax:
            ret = ExtendedAtomDict(dict)
        else:
            ret = {}
        file_dict = grabdict_package(file_name,
                                     recursive=recursive,
                                     allow_wildcard=extended_syntax,
                                     allow_repo=extended_syntax,
                                     verify_eapi=(not extended_syntax),
                                     eapi=eapi,
                                     eapi_default=eapi_default,
                                     allow_build_id=allow_build_id,
                                     allow_use=False)
        if eapi is not None and eapi_filter is not None and not eapi_filter(
                eapi):
            if file_dict:
                writemsg(_("--- EAPI '%s' does not support '%s': '%s'\n") %
                         (eapi, os.path.basename(file_name), file_name),
                         noiselevel=-1)
            return ret
        useflag_re = _get_useflag_re(eapi)
        for k, v in file_dict.items():
            useflags = []
            use_expand_prefix = ''
            for prefixed_useflag in v:
                if extended_syntax and prefixed_useflag == "\n":
                    use_expand_prefix = ""
                    continue
                if extended_syntax and prefixed_useflag[-1] == ":":
                    use_expand_prefix = prefixed_useflag[:-1].lower() + "_"
                    continue

                if prefixed_useflag[:1] == "-":
                    useflag = use_expand_prefix + prefixed_useflag[1:]
                    prefixed_useflag = "-" + useflag
                else:
                    useflag = use_expand_prefix + prefixed_useflag
                    prefixed_useflag = useflag
                if useflag_re.match(useflag) is None:
                    writemsg(
                        _("--- Invalid USE flag for '%s' in '%s': '%s'\n") %
                        (k, file_name, prefixed_useflag),
                        noiselevel=-1)
                else:
                    useflags.append(prefixed_useflag)
            location_dict.setdefault(k, []).extend(useflags)
        for k, v in location_dict.items():
            if juststrings:
                v = " ".join(v)
            else:
                v = tuple(v)
            ret.setdefault(k.cp, {})[k] = v
        return ret
Example #24
0
	def __init__(self, name, repo_opts):
		"""Build a RepoConfig with options in repo_opts
		   Try to read repo_name in repository location, but if
		   it is not found use variable name as repository name"""
		aliases = repo_opts.get('aliases')
		if aliases is not None:
			aliases = tuple(aliases.split())
		self.aliases = aliases

		eclass_overrides = repo_opts.get('eclass-overrides')
		if eclass_overrides is not None:
			eclass_overrides = tuple(eclass_overrides.split())
		self.eclass_overrides = eclass_overrides
		# Eclass databases and locations are computed later.
		self.eclass_db = None
		self.eclass_locations = None

		# Masters from repos.conf override layout.conf.
		masters = repo_opts.get('masters')
		if masters is not None:
			masters = tuple(masters.split())
		self.masters = masters

		#The main-repo key makes only sense for the 'DEFAULT' section.
		self.main_repo = repo_opts.get('main-repo')

		priority = repo_opts.get('priority')
		if priority is not None:
			try:
				priority = int(priority)
			except ValueError:
				priority = None
		self.priority = priority

		sync = repo_opts.get('sync')
		if sync is not None:
			sync = sync.strip()
		self.sync = sync

		format = repo_opts.get('format')
		if format is not None:
			format = format.strip()
		self.format = format

		location = repo_opts.get('location')
		self.user_location = location
		if location is not None and location.strip():
			if os.path.isdir(location):
				location = os.path.realpath(location)
		else:
			location = None
		self.location = location

		eapi = None
		missing = True
		if self.location is not None:
			eapi = read_corresponding_eapi_file(os.path.join(self.location, REPO_NAME_LOC))
			name, missing = self._read_valid_repo_name(self.location)
		elif name == "DEFAULT": 
			missing = False

		self.eapi = eapi
		self.name = name
		self.missing_repo_name = missing
		# sign_commit is disabled by default, since it requires Git >=1.7.9,
		# and key_id configured by `git config user.signingkey key_id`
		self.sign_commit = False
		self.sign_manifest = True
		self.thin_manifest = False
		self.allow_missing_manifest = False
		self.allow_provide_virtual = False
		self.create_manifest = True
		self.disable_manifest = False
		self.manifest_hashes = None
		self.update_changelog = False
		self.cache_formats = None
		self.portage1_profiles = True
		self.portage1_profiles_compat = False
		self.find_invalid_path_char = _find_invalid_path_char

		# Parse layout.conf.
		if self.location:
			layout_filename = os.path.join(self.location, "metadata", "layout.conf")
			layout_data = parse_layout_conf(self.location, self.name)[0]

			# layout.conf masters may be overridden here if we have a masters
			# setting from the user's repos.conf
			if self.masters is None:
				self.masters = layout_data['masters']

			if layout_data['aliases']:
				aliases = self.aliases
				if aliases is None:
					aliases = ()
				# repos.conf aliases come after layout.conf aliases, giving
				# them the ability to do incremental overrides
				self.aliases = layout_data['aliases'] + tuple(aliases)

			for value in ('allow-missing-manifest',
				'allow-provide-virtual', 'cache-formats',
				'create-manifest', 'disable-manifest', 'manifest-hashes',
				'profile-formats',
				'sign-commit', 'sign-manifest', 'thin-manifest', 'update-changelog'):
				setattr(self, value.lower().replace("-", "_"), layout_data[value])

			self.portage1_profiles = eapi_allows_directories_on_profile_level_and_repository_level(eapi) or \
				any(x in _portage1_profiles_allow_directories for x in layout_data['profile-formats'])
			self.portage1_profiles_compat = not eapi_allows_directories_on_profile_level_and_repository_level(eapi) and \
				layout_data['profile-formats'] == ('portage-1-compat',)