PrintOptions( System.Collections.Generic.IEnumerable <System.Type> optionTypes) { var options = new Core.Array <Core.ICommandLineArgument>(); foreach (var optType in optionTypes) { var arg = System.Activator.CreateInstance(optType) as Core.ICommandLineArgument; options.Add(arg); } foreach (var arg in options.OrderBy(key => key.LongName)) { if (arg is Core.ICustomHelpText) { Core.Log.Info("{0}: {1}", (arg as Core.ICustomHelpText).OptionHelp, arg.ContextHelp); } else { if (null == arg.ShortName) { Core.Log.Info("{0}: {1}", arg.LongName, arg.ContextHelp); } else { Core.Log.Info("{0} (or {1}): {2}", arg.LongName, arg.ShortName, arg.ContextHelp); } } Core.Log.Info(""); } }
IdentifyAllPackages( bool allowDuplicates = false, bool enforceBamAssemblyVersions = true) { var packageRepos = new System.Collections.Generic.LinkedList <System.Tuple <string, PackageDefinition> >(); foreach (var repo in Graph.Instance.PackageRepositories) { EnqueuePackageRepositoryToVisit(packageRepos, repo, null); } var masterDefinitionFile = GetMasterPackage(); foreach (var repo in masterDefinitionFile.PackageRepositories) { EnqueuePackageRepositoryToVisit(packageRepos, repo, masterDefinitionFile); } // read the definition files of any package found in the package roots var candidatePackageDefinitions = new Array <PackageDefinition>(); candidatePackageDefinitions.Add(masterDefinitionFile); while (packageRepos.Count > 0) { var repoTuple = packageRepos.First(); packageRepos.RemoveFirst(); var repo = repoTuple.Item1; if (!System.IO.Directory.Exists(repo)) { var message = new System.Text.StringBuilder(); message.AppendFormat("Package repository directory {0} does not exist.", repo); message.AppendLine(); message.AppendFormat("Repository requested from {0}", repoTuple.Item2.XMLFilename); message.AppendLine(); throw new Exception(message.ToString()); } var candidatePackageDirs = System.IO.Directory.GetDirectories(repo, BamSubFolder, System.IO.SearchOption.AllDirectories); Graph.Instance.PackageRepositories.Add(repo); foreach (var bamDir in candidatePackageDirs) { var packageDir = System.IO.Path.GetDirectoryName(bamDir); var packageDefinitionPath = GetPackageDefinitionPathname(packageDir); // ignore any duplicates (can be found due to nested repositories) if (null != candidatePackageDefinitions.FirstOrDefault(item => item.XMLFilename == packageDefinitionPath)) { continue; } var definitionFile = new PackageDefinition(packageDefinitionPath); definitionFile.Read(); candidatePackageDefinitions.Add(definitionFile); foreach (var newRepo in definitionFile.PackageRepositories) { EnqueuePackageRepositoryToVisit(packageRepos, newRepo, definitionFile); } } } // defaults come from // - the master definition file // - command line args (these trump the mdf) // and only requires resolving when referenced var packageDefinitions = new Array <PackageDefinition>(); PackageDefinition.ResolveDependencies(masterDefinitionFile, packageDefinitions, candidatePackageDefinitions); // now resolve any duplicate names using defaults // unless duplicates are allowed var duplicatePackageNames = packageDefinitions.GroupBy(item => item.Name).Where(item => item.Count() > 1).Select(item => item.Key); var uniquePackageNames = packageDefinitions.GroupBy(item => item.Name).Where(item => item.Count() == 1).Select(item => item.Key); var versionSpeciferArgs = new Options.PackageDefaultVersion(); var packageVersionSpecifiers = CommandLineProcessor.Evaluate(versionSpeciferArgs); if ((duplicatePackageNames.Count() > 0) && !allowDuplicates) { var toRemove = new Array <PackageDefinition>(); foreach (var dupName in duplicatePackageNames) { var duplicates = packageDefinitions.Where(item => item.Name == dupName); var resolvedDuplicate = TryToResolveDuplicate(masterDefinitionFile, dupName, duplicates, packageDefinitions, packageVersionSpecifiers, toRemove); if (null != resolvedDuplicate) { continue; } // try removing any packages that have already been resolved // which can remove additional packages (recursive check) because they had been added solely by those we are just about to remove packageDefinitions.RemoveAll(PackagesToRemove(toRemove, packageDefinitions, masterDefinitionFile)); packageDefinitions.RemoveAll(toRemove); // and if that has reduced the duplicates for this package down to a single version, we're good to carry on var numDuplicates = duplicates.Count(); if (1 == numDuplicates) { toRemove.Clear(); continue; } // otherwise, error var resolveErrorMessage = new System.Text.StringBuilder(); if (numDuplicates > 0) { resolveErrorMessage.AppendFormat("Unable to resolve to a single version of package {0}. Use --{0}.version=<version> to resolve.", dupName); resolveErrorMessage.AppendLine(); resolveErrorMessage.AppendLine("Available versions of the package are:"); foreach (var dup in duplicates) { resolveErrorMessage.AppendFormat("\t{0}", dup.Version); resolveErrorMessage.AppendLine(); } } else { resolveErrorMessage.AppendFormat("No version of package {0} has been determined to be available.", dupName); resolveErrorMessage.AppendLine(); if (toRemove.Count() > 0) { resolveErrorMessage.AppendFormat("If there were any references to {0}, they may have been removed from consideration by the following packages being discarded:", dupName); resolveErrorMessage.AppendLine(); foreach (var removed in toRemove) { resolveErrorMessage.AppendFormat("\t{0}", removed.FullName); resolveErrorMessage.AppendLine(); } } resolveErrorMessage.AppendFormat("Please add an explicit dependency to (a version of) the {0} package either in your master package or one of its dependencies.", dupName); resolveErrorMessage.AppendLine(); } throw new Exception(resolveErrorMessage.ToString()); } // finally, clean up the package definition list to use, with all those that need to be deleted packageDefinitions.RemoveAll(toRemove); } // ensure that all packages with a single version in the definition files, does not have a command line override // that refers to a completely different version foreach (var uniquePkgName in uniquePackageNames) { foreach (var versionSpecifier in packageVersionSpecifiers) { if (!versionSpecifier.Contains(uniquePkgName)) { continue; } var versionFromDefinition = packageDefinitions.First(item => item.Name == uniquePkgName).Version; if (versionSpecifier[1] != versionFromDefinition) { var noMatchMessage = new System.Text.StringBuilder(); noMatchMessage.AppendFormat("Command line version specified, {0}, could not resolve to one of the available versions of package {1}:", versionSpecifier[1], uniquePkgName); noMatchMessage.AppendLine(); noMatchMessage.AppendFormat("\t{0}", versionFromDefinition); noMatchMessage.AppendLine(); throw new Exception(noMatchMessage.ToString()); } } } if (enforceBamAssemblyVersions) { // for all packages that make up this assembly, ensure that their requirements on the version of the Bam // assemblies are upheld, prior to compiling the code foreach (var pkgDefn in packageDefinitions) { pkgDefn.ValidateBamAssemblyRequirements(); } } Graph.Instance.SetPackageDefinitions(packageDefinitions); }
Main( string[] args) { #if false // take control of Ctrl+C System.Console.CancelKeyPress += new System.ConsoleCancelEventHandler(HandleCancellation); #endif try { var totalTimeProfile = new Core.TimeProfile(Core.ETimingProfiles.TimedTotal); var processCommandLineProfile = new Core.TimeProfile(Core.ETimingProfiles.ProcessCommandLine); totalTimeProfile.StartProfile(); processCommandLineProfile.StartProfile(); var verbosityLevel = (Core.EVerboseLevel)Core.CommandLineProcessor.Evaluate(new Core.Options.VerbosityLevel()); switch (verbosityLevel) { case Core.EVerboseLevel.None: case Core.EVerboseLevel.Info: case Core.EVerboseLevel.Detail: case Core.EVerboseLevel.Full: Core.Graph.Instance.VerbosityLevel = verbosityLevel; break; default: throw new Core.Exception("Unrecognized verbosity level, {0}", verbosityLevel); } if (Core.CommandLineProcessor.Evaluate(new Core.Options.PrintHelp())) { CommandLineArgumentHelper.PrintHelp(); return; } if (Core.CommandLineProcessor.Evaluate(new Core.Options.PrintVersion())) { CommandLineArgumentHelper.PrintVersion(); return; } if (Core.CommandLineProcessor.Evaluate(new Core.Options.CreateDebugProject())) { DebugProject.Create(); return; } if (Core.CommandLineProcessor.Evaluate(new Core.Options.MakePackage())) { Core.PackageUtilities.MakePackage(); return; } if (Core.CommandLineProcessor.Evaluate(new Core.Options.AddDependentPackage())) { Core.PackageUtilities.AddDependentPackage(); return; } if (Core.CommandLineProcessor.Evaluate(new Core.Options.ShowDefinitionFile())) { Core.PackageUtilities.IdentifyAllPackages(allowDuplicates: true, enforceBamAssemblyVersions: false); Core.Graph.Instance.MasterPackage.Show(); return; } // configure Core.Graph.Instance.BuildRoot = Core.CommandLineProcessor.Evaluate(new Core.Options.BuildRoot()); Core.Graph.Instance.Mode = Core.CommandLineProcessor.Evaluate(new Core.Options.BuildMode()); if (null == Core.Graph.Instance.Mode) { throw new Core.Exception("No build mode specified"); } var configs = new Core.Array <Core.Environment>(); var requestedConfigs = Core.CommandLineProcessor.Evaluate(new Core.Options.BuildConfigurations()); if (0 == requestedConfigs.Count) { // default requestedConfigs.Add(new Core.StringArray("debug")); } foreach (var configOption in requestedConfigs) { foreach (var config in configOption) { var env = new Core.Environment(); env.Configuration = Core.Configuration.FromString(config); configs.Add(env); } } processCommandLineProfile.StopProfile(); Core.EntryPoint.Execute(configs); totalTimeProfile.StopProfile(); } catch (Core.Exception exception) { Core.Exception.DisplayException(exception); System.Environment.ExitCode = -1; } catch (System.Exception exception) { var message = new System.Text.StringBuilder(); message.AppendFormat("{0} not handled: {1}", exception.GetType().ToString(), exception.Message); message.AppendLine(); message.AppendLine(exception.StackTrace); Core.Log.ErrorMessage(message.ToString()); System.Environment.ExitCode = -2; } finally { if (Core.Graph.Instance.BuildEnvironments.Count > 0) { Core.Log.Info((0 == System.Environment.ExitCode) ? "\nBuild Succeeded" : "\nBuild Failed"); if (Core.CommandLineProcessor.Evaluate(new Core.Options.PrintStatistics())) { Core.Statistics.Display(); } Core.Log.DebugMessage("Exit code {0}", System.Environment.ExitCode); } } }
CheckIfModulesNeedRebuilding( System.Type metaType) { var graph = Graph.Instance; var modulesNeedEvaluating = new Array <Module>(); // not all build modes need to determine if modules are up-to-date var evaluationRequiredAttr = metaType.GetCustomAttributes(typeof(EvaluationRequiredAttribute), false) as EvaluationRequiredAttribute[]; if (0 == evaluationRequiredAttr.Length) { // query if any individual modules override this foreach (var rank in graph.Reverse()) { foreach (Module module in rank) { var moduleEvaluationRequiredAttr = module.GetType().GetCustomAttributes(typeof(EvaluationRequiredAttribute), true) as EvaluationRequiredAttribute[]; if (moduleEvaluationRequiredAttr.Length > 0 && moduleEvaluationRequiredAttr[0].Enabled) { modulesNeedEvaluating.Add(module); } } } if (0 == modulesNeedEvaluating.Count) { Log.DebugMessage("No Bam.Core.EvaluationRequired attribute on build mode metadata, assume rebuilds necessary"); return(false); } } if ((evaluationRequiredAttr.Length > 0) && !evaluationRequiredAttr[0].Enabled && 0 == modulesNeedEvaluating.Count) { Log.DebugMessage("Module evaluation disabled"); return(false); } using (var cancellationSource = new System.Threading.CancellationTokenSource()) { var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var threadCount = 1; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); graph.MetaData = factory; if (0 == modulesNeedEvaluating.Count) { Log.DebugMessage("Module evaluation enabled for build mode {0}", graph.Mode); foreach (var rank in graph.Reverse()) { foreach (Module module in rank) { module.Evaluate(); } } } else { Log.DebugMessage("Module evaluation disabled for build mode {0}, but enabled for individual modules:", graph.Mode); foreach (var module in modulesNeedEvaluating) { Log.DebugMessage("\tEvaluation for module {0}", module.GetType().ToString()); module.Evaluate(); } } } return(true); }
Run() { Log.Detail("Running build..."); // TODO: should the rank collections be sorted, so that modules with fewest dependencies are first? var graph = Graph.Instance; var metaDataType = graph.BuildModeMetaData.GetType(); var useEvaluation = CheckIfModulesNeedRebuilding(metaDataType); var explainRebuild = CommandLineProcessor.Evaluate(new Options.ExplainBuildReason()); var immediateOutput = CommandLineProcessor.Evaluate(new Options.ImmediateOutput()); ExecutePreBuild(metaDataType); // necessary if built with debug symbols IOWrapper.CreateDirectoryIfNotExists(graph.BuildRoot); var threadCount = CommandLineProcessor.Evaluate(new Options.MultiThreaded()); if (0 == threadCount) { threadCount = System.Environment.ProcessorCount; } System.Exception abortException = null; if (threadCount > 1) { using (var cancellationSource = new System.Threading.CancellationTokenSource()) { var cancellationToken = cancellationSource.Token; // LongRunning is absolutely necessary in order to achieve paralleism var creationOpts = System.Threading.Tasks.TaskCreationOptions.LongRunning; var continuationOpts = System.Threading.Tasks.TaskContinuationOptions.LongRunning; var scheduler = new LimitedConcurrencyLevelTaskScheduler(threadCount); var factory = new System.Threading.Tasks.TaskFactory( cancellationToken, creationOpts, continuationOpts, scheduler); var tasks = new Array <System.Threading.Tasks.Task>(); foreach (var rank in graph.Reverse()) { foreach (var module in rank) { var context = new ExecutionContext(useEvaluation, explainRebuild, immediateOutput); var task = factory.StartNew(() => { if (cancellationToken.IsCancellationRequested) { return; } var depTasks = new Array <System.Threading.Tasks.Task>(); foreach (var dep in module.Dependents) { if (null == dep.ExecutionTask) { continue; } depTasks.Add(dep.ExecutionTask); } foreach (var dep in module.Requirements) { if (null == dep.ExecutionTask) { continue; } depTasks.Add(dep.ExecutionTask); } System.Threading.Tasks.Task.WaitAll(depTasks.ToArray()); if (cancellationToken.IsCancellationRequested) { return; } try { (module as IModuleExecution).Execute(context); } catch (Exception ex) { abortException = ex; cancellationSource.Cancel(); } finally { if (context.OutputStringBuilder != null && context.OutputStringBuilder.Length > 0) { Log.Info(context.OutputStringBuilder.ToString()); } if (context.ErrorStringBuilder != null && context.ErrorStringBuilder.Length > 0) { Log.Info(context.ErrorStringBuilder.ToString()); } } }); tasks.Add(task); module.ExecutionTask = task; } } try { System.Threading.Tasks.Task.WaitAll(tasks.ToArray()); } catch (System.AggregateException exception) { if (!(exception.InnerException is System.Threading.Tasks.TaskCanceledException)) { throw new Exception(exception, "Error during threaded build"); } } } } else { foreach (var rank in graph.Reverse()) { if (null != abortException) { break; } foreach (IModuleExecution module in rank) { var context = new ExecutionContext(useEvaluation, explainRebuild, immediateOutput); try { module.Execute(context); } catch (Exception ex) { abortException = ex; break; } finally { if (context.OutputStringBuilder != null && context.OutputStringBuilder.Length > 0) { Log.Info(context.OutputStringBuilder.ToString()); } if (context.ErrorStringBuilder != null && context.ErrorStringBuilder.Length > 0) { Log.Info(context.ErrorStringBuilder.ToString()); } } } } } if (null != abortException) { throw new Exception(abortException, "Error during {0}threaded build", (threadCount > 1) ? string.Empty : "non-"); } ExecutePostBuild(metaDataType); }
IdentifyAllPackages( bool allowDuplicates = false, bool enforceBamAssemblyVersions = true) { var packageRepos = new System.Collections.Generic.Queue <string>(); foreach (var repo in Graph.Instance.PackageRepositories) { if (packageRepos.Contains(repo)) { continue; } packageRepos.Enqueue(repo); } var masterDefinitionFile = GetMasterPackage(enforceBamAssemblyVersions: enforceBamAssemblyVersions); foreach (var repo in masterDefinitionFile.PackageRepositories) { if (packageRepos.Contains(repo)) { continue; } packageRepos.Enqueue(repo); } // read the definition files of any package found in the package roots var candidatePackageDefinitions = new Array <PackageDefinition>(); candidatePackageDefinitions.Add(masterDefinitionFile); while (packageRepos.Count > 0) { var repo = packageRepos.Dequeue(); if (!System.IO.Directory.Exists(repo)) { throw new Exception("Package repository directory {0} does not exist", repo); } var candidatePackageDirs = System.IO.Directory.GetDirectories(repo, BamSubFolder, System.IO.SearchOption.AllDirectories); Graph.Instance.PackageRepositories.Add(repo); foreach (var bamDir in candidatePackageDirs) { var packageDir = System.IO.Path.GetDirectoryName(bamDir); var packageDefinitionPath = GetPackageDefinitionPathname(packageDir); // ignore any duplicates (can be found due to nested repositories) if (null != candidatePackageDefinitions.Where(item => item.XMLFilename == packageDefinitionPath).FirstOrDefault()) { continue; } var definitionFile = new PackageDefinition(packageDefinitionPath, !Graph.Instance.ForceDefinitionFileUpdate); definitionFile.Read(true, enforceBamAssemblyVersions); candidatePackageDefinitions.Add(definitionFile); foreach (var newRepo in definitionFile.PackageRepositories) { if (Graph.Instance.PackageRepositories.Contains(newRepo)) { continue; } packageRepos.Enqueue(newRepo); } } } // defaults come from // - the master definition file // - command line args (these trump the mdf) // and only requires resolving when referenced var packageDefinitions = new Array <PackageDefinition>(); PackageDefinition.ResolveDependencies(masterDefinitionFile, packageDefinitions, candidatePackageDefinitions); // now resolve any duplicate names using defaults // unless duplicates are allowed var duplicatePackageNames = packageDefinitions.GroupBy(item => item.Name).Where(item => item.Count() > 1).Select(item => item.Key); if ((duplicatePackageNames.Count() > 0) && !allowDuplicates) { var versionSpeciferArgs = new Options.PackageDefaultVersion(); var packageVersionSpecifiers = CommandLineProcessor.Evaluate(versionSpeciferArgs); var toRemove = new Array <PackageDefinition>(); foreach (var dupName in duplicatePackageNames) { var duplicates = packageDefinitions.Where(item => item.Name == dupName); PackageDefinition resolvedDuplicate = null; // command line specifications take precedence to resolve a duplicate foreach (var specifier in packageVersionSpecifiers) { if (!specifier.Contains(dupName)) { continue; } foreach (var dupPackage in duplicates) { if (specifier[1] == dupPackage.Version) { resolvedDuplicate = dupPackage; break; } } if (resolvedDuplicate != null) { break; } var noMatchMessage = new System.Text.StringBuilder(); noMatchMessage.AppendFormat("Command line version specified, {0}, could not resolve to one of the available versions of package {1}:", specifier[1], duplicates.First().Name); noMatchMessage.AppendLine(); foreach (var dup in duplicates) { noMatchMessage.AppendFormat("\t{0}", dup.Version); noMatchMessage.AppendLine(); } throw new Exception(noMatchMessage.ToString()); } if (resolvedDuplicate != null) { toRemove.AddRange(packageDefinitions.Where(item => (item.Name == dupName) && (item != resolvedDuplicate))); continue; } // now look at the master dependency file, for any 'default' specifications var masterDependency = masterDefinitionFile.Dependents.Where(item => item.Item1 == dupName && item.Item3.HasValue && item.Item3.Value).FirstOrDefault(); if (null != masterDependency) { toRemove.AddRange(packageDefinitions.Where(item => (item.Name == dupName) && (item.Version != masterDependency.Item2))); continue; } var resolveErrorMessage = new System.Text.StringBuilder(); resolveErrorMessage.AppendFormat("Unable to resolve to a single version of package {0}. Use --{0}.version=<version> to resolve. Available versions of the package are:", duplicates.First().Name); resolveErrorMessage.AppendLine(); foreach (var dup in duplicates) { resolveErrorMessage.AppendFormat("\t{0}", dup.Version); resolveErrorMessage.AppendLine(); } throw new Exception(resolveErrorMessage.ToString()); } packageDefinitions.RemoveAll(toRemove); } Graph.Instance.SetPackageDefinitions(packageDefinitions); }
IdentifyAllPackages( bool allowDuplicates = false, bool enforceBamAssemblyVersions = true) { var packageRepos = new System.Collections.Generic.LinkedList <System.Tuple <string, PackageDefinition> >(); int reposHWM = 0; foreach (var repo in Graph.Instance.PackageRepositories) { EnqueuePackageRepositoryToVisit(packageRepos, ref reposHWM, repo, null); } var masterDefinitionFile = GetMasterPackage(); // inject any packages from the command line into the master definition file // and these will be defaults var injectPackages = CommandLineProcessor.Evaluate(new Options.InjectDefaultPackage()); if (null != injectPackages) { foreach (var injected in injectPackages) { var name = injected[0]; string version = null; if (injected.Count > 1) { version = injected[1].TrimStart(new [] { '-' }); // see regex in InjectDefaultPackage } var is_default = true; var dependent = new System.Tuple <string, string, bool?>(name, version, is_default); masterDefinitionFile.Dependents.AddUnique(dependent); } } foreach (var repo in masterDefinitionFile.PackageRepositories) { EnqueuePackageRepositoryToVisit(packageRepos, ref reposHWM, repo, masterDefinitionFile); } // read the definition files of any package found in the package roots var candidatePackageDefinitions = new Array <PackageDefinition>(); candidatePackageDefinitions.Add(masterDefinitionFile); var packageReposVisited = 0; Log.Detail("Querying package repositories..."); while (packageRepos.Count > 0) { var repoTuple = packageRepos.First(); packageRepos.RemoveFirst(); var repo = repoTuple.Item1; if (!System.IO.Directory.Exists(repo)) { var message = new System.Text.StringBuilder(); message.AppendFormat("Package repository directory {0} does not exist.", repo); message.AppendLine(); message.AppendFormat("Repository requested from {0}", repoTuple.Item2.XMLFilename); message.AppendLine(); throw new Exception(message.ToString()); } // faster than System.IO.Directory.GetDirectories(repo, BamSubFolder, System.IO.SearchOption.AllDirectories); // when there are deep directories StringArray candidatePackageDirs = new StringArray(); var possiblePackages = System.IO.Directory.GetDirectories(repo, "*", System.IO.SearchOption.TopDirectoryOnly); foreach (var packageDir in possiblePackages) { var possibleBamFolder = System.IO.Path.Combine(packageDir, BamSubFolder); if (System.IO.Directory.Exists(possibleBamFolder)) { candidatePackageDirs.Add(packageDir); } } Graph.Instance.PackageRepositories.Add(repo); foreach (var packageDir in candidatePackageDirs) { var packageDefinitionPath = GetPackageDefinitionPathname(packageDir); // ignore any duplicates (can be found due to nested repositories) if (null != candidatePackageDefinitions.FirstOrDefault(item => item.XMLFilename == packageDefinitionPath)) { continue; } var definitionFile = new PackageDefinition(packageDefinitionPath); definitionFile.Read(); candidatePackageDefinitions.Add(definitionFile); foreach (var newRepo in definitionFile.PackageRepositories) { EnqueuePackageRepositoryToVisit(packageRepos, ref reposHWM, newRepo, definitionFile); } } ++packageReposVisited; Log.DetailProgress("{0,3}%", (int)(100 * ((float)packageReposVisited / reposHWM))); } #if DEBUG if (packageReposVisited != reposHWM) { throw new Exception("Inconsistent package repository count: {0} added, {1} visited", reposHWM, packageReposVisited); } #endif // defaults come from // - the master definition file // - command line args (these trump the mdf) // and only requires resolving when referenced var packageDefinitions = new Array <PackageDefinition>(); PackageDefinition.ResolveDependencies(masterDefinitionFile, packageDefinitions, candidatePackageDefinitions); // now resolve any duplicate names using defaults // unless duplicates are allowed var duplicatePackageNames = packageDefinitions.GroupBy(item => item.Name).Where(item => item.Count() > 1).Select(item => item.Key); var uniquePackageNames = packageDefinitions.GroupBy(item => item.Name).Where(item => item.Count() == 1).Select(item => item.Key); var versionSpeciferArgs = new Options.PackageDefaultVersion(); var packageVersionSpecifiers = CommandLineProcessor.Evaluate(versionSpeciferArgs); if ((duplicatePackageNames.Count() > 0) && !allowDuplicates) { foreach (var dupName in duplicatePackageNames) { Log.DebugMessage("Duplicate '{0}'; total packages {1}", dupName, packageDefinitions.Count); var duplicates = packageDefinitions.Where(item => item.Name == dupName); var toRemove = new Array <PackageDefinition>(); var resolvedDuplicate = TryToResolveDuplicate(masterDefinitionFile, dupName, duplicates, packageDefinitions, packageVersionSpecifiers, toRemove); Log.DebugMessage("Attempting to remove:\n\t{0}", toRemove.ToString("\n\t")); // try removing any packages that have already been resolved // which, in turn, can remove additional packages that have become orphaned by other removals packageDefinitions.RemoveAll(FindPackagesToRemove(toRemove, packageDefinitions, masterDefinitionFile)); if (null != resolvedDuplicate) { continue; } // and if that has reduced the duplicates for this package down to a single version, we're good to carry on var numDuplicates = duplicates.Count(); // this is LINQ, so it's 'live' if (1 == numDuplicates) { continue; } // otherwise, error var resolveErrorMessage = new System.Text.StringBuilder(); if (numDuplicates > 0) { resolveErrorMessage.AppendFormat("Unable to resolve to a single version of package {0}. Use --{0}.version=<version> to resolve.", dupName); resolveErrorMessage.AppendLine(); resolveErrorMessage.AppendLine("Available versions of the package are:"); foreach (var dup in duplicates) { resolveErrorMessage.AppendFormat("\t{0}", dup.Version); resolveErrorMessage.AppendLine(); } } else { resolveErrorMessage.AppendFormat("No version of package {0} has been determined to be available.", dupName); resolveErrorMessage.AppendLine(); if (toRemove.Count() > 0) { resolveErrorMessage.AppendFormat("If there were any references to {0}, they may have been removed from consideration by the following packages being discarded:", dupName); resolveErrorMessage.AppendLine(); foreach (var removed in toRemove) { resolveErrorMessage.AppendFormat("\t{0}", removed.FullName); resolveErrorMessage.AppendLine(); } } resolveErrorMessage.AppendFormat("Please add an explicit dependency to (a version of) the {0} package either in your master package or one of its dependencies.", dupName); resolveErrorMessage.AppendLine(); } throw new Exception(resolveErrorMessage.ToString()); } } // ensure that all packages with a single version in the definition files, does not have a command line override // that refers to a completely different version foreach (var uniquePkgName in uniquePackageNames) { foreach (var versionSpecifier in packageVersionSpecifiers) { if (!versionSpecifier.Contains(uniquePkgName)) { continue; } var versionFromDefinition = packageDefinitions.First(item => item.Name == uniquePkgName).Version; if (versionSpecifier[1] != versionFromDefinition) { var noMatchMessage = new System.Text.StringBuilder(); noMatchMessage.AppendFormat("Command line version specified, {0}, could not resolve to one of the available versions of package {1}:", versionSpecifier[1], uniquePkgName); noMatchMessage.AppendLine(); noMatchMessage.AppendFormat("\t{0}", versionFromDefinition); noMatchMessage.AppendLine(); throw new Exception(noMatchMessage.ToString()); } } } if (enforceBamAssemblyVersions) { // for all packages that make up this assembly, ensure that their requirements on the version of the Bam // assemblies are upheld, prior to compiling the code foreach (var pkgDefn in packageDefinitions) { pkgDefn.ValidateBamAssemblyRequirements(); } } Graph.Instance.SetPackageDefinitions(packageDefinitions); }
RegisterProfile( TimeProfile profile) { Profiles.Add(profile); }