GetMasterPackage() { var workingDir = Graph.Instance.ProcessState.WorkingDirectory; var isWorkingPackageWellDefined = IsPackageDirectory(workingDir); if (!isWorkingPackageWellDefined) { throw new Exception("Working directory package is not well defined"); } var masterDefinitionFile = new PackageDefinition(GetPackageDefinitionPathname(workingDir)); masterDefinitionFile.Read(); return(masterDefinitionFile); }
GetMasterPackage( bool enforceBamAssemblyVersions = true) { var workingDir = Graph.Instance.ProcessState.WorkingDirectory; var isWorkingPackageWellDefined = IsPackageDirectory(workingDir); if (!isWorkingPackageWellDefined) { throw new Exception("Working directory package is not well defined"); } var masterDefinitionFile = new PackageDefinition(GetPackageDefinitionPathname(workingDir), !Graph.Instance.ForceDefinitionFileUpdate); masterDefinitionFile.Read(true, enforceBamAssemblyVersions); return(masterDefinitionFile); }
GetMasterPackage() { var workingDir = Graph.Instance.ProcessState.WorkingDirectory; var isWorkingPackageWellDefined = IsPackageDirectory(workingDir); if (!isWorkingPackageWellDefined) { throw new Exception("Working directory package is not well defined"); } var masterDefinitionFile = new PackageDefinition(GetPackageDefinitionPathname(workingDir)); masterDefinitionFile.Read(); // in case the master package is not in a formal package repository structure, add it's parent directory // as a repository, so that sibling packages can be found var parentDir = System.IO.Path.GetDirectoryName(workingDir); masterDefinitionFile.PackageRepositories.AddUnique(parentDir); return(masterDefinitionFile); }
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); }
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); }