MakePackage() { var packageDir = Graph.Instance.ProcessState.WorkingDirectory; var bamDir = System.IO.Path.Combine(packageDir, BamSubFolder); if (System.IO.Directory.Exists(bamDir)) { throw new Exception("A Bam package already exists at {0}", packageDir); } var packageNameArgument = new Options.PackageName(); var packageName = CommandLineProcessor.Evaluate(packageNameArgument); if (null == packageName) { throw new Exception("No name was defined. Use {0} on the command line to specify it.", (packageNameArgument as ICommandLineArgument).LongName); } var packageVersion = CommandLineProcessor.Evaluate(new Options.PackageVersion()); var definition = new PackageDefinition(bamDir, packageName, packageVersion); System.IO.Directory.CreateDirectory(bamDir); definition.Write(); var scriptsDir = System.IO.Path.Combine(bamDir, ScriptsSubFolder); System.IO.Directory.CreateDirectory(scriptsDir); var initialScriptFile = System.IO.Path.Combine(scriptsDir, packageName) + ".cs"; using (System.IO.TextWriter writer = new System.IO.StreamWriter(initialScriptFile)) { writer.WriteLine("using Bam.Core;"); writer.WriteLine("namespace {0}", packageName); writer.WriteLine("{"); writer.WriteLine(" // write modules here ..."); writer.WriteLine("}"); } }
/// <summary> /// Based on the dependents lists in the XML file, resolve all dependents by reading more /// package definition files. /// </summary> /// <param name="current">Current.</param> /// <param name="authenticated">Authenticated.</param> /// <param name="candidatePackageDefinitions">Candidate package definitions.</param> public static void ResolveDependencies( PackageDefinition current, Array<PackageDefinition> authenticated, Array<PackageDefinition> candidatePackageDefinitions) { var matchingPackages = authenticated.Where(item => item.Name == current.Name); if (null != current.Version) { matchingPackages = matchingPackages.Where(item => item.Version == current.Version); } if (matchingPackages.FirstOrDefault() != null) { return; } if (!current.SupportedPlatforms.Includes(OSUtilities.CurrentOS)) { throw new Exception("Package {0} is not supported on {1}", current.FullName, OSUtilities.CurrentOS.ToString()); } authenticated.Add(current); foreach (var dependent in current.Dependents) { var depName = dependent.Item1; var depVersion = dependent.Item2; var candidates = candidatePackageDefinitions.Where(item => item.Name == depName); if (depVersion != null) { candidates = candidates.Where(item => item.Version == depVersion); } var candidateCount = candidates.Count(); if (0 == candidateCount) { var message = new System.Text.StringBuilder(); message.AppendFormat("Unable to find a candidate package with name '{0}'", depName); if (null != depVersion) { message.AppendFormat(" and version {0}", depVersion); } message.AppendLine(); var packageRepos = new StringArray(); Graph.Instance.PackageRepositories.ToList().ForEach(item => packageRepos.AddUnique(item)); message.AppendLine("Searched in the package repositories:"); message.AppendLine(packageRepos.ToString("\n")); throw new Exception(message.ToString()); } if (candidateCount > 1) { var message = new System.Text.StringBuilder(); message.AppendFormat("There are {0} identical candidate packages with name '{1}'", candidateCount, depName); if (null != depVersion) { message.AppendFormat(" and version {0}", depVersion); } message.AppendLine(" from the following package definition files:"); foreach (var candidate in candidates) { message.AppendFormat(candidate.XMLFilename); message.AppendLine(); } var packageRepos = new StringArray(); Graph.Instance.PackageRepositories.ToList().ForEach(item => packageRepos.AddUnique(item)); message.AppendLine("Found in the package repositories:"); message.AppendLine(packageRepos.ToString("\n")); throw new Exception(message.ToString()); } ResolveDependencies(candidates.First(), authenticated, candidatePackageDefinitions); } }
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); }
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; }