Ejemplo n.º 1
0
        public override bool Execute()
        {
            if (Dependencies == null || Dependencies.Length == 0)
            {
                Log.LogError("Dependencies argument must be specified");
                return(false);
            }

            if (String.IsNullOrEmpty(PackageId))
            {
                Log.LogError("PackageID argument must be specified");
                return(false);
            }

            if (RuntimeJson == null)
            {
                Log.LogError("RuntimeJson argument must be specified");
                return(false);
            }

            string sourceRuntimeFilePath = null;

            if (RuntimeJsonTemplate != null)
            {
                sourceRuntimeFilePath = RuntimeJsonTemplate.GetMetadata("FullPath");
            }
            string destRuntimeFilePath = RuntimeJson.GetMetadata("FullPath");


            Dictionary <string, string> packageAliases = new Dictionary <string, string>();

            foreach (var dependency in Dependencies)
            {
                string alias = dependency.GetMetadata("PackageAlias");

                if (String.IsNullOrEmpty(alias))
                {
                    continue;
                }

                Log.LogMessage(LogImportance.Low, "Aliasing {0} -> {1}", alias, dependency.ItemSpec);
                packageAliases[alias] = dependency.ItemSpec;
            }

            var runtimeGroups = Dependencies.GroupBy(d => d.GetMetadata("TargetRuntime"));

            List <RuntimeDescription> runtimes = new List <RuntimeDescription>();

            foreach (var runtimeGroup in runtimeGroups)
            {
                string targetRuntimeId = runtimeGroup.Key;

                if (String.IsNullOrEmpty(targetRuntimeId))
                {
                    Log.LogMessage(LogImportance.Low, "Skipping dependencies {0} since they don't have a TargetRuntime.", String.Join(", ", runtimeGroup.Select(d => d.ItemSpec)));
                    continue;
                }

                if (runtimeGroup.Any(d => d.ItemSpec == c_emptyDependency))
                {
                    runtimes.Add(new RuntimeDescription(targetRuntimeId));
                    continue;
                }

                List <RuntimeDependencySet> runtimeDependencySets = new List <RuntimeDependencySet>();
                var targetPackageGroups = runtimeGroup.GroupBy(d => GetTargetPackageId(d, packageAliases));
                foreach (var targetPackageGroup in targetPackageGroups)
                {
                    string targetPackageId = targetPackageGroup.Key;

                    List <RuntimePackageDependency> runtimePackageDependencies = new List <RuntimePackageDependency>();
                    var dependencyGroups = targetPackageGroup.GroupBy(d => d.ItemSpec);
                    foreach (var dependencyGroup in dependencyGroups)
                    {
                        string dependencyId         = dependencyGroup.Key;
                        var    dependencyVersions   = dependencyGroup.Select(d => GetDependencyVersion(d));
                        var    maxDependencyVersion = dependencyVersions.Max();
                        runtimePackageDependencies.Add(new RuntimePackageDependency(dependencyId, new VersionRange(maxDependencyVersion)));
                    }
                    runtimeDependencySets.Add(new RuntimeDependencySet(targetPackageId, runtimePackageDependencies));
                }
                runtimes.Add(new RuntimeDescription(targetRuntimeId, runtimeDependencySets));
            }

            RuntimeGraph runtimeGraph = new RuntimeGraph(runtimes);

            // read in existing JSON, if it was provided so that we preserve any
            // hand authored #imports or dependencies
            if (!String.IsNullOrEmpty(sourceRuntimeFilePath))
            {
                RuntimeGraph existingGraph = JsonRuntimeFormat.ReadRuntimeGraph(sourceRuntimeFilePath);
                runtimeGraph = RuntimeGraph.Merge(existingGraph, runtimeGraph);
            }

            string destRuntimeFileDir = Path.GetDirectoryName(destRuntimeFilePath);

            if (!String.IsNullOrEmpty(destRuntimeFileDir) && !Directory.Exists(destRuntimeFileDir))
            {
                Directory.CreateDirectory(destRuntimeFileDir);
            }

            JsonRuntimeFormat.WriteRuntimeGraph(destRuntimeFilePath, runtimeGraph);

            return(true);
        }
Ejemplo n.º 2
0
        public override bool Execute()
        {
            if (Dependencies == null || Dependencies.Length == 0)
            {
                Log.LogError("Dependencies argument must be specified");
                return(false);
            }

            if (String.IsNullOrEmpty(PackageId))
            {
                Log.LogError("PackageID argument must be specified");
                return(false);
            }

            if (RuntimeJson == null)
            {
                Log.LogError("RuntimeJson argument must be specified");
                return(false);
            }

            RuntimeFileFormatter formatter   = new RuntimeFileFormatter();
            RuntimeFile          runtimeFile = null;
            string sourceRuntimeFilePath     = null;

            if (RuntimeJsonTemplate != null)
            {
                sourceRuntimeFilePath = RuntimeJsonTemplate.GetMetadata("FullPath");
            }
            string destRuntimeFilePath = RuntimeJson.GetMetadata("FullPath");

            // read in existing JSON, if it was provided so that we preserve any
            // hand authored #imports or dependencies
            if (!String.IsNullOrEmpty(sourceRuntimeFilePath))
            {
                runtimeFile = formatter.ReadRuntimeFile(sourceRuntimeFilePath);
            }
            else
            {
                runtimeFile = new RuntimeFile();
            }

            Dictionary <string, string> packageAliases = new Dictionary <string, string>();

            foreach (var dependency in Dependencies)
            {
                string alias = dependency.GetMetadata("PackageAlias");

                if (String.IsNullOrEmpty(alias))
                {
                    continue;
                }

                Log.LogMessage(LogImportance.Low, "Aliasing {0} -> {1}", alias, dependency.ItemSpec);
                packageAliases[alias] = dependency.ItemSpec;
            }

            foreach (var dependency in Dependencies)
            {
                string targetRuntimeId    = dependency.GetMetadata("TargetRuntime");
                string targetPackageId    = dependency.GetMetadata("TargetPackage");
                string targetPackageAlias = dependency.GetMetadata("TargetPackageAlias");
                string dependencyId       = dependency.ItemSpec;
                string dependencyVersion  = dependency.GetMetadata("version");

                if (String.IsNullOrEmpty(targetRuntimeId))
                {
                    Log.LogMessage(LogImportance.Low, "Skipping dependency {0} since it doesn't have a TargetRuntime.", dependency.ItemSpec);
                    continue;
                }

                if (!String.IsNullOrEmpty(targetPackageAlias) && !packageAliases.TryGetValue(targetPackageAlias, out targetPackageId))
                {
                    Log.LogWarning("Dependency {0} specified TargetPackageAlias {1} but no package was found defining this alias.", dependency.ItemSpec, targetPackageAlias);
                }
                else
                {
                    Log.LogMessage(LogImportance.Low, "Using {0} for TargetPackageAlias {1}", targetPackageId, targetPackageAlias);
                }

                RuntimeSpec targetRuntime = null;
                if (!runtimeFile.Runtimes.TryGetValue(targetRuntimeId, out targetRuntime))
                {
                    targetRuntime = new RuntimeSpec()
                    {
                        Name = targetRuntimeId
                    };
                    runtimeFile.Runtimes.Add(targetRuntimeId, targetRuntime);
                }

                if (String.IsNullOrEmpty(targetPackageId))
                {
                    Log.LogMessage(LogImportance.Low, "Dependency {0} has no parent so will assume {1}.", dependency.ItemSpec, PackageId);
                    targetPackageId = PackageId;
                }

                DependencySpec targetPackage = null;
                if (!targetRuntime.Dependencies.TryGetValue(targetPackageId, out targetPackage))
                {
                    targetPackage = new DependencySpec()
                    {
                        Name = targetPackageId
                    };
                    targetRuntime.Dependencies.Add(targetPackageId, targetPackage);
                }

                if (dependencyId == c_emptyDependency)
                {
                    targetPackage.Implementations.Clear();
                }
                else
                {
                    if (String.IsNullOrEmpty(dependencyVersion))
                    {
                        Log.LogWarning("Dependency {0} has no version", dependency.ItemSpec);
                    }

                    ImplementationSpec existing;

                    if (targetPackage.Implementations.TryGetValue(dependencyId, out existing))
                    {
                        string newVersion = CompareSemanticVersion(dependencyVersion, existing.Version) > 0 ? dependencyVersion : existing.Version;
                        Log.LogMessage(LogImportance.Low, "Dependency {0} has been added more than once, {1}, {2}, using {3}", dependencyId, existing.Version, dependencyVersion, newVersion);
                        dependencyVersion = newVersion;
                    }

                    targetPackage.Implementations[dependencyId] = new ImplementationSpec()
                    {
                        Name = dependencyId, Version = dependencyVersion
                    };
                }
            }

            if (EnsureBase)
            {
                // RID base is used to lift the library packages up to a baseline version
                // we don't want to obscure these associations or else we may bring in
                // old reference packages prior to an implementation package split
                // and thus, clashing implementations.

                // EG: Version 1 of System.Banana had a single implementation that was
                //     windows specific.
                //     Version 2 split the implementation to Windows and Unix
                //     If Version 1 was referenced we'd get both the V1 windows implementation
                //     and the V2 unix implementation when resolving for Unix

                // To avoid this problem we always ensure that we have the matching
                // reference package in the runtime graph.

                RuntimeSpec baseRuntime = null;
                if (runtimeFile.Runtimes.TryGetValue("base", out baseRuntime))
                {
                    // look at all sections other than base
                    foreach (var runtime in runtimeFile.Runtimes.Values.Where(rt => rt != baseRuntime))
                    {
                        // examine each dependency and copy the content from base, if it exists
                        foreach (var dependency in runtime.Dependencies)
                        {
                            string         packageName         = dependency.Key;
                            DependencySpec packageDependencies = dependency.Value;

                            // are there any entries for this package in base?
                            DependencySpec baseDependencies = null;
                            if (!baseRuntime.Dependencies.TryGetValue(dependency.Key, out baseDependencies))
                            {
                                continue;
                            }

                            // copy all entries from base to this runtime
                            foreach (var baseImplementation in baseDependencies.Implementations)
                            {
                                packageDependencies.Implementations.Add(baseImplementation.Key, baseImplementation.Value);
                            }
                        }
                    }
                }
            }

            string destRuntimeFileDir = Path.GetDirectoryName(destRuntimeFilePath);

            if (!String.IsNullOrEmpty(destRuntimeFileDir) && !Directory.Exists(destRuntimeFileDir))
            {
                Directory.CreateDirectory(destRuntimeFileDir);
            }

            formatter.WriteRuntimeFile(destRuntimeFilePath, runtimeFile);

            return(true);
        }