def Load( cls, repository_root, configuration, is_fast_environment, force=False, ): if not force and os.getenv(Constants.DE_REPO_ROOT_NAME): repository_root = os.getenv(Constants.DE_REPO_ROOT_NAME) configuration = os.getenv(Constants.DE_REPO_CONFIGURATION_NAME) filename = cls._GetFilename(repository_root, configuration, is_fast_environment) if not force and os.path.isfile(filename): try: # Load the json with open(filename, 'r') as f: data = json.load(f) # Convert the json structure into concrete types tool_version_specs = [ Configuration.VersionInfo( vi_data["Name"], vi_data["Version"], ) for vi_data in data["VersionSpecs"]["Tools"] ] library_version_specs = { language: [ Configuration.VersionInfo( vi_data["Name"], vi_data["Version"], ) for vi_data in language_version_infos ] for language, language_version_infos in six.iteritems( data["VersionSpecs"]["Libraries"]) } return cls( data["Id"], data["Root"], data["IsMixinRepo"], data["Configuration"], [ Repository( repo_data["Id"], repo_data["Name"], repo_data["Root"], repo_data["Configuration"], repo_data["IsMixinRepo"], ) for repo_data in data["PrioritizedRepositories"] ], Configuration.VersionSpecs( tool_version_specs, library_version_specs, ), ) except: pass # Generate the data repository_root = CommonEnvironmentImports.FileSystem.Normalize( repository_root) assert os.path.isdir(repository_root), repository_root repositories = OrderedDict() tool_version_info = [] library_version_info = {} version_info_lookup = {} # ---------------------------------------------------------------------- def Walk( referencing_repo, repo, priority_modifier, ): if repo.Id not in repositories: bootstrap_info = EnvironmentBootstrap.Load(repo.Root) bootstrap_info.Repo = repo bootstrap_info.ReferencingRepo = referencing_repo bootstrap_info.priority_modifier = 0 repositories[repo.Id] = bootstrap_info recurse = True else: recurse = False bootstrap_info = repositories[repo.Id] bootstrap_info.priority_modifier += priority_modifier # Ensure that the configuration name is valid if bootstrap_info.IsConfigurable and not repo.Configuration: raise Exception( "The repository at '{}' is configurable, but no configuration was provided." .format(repo.Root)) if not bootstrap_info.IsConfigurable and repo.Configuration: raise Exception( "The repository at '{}' is not configurable, but a configuration was provided ({})." .format(repo.Root, repo.Configuration)) if repo.Configuration not in bootstrap_info.Configurations: raise Exception( textwrap.dedent("""\ The configuration '{config}' is not a valid configuration for the repository at '{root}'. Valid configuration values are: {configs} """).format( config=repo.Configuration, root=repo.Root, configs='\n'.join([ " - {}".format(config or "<None>") for config in six.iterkeys(bootstrap_info.Configurations) ]), )) # Check for consistent repo locations if repo.Root != bootstrap_info.Repo.Root: raise Exception( textwrap.dedent("""\ There is a mismatch in repository locations. Repository: {name} <{id}> New Location: {new_value} Referenced By: {new_name} <{new_id}> [{new_root}] Original Location: {original_value} Referenced By: {original_name} <{original_id}> [{original_root}] """).format( name=repo.Name, id=repo.Id, new_value=repo.Root, new_name=referencing_repo.Name, new_id=referencing_repo.Id, new_root=referencing_repo.Root, original_value=bootstrap_info.Repo.Root, original_name=bootstrap_info.Repo.Name, original_id=bootstrap_info.Repo.Id, original_root=bootstrap_info.Repo.Root, )) # Check for consistent configurations if repo.Configuration != bootstrap_info.Repo.Configuration: raise Exception( textwrap.dedent("""\ There is a mismatch in repository configurations: Repository: {name} <{id}> New Configuration: {new_value} Referenced By: {new_name} <{new_id}> [{new_root}] Original Configuration: {original_value} Referenced By: {original_name} <{original_id}> [{original_root}] """).format( name=repo.Name, id=repo.Id, new_value=repo.Configuration, new_name=referencing_repo.Name, new_id=referencing_repo.Id, new_root=referencing_repo.Root, original_value=bootstrap_info.Repo.Configuration, original_name=bootstrap_info.Repo.Name, original_id=bootstrap_info.Repo.Id, original_root=bootstrap_info.Repo.Root, )) # Process the version info # ---------------------------------------------------------------------- def OnVersionMismatch(type_, version_info, existing_version_info): original_repo = version_info_lookup[existing_version_info] raise Exception( textwrap.dedent("""\ There was a mismatch in version information. Item: {name} <{type_}> New Version: {new_value} Specified By: {new_name} ({new_config}) <{new_id}> [{new_root}] Original Version: {original_value} Specified By: {original_name} ({original_config}) <{original_id}> [{original_root}] """).format( name=version_info.Name, type_=type_, new_value=version_info.Version, new_name=repo.Name, new_config=repo.Configuration, new_id=repo.Id, new_root=repo.Root, original_value=existing_version_info.Version, original_name=original_repo.Name, original_config=original_repo.Configuration, original_id=original_repo.Id, original_root=original_repo.Root, )) # ---------------------------------------------------------------------- for version_info in bootstrap_info.Configurations[ repo.Configuration].VersionSpecs.Tools: existing_version_info = next( (tvi for tvi in tool_version_info if tvi.Name == version_info.Name), None) if existing_version_info is None: tool_version_info.append(version_info) version_info_lookup[version_info] = repo elif version_info.Version != existing_version_info.Version: OnVersionMismatch("Tools", version_info, existing_version_info) for library_language, version_info_items in six.iteritems( bootstrap_info.Configurations[ repo.Configuration].VersionSpecs.Libraries): for version_info in version_info_items: existing_version_info = next( (lvi for lvi in library_version_info.get( library_language, []) if lvi.Name == version_info.Name), None) if existing_version_info is None: library_version_info.setdefault( library_language, []).append(version_info) version_info_lookup[version_info] = repo elif version_info.Version != existing_version_info.Version: OnVersionMismatch( "{} Libraries".format(library_language), version_info, existing_version_info) # Process this repository's dependencies if recurse: for dependency_info in bootstrap_info.Configurations[ repo.Configuration].Dependencies: Walk( repo, Repository.Create(dependency_info.RepositoryRoot, dependency_info.Configuration), priority_modifier + 1, ) # ---------------------------------------------------------------------- this_repository = Repository.Create(repository_root, configuration) Walk(None, this_repository, 1) # Order the results from the most- to least-frequently requested priority_values = [(id, info.priority_modifier) for id, info in six.iteritems(repositories)] priority_values.sort(key=lambda x: x[1], reverse=True) this_bootstrap_info = repositories[priority_values[-1][0]] this_configuration = this_bootstrap_info.Configurations[configuration] # Check the fingerprints calculated_fingerprint = Utilities.CalculateFingerprint( [ repository_root, ] + [ dependency.RepositoryRoot for dependency in this_configuration.Dependencies ], repository_root, ) if this_configuration.Fingerprint != calculated_fingerprint: lines = [] line_template = "{0:<80} : {1}" for k, v in six.iteritems(calculated_fingerprint): if k not in this_configuration.Fingerprint: lines.append(line_template.format(k[0], "Added")) else: lines.append( line_template.format( k, "Identical" if v == this_configuration.Fingerprint[k] else "Modified")) for k in six.iteritems(this_configuration.Fingerprint): if k not in calculated_fingerprint: lines.append(line_template.format(k[0], "Removed")) assert lines raise Exception( textwrap.dedent("""\ ******************************************************************************** ******************************************************************************** It appears that one or more of the repositories that this repository depends on have changed. Please run '{setup}' again. {status} ******************************************************************************** ******************************************************************************** """).format( setup=CommonEnvironmentImports.CurrentShell. CreateScriptName(Constants.SETUP_ENVIRONMENT_NAME), status=CommonEnvironmentImports.StringHelpers.LeftJustify( '\n'.join(lines), 4), )) # Create the object return cls( this_repository.Id, repository_root, this_bootstrap_info.IsMixinRepo, configuration, is_fast_environment, [repositories[id].Repo for id, _ in priority_values], Configuration.VersionSpecs(tool_version_info, library_version_info), )
def Execute(): commands = [] # Load the activation data output_stream.write("\nLoading data...") with output_stream.DoneManager(suffix='\n', ): is_activated = bool(os.getenv(Constants.DE_REPO_ACTIVATED_FLAG)) activation_data = ActivationData.Load( repository_root, configuration, fast, force=force or not is_activated, ) # Augment the version specs with those provided on the command line for k, v in six.iteritems(version_specs): keys = k.split('/') if keys[0] == Constants.TOOLS_SUBDIR: if len(keys) != 2: raise Exception( "'{}' is not a valid version spec; expected '{}/<Tool Name>'." .format(k, Constants.TOOLS_SUBDIR)) name = keys[1] version_infos = activation_data.VersionSpecs.Tools elif keys[0] == Constants.LIBRARIES_SUBDIR: if len(keys) != 3: raise Exception( "'{}' is not a valid version spec; expected '{}/<Language>/<Library Name>'." .format(k, Constants.LIBRARIES_SUBDIR)) name = keys[2] version_infos = activation_data.VersionSpecs.Libraries.setdefault( keys[1], []) else: raise Exception( "'{}' is not a valid version spec prefix".format(keys[0])) found = False for version_info in version_infos: if version_info.Name == name: version_info.Version = v found = True break if not found: version_infos.append(Configuration.VersionInfo(name, v)) # ---------------------------------------------------------------------- def LoadMixinLibrary(mixin_path): mixin_activation_data = ActivationData.Load( mixin_path, configuration=None, force=True, ) if not mixin_activation_data.IsMixinRepo: raise Exception( "The repository at '{}' is not a mixin repository".format( mixin_path)) assert not mixin_activation_data.VersionSpecs.Tool assert not mixin_activation_data.VersionSpecs.Libraries assert len(mixin_activation_data.PrioritizedRepositories) == 1 mixin_repo = mixin_activation_data.PrioritizedRepositories[0] mixin_repo.IsMixinRepo = True # Add this repo as a repo to be activated if it isn't already in the list if not any(r.Id == mixin_repo.Id for r in activation_data.PrioritizedRepositories): activation_data.PrioritizedRepositories.append(mixin_repo) # ---------------------------------------------------------------------- # Are we activating a mixin repository? is_mixin_repo = EnvironmentBootstrap.Load(repository_root).IsMixinRepo if is_mixin_repo: if force: raise Exception( "'force' cannot be used with mixin repositories") LoadMixinLibrary(repository_root) for mixin in mixins: LoadMixinLibrary(mixin) # Ensure that the generated dir exists generated_dir = activation_data.GetActivationDir() CommonEnvironmentImports.FileSystem.MakeDirs(generated_dir) methods = [ _ActivateActivationData, _ActivateNames, _ActivateTools, _ActivatePython, _ActivateScripts, _ActivateCustom, _ActivatePrompt, ] if not is_mixin_repo: methods = [ _ActivateOriginalEnvironment, _ActivateRepoEnvironmentVars, ] + methods args = OrderedDict([ ("output_stream", output_stream), ("configuration", configuration), ("activation_data", activation_data), ("version_specs", activation_data.VersionSpecs), ("generated_dir", generated_dir), ("debug", debug), ("verbose", verbose), ("no_python_libraries", no_python_libraries), ("fast", fast), ("repositories", activation_data.PrioritizedRepositories), ("is_mixin_repo", is_mixin_repo), ]) # Invoke the methods for original_method in methods: method = CommonEnvironmentImports.Interface.CreateCulledCallable( original_method) result = method(args) if isinstance(result, list): commands += result elif result is not None: commands.append(result) return commands