public PackageRef LookupPackageByName(ModuleInfo module, string url)
        {
            var packages = module.Packages.Where(x => x.Uri.Contains(url)).ToArray();

            PackageRef packageRef;
            if (packages.Length == 1)
            {
                packageRef = packages[0];
            }
            else if (packages.Length == 0)
            {
                throw new InvalidOperationException("No such package has been added");
            }
            else
            {
                if (packages.Any(x => x.Uri == url))
                {
                    packageRef = packages.First(x => x.Uri == url);
                }
                else
                {
                    throw new InvalidOperationException("Package reference is ambigious");
                }
            }

            return packageRef;
        }
        /// <summary>
        /// Normalizes the platform string from user input, automatically correcting case
        /// and validating against a list of supported platforms.
        /// </summary>
        /// <returns>The platform string.</returns>
        /// <param name="platform">The normalized platform string.</param>
        public string NormalizePlatform(ModuleInfo module, string platform)
        {
            var supportedPlatforms = ModuleInfo.GetSupportedPlatformsDefault();
            var defaultPlatforms = true;

            if (!string.IsNullOrEmpty(module.SupportedPlatforms))
            {
                supportedPlatforms = module.SupportedPlatforms;
                defaultPlatforms = false;
            }

            var supportedPlatformsArray = supportedPlatforms.Split(new[] { ',' })
                .Select(x => x.Trim())
                .Where(x => !string.IsNullOrWhiteSpace(x))
                .ToArray();

            var allowWeb = _featureManager.IsFeatureEnabled(Feature.PackageManagement);

            // Search the array to find a platform that matches case insensitively
            // to the specified platform.  If we are using the default list, then we allow
            // other platforms to be specified (in case the developer has modified the XSLT to
            // support others but is not using <SupportedPlatforms>).  If the developer has
            // explicitly set the supported platforms, then we return null if the user passes
            // an unknown platform (the caller is expected to exit at this point).
            foreach (var supportedPlatform in supportedPlatformsArray)
            {
                if (string.Compare(supportedPlatform, platform, StringComparison.InvariantCultureIgnoreCase) == 0)
                {
                    if (supportedPlatform == "Web" && !allowWeb)
                    {
                        // We don't permit the web platform when package management
                        // is disabled, as we can't install JSIL properly.
                        return null;
                    }

                    return supportedPlatform;
                }
            }

            if (defaultPlatforms)
            {
                if (string.Compare("Web", platform, StringComparison.InvariantCultureIgnoreCase) == 0 && !allowWeb)
                {
                    // We don't permit the web platform when package management
                    // is disabled, as we can't install JSIL properly.
                    return null;
                }

                return platform;
            }
            else
            {
                return null;
            }
        }
 /// <summary>
 /// Performs the default action on the specified module.
 /// </summary>
 /// <returns><c>true</c>, if the default action succeeded, <c>false</c> otherwise.</returns>
 /// <param name="module">The module to perform the action on.</param>
 /// <param name="platform">The platform to perform the action for.</param>
 /// <param name="enabledServices">A list of enabled services.</param>
 /// <param name="disabledServices">A list of disabled services.</param>
 /// <param name="serviceSpecPath">The service specification path.</param>
 /// <param name="debugServiceResolution">Whether to enable debugging information during service resolution.</param>
 /// <param name="disablePackageResolution">Whether to disable package resolution.</param>
 /// <param name="disableHostPlatformGeneration">Whether to disable generation of the host platform projects.</param>
 public bool DefaultAction(
     ModuleInfo module, 
     string platform = null, 
     string[] enabledServices = null, 
     string[] disabledServices = null, 
     string serviceSpecPath = null,
     bool debugServiceResolution = false,
     bool disablePackageResolution = false,
     bool disableHostPlatformGeneration = false)
 {
     return PerformAction(
         module,
         module.DefaultAction,
         platform,
         enabledServices,
         disabledServices,
         serviceSpecPath,
         debugServiceResolution,
         disablePackageResolution,
         disableHostPlatformGeneration);
 }
Exemple #4
0
        /// <summary>
        /// Performs a resynchronisation, synchronisation, generation or clean on the specified module.
        /// </summary>
        /// <returns><c>true</c>, if the action succeeded, <c>false</c> otherwise.</returns>
        /// <param name="module">The module to perform the action on.</param>
        /// <param name="action">The action to perform, either "resync", "sync", "generate" or "clean".</param>
        /// <param name="platform">The platform to perform the action for.</param>
        /// <param name="enabledServices">A list of enabled services.</param>
        /// <param name="disabledServices">A list of disabled services.</param>
        /// <param name="serviceSpecPath">The service specification path.</param>
        /// <param name="debugServiceResolution">Whether to enable debugging information during service resolution.</param>
        /// <param name="disablePackageResolution">Whether to disable package resolution.</param>
        /// <param name="disableHostPlatformGeneration">Whether to disable generation of the host platform projects.</param>
        public bool PerformAction(
            ModuleInfo module,
            string action,
            string platform                    = null,
            string[] enabledServices           = null,
            string[] disabledServices          = null,
            string serviceSpecPath             = null,
            bool debugServiceResolution        = false,
            bool disablePackageResolution      = false,
            bool disableHostPlatformGeneration = false)
        {
            var platformSupplied = !string.IsNullOrWhiteSpace(platform);

            var hostPlatform = this.m_HostPlatformDetector.DetectPlatform();

            if (string.IsNullOrWhiteSpace(platform))
            {
                platform = hostPlatform;
            }

            var    originalPlatform  = platform;
            string primaryPlatform   = null;
            string multiplePlatforms = null;

            if (platform.Contains(","))
            {
                // The user requested multiple platforms; the first one
                // is the primary platform.
                var platforms = platform.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (platforms.Length == 0)
                {
                    Console.Error.WriteLine("You supplied only commas where a list of platforms was expected.");
                    ExecEnvironment.Exit(1);
                    return(false);
                }
                else
                {
                    for (var i = 0; i < platforms.Length; i++)
                    {
                        var newPlatform = _moduleUtilities.NormalizePlatform(module, platforms[i]);
                        if (newPlatform == null)
                        {
                            ShowSupportedPlatformsError(module, platforms[i]);
                            return(false);
                        }
                        platforms[i] = newPlatform;
                    }

                    primaryPlatform   = platforms[0];
                    multiplePlatforms = platforms.Aggregate((a, b) => a + "," + b);
                }
            }
            else
            {
                platform = _moduleUtilities.NormalizePlatform(module, platform);

                if (platform == null && !platformSupplied)
                {
                    // The current host platform isn't supported, so we shouldn't try to
                    // operate on it.
                    string firstPlatform = null;
                    switch (this.m_HostPlatformDetector.DetectPlatform())
                    {
                    case "Windows":
                        firstPlatform = module.DefaultWindowsPlatforms.Split(',').FirstOrDefault();
                        break;

                    case "MacOS":
                        firstPlatform = module.DefaultMacOSPlatforms.Split(',').FirstOrDefault();
                        break;

                    case "Linux":
                        firstPlatform = module.DefaultLinuxPlatforms.Split(',').FirstOrDefault();
                        break;
                    }

                    if (firstPlatform != null)
                    {
                        // This will end up null if the first platform isn't supported
                        // either and hence throw the right message.
                        platform = _moduleUtilities.NormalizePlatform(module, firstPlatform);
                    }
                }

                if (platform == null)
                {
                    ShowSupportedPlatformsError(module, originalPlatform);
                    return(false);
                }

                primaryPlatform = platform;
            }

            // You can generate multiple targets by default by setting the <DefaultWindowsPlatforms>
            // <DefaultMacOSPlatforms> and <DefaultLinuxPlatforms> tags in Module.xml.  Note that
            // synchronisation will only be done for the primary platform, as there is no correct
            // synchronisation behaviour when dealing with multiple C# projects.
            //
            // We only trigger this behaviour when the platform is omitted; if you explicitly
            // specify "Windows" on the command line, we'll only generate / resync / sync
            // the Windows platform.
            if (!platformSupplied)
            {
                switch (platform)
                {
                case "Windows":
                    multiplePlatforms = module.DefaultWindowsPlatforms;
                    break;

                case "MacOS":
                    multiplePlatforms = module.DefaultMacOSPlatforms;
                    break;

                case "Linux":
                    multiplePlatforms = module.DefaultLinuxPlatforms;
                    break;
                }
            }

            // If no overrides are set, just use the current platform.
            if (string.IsNullOrEmpty(multiplePlatforms))
            {
                multiplePlatforms = platform;
            }

            // Resolve submodules as needed.
            if (!disablePackageResolution)
            {
                this.m_PackageManager.ResolveAll(module, primaryPlatform);
            }

            // Create the list of multiple platforms.
            var multiplePlatformsList =
                multiplePlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();

            // Remember whether or not we need to implicitly generate the host
            // platform.
            var    implicitlyGenerateHostPlatform = false;
            Action requiresHostPlatform           = () => implicitlyGenerateHostPlatform = true;

            // If we are already generating the host platform, then requiring the
            // host platform is already satisifed.
            if (platform == hostPlatform || multiplePlatformsList.Contains(hostPlatform))
            {
                requiresHostPlatform = () => {};
            }
            else if (!_featureManager.IsFeatureEnabled(Feature.HostPlatformGeneration))
            {
                requiresHostPlatform = () =>
                {
                    Console.Error.WriteLine(
                        "WARNING: One or more projects requires host platforms to be generated, " +
                        "but the HostPlatformGeneration feature is not enabled.  Expect your " +
                        "build to fail.");
                };
            }

            // You can configure the default action for Protobuild in their project
            // with the <DefaultAction> tag in Module.xml.  If omitted, default to a resync.
            // Valid options for this tag are either "Generate", "Resync" or "Sync".

            // If the actions are "Resync" or "Sync", then we need to perform an initial
            // step against the primary platform.
            switch (action.ToLower())
            {
            case "generate":
                if (!this.GenerateProjectsForPlatform(
                        module,
                        primaryPlatform,
                        enabledServices,
                        disabledServices,
                        serviceSpecPath,
                        debugServiceResolution,
                        disablePackageResolution,
                        disableHostPlatformGeneration,
                        requiresHostPlatform))
                {
                    return(false);
                }

                break;

            case "resync":
                if (!this.ResyncProjectsForPlatform(
                        module,
                        primaryPlatform,
                        enabledServices,
                        disabledServices,
                        serviceSpecPath,
                        debugServiceResolution,
                        disablePackageResolution,
                        disableHostPlatformGeneration,
                        requiresHostPlatform))
                {
                    return(false);
                }

                break;

            case "sync":
                return(this.SyncProjectsForPlatform(module, primaryPlatform));

            case "clean":
                if (!this.CleanProjectsForPlatform(module, primaryPlatform))
                {
                    return(false);
                }

                break;

            default:
                Console.Error.WriteLine("Unknown option in <DefaultAction> tag of Module.xml.  Defaulting to resync!");
                return(this.ResyncProjectsForPlatform(
                           module,
                           primaryPlatform,
                           enabledServices,
                           disabledServices,
                           serviceSpecPath,
                           debugServiceResolution,
                           disablePackageResolution,
                           disableHostPlatformGeneration,
                           requiresHostPlatform));
            }

            // Now iterate through the multiple platforms specified.
            foreach (var platformIter in multiplePlatformsList.Distinct())
            {
                if (platformIter == primaryPlatform)
                {
                    // Already handled above.
                    continue;
                }

                // Resolve submodules as needed.
                if (!disablePackageResolution)
                {
                    this.m_PackageManager.ResolveAll(module, platformIter);
                }

                switch (action.ToLower())
                {
                case "generate":
                case "resync":
                    // We do a generate under resync mode since we only want the primary platform
                    // to have synchronisation done (and it has had above).
                    if (!this.GenerateProjectsForPlatform(
                            module,
                            platformIter,
                            enabledServices,
                            disabledServices,
                            serviceSpecPath,
                            debugServiceResolution,
                            disablePackageResolution,
                            disableHostPlatformGeneration,
                            requiresHostPlatform))
                    {
                        return(false);
                    }

                    break;

                case "clean":
                    if (!this.CleanProjectsForPlatform(module, platformIter))
                    {
                        return(false);
                    }

                    break;

                default:
                    throw new InvalidOperationException("Code should never reach this point");
                }
            }

            // If we implicitly require the host platform, generate that now (this variable can
            // only ever be set to true if the host platform is not already in the list of
            // platforms generated previously).
            if (implicitlyGenerateHostPlatform)
            {
                // Check to see if the host platform is supported.
                var hostPlatformNormalized = _moduleUtilities.NormalizePlatform(module, hostPlatform);
                if (hostPlatformNormalized == null)
                {
                    Console.WriteLine(
                        "WARNING: The current host platform is not a supported platform for the solution.  IDE editor " +
                        "projects and post-build hooks will not be available, and this may cause the project to be " +
                        "built incorrectly!");
                    return(true);
                }

                Console.WriteLine(
                    "One or more projects required the presence of host platform " +
                    "projects, implicitly starting generation for " + hostPlatform + "...");

                // Resolve submodules as needed.
                if (!disablePackageResolution)
                {
                    this.m_PackageManager.ResolveAll(module, hostPlatform);
                }

                switch (action.ToLower())
                {
                case "generate":
                case "resync":
                    // We do a generate under resync mode since we only want the primary platform
                    // to have synchronisation done (and it has had above).
                    if (!this.GenerateProjectsForPlatform(
                            module,
                            hostPlatform,
                            enabledServices,
                            disabledServices,
                            serviceSpecPath,
                            debugServiceResolution,
                            disablePackageResolution,
                            disableHostPlatformGeneration,
                            requiresHostPlatform))
                    {
                        return(false);
                    }

                    break;

                case "clean":
                    if (!this.CleanProjectsForPlatform(module, hostPlatform))
                    {
                        return(false);
                    }

                    break;

                default:
                    throw new InvalidOperationException("Code should never reach this point");
                }
            }

            // All the steps succeeded, so return true.
            return(true);
        }
        public LoadedDefinitionInfo Load(string targetPlatform, ModuleInfo module, DefinitionInfo definition)
        {
            var doc = new XmlDocument();
            doc.Load(definition.DefinitionPath);

            // If this is a ContentProject, we actually need to generate the
            // full project node from the files that are in the Source folder.
            XmlDocument newDoc = null;
            if (doc.DocumentElement.Name == "ContentProject")
                newDoc = this.m_ContentProjectGenerator.Generate(targetPlatform, doc, definition.ModulePath);
            else
                newDoc = doc;
            if (module.Path != null && definition.ModulePath != null)
            {
                var additionalPath = PathUtils.GetRelativePath(
                    module.Path.TrimEnd(System.IO.Path.DirectorySeparatorChar) + System.IO.Path.DirectorySeparatorChar,
                    definition.ModulePath.TrimEnd(System.IO.Path.DirectorySeparatorChar) + System.IO.Path.DirectorySeparatorChar);

                if (newDoc.DocumentElement != null &&
                    newDoc.DocumentElement.Attributes["Path"] != null &&
                    additionalPath != null)
                {
                    newDoc.DocumentElement.Attributes["Path"].Value =
                        (additionalPath.Trim('\\') + '\\' +
                            newDoc.DocumentElement.Attributes["Path"].Value).Replace('/', '\\').Trim('\\');
                }
                if (newDoc.DocumentElement.Name == "ExternalProject")
                {
                    // Need to find all descendant Binary and Project tags
                    // and update their paths as well.
                    var xDoc = newDoc.ToXDocument();
                    var projectsToUpdate = xDoc.Descendants().Where(x => x.Name == "Project");
                    var binariesToUpdate = xDoc.Descendants().Where(x => x.Name == "Binary");
                    var nativeBinariesToUpdate = xDoc.Descendants().Where(x => x.Name == "NativeBinary");
                    var toolsToUpdate = xDoc.Descendants().Where(x => x.Name == "Tool");
                    foreach (var pathToUpdate in projectsToUpdate.Concat(binariesToUpdate).Concat(nativeBinariesToUpdate).Concat(toolsToUpdate)
                        .Where(x => x.Attribute("Path") != null))
                    {
                        pathToUpdate.Attribute("Path").Value =
                            (additionalPath.Trim('\\') + '\\' +
                                pathToUpdate.Attribute("Path").Value).Replace('/', '\\').Trim('\\');
                    }
                    newDoc = xDoc.ToXmlDocument();
                }
            }

            // If the ProjectGuids element doesn't exist, create it.
            var projectGuids = doc.DocumentElement.ChildNodes.OfType<XmlElement>().FirstOrDefault(x => x.Name == "ProjectGuids");
            if (projectGuids == null)
            {
                projectGuids = doc.CreateElement("ProjectGuids");
                doc.DocumentElement.AppendChild(projectGuids);
            }

            // For all the supported platforms of this project, or all the
            // supported platforms of the module, generate GUIDs for any platform
            // that doesn't already exist.
            var platforms = doc.DocumentElement.GetAttribute("Platforms");
            if (string.IsNullOrWhiteSpace(platforms))
            {
                platforms = module.SupportedPlatforms;
            }
            if (string.IsNullOrWhiteSpace(platforms))
            {
                platforms = ModuleInfo.GetSupportedPlatformsDefault();
            }
            var platformsList = platforms.Split(',').ToList();
            if (!platformsList.Contains(targetPlatform))
            {
                platformsList.Add(targetPlatform);
            }
            foreach (var platform in platformsList)
            {
                var existing = projectGuids.ChildNodes.OfType<XmlElement>().FirstOrDefault(x =>
                    x.Name == "Platform" && x.HasAttribute("Name") && x.GetAttribute("Name") == platform);
                if (existing == null)
                {
                    var platformElement = doc.CreateElement("Platform");
                    platformElement.SetAttribute("Name", platform);

                    var name = doc.DocumentElement.GetAttribute("Name") + "." + platform;
                    var guidBytes = new byte[16];
                    for (var i = 0; i < guidBytes.Length; i++)
                        guidBytes[i] = (byte)0;
                    var nameBytes = Encoding.ASCII.GetBytes(name);
                    unchecked
                    {
                        for (var i = 0; i < nameBytes.Length; i++)
                            guidBytes[i % 16] += nameBytes[i];
                        for (var i = nameBytes.Length; i < 16; i++)
                            guidBytes[i] += nameBytes[i % nameBytes.Length];
                    }
                    var guid = new Guid(guidBytes);
                    platformElement.InnerText = guid.ToString().ToUpper();
                    projectGuids.AppendChild(platformElement);
                }
            }

            // If the Language property doesn't exist, set it to the default of "C#"
            if (doc.DocumentElement.Attributes["Language"] == null)
            {
                doc.DocumentElement.SetAttribute("Language", "C#");
            }

            // Normalize the project type for backwards compatibility.
            var projectType = doc.DocumentElement.Attributes["Type"];
            if (projectType == null)
            {
                doc.DocumentElement.SetAttribute("Type", "Library");
            }
            else
            {
                switch (projectType.Value)
                {
                    case "Library":
                    case "App":
                    case "Console":
                    case "Website":
                        break;
                    case "GUI":
                    case "XNA":
                    case "GTK":
                        doc.DocumentElement.SetAttribute("Type", "App");
                        break;
                }
            }

            return new LoadedDefinitionInfo
            {
                Definition = definition,
                Project = newDoc,
            };
        }
 public void LoadFeaturesFromSpecificModule(ModuleInfo module)
 {
     if (module.FeatureSet == null)
     {
         _featuresEnabledFromModules = null;
     }
     else
     {
         _featuresEnabledFromModules = module.FeatureSet.ToList();
     }
 }
 public virtual void FinalizeNewProject(ModuleInfo module, DefinitionInfo definition)
 {
 }
        public void Generate(
            ModuleInfo moduleInfo,
            List <XmlDocument> definitions,
            string platformName,
            string solutionPath,
            List <Service> services,
            IEnumerable <string> repositoryPaths)
        {
            var generateSolutionTransform = this.m_ResourceProvider.LoadXSLT(ResourceType.GenerateSolution, Language.CSharp);
            var selectSolutionTransform   = this.m_ResourceProvider.LoadXSLT(ResourceType.SelectSolution, Language.CSharp);

            var input = this.m_SolutionInputGenerator.GenerateForSelectSolution(definitions, platformName, services);

            using (var memory = new MemoryStream())
            {
                selectSolutionTransform.Transform(input, null, memory);

                memory.Seek(0, SeekOrigin.Begin);

                var document = new XmlDocument();
                document.Load(memory);

                var defaultProject = (XmlElement)null;
                var existingGuids  = new List <string>();
                foreach (var element in document.DocumentElement.SelectNodes("/Projects/Project").OfType <XmlElement>().ToList())
                {
                    var f = element.SelectNodes("Guid").OfType <XmlElement>().FirstOrDefault();

                    if (f != null)
                    {
                        if (existingGuids.Contains(f.InnerText.Trim()))
                        {
                            element.ParentNode.RemoveChild(element);
                            continue;
                        }
                        else
                        {
                            existingGuids.Add(f.InnerText.Trim());
                        }
                    }

                    var n = element.SelectNodes("RawName").OfType <XmlElement>().FirstOrDefault();

                    if (n != null)
                    {
                        if (n.InnerText.Trim() == moduleInfo.DefaultStartupProject)
                        {
                            defaultProject = element;
                        }
                    }
                }

                if (defaultProject != null)
                {
                    // Move the default project to the first element of it's parent.  The first project
                    // in the solution is the default startup project.
                    var parent = defaultProject.ParentNode;
                    parent.RemoveChild(defaultProject);
                    parent.InsertBefore(defaultProject, parent.FirstChild);
                }

                var documentInput = this.m_SolutionInputGenerator.GenerateForGenerateSolution(
                    platformName,
                    document.DocumentElement.SelectNodes("/Projects/Project").OfType <XmlElement>());

                using (var writer = new StreamWriter(solutionPath))
                {
                    generateSolutionTransform.Transform(documentInput, null, writer);
                }
            }

            if (repositoryPaths != null && repositoryPaths.Any())
            {
                this.m_NuGetRepositoriesConfigGenerator.Generate(solutionPath, repositoryPaths);
            }
        }
        /// <summary>
        /// Loads all of the submodules present in this module.
        /// </summary>
        /// <returns>The loaded submodules.</returns>
        public ModuleInfo[] GetSubmodules(string platform = null)
        {
            if (!_cachedSubmodules.ContainsKey(platform ?? "<null>"))
            {
                var modules = new List <ModuleInfo>();
                foreach (var directoryInit in new DirectoryInfo(this.Path).GetDirectories())
                {
                    var directory = directoryInit;

                    if (File.Exists(System.IO.Path.Combine(directory.FullName, ".redirect")))
                    {
                        // This is a redirected submodule (due to package resolution).  Load the
                        // module from it's actual path.
                        using (var reader = new StreamReader(System.IO.Path.Combine(directory.FullName, ".redirect")))
                        {
                            var targetPath = reader.ReadToEnd().Trim();
                            directory = new DirectoryInfo(targetPath);
                        }
                    }

                    var build = directory.GetDirectories().FirstOrDefault(x => x.Name == "Build");
                    if (build == null)
                    {
                        continue;
                    }

                    var module = build.GetFiles().FirstOrDefault(x => x.Name == "Module.xml");
                    if (module == null)
                    {
                        continue;
                    }

                    modules.Add(ModuleInfo.Load(module.FullName));
                }

                if (platform != null)
                {
                    foreach (var directoryInit in new DirectoryInfo(this.Path).GetDirectories())
                    {
                        var directory = directoryInit;

                        if (File.Exists(System.IO.Path.Combine(directory.FullName, ".redirect")))
                        {
                            // This is a redirected submodule (due to package resolution).  Load the
                            // module from it's actual path.
                            using (
                                var reader = new StreamReader(System.IO.Path.Combine(directory.FullName, ".redirect")))
                            {
                                var targetPath = reader.ReadToEnd().Trim();
                                directory = new DirectoryInfo(targetPath);
                            }
                        }

                        var platformDirectory = new DirectoryInfo(System.IO.Path.Combine(directory.FullName, platform));

                        if (!platformDirectory.Exists)
                        {
                            continue;
                        }

                        var build = platformDirectory.GetDirectories().FirstOrDefault(x => x.Name == "Build");
                        if (build == null)
                        {
                            continue;
                        }

                        var module = build.GetFiles().FirstOrDefault(x => x.Name == "Module.xml");
                        if (module == null)
                        {
                            continue;
                        }

                        modules.Add(ModuleInfo.Load(module.FullName));
                    }
                }

                _cachedSubmodules[platform ?? "<null>"] = modules.ToArray();
            }

            return(_cachedSubmodules[platform ?? "<null>"]);
        }
        public int Execute(Execution execution)
        {
            var    hostPlatform          = _hostPlatformDetector.DetectPlatform();
            string builderPathNativeArch = null;
            string builderPath64         = null;
            string builderPath32         = null;
            var    extraArgsNativeArch   = string.Empty;
            var    extraArgs64           = string.Empty;
            var    extraArgs32           = string.Empty;
            var    extraArgsGeneral      = string.Empty;

            if (hostPlatform == "Windows")
            {
                foreach (var arch in new[] { RegistryView.Default, RegistryView.Registry32, RegistryView.Registry64 })
                {
                    // Find latest version of MSBuild.
                    var registryKey =
                        RegistryKey.OpenBaseKey(
                            RegistryHive.LocalMachine,
                            arch)
                        .OpenSubKey("SOFTWARE")?
                        .OpenSubKey("Microsoft")?
                        .OpenSubKey("MSBuild")?
                        .OpenSubKey("ToolsVersions");
                    if (registryKey == null)
                    {
                        if (arch == RegistryView.Registry64)
                        {
                            continue;
                        }

                        RedirectableConsole.ErrorWriteLine(
                            "ERROR: No versions of MSBuild were available " +
                            "according to the registry (or they were not readable).");
                        return(1);
                    }

                    var subkeys         = registryKey.GetSubKeyNames();
                    var orderedVersions =
                        subkeys.OrderByDescending(x => int.Parse(x.Split('.').First(), CultureInfo.InvariantCulture));
                    var builderPath = (from version in orderedVersions
                                       let path = (string)registryKey.OpenSubKey(version)?.GetValue("MSBuildToolsPath")
                                                  where path != null && Directory.Exists(path)
                                                  let msbuild = Path.Combine(path, "MSBuild.exe")
                                                                where File.Exists(msbuild)
                                                                select msbuild).FirstOrDefault();

                    if (builderPath == null)
                    {
                        if (arch == RegistryView.Registry64)
                        {
                            continue;
                        }

                        RedirectableConsole.ErrorWriteLine(
                            "ERROR: Unable to find installed MSBuild in any installed tools version.");
                        return(1);
                    }

                    var extraArgs = string.Empty;
                    if (!builderPath.Contains("v2.0.50727"))
                    {
                        extraArgs = "/m /nodeReuse:false ";
                    }

                    switch (arch)
                    {
                    case RegistryView.Default:
                        builderPathNativeArch = builderPath;
                        extraArgsNativeArch   = extraArgs;
                        break;

                    case RegistryView.Registry32:
                        builderPath32 = builderPath;
                        extraArgs32   = extraArgs;
                        break;

                    case RegistryView.Registry64:
                        builderPath64 = builderPath;
                        extraArgs64   = extraArgs;
                        break;
                    }
                }
            }
            else
            {
                // Find path to xbuild.
                var whichPaths = new[] { "/bin/which", "/usr/bin/which" };
                foreach (var w in whichPaths)
                {
                    if (File.Exists(w))
                    {
                        var whichProcess = Process.Start(new ProcessStartInfo(w, "xbuild")
                        {
                            RedirectStandardOutput = true,
                            UseShellExecute        = false
                        });
                        if (whichProcess == null)
                        {
                            continue;
                        }
                        var result = whichProcess.StandardOutput.ReadToEnd().Trim();
                        if (!string.IsNullOrWhiteSpace(result) && File.Exists(result))
                        {
                            builderPathNativeArch = result;
                            break;
                        }
                    }
                }

                if (builderPathNativeArch == null && _hostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/xbuild"))
                {
                    // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in
                    // the system PATH.  If we can't find xbuild with the which tool, manually set the
                    // path here in an attempt to find it.
                    builderPathNativeArch = "/usr/local/bin/xbuild";
                }

                if (builderPathNativeArch == null)
                {
                    RedirectableConsole.ErrorWriteLine("ERROR: Unable to find xbuild on the current PATH.");
                    return(1);
                }

                builderPath32 = builderPathNativeArch;
                builderPath64 = builderPathNativeArch;
            }

            if (!string.IsNullOrWhiteSpace(execution.BuildTarget))
            {
                extraArgsGeneral += "/t:\"" + execution.BuildTarget + "\" ";
            }
            foreach (var prop in execution.BuildProperties)
            {
                extraArgsGeneral += "/p:\"" + prop.Key.Replace("\"", "\\\"") + "\"=\"" + (prop.Value ?? string.Empty).Replace("\"", "\\\"") + "\" ";
            }

            switch (execution.BuildProcessArchitecture)
            {
            case "x86":
                RedirectableConsole.WriteLine("INFO: Using " + builderPath32 + " (forced 32-bit) to perform this build.");
                break;

            case "x64":
                RedirectableConsole.WriteLine("INFO: Using " + builderPath64 + " (forced 64-bit) to perform this build.");
                break;

            case "Default":
            default:
                RedirectableConsole.WriteLine("INFO: Using " + builderPathNativeArch + " (32-bit: " + builderPath32 + ") to perform this build.");
                break;
            }

            var targetPlatforms = (execution.Platform ?? hostPlatform).Split(',');
            var module          = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml"));

            foreach (var platform in targetPlatforms)
            {
                string builderPath;
                string extraArgs;

                switch (execution.BuildProcessArchitecture)
                {
                case "x86":
                    builderPath = builderPath32;
                    extraArgs   = extraArgs32 + extraArgsGeneral;
                    break;

                case "x64":
                    builderPath = builderPath64;
                    extraArgs   = extraArgs64 + extraArgsGeneral;
                    break;

                case "Default":
                default:
                    builderPath = platform == "WindowsPhone" ? builderPath32 : builderPathNativeArch;
                    extraArgs   = (platform == "WindowsPhone" ? extraArgs32 : extraArgsNativeArch) + extraArgsGeneral;
                    break;
                }

                var fileToBuild = module.Name + "." + platform + ".sln";

                RedirectableConsole.WriteLine("INFO: Executing " + builderPath + " with arguments: " + extraArgs + fileToBuild);

                var process =
                    Process.Start(new ProcessStartInfo(builderPath, extraArgs + fileToBuild)
                {
                    UseShellExecute = false
                });
                if (process == null)
                {
                    RedirectableConsole.ErrorWriteLine("ERROR: Build process did not start successfully.");
                    return(1);
                }
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    return(process.ExitCode);
                }
            }

            return(0);
        }
        private void ShowSupportedPlatformsError(ModuleInfo module, string requestedPlatform)
        {
            Console.Error.WriteLine("The platform '" + requestedPlatform + "' is not supported.");
            Console.Error.WriteLine("The following platforms are supported by this module:");
            foreach (
                var supportedPlatform in
                module.SupportedPlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                .Select(x => x.Trim())
                .Where(x => !string.IsNullOrWhiteSpace(x)))
            {
                Console.Error.WriteLine("  * " + supportedPlatform);
            }

            ExecEnvironment.Exit(1);
        }
        /// <summary>
        /// Generates the projects for the specified platform.
        /// </summary>
        /// <returns><c>true</c>, if the generation succeeded, <c>false</c> otherwise.</returns>
        /// <param name="module">The module whose projects should be generated.</param>
        /// <param name="platform">The platform to generate for.</param>
        /// <param name="enabledServices">A list of enabled services.</param>
        /// <param name="disabledServices">A list of disabled services.</param>
        /// <param name="serviceSpecPath">The service specification path.</param>
        /// <param name="debugServiceResolution">Whether to enable debugging information during service resolution.</param>
        /// <param name="disablePackageResolution">Whether to disable package resolution.</param>
        /// <param name="disableHostPlatformGeneration">Whether to disable generation of the host platform projects.</param>
        /// <param name="requiresHostPlatform">A callback which indicates the generation requires host platform projects in the same solution.</param> 
        private bool GenerateProjectsForPlatform(
            ModuleInfo module,
            string platform,
            string[] enabledServices,
            string[] disabledServices,
            string serviceSpecPath,
            bool debugServiceResolution,
            bool disablePackageResolution,
            bool disableHostPlatformGeneration,
            Action requiresHostPlatform)
        {
            if (string.IsNullOrWhiteSpace(platform))
            {
                platform = this.m_HostPlatformDetector.DetectPlatform();
            }

            var task = this.m_LightweightKernel.Get<GenerateProjectsTask>();
            task.SourcePath = Path.Combine(module.Path, "Build", "Projects");
            task.RootPath = module.Path + Path.DirectorySeparatorChar;
            task.Platform = platform;
            task.ModuleName = module.Name;
            task.EnableServices = enabledServices;
            task.DisableServices = disabledServices;
            task.ServiceSpecPath = serviceSpecPath;
            task.DebugServiceResolution = debugServiceResolution;
            task.DisablePackageResolution = disablePackageResolution;
            task.DisableHostPlatformGeneration = disableHostPlatformGeneration;
            task.RequiresHostPlatform = requiresHostPlatform;
            return task.Execute();
        }
        /// <summary>
        /// Resynchronises the projects for the specified platform.
        /// </summary>
        /// <returns><c>true</c>, if the resynchronisation succeeded, <c>false</c> otherwise.</returns>
        /// <param name="module">The module to resynchronise.</param>
        /// <param name="platform">The platform to resynchronise for.</param>
        /// <param name="enabledServices">A list of enabled services.</param>
        /// <param name="disabledServices">A list of disabled services.</param>
        /// <param name="serviceSpecPath">The service specification path.</param>
        /// <param name="debugServiceResolution">Whether to enable debugging information during service resolution.</param>
        /// <param name="disablePackageResolution">Whether to disable package resolution.</param>
        /// <param name="disableHostPlatformGeneration">Whether to disable generation of the host platform projects.</param>
        /// <param name="requiresHostPlatform">A callback which indicates the generation requires host platform projects in the same solution.</param> 
        private bool ResyncProjectsForPlatform(
            ModuleInfo module, 
            string platform, 
            string[] enabledServices, 
            string[] disabledServices, 
            string serviceSpecPath,
            bool debugServiceResolution,
            bool disablePackageResolution,
            bool disableHostPlatformGeneration,
            Action requiresHostPlatform)
        {
            if (module.DisableSynchronisation ?? false)
            {
                Console.WriteLine("Synchronisation is disabled for " + module.Name + ".");
                Console.WriteLine("To generate projects, use the --generate option instead.");

                return false;
            }
            else
            {
                if (!SyncProjectsForPlatform(module, platform))
                {
                    return false;
                }

                return GenerateProjectsForPlatform(
                    module,
                    platform,
                    enabledServices,
                    disabledServices,
                    serviceSpecPath,
                    debugServiceResolution,
                    disablePackageResolution,
                    disableHostPlatformGeneration,
                    requiresHostPlatform);
            }
        }
        /// <summary>
        /// Cleans the projects for the specified platform.
        /// </summary>
        /// <returns><c>true</c>, if projects were cleaned successfully, <c>false</c> otherwise.</returns>
        /// <param name="module">The module to clean projects in.</param>
        /// <param name="platform">The platform to clean for.</param>
        private bool CleanProjectsForPlatform(ModuleInfo module, string platform)
        {
            if (string.IsNullOrWhiteSpace(platform))
            {
                platform = this.m_HostPlatformDetector.DetectPlatform();
            }

            var task = this.m_LightweightKernel.Get<CleanProjectsTask>();
            task.SourcePath = Path.Combine(module.Path, "Build", "Projects");
            task.RootPath = module.Path + Path.DirectorySeparatorChar;
            task.Platform = platform;
            task.ModuleName = module.Name;
            return task.Execute();
        }
Exemple #15
0
        public void Autopackage(string workingDirectory, FileFilter fileFilter, Execution execution, ModuleInfo module, string rootPath, string platform, string packageFormat, List <string> temporaryFiles)
        {
            switch (packageFormat)
            {
            case PackageManager.ARCHIVE_FORMAT_NUGET_ZIP:
                _nuGetAutomaticModulePackager.Autopackage(
                    workingDirectory,
                    fileFilter,
                    execution,
                    module,
                    rootPath,
                    platform,
                    packageFormat,
                    temporaryFiles);
                break;

            case PackageManager.ARCHIVE_FORMAT_TAR_GZIP:
            case PackageManager.ARCHIVE_FORMAT_TAR_LZMA:
            default:
                _protobuildAutomaticModulePackager.Autopackage(
                    workingDirectory,
                    fileFilter,
                    execution,
                    module,
                    rootPath,
                    platform,
                    packageFormat,
                    temporaryFiles);
                break;
            }
        }
 public virtual void StartNewProject(ModuleInfo module, string name)
 {
 }
 public virtual void FinalizeNewProject(ModuleInfo module, DefinitionInfo definition)
 {
 }
        /// <summary>
        /// Synchronises the projects for the specified platform.
        /// </summary>
        /// <returns><c>true</c>, if the synchronisation succeeded, <c>false</c> otherwise.</returns>
        /// <param name="module">The module to synchronise.</param>
        /// <param name="platform">The platform to synchronise for.</param>
        private bool SyncProjectsForPlatform(ModuleInfo module, string platform)
        {
            if (module.DisableSynchronisation ?? false)
            {
                Console.WriteLine("Synchronisation is disabled for " + module.Name + ".");
                return false;
            }

            if (string.IsNullOrWhiteSpace(platform))
            {
                platform = this.m_HostPlatformDetector.DetectPlatform();
            }

            var task = this.m_LightweightKernel.Get<SyncProjectsTask>();
            task.SourcePath = Path.Combine(module.Path, "Build", "Projects");
            task.RootPath = module.Path + Path.DirectorySeparatorChar;
            task.Platform = platform;
            task.ModuleName = module.Name;
            return task.Execute();
        }
Exemple #19
0
        /// <summary>
        /// Performs a resynchronisation, synchronisation, generation or clean on the specified module.
        /// </summary>
        /// <returns><c>true</c>, if the action succeeded, <c>false</c> otherwise.</returns>
        /// <param name="module">The module to perform the action on.</param>
        /// <param name="action">The action to perform, either "resync", "sync", "generate" or "clean".</param>
        /// <param name="platform">The platform to perform the action for.</param>
        /// <param name="enabledServices">A list of enabled services.</param>
        /// <param name="disabledServices">A list of disabled services.</param>
        /// <param name="serviceSpecPath">The service specification path.</param>
        public bool PerformAction(
            ModuleInfo module,
            string action,
            string platform           = null,
            string[] enabledServices  = null,
            string[] disabledServices = null,
            string serviceSpecPath    = null)
        {
            var platformSupplied = !string.IsNullOrWhiteSpace(platform);

            if (string.IsNullOrWhiteSpace(platform))
            {
                platform = this.m_HostPlatformDetector.DetectPlatform();
            }

            var originalPlatform = platform;

            platform = module.NormalizePlatform(platform);

            if (platform == null && !platformSupplied)
            {
                // The current host platform isn't supported, so we shouldn't try to
                // operate on it.
                string firstPlatform = null;
                switch (this.m_HostPlatformDetector.DetectPlatform())
                {
                case "Windows":
                    firstPlatform = module.DefaultWindowsPlatforms.Split(',').FirstOrDefault();
                    break;

                case "MacOS":
                    firstPlatform = module.DefaultMacOSPlatforms.Split(',').FirstOrDefault();
                    break;

                case "Linux":
                    firstPlatform = module.DefaultLinuxPlatforms.Split(',').FirstOrDefault();
                    break;
                }

                if (firstPlatform != null)
                {
                    // This will end up null if the first platform isn't supported
                    // either and hence throw the right message.
                    platform = module.NormalizePlatform(firstPlatform);
                }
            }

            if (platform == null)
            {
                Console.Error.WriteLine("The platform '" + originalPlatform + "' is not supported.");
                Console.Error.WriteLine("The following platforms are supported by this module:");
                foreach (
                    var supportedPlatform in
                    module.SupportedPlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .Select(x => x.Trim())
                    .Where(x => !string.IsNullOrWhiteSpace(x)))
                {
                    Console.Error.WriteLine("  * " + supportedPlatform);
                }

                ExecEnvironment.Exit(1);
                return(false);
            }

            var primaryPlatform = platform;

            // You can generate multiple targets by default by setting the <DefaultWindowsPlatforms>
            // <DefaultMacOSPlatforms> and <DefaultLinuxPlatforms> tags in Module.xml.  Note that
            // synchronisation will only be done for the primary platform, as there is no correct
            // synchronisation behaviour when dealing with multiple C# projects.
            //
            // We only trigger this behaviour when the platform is omitted; if you explicitly
            // specify "Windows" on the command line, we'll only generate / resync / sync
            // the Windows platform.
            string multiplePlatforms = null;

            if (!platformSupplied)
            {
                switch (platform)
                {
                case "Windows":
                    multiplePlatforms = module.DefaultWindowsPlatforms;
                    break;

                case "MacOS":
                    multiplePlatforms = module.DefaultMacOSPlatforms;
                    break;

                case "Linux":
                    multiplePlatforms = module.DefaultLinuxPlatforms;
                    break;
                }
            }

            // If no overrides are set, just use the current platform.
            if (string.IsNullOrEmpty(multiplePlatforms))
            {
                multiplePlatforms = platform;
            }

            // Resolve submodules as needed.
            this.m_PackageManager.ResolveAll(module, primaryPlatform);

            // You can configure the default action for Protobuild in their project
            // with the <DefaultAction> tag in Module.xml.  If omitted, default to a resync.
            // Valid options for this tag are either "Generate", "Resync" or "Sync".

            // If the actions are "Resync" or "Sync", then we need to perform an initial
            // step against the primary platform.
            switch (action.ToLower())
            {
            case "generate":
                if (!this.GenerateProjectsForPlatform(module, primaryPlatform, enabledServices, disabledServices, serviceSpecPath))
                {
                    return(false);
                }

                break;

            case "resync":
                if (!this.ResyncProjectsForPlatform(module, primaryPlatform, enabledServices, disabledServices, serviceSpecPath))
                {
                    return(false);
                }

                break;

            case "sync":
                return(this.SyncProjectsForPlatform(module, primaryPlatform));

            case "clean":
                if (!this.CleanProjectsForPlatform(module, primaryPlatform))
                {
                    return(false);
                }

                break;

            default:
                Console.Error.WriteLine("Unknown option in <DefaultAction> tag of Module.xml.  Defaulting to resync!");
                return(this.ResyncProjectsForPlatform(module, primaryPlatform, enabledServices, disabledServices, serviceSpecPath));
            }

            // Now iterate through the multiple platforms specified.
            var multiplePlatformsArray =
                multiplePlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim());

            foreach (var platformIter in multiplePlatformsArray)
            {
                if (platformIter == primaryPlatform)
                {
                    // Already handled above.
                    continue;
                }

                // Resolve submodules as needed.
                this.m_PackageManager.ResolveAll(module, platformIter);

                switch (action.ToLower())
                {
                case "generate":
                case "resync":
                    // We do a generate under resync mode since we only want the primary platform
                    // to have synchronisation done (and it has had above).
                    if (!this.GenerateProjectsForPlatform(module, platformIter, enabledServices, disabledServices, serviceSpecPath))
                    {
                        return(false);
                    }

                    break;

                case "clean":
                    if (!this.CleanProjectsForPlatform(module, platformIter))
                    {
                        return(false);
                    }

                    break;

                default:
                    throw new InvalidOperationException("Code should never reach this point");
                }
            }

            // All the steps succeeded, so return true.
            return(true);
        }
        /// <summary>
        /// Performs a resynchronisation, synchronisation, generation or clean on the specified module.
        /// </summary>
        /// <returns><c>true</c>, if the action succeeded, <c>false</c> otherwise.</returns>
        /// <param name="module">The module to perform the action on.</param>
        /// <param name="action">The action to perform, either "resync", "sync", "generate" or "clean".</param>
        /// <param name="platform">The platform to perform the action for.</param>
        /// <param name="enabledServices">A list of enabled services.</param>
        /// <param name="disabledServices">A list of disabled services.</param>
        /// <param name="serviceSpecPath">The service specification path.</param>
        /// <param name="debugServiceResolution">Whether to enable debugging information during service resolution.</param>
        /// <param name="disablePackageResolution">Whether to disable package resolution.</param>
        /// <param name="disableHostPlatformGeneration">Whether to disable generation of the host platform projects.</param>
        public bool PerformAction(
            ModuleInfo module, 
            string action, 
            string platform = null, 
            string[] enabledServices = null, 
            string[] disabledServices = null, 
            string serviceSpecPath = null,
            bool debugServiceResolution = false,
            bool disablePackageResolution = false,
            bool disableHostPlatformGeneration = false)
        {
            var platformSupplied = !string.IsNullOrWhiteSpace(platform);

            var hostPlatform = this.m_HostPlatformDetector.DetectPlatform();
            if (string.IsNullOrWhiteSpace(platform))
            {
                platform = hostPlatform;
            }

            var originalPlatform = platform;
            string primaryPlatform = null;
            string multiplePlatforms = null;

            if (platform.Contains(","))
            {
                // The user requested multiple platforms; the first one
                // is the primary platform.
                var platforms = platform.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                if (platforms.Length == 0)
                {
                    Console.Error.WriteLine("You supplied only commas where a list of platforms was expected.");
                    ExecEnvironment.Exit(1);
                    return false;
                }
                else
                {
                    for (var i = 0; i < platforms.Length; i++)
                    {
                        var newPlatform = _moduleUtilities.NormalizePlatform(module, platforms[i]);
                        if (newPlatform == null)
                        {
                            ShowSupportedPlatformsError(module, platforms[i]);
                            return false;
                        }
                        platforms[i] = newPlatform;
                    }

                    primaryPlatform = platforms[0];
                    multiplePlatforms = platforms.Aggregate((a, b) => a + "," + b);
                }
            }
            else
            {
                platform = _moduleUtilities.NormalizePlatform(module, platform);

                if (platform == null && !platformSupplied)
                {
                    // The current host platform isn't supported, so we shouldn't try to
                    // operate on it.
                    string firstPlatform = null;
                    switch (this.m_HostPlatformDetector.DetectPlatform())
                    {
                        case "Windows":
                            firstPlatform = module.DefaultWindowsPlatforms.Split(',').FirstOrDefault();
                            break;
                        case "MacOS":
                            firstPlatform = module.DefaultMacOSPlatforms.Split(',').FirstOrDefault();
                            break;
                        case "Linux":
                            firstPlatform = module.DefaultLinuxPlatforms.Split(',').FirstOrDefault();
                            break;
                    }

                    if (firstPlatform != null)
                    {
                        // This will end up null if the first platform isn't supported
                        // either and hence throw the right message.
                        platform = _moduleUtilities.NormalizePlatform(module, firstPlatform);
                    }
                }

                if (platform == null)
                {
                    ShowSupportedPlatformsError(module, originalPlatform);
                    return false;
                }

                primaryPlatform = platform;
            }

            // You can generate multiple targets by default by setting the <DefaultWindowsPlatforms>
            // <DefaultMacOSPlatforms> and <DefaultLinuxPlatforms> tags in Module.xml.  Note that
            // synchronisation will only be done for the primary platform, as there is no correct
            // synchronisation behaviour when dealing with multiple C# projects.
            //
            // We only trigger this behaviour when the platform is omitted; if you explicitly
            // specify "Windows" on the command line, we'll only generate / resync / sync
            // the Windows platform.
            if (!platformSupplied)
            {
                switch (platform)
                {
                    case "Windows":
                        multiplePlatforms = module.DefaultWindowsPlatforms;
                        break;
                    case "MacOS":
                        multiplePlatforms = module.DefaultMacOSPlatforms;
                        break;
                    case "Linux":
                        multiplePlatforms = module.DefaultLinuxPlatforms;
                        break;
                }
            }

            // If no overrides are set, just use the current platform.
            if (string.IsNullOrEmpty(multiplePlatforms))
            {
                multiplePlatforms = platform;
            }

            // Resolve submodules as needed.
            if (!disablePackageResolution)
            {
                this.m_PackageManager.ResolveAll(module, primaryPlatform);
            }

            // Create the list of multiple platforms.
            var multiplePlatformsList =
                multiplePlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList();

            // Remember whether or not we need to implicitly generate the host
            // platform.
            var implicitlyGenerateHostPlatform = false;
            Action requiresHostPlatform = () => implicitlyGenerateHostPlatform = true;

            // If we are already generating the host platform, then requiring the
            // host platform is already satisifed.
            if (platform == hostPlatform || multiplePlatformsList.Contains(hostPlatform))
            {
                requiresHostPlatform = () => {};
            }
            else if (!_featureManager.IsFeatureEnabled(Feature.HostPlatformGeneration))
            {
                requiresHostPlatform = () =>
                {
                    Console.Error.WriteLine(
                        "WARNING: One or more projects requires host platforms to be generated, " +
                        "but the HostPlatformGeneration feature is not enabled.  Expect your " +
                        "build to fail.");
                };
            }

            // You can configure the default action for Protobuild in their project
            // with the <DefaultAction> tag in Module.xml.  If omitted, default to a resync.
            // Valid options for this tag are either "Generate", "Resync" or "Sync".

            // If the actions are "Resync" or "Sync", then we need to perform an initial
            // step against the primary platform.
            switch (action.ToLower())
            {
                case "generate":
                    if (!this.GenerateProjectsForPlatform(
                        module,
                        primaryPlatform,
                        enabledServices,
                        disabledServices,
                        serviceSpecPath,
                        debugServiceResolution,
                        disablePackageResolution,
                        disableHostPlatformGeneration,
                        requiresHostPlatform))
                    {
                        return false;
                    }

                    break;
                case "resync":
                    if (!this.ResyncProjectsForPlatform(
                        module,
                        primaryPlatform,
                        enabledServices,
                        disabledServices,
                        serviceSpecPath,
                        debugServiceResolution,
                        disablePackageResolution,
                        disableHostPlatformGeneration,
                        requiresHostPlatform))
                    {
                        return false;
                    }

                    break;
                case "sync":
                    return this.SyncProjectsForPlatform(module, primaryPlatform);
                case "clean":
                    if (!this.CleanProjectsForPlatform(module, primaryPlatform))
                    {
                        return false;
                    }

                    break;
                default:
                    Console.Error.WriteLine("Unknown option in <DefaultAction> tag of Module.xml.  Defaulting to resync!");
                    return this.ResyncProjectsForPlatform(
                        module,
                        primaryPlatform,
                        enabledServices,
                        disabledServices,
                        serviceSpecPath,
                        debugServiceResolution,
                        disablePackageResolution,
                        disableHostPlatformGeneration,
                        requiresHostPlatform);
            }

            // Now iterate through the multiple platforms specified.
            foreach (var platformIter in multiplePlatformsList.Distinct())
            {
                if (platformIter == primaryPlatform)
                {
                    // Already handled above.
                    continue;
                }

                // Resolve submodules as needed.
                if (!disablePackageResolution)
                {
                    this.m_PackageManager.ResolveAll(module, platformIter);
                }

                switch (action.ToLower())
                {
                    case "generate":
                    case "resync":
                        // We do a generate under resync mode since we only want the primary platform
                        // to have synchronisation done (and it has had above).
                        if (!this.GenerateProjectsForPlatform(
                            module,
                            platformIter,
                            enabledServices,
                            disabledServices,
                            serviceSpecPath,
                            debugServiceResolution,
                            disablePackageResolution,
                            disableHostPlatformGeneration,
                            requiresHostPlatform))
                        {
                            return false;
                        }

                        break;
                    case "clean":
                        if (!this.CleanProjectsForPlatform(module, platformIter))
                        {
                            return false;
                        }

                        break;
                    default:
                        throw new InvalidOperationException("Code should never reach this point");
                }
            }

            // If we implicitly require the host platform, generate that now (this variable can
            // only ever be set to true if the host platform is not already in the list of
            // platforms generated previously).
            if (implicitlyGenerateHostPlatform)
            {
                // Check to see if the host platform is supported.
                var hostPlatformNormalized = _moduleUtilities.NormalizePlatform(module, hostPlatform);
                if (hostPlatformNormalized == null)
                {
                    Console.WriteLine(
                        "WARNING: The current host platform is not a supported platform for the solution.  IDE editor " +
                        "projects and post-build hooks will not be available, and this may cause the project to be " +
                        "built incorrectly!");
                    return true;
                }

                Console.WriteLine(
                    "One or more projects required the presence of host platform " +
                    "projects, implicitly starting generation for " + hostPlatform + "...");

                // Resolve submodules as needed.
                if (!disablePackageResolution)
                {
                    this.m_PackageManager.ResolveAll(module, hostPlatform);
                }

                switch (action.ToLower())
                {
                case "generate":
                case "resync":
                    // We do a generate under resync mode since we only want the primary platform
                    // to have synchronisation done (and it has had above).
                    if (!this.GenerateProjectsForPlatform(
                        module,
                        hostPlatform,
                        enabledServices,
                        disabledServices,
                        serviceSpecPath,
                        debugServiceResolution,
                        disablePackageResolution,
                        disableHostPlatformGeneration,
                        requiresHostPlatform))
                    {
                        return false;
                    }

                    break;
                case "clean":
                    if (!this.CleanProjectsForPlatform(module, hostPlatform))
                    {
                        return false;
                    }

                    break;
                default:
                    throw new InvalidOperationException("Code should never reach this point");
                }
            }

            // All the steps succeeded, so return true.
            return true;
        }
Exemple #21
0
        private static ModuleInfo LoadInternal(XDocument doc, string modulePath, Func <ModuleInfo> fallback)
        {
            var def = new ModuleInfo();
            var xsi = doc.Root == null ? null : doc.Root.Attribute(XName.Get("xsi", "http://www.w3.org/2000/xmlns/"));

            if (xsi != null && xsi.Value == "http://www.w3.org/2001/XMLSchema-instance")
            {
                return(fallback());
            }

            Func <string, string> getStringValue = name =>
            {
                if (doc.Root == null)
                {
                    return(null);
                }

                var elem = doc.Root.Element(XName.Get(name));
                if (elem == null)
                {
                    return(null);
                }

                return(elem.Value);
            };

            def.Name                      = getStringValue("Name");
            def.Authors                   = getStringValue("Authors");
            def.Description               = getStringValue("Description");
            def.ProjectUrl                = getStringValue("ProjectUrl");
            def.LicenseUrl                = getStringValue("LicenseUrl");
            def.IconUrl                   = getStringValue("IconUrl");
            def.GitRepositoryUrl          = getStringValue("GitRepositoryUrl");
            def.SemanticVersion           = getStringValue("SemanticVersion");
            def.Path                      = modulePath;
            def.DefaultAction             = getStringValue("DefaultAction");
            def.DefaultLinuxPlatforms     = getStringValue("DefaultLinuxPlatforms");
            def.DefaultMacOSPlatforms     = getStringValue("DefaultMacOSPlatforms");
            def.DefaultWindowsPlatforms   = getStringValue("DefaultWindowsPlatforms");
            def.DefaultStartupProject     = getStringValue("DefaultStartupProject");
            def.SupportedPlatforms        = getStringValue("SupportedPlatforms");
            def.DisableSynchronisation    = getStringValue("DisableSynchronisation") == "true";
            def.GenerateNuGetRepositories = getStringValue("GenerateNuGetRepositories") == "true";
            def.Packages                  = new List <PackageRef>();

            if (doc.Root != null)
            {
                var packagesElem = doc.Root.Element(XName.Get("Packages"));
                if (packagesElem != null)
                {
                    var packages = packagesElem.Elements();
                    foreach (var package in packages)
                    {
                        var folder = package.Attribute(XName.Get("Folder"))?.Value;
                        var gitRef = package.Attribute(XName.Get("GitRef"))?.Value;
                        var uri    = package.Attribute(XName.Get("Uri"))?.Value;

                        var repository  = package.Attribute(XName.Get("Repository"))?.Value;
                        var packageName = package.Attribute(XName.Get("Package"))?.Value;
                        var version     = package.Attribute(XName.Get("Version"))?.Value;

                        if (!string.IsNullOrWhiteSpace(repository) && !string.IsNullOrWhiteSpace(packageName) && !string.IsNullOrWhiteSpace(version))
                        {
                            // This is NuGet v3 package.  Rather than writing a different interface,
                            // we just automatically form a URI that complies with the rest of the
                            // package resolution system.
                            uri = repository;
                            if (!string.IsNullOrWhiteSpace(uri))
                            {
                                uri  = uri.Replace("https://", "https-nuget-v3://");
                                uri  = uri.Replace("http://", "http-nuget-v3://");
                                uri += $"|{packageName}";
                            }

                            gitRef = version;
                        }

                        if (string.IsNullOrWhiteSpace(folder) && !string.IsNullOrWhiteSpace(packageName))
                        {
                            folder = packageName;
                        }

                        if (string.IsNullOrWhiteSpace(folder) || string.IsNullOrWhiteSpace(gitRef) ||
                            string.IsNullOrWhiteSpace(uri))
                        {
                            RedirectableConsole.ErrorWriteLine("WARNING: Invalid package declaration in module; skipping package.");
                            continue;
                        }

                        var packageRef = new PackageRef
                        {
                            Folder    = folder,
                            GitRef    = gitRef,
                            Uri       = uri,
                            Platforms = null,
                        };

                        var platforms      = package.Attribute(XName.Get("Platforms"));
                        var platformsArray = platforms?.Value.Split(',');
                        if (platformsArray?.Length > 0)
                        {
                            packageRef.Platforms = platformsArray;
                        }

                        def.Packages.Add(packageRef);
                    }
                }

                var featureSetElem = doc.Root.Element(XName.Get("FeatureSet"));
                if (featureSetElem != null)
                {
                    def.FeatureSet = new List <Feature>();

                    var features = featureSetElem.Elements();
                    foreach (var feature in features)
                    {
                        try
                        {
                            def.FeatureSet.Add((Feature)Enum.Parse(typeof(Feature), feature.Value));
                        }
                        catch
                        {
                            RedirectableConsole.ErrorWriteLine("Unknown feature in Module.xml; ignoring: " + feature.Value);
                        }
                    }
                }
                else
                {
                    def.FeatureSet = null;
                }

                // Check if the feature set is present and if it does not contain
                // the PackageManagement feature.  If that feature isn't there, we
                // ignore any of the data in Packages and just set the value to
                // an empty list.
                if (def.FeatureSet != null && !def.FeatureSet.Contains(Feature.PackageManagement))
                {
                    def.Packages.Clear();
                }
            }

            return(def);
        }
 public DefinitionSynchroniser(ModuleInfo moduleInfo, DefinitionInfo info, CSharpProject project)
 {
     this.m_ModuleInfo = moduleInfo;
     this.m_DefinitionInfo = info;
     this.m_CSharpProject = project;
 }
        public int Execute(Execution execution)
        {
            var assemblyPath = Assembly.GetEntryAssembly().Location;
            var fileInfo     = new FileInfo(assemblyPath);
            var modulePath   = fileInfo.DirectoryName;

            if (modulePath == null)
            {
                RedirectableConsole.WriteLine(
                    "Unable to determine the location of Protobuild.");
                return(1);
            }

            if (!File.Exists(Path.Combine(modulePath, "Build", "Module.xml")))
            {
                modulePath = execution.WorkingDirectory;
            }

            string executablePath = null;

            if (!File.Exists(Path.Combine(modulePath, "Build", "Module.xml")))
            {
                // We can only run global tools.
                var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                if (globalToolPath == null)
                {
                    RedirectableConsole.WriteLine(
                        "There is no global tool registered as '" + execution.ExecuteProjectName + "'");
                    return(1);
                }
                else
                {
                    executablePath = globalToolPath;
                }
            }
            else
            {
                var platform    = this.m_HostPlatformDetector.DetectPlatform();
                var module      = ModuleInfo.Load(Path.Combine(modulePath, "Build", "Module.xml"));
                var definitions = module.GetDefinitionsRecursively(platform).ToList();
                var target      = definitions.FirstOrDefault(x => x.Name == execution.ExecuteProjectName);
                if (target == null)
                {
                    // Check to see if there is any external project definition that provides the tool.
                    foreach (var definition in definitions)
                    {
                        var document = XDocument.Load(definition.DefinitionPath);
                        if (document.Root.Name.LocalName == "ExternalProject")
                        {
                            foreach (var node in document.Root.Elements().Where(x => x.Name.LocalName == "Tool"))
                            {
                                var name = node.Attribute(XName.Get("Name")).Value;
                                var path = node.Attribute(XName.Get("Path")).Value;

                                if (name == execution.ExecuteProjectName)
                                {
                                    executablePath = Path.Combine(definition.ModulePath, path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));
                                    break;
                                }
                            }
                        }
                    }

                    if (executablePath == null)
                    {
                        var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                        if (globalToolPath == null)
                        {
                            RedirectableConsole.WriteLine(
                                "There is no project definition with name '" + execution.ExecuteProjectName + "'");
                            return(1);
                        }
                        else
                        {
                            executablePath = globalToolPath;
                        }
                    }
                }
                else
                {
                    var document = XDocument.Load(target.DefinitionPath);
                    if (document.Root.Name.LocalName == "Project")
                    {
                        var assemblyName       = this.m_ProjectOutputPathCalculator.GetProjectAssemblyName(platform, target, document);
                        var prefixPath         = this.m_ProjectOutputPathCalculator.GetProjectOutputPathPrefix(platform, target, document, false);
                        var directory          = new DirectoryInfo(Path.Combine(modulePath, prefixPath));
                        var subdirectories     = directory.GetDirectories();
                        var preferredName      = (execution.ExecuteProjectConfiguration ?? "Debug").ToLowerInvariant();
                        var preferredDirectory = subdirectories.FirstOrDefault(x => x.Name.ToLowerInvariant() == preferredName);
                        if (preferredDirectory != null && File.Exists(Path.Combine(preferredDirectory.FullName, assemblyName + ".exe")))
                        {
                            executablePath = Path.Combine(preferredDirectory.FullName, assemblyName + ".exe");
                        }
                        else
                        {
                            string tempPath = null;
                            foreach (var subdirectory in subdirectories)
                            {
                                tempPath = Path.Combine(subdirectory.FullName, assemblyName + ".exe");
                                if (File.Exists(tempPath))
                                {
                                    break;
                                }
                            }
                            if (tempPath != null && File.Exists(tempPath))
                            {
                                executablePath = tempPath;
                            }
                        }
                    }
                    else if (document.Root.Name.LocalName == "ExternalProject")
                    {
                        foreach (var node in document.Root.Elements().Where(x => x.Name.LocalName == "Tool"))
                        {
                            var name = node.Attribute(XName.Get("Name")).Value;
                            var path = node.Attribute(XName.Get("Path")).Value;

                            if (name == execution.ExecuteProjectName)
                            {
                                executablePath = Path.Combine(target.ModulePath, path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar));
                                break;
                            }
                        }
                    }

                    if (executablePath == null)
                    {
                        var globalToolPath = this.m_PackageGlobalTool.ResolveGlobalToolIfPresent(execution.ExecuteProjectName);
                        if (globalToolPath == null)
                        {
                            RedirectableConsole.WriteLine(
                                "There is no output path for '" + execution.ExecuteProjectName + "'; has the project been built?");
                            return(1);
                        }
                        else
                        {
                            executablePath = globalToolPath;
                        }
                    }
                }
            }

            if (!File.Exists(executablePath))
            {
                RedirectableConsole.WriteLine(
                    "There is no executable for '" + execution.ExecuteProjectName + "'; has the project been built?");
                return(1);
            }

            var arguments = string.Empty;

            if (execution.ExecuteProjectArguments.Length > 0)
            {
                arguments = execution.ExecuteProjectArguments
                            .Select(x => "\"" + x.Replace("\"", "\\\"") + "\"")
                            .Aggregate((a, b) => a + " " + b);
            }

            ProcessStartInfo startInfo;

            if (Path.DirectorySeparatorChar == '/')
            {
                var mono = "mono";
                if (m_HostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/mono"))
                {
                    // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in
                    // the system PATH.  If we can't find Mono with the which tool, manually set the
                    // path here in an attempt to find it.
                    mono = "/usr/local/bin/mono";
                }

                startInfo = new ProcessStartInfo(
                    mono,
                    "--debug \"" + executablePath + "\" " + arguments);
            }
            else
            {
                startInfo = new ProcessStartInfo(
                    executablePath,
                    arguments);
            }
            startInfo.UseShellExecute = false;

            var process = Process.Start(startInfo);

            process.WaitForExit();
            return(process.ExitCode);
        }
        public void Generate(
            ModuleInfo moduleInfo,
            List<XmlDocument> definitions,
            string platformName,
            string solutionPath,
            List<Service> services,
            IEnumerable<string> repositoryPaths)
        {
            var generateSolutionTransform = this.m_ResourceProvider.LoadXSLT(ResourceType.GenerateSolution, Language.CSharp, platformName);
            var selectSolutionTransform = this.m_ResourceProvider.LoadXSLT(ResourceType.SelectSolution, Language.CSharp, platformName);

            var input = this.m_SolutionInputGenerator.GenerateForSelectSolution(definitions, platformName, services);
            using (var memory = new MemoryStream())
            {
                selectSolutionTransform.Transform(input, null, memory);

                memory.Seek(0, SeekOrigin.Begin);

                var document = new XmlDocument();
                document.Load(memory);

                var defaultProject = (XmlElement)null;
                var existingGuids = new List<string>();
                foreach (var element in document.DocumentElement.SelectNodes("/Projects/Project").OfType<XmlElement>().ToList())
                {
                    var f = element.SelectNodes("ProjectGuids/Platform[@Name='" + platformName + "']").OfType<XmlElement>().FirstOrDefault();

                    if (f != null)
                    {
                        if (existingGuids.Contains(f.InnerText.Trim()))
                        {
                            element.ParentNode.RemoveChild(element);
                            continue;
                        }
                        else
                        {
                            existingGuids.Add(f.InnerText.Trim());
                        }
                    }

                    var s = element.SelectNodes("Guid").OfType<XmlElement>().FirstOrDefault();

                    if (s != null)
                    {
                        if (existingGuids.Contains(s.InnerText.Trim()))
                        {
                            element.ParentNode.RemoveChild(element);
                            continue;
                        }
                        else
                        {
                            existingGuids.Add(s.InnerText.Trim());
                        }
                    }

                    var n = element.SelectNodes("RawName").OfType<XmlElement>().FirstOrDefault();

                    if (n != null)
                    {
                        if (n.InnerText.Trim() == moduleInfo.DefaultStartupProject)
                        {
                            defaultProject = element;
                        }
                    }
                }

                if (defaultProject != null)
                {
                    // Move the default project to the first element of it's parent.  The first project
                    // in the solution is the default startup project.
                    var parent = defaultProject.ParentNode;
                    parent.RemoveChild(defaultProject);
                    parent.InsertBefore(defaultProject, parent.FirstChild);
                }

                var documentInput = this.m_SolutionInputGenerator.GenerateForGenerateSolution(
                    platformName,
                    document.DocumentElement.SelectNodes("/Projects/Project").OfType<XmlElement>());

                using (var writer = new StreamWriter(solutionPath))
                {
                    generateSolutionTransform.Transform(documentInput, null, writer);
                }
            }

            if (repositoryPaths != null && repositoryPaths.Any())
            {
                this.m_NuGetRepositoriesConfigGenerator.Generate(solutionPath, repositoryPaths);
            }
        }
        public void ResolveAll(string workingDirectory, ModuleInfo module, string platform, bool?enableParallelisation, bool forceUpgrade, bool?safeResolve, bool?overrideSourcePreference)
        {
            if (!_featureManager.IsFeatureEnabled(Feature.PackageManagement))
            {
                return;
            }

            RedirectableConsole.WriteLine("Starting resolution of packages for " + platform + "...");

            var parallelisation = enableParallelisation ?? _hostPlatformDetector.DetectPlatform() == "Windows";

            if (parallelisation)
            {
                RedirectableConsole.WriteLine("Enabled parallelisation; use --no-parallel to disable...");
            }

            if (module.Packages != null && module.Packages.Count > 0)
            {
                var taskList   = new List <Task <Tuple <string, Action> > >();
                var resultList = new List <Tuple <string, Action> >();
                foreach (var submodule in module.Packages)
                {
                    if (submodule.IsActiveForPlatform(platform))
                    {
                        RedirectableConsole.WriteLine("Querying: " + submodule.Uri);
                        var submodule1 = submodule;
                        if (parallelisation)
                        {
                            var task = new Func <Task <Tuple <string, Action> > >(async() =>
                            {
                                var metadata = await Task.Run(() =>
                                                              Lookup(workingDirectory, module, submodule1, platform, null, overrideSourcePreference, forceUpgrade, safeResolve));
                                if (metadata == null)
                                {
                                    return(new Tuple <string, Action>(submodule1.Uri, () => { }));
                                }
                                return(new Tuple <string, Action>(submodule1.Uri,
                                                                  () => { this.Resolve(workingDirectory, metadata, submodule1, null, overrideSourcePreference, forceUpgrade, safeResolve); }));
                            });
                            taskList.Add(task());
                        }
                        else
                        {
                            var metadata = Lookup(workingDirectory, module, submodule1, platform, null, overrideSourcePreference, forceUpgrade, safeResolve);
                            if (metadata == null)
                            {
                                resultList.Add(new Tuple <string, Action>(submodule1.Uri, () => { }));
                            }
                            else
                            {
                                resultList.Add(new Tuple <string, Action>(submodule1.Uri,
                                                                          () => { this.Resolve(workingDirectory, metadata, submodule1, null, overrideSourcePreference, forceUpgrade, safeResolve); }));
                            }
                        }
                    }
                    else
                    {
                        RedirectableConsole.WriteLine("Skipping resolution for " + submodule.Uri + " because it is not active for this target platform");
                    }
                }

                if (parallelisation)
                {
                    var taskArray = taskList.ToArray();
                    Task.WaitAll(taskArray);
                    foreach (var tuple in taskArray)
                    {
                        RedirectableConsole.WriteLine("Resolving: " + tuple.Result.Item1);
                        tuple.Result.Item2();
                    }
                }
                else
                {
                    foreach (var tuple in resultList)
                    {
                        RedirectableConsole.WriteLine("Resolving: " + tuple.Item1);
                        tuple.Item2();
                    }
                }
            }

            foreach (var submodule in module.GetSubmodules(platform))
            {
                if (submodule.Packages.Count == 0 && submodule.GetSubmodules(platform).Length == 0)
                {
                    if (_featureManager.IsFeatureEnabledInSubmodule(module, submodule, Feature.OptimizationSkipResolutionOnNoPackagesOrSubmodules))
                    {
                        RedirectableConsole.WriteLine(
                            "Skipping package resolution in submodule for " + submodule.Name + " (there are no submodule or packages)");
                        continue;
                    }
                }

                RedirectableConsole.WriteLine(
                    "Invoking package resolution in submodule for " + submodule.Name);
                string parallelMode = null;
                if (_featureManager.IsFeatureEnabledInSubmodule(module, submodule, Feature.TaskParallelisation))
                {
                    if (parallelisation)
                    {
                        parallelMode += "-parallel ";
                    }
                    else
                    {
                        parallelMode += "-no-parallel ";
                    }
                }
                _moduleExecution.RunProtobuild(
                    submodule,
                    _featureManager.GetFeatureArgumentToPassToSubmodule(module, submodule) + parallelMode +
                    "-resolve " + platform + " " + packageRedirector.GetRedirectionArguments());
                RedirectableConsole.WriteLine(
                    "Finished submodule package resolution for " + submodule.Name);
            }

            RedirectableConsole.WriteLine("Package resolution complete.");
        }
        public int Execute(Execution execution)
        {
            if (!Directory.Exists(execution.PackageSourceFolder))
            {
                throw new InvalidOperationException("The source folder " + execution.PackageSourceFolder + " does not exist.");
            }

            if (execution.PackagePlatform == "Template" && execution.PackageFormat != PackageManager.ARCHIVE_FORMAT_NUGET_ZIP)
            {
                return(ExecuteForTemplate(execution));
            }

            var        allowAutopackage   = true;
            var        moduleExpectedPath = Path.Combine(execution.PackageSourceFolder, "Build", "Module.xml");
            ModuleInfo rootModule         = null;

            if (!File.Exists(moduleExpectedPath))
            {
                if (execution.PackageFilterFile == null)
                {
                    RedirectableConsole.WriteLine(
                        "There is no module in the path '" + execution.PackageSourceFolder + "' (expected to " +
                        "find a Build\\Module.xml file within that directory).");
                    return(1);
                }
                else
                {
                    // We allow this mode if the user has provided a filter file and are constructing
                    // the package manually.
                    allowAutopackage = false;
                }
            }
            else
            {
                rootModule = ModuleInfo.Load(moduleExpectedPath);
            }

            var temporaryFiles = new List <string>();

            try
            {
                var customDirectives = new Dictionary <string, Action <FileFilter> >()
                {
                    {
                        "autopackage",
                        f =>
                        {
                            if (allowAutopackage && rootModule != null)
                            {
                                this.m_AutomaticProjectPackager.Autopackage(
                                    execution.WorkingDirectory,
                                    f,
                                    execution,
                                    rootModule,
                                    execution.PackageSourceFolder,
                                    execution.PackagePlatform,
                                    execution.PackageFormat,
                                    temporaryFiles);
                            }
                            else
                            {
                                RedirectableConsole.WriteLine(
                                    "WARNING: There is no module in the path '" + execution.PackageSourceFolder +
                                    "' (expected to " +
                                    "find a Build\\Module.xml file within that directory).  Ignoring the 'autopackage' directive.");
                            }
                        }
                    }
                };

                RedirectableConsole.WriteLine("Starting package creation for " + execution.PackagePlatform);

                var filter =
                    new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(execution.PackageSourceFolder));
                if (execution.PackageFilterFile != null)
                {
                    using (var reader = new StreamReader(execution.PackageFilterFile))
                    {
                        var contents = reader.ReadToEnd();
                        contents = contents.Replace("%PLATFORM%", execution.PackagePlatform);

                        using (var inputStream = new MemoryStream(Encoding.ASCII.GetBytes(contents)))
                        {
                            this.m_FileFilterParser.ParseAndApply(filter, inputStream, customDirectives);
                        }
                    }
                }
                else
                {
                    customDirectives["autopackage"](filter);
                }

                if (File.Exists(execution.PackageDestinationFile))
                {
                    RedirectableConsole.WriteLine("The destination file " + execution.PackageDestinationFile +
                                                  " already exists; it will be overwritten.");
                    File.Delete(execution.PackageDestinationFile);
                }

                filter.ImplyDirectories();

                if (execution.PackageFormat != PackageManager.ARCHIVE_FORMAT_NUGET_ZIP)
                {
                    if (!filter.ContainsTargetPath("Build/"))
                    {
                        RedirectableConsole.WriteLine("ERROR: The Build directory does not exist in the source folder.");
                        if (execution.PackageFilterFile != null)
                        {
                            this.PrintFilterMappings(filter);
                        }
                        return(1);
                    }

                    if (!filter.ContainsTargetPath("Build/Projects/"))
                    {
                        RedirectableConsole.WriteLine("ERROR: The Build\\Projects directory does not exist in the source folder.");
                        if (execution.PackageFilterFile != null)
                        {
                            this.PrintFilterMappings(filter);
                        }
                        return(1);
                    }

                    if (!filter.ContainsTargetPath("Build/Module.xml"))
                    {
                        RedirectableConsole.WriteLine("ERROR: The Build\\Module.xml file does not exist in the source folder.");
                        if (execution.PackageFilterFile != null)
                        {
                            this.PrintFilterMappings(filter);
                        }
                        return(1);
                    }
                }

                if (filter.ContainsTargetPath("Protobuild.exe"))
                {
                    RedirectableConsole.WriteLine("ERROR: The Protobuild.exe file should not be included in the package file.");
                    if (execution.PackageFilterFile != null)
                    {
                        this.PrintFilterMappings(filter);
                    }
                    return(1);
                }

                using (
                    var target = new FileStream(execution.PackageDestinationFile, FileMode.CreateNew, FileAccess.Write,
                                                FileShare.None))
                {
                    _packageCreator.Create(
                        target,
                        filter,
                        execution.PackageSourceFolder,
                        execution.PackageFormat,
                        execution.PackagePlatform,
                        execution.PackageDestinationFile);
                }

                RedirectableConsole.WriteLine("\rPackage written to " + execution.PackageDestinationFile + " successfully.");
                return(0);
            }
            finally
            {
                foreach (var file in temporaryFiles)
                {
                    File.Delete(file);
                }
            }
        }
        public void Autopackage(
            FileFilter fileFilter,
            Execution execution,
            ModuleInfo module, 
            string rootPath,
            string platform,
            List<string> temporaryFiles)
        {
            var definitions = module.GetDefinitionsRecursively(platform).ToArray();
            var loadedProjects = new List<LoadedDefinitionInfo>();

            foreach (var definition in definitions)
            {
                Console.WriteLine("Loading: " + definition.Name);
                loadedProjects.Add(
                    this.m_ProjectLoader.Load(
                        platform,
                        module,
                        definition));
            }

            var serviceManager = new ServiceManager(platform);
            List<Service> services;

            serviceManager.SetRootDefinitions(module.GetDefinitions());

            var enabledServices = execution.EnabledServices.ToArray();
            var disabledServices = execution.DisabledServices.ToArray();

            foreach (var service in enabledServices)
            {
                serviceManager.EnableService(service);
            }

            foreach (var service in disabledServices)
            {
                serviceManager.DisableService(service);
            }

            if (execution.DebugServiceResolution)
            {
                serviceManager.EnableDebugInformation();
            }

            services = serviceManager.CalculateDependencyGraph(loadedProjects.Select(x => x.Project).ToList());

            foreach (var service in services)
            {
                if (service.ServiceName != null)
                {
                    Console.WriteLine("Enabled service: " + service.FullName);
                }
            }

            var packagePaths = module.Packages
                .Select(x => new DirectoryInfo(System.IO.Path.Combine(module.Path, x.Folder)).FullName)
                .ToArray();

            foreach (var definition in definitions)
            {
                if (definition.SkipAutopackage)
                {
                    Console.WriteLine("Skipping: " + definition.Name);
                    continue;
                }

                var definitionNormalizedPath = new FileInfo(definition.AbsolutePath).FullName;
                if (packagePaths.Any(definitionNormalizedPath.StartsWith))
                {
                    Console.WriteLine("Skipping: " + definition.Name + " (part of another package)");
                    continue;
                }

                switch (definition.Type)
                {
                    case "External":
                        Console.WriteLine("Packaging: " + definition.Name);
                        this.AutomaticallyPackageExternalProject(definitions, services, fileFilter, rootPath, platform, definition, temporaryFiles);
                        break;
                    case "Include":
                        Console.WriteLine("Packaging: " + definition.Name);
                        this.AutomaticallyPackageIncludeProject(definitions, services, fileFilter, rootPath, platform, definition);
                        break;
                    case "Content":
                        Console.WriteLine("Content project definition skipped: " + definition.Name);
                        break;
                    default:
                        Console.WriteLine("Packaging: " + definition.Name);
                        this.AutomaticallyPackageNormalProject(definitions, services, fileFilter, rootPath, platform, definition, temporaryFiles);
                        break;
                }
            }

            // If there is no Module.xml in the source mappings already, then copy the current module.
            var filterDictionary = fileFilter.ToDictionarySafe(
                k => k.Key,
                v => v.Value,
                (dict, d) => Console.WriteLine ("WARNING: More than one file maps to " + d.Key));
            if (!filterDictionary.ContainsValue("Build/Module.xml"))
            {
                fileFilter.AddManualMapping(Path.Combine(module.Path, "Build", "Module.xml"), "Build/Module.xml");
            }
        }
        public byte[] Transform(string url, string gitReference, string platform, string format)
        {
            var urlAndPackageName = url.Split(new[] { '|' }, 2);

            if (urlAndPackageName.Length != 2)
            {
                Console.Error.WriteLine(
                    "ERROR: Malformed NuGet package reference '" + url +
                    "'.  Make sure you split the NuGet server URL and the package name with a pipe character (|).");
                ExecEnvironment.Exit(1);
            }

            var repoUrl     = urlAndPackageName[0];
            var packageName = urlAndPackageName[1];

            var originalFolder = DownloadOrUseExistingNuGetPackage(repoUrl.TrimEnd('/'), packageName, gitReference);

            var folder = Path.GetTempFileName();

            File.Delete(folder);
            Directory.CreateDirectory(folder);

            byte[] bytes;
            try
            {
                Console.WriteLine("Copying directory for package transformation...");
                CopyFolder(new DirectoryInfo(originalFolder), new DirectoryInfo(folder));

                Console.WriteLine("Auto-detecting libraries to reference from NuGet package...");

                var packagePath         = new DirectoryInfo(folder).GetFiles("*.nuspec").First().FullName;
                var libraryReferences   = new Dictionary <string, string>();
                var packageDependencies = new Dictionary <string, string>();

                // Use the nuspec file if it exists.
                List <string> references = new List <string>();
                if (File.Exists(packagePath))
                {
                    var packageDoc = new XmlDocument();
                    packageDoc.Load(packagePath);

                    // If the references are explicitly provided in the nuspec, use
                    // those as to what files should be referenced by the projects.
                    if (
                        packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>()
                        .Count(x => x.Name == "references") > 0)
                    {
                        references =
                            packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>()
                            .First(x => x.Name == "references")
                            .ChildNodes.OfType <XmlElement>()
                            .Where(x => x.Name == "reference")
                            .Select(x => x.Attributes["file"].Value)
                            .ToList();
                    }

                    // If there are dependencies specified, store them and convert them to
                    // Protobuild references, and reference them in the Module.xml file.
                    if (
                        packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>()
                        .Count(x => x.Name == "dependencies") > 0)
                    {
                        packageDependencies =
                            packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>()
                            .First(x => x.Name == "dependencies")
                            .ChildNodes.OfType <XmlElement>()
                            .Where(x => x.Name == "dependency")
                            .ToDictionarySafe(
                                k => k.Attributes["id"].Value,
                                v => v.Attributes["version"].Value,
                                (dict, c) =>
                                Console.WriteLine("WARNING: More than one dependency on " + c +
                                                  " in NuGet package."));
                    }
                }

                // Determine the priority of the frameworks that we want to target
                // out of the available versions.
                string[] clrNames = new[]
                {
                    // Exact matches
                    "=net40-client",
                    "=Net40-client",
                    "=net40",
                    "=Net40",
                    "=net35",
                    "=Net35",
                    "=net20",
                    "=Net20",
                    "=20",
                    "=11",
                    "=",
                    "=net45",
                    "=Net45",

                    // Substring matches
                    "?net4",
                    "?Net4",
                    "?MonoAndroid",
                };

                if (platform == "WindowsUniversal")
                {
                    // This is the priority list for Windows Universal Apps.
                    clrNames = new[]
                    {
                        "=uap10.0",
                        "=uap",
                        "=netcore451",
                        "=netcore",
                        "=dotnet"
                    };
                }

                var referenceDirectories = new string[] { "ref", "lib" };

                foreach (var directory in referenceDirectories)
                {
                    // Determine the base path for all references; that is, the lib/ folder.
                    var referenceBasePath = Path.Combine(
                        folder,
                        directory);

                    if (Directory.Exists(referenceBasePath))
                    {
                        // If no references are in nuspec, reference all of the libraries that
                        // are on disk.
                        if (references.Count == 0)
                        {
                            // Search through all of the target frameworks until we find one that
                            // has at least one file in it.
                            foreach (var clrNameOriginal in clrNames)
                            {
                                var clrName  = clrNameOriginal;
                                var foundClr = false;

                                if (clrName[0] == '=')
                                {
                                    // Exact match (strip the equals).
                                    clrName = clrName.Substring(1);

                                    // If this target framework doesn't exist for this library, skip it.
                                    var dirPath = Path.Combine(
                                        referenceBasePath,
                                        clrName);
                                    if (!Directory.Exists(dirPath))
                                    {
                                        continue;
                                    }
                                }
                                else if (clrName[0] == '?')
                                {
                                    // Substring, search the reference base path for any folders
                                    // with a matching substring.
                                    clrName = clrName.Substring(1);

                                    var baseDirPath = referenceBasePath;
                                    var found       = false;
                                    foreach (var subdir in new DirectoryInfo(baseDirPath).GetDirectories())
                                    {
                                        if (subdir.Name.Contains(clrName))
                                        {
                                            clrName = subdir.Name;
                                            found   = true;
                                            break;
                                        }
                                    }

                                    if (!found)
                                    {
                                        continue;
                                    }
                                }
                                else
                                {
                                    throw new InvalidOperationException("Unknown CLR name match type with '" + clrName +
                                                                        "'");
                                }

                                // Otherwise enumerate through all of the libraries in this folder.
                                foreach (var dll in Directory.EnumerateFiles(
                                             Path.Combine(
                                                 referenceBasePath, clrName),
                                             "*.dll"))
                                {
                                    // Determine the relative path to the library.
                                    var packageDll = Path.Combine(
                                        referenceBasePath,
                                        clrName,
                                        Path.GetFileName(dll));

                                    // Confirm again that the file actually exists on disk when
                                    // combined with the root path.
                                    if (File.Exists(
                                            Path.Combine(
                                                packageDll)))
                                    {
                                        // Create the library reference.
                                        if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(dll)))
                                        {
                                            libraryReferences.Add(
                                                Path.GetFileNameWithoutExtension(dll),
                                                packageDll);
                                        }

                                        // Mark this target framework as having provided at least
                                        // one reference.
                                        foundClr = true;
                                    }
                                }

                                // Break if we have found at least one reference.
                                if (foundClr)
                                {
                                    break;
                                }
                            }
                        }

                        // For all of the references that were found in the original nuspec file,
                        // add those references.
                        foreach (var reference in references)
                        {
                            // Search through all of the target frameworks until we find the one
                            // that has the reference in it.
                            foreach (var clrName in clrNames)
                            {
                                // If this target framework doesn't exist for this library, skip it.
                                var packageDll = Path.Combine(
                                    referenceBasePath,
                                    clrName,
                                    reference);

                                if (File.Exists(
                                        Path.Combine(
                                            packageDll)))
                                {
                                    if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(packageDll)))
                                    {
                                        libraryReferences.Add(
                                            Path.GetFileNameWithoutExtension(packageDll),
                                            packageDll);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                }

                foreach (var kv in libraryReferences)
                {
                    Console.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")");
                }

                Console.WriteLine("Generating external project reference...");
                var document        = new XmlDocument();
                var externalProject = document.CreateElement("ExternalProject");
                externalProject.SetAttribute("Name", packageName);
                document.AppendChild(externalProject);
                foreach (var kv in libraryReferences)
                {
                    var binaryReference = document.CreateElement("Binary");
                    binaryReference.SetAttribute("Name", kv.Key);
                    binaryReference.SetAttribute("Path",
                                                 kv.Value.Substring(folder.Length).TrimStart(new[] { '/', '\\' }).Replace("%2B", "-"));
                    externalProject.AppendChild(binaryReference);
                }
                foreach (var package in packageDependencies)
                {
                    var externalReference = document.CreateElement("Reference");
                    externalReference.SetAttribute("Include", package.Key);
                    externalProject.AppendChild(externalReference);
                }
                document.Save(Path.Combine(folder, "_ProtobuildExternalProject.xml"));

                Console.WriteLine("Generating module...");
                var generatedModule = new ModuleInfo();
                generatedModule.Name     = packageName;
                generatedModule.Packages = new List <PackageRef>();

                foreach (var package in packageDependencies)
                {
                    generatedModule.Packages.Add(new PackageRef
                    {
                        Uri =
                            repoUrl.Replace("http://", "http-nuget://").Replace("https://", "https-nuget://") + "|" +
                            package.Key,
                        GitRef = package.Value.TrimStart('[').TrimEnd(']'),
                        Folder = package.Key
                    });
                }

                generatedModule.Save(Path.Combine(folder, "_ProtobuildModule.xml"));

                Console.WriteLine("Converting to a Protobuild package...");

                var target = new MemoryStream();
                var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(folder));

                foreach (var kv in libraryReferences)
                {
                    filter.ApplyInclude(
                        Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/')));
                    filter.ApplyRewrite(
                        Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/')),
                        kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-"));
                }

                filter.ApplyInclude("_ProtobuildExternalProject\\.xml");
                filter.ApplyRewrite("_ProtobuildExternalProject\\.xml", "Build/Projects/" + packageName + ".definition");
                filter.ApplyInclude("_ProtobuildModule\\.xml");
                filter.ApplyRewrite("_ProtobuildModule\\.xml", "Build/Module.xml");

                filter.ImplyDirectories();

                _packageCreator.Create(
                    target,
                    filter,
                    folder,
                    format);

                Console.WriteLine("Package conversion complete.");
                bytes = new byte[target.Position];
                target.Seek(0, SeekOrigin.Begin);
                target.Read(bytes, 0, bytes.Length);
            }
            finally
            {
                Console.WriteLine("Cleaning up temporary data...");
                PathUtils.AggressiveDirectoryDelete(folder);
            }

            return(bytes);
        }
        public bool IsFeatureEnabledInSubmodule(ModuleInfo module, ModuleInfo submodule, Feature feature)
        {
            if (submodule.CachedInternalFeatures == null)
            {
                var result = _moduleExecution.RunProtobuild(submodule, "-query-features", true);
                var exitCode = result.Item1;
                var stdout = result.Item2 + result.Item3;

                if (exitCode != 0 || stdout.Contains("Protobuild.exe [options]") || stdout.Contains("Unknown argument"))
                {
                    submodule.CachedInternalFeatures = new Feature[0];
                }

                submodule.CachedInternalFeatures = ParseFeaturesFromStdout(stdout);

                if (submodule.CachedInternalFeatures.Contains(Feature.PropagateFeatures))
                {
                    // If we have a limited feature set, we need to query again with
                    // only our features propagated.
                    result = _moduleExecution.RunProtobuild(submodule, GetFeatureArgumentToPassToSubmodule(module, submodule) + "-query-features", true);
                    exitCode = result.Item1;
                    stdout = result.Item2 + result.Item3;

                    if (!(exitCode != 0 || stdout.Contains("Protobuild.exe [options]") || stdout.Contains("Unknown argument")))
                    {
                        submodule.CachedInternalFeatures = ParseFeaturesFromStdout(stdout);
                    }
                }
            }

            return submodule.CachedInternalFeatures.Contains(feature);
        }
        public int Execute(Execution execution)
        {
            if (!Directory.Exists(execution.PackageSourceFolder))
            {
                throw new InvalidOperationException("The source folder " + execution.PackageSourceFolder + " does not exist.");
            }

            var        allowAutopackage   = true;
            var        moduleExpectedPath = Path.Combine(execution.PackageSourceFolder, "Build", "Module.xml");
            ModuleInfo rootModule         = null;

            if (!File.Exists(moduleExpectedPath))
            {
                if (execution.PackageFilterFile == null)
                {
                    Console.WriteLine(
                        "There is no module in the path '" + execution.PackageSourceFolder + "' (expected to " +
                        "find a Build\\Module.xml file within that directory).");
                    return(1);
                }
                else
                {
                    // We allow this mode if the user has provided a filter file and are constructing
                    // the package manually.
                    allowAutopackage = false;
                }
            }
            else
            {
                rootModule = ModuleInfo.Load(moduleExpectedPath);
            }

            var customDirectives = new Dictionary <string, Action <FileFilter> >()
            {
                {
                    "autopackage",
                    f =>
                    {
                        if (allowAutopackage && rootModule != null)
                        {
                            this.m_AutomaticProjectPackager.Autopackage(
                                f,
                                execution,
                                rootModule,
                                execution.PackageSourceFolder,
                                execution.PackagePlatform);
                        }
                        else
                        {
                            Console.WriteLine(
                                "WARNING: There is no module in the path '" + execution.PackageSourceFolder + "' (expected to " +
                                "find a Build\\Module.xml file within that directory).  Ignoring the 'autopackage' directive.");
                        }
                    }
                }
            };

            Console.WriteLine("Starting package creation for " + execution.PackagePlatform);

            var filter = new FileFilter(GetRecursiveFilesInPath(execution.PackageSourceFolder));

            if (execution.PackageFilterFile != null)
            {
                using (var reader = new StreamReader(execution.PackageFilterFile))
                {
                    var contents = reader.ReadToEnd();
                    contents = contents.Replace("%PLATFORM%", execution.PackagePlatform);

                    using (var inputStream = new MemoryStream(Encoding.ASCII.GetBytes(contents)))
                    {
                        this.m_FileFilterParser.ParseAndApply(filter, inputStream, customDirectives);
                    }
                }
            }
            else
            {
                customDirectives["autopackage"](filter);
            }

            if (File.Exists(execution.PackageDestinationFile))
            {
                Console.WriteLine("The destination file " + execution.PackageDestinationFile + " already exists; it will be overwritten.");
                File.Delete(execution.PackageDestinationFile);
            }

            filter.ImplyDirectories();

            var filterDictionary = filter.ToDictionary(k => k.Key, v => v.Value);

            if (!filterDictionary.ContainsValue("Build/"))
            {
                Console.WriteLine("ERROR: The Build directory does not exist in the source folder.");
                if (execution.PackageFilterFile != null)
                {
                    this.PrintFilterMappings(filterDictionary);
                }
                return(1);
            }

            if (!filterDictionary.ContainsValue("Build/Projects/"))
            {
                Console.WriteLine("ERROR: The Build\\Projects directory does not exist in the source folder.");
                if (execution.PackageFilterFile != null)
                {
                    this.PrintFilterMappings(filterDictionary);
                }
                return(1);
            }

            if (!filterDictionary.ContainsValue("Build/Module.xml"))
            {
                Console.WriteLine("ERROR: The Build\\Module.xml file does not exist in the source folder.");
                if (execution.PackageFilterFile != null)
                {
                    this.PrintFilterMappings(filterDictionary);
                }
                return(1);
            }

            if (filterDictionary.ContainsValue("Protobuild.exe"))
            {
                Console.WriteLine("ERROR: The Protobuild.exe file should not be included in the package file.");
                if (execution.PackageFilterFile != null)
                {
                    this.PrintFilterMappings(filterDictionary);
                }
                return(1);
            }

            using (var target = new FileStream(execution.PackageDestinationFile, FileMode.CreateNew, FileAccess.Write, FileShare.None))
            {
                var archive = new MemoryStream();

                switch (execution.PackageFormat)
                {
                case PackageManager.ARCHIVE_FORMAT_TAR_GZIP:
                {
                    Console.WriteLine("Writing package in tar/gzip format...");
                    break;
                }

                case PackageManager.ARCHIVE_FORMAT_TAR_LZMA:
                default:
                {
                    Console.WriteLine("Writing package in tar/lzma format...");
                    break;
                }
                }

                switch (execution.PackageFormat)
                {
                case PackageManager.ARCHIVE_FORMAT_TAR_GZIP:
                case PackageManager.ARCHIVE_FORMAT_TAR_LZMA:
                default:
                {
                    var state = this.m_Deduplicator.CreateState();

                    Console.Write("Deduplicating files in package...");

                    var progressHelper = new DedupProgressRenderer(filter.Count());
                    var current        = 0;

                    foreach (var kv in filter.OrderBy(kv => kv.Value))
                    {
                        if (kv.Value.EndsWith("/"))
                        {
                            // Directory
                            this.m_Deduplicator.AddDirectory(state, kv.Value);
                        }
                        else
                        {
                            // File
                            var realFile     = Path.Combine(execution.PackageSourceFolder, kv.Key);
                            var realFileInfo = new FileInfo(realFile);

                            this.m_Deduplicator.AddFile(state, realFileInfo, kv.Value);
                        }

                        current++;

                        progressHelper.SetProgress(current);
                    }

                    Console.WriteLine();
                    Console.WriteLine("Adding files to package...");

                    using (var writer = new tar_cs.TarWriter(archive))
                    {
                        this.m_Deduplicator.PushToTar(state, writer);
                    }

                    break;
                }
                }

                archive.Seek(0, SeekOrigin.Begin);

                switch (execution.PackageFormat)
                {
                case PackageManager.ARCHIVE_FORMAT_TAR_GZIP:
                {
                    Console.WriteLine("Compressing package...");

                    using (var compress = new GZipStream(target, CompressionMode.Compress))
                    {
                        archive.CopyTo(compress);
                    }

                    break;
                }

                case PackageManager.ARCHIVE_FORMAT_TAR_LZMA:
                default:
                {
                    Console.Write("Compressing package...");

                    var progressHelper = new CompressProgressRenderer(archive.Length);

                    LZMA.LzmaHelper.Compress(archive, target, progressHelper);

                    Console.WriteLine();

                    break;
                }
                }
            }

            Console.WriteLine("\rPackage written to " + execution.PackageDestinationFile + " successfully.");
            return(0);
        }
        public string GetFeatureArgumentToPassToSubmodule(ModuleInfo module, ModuleInfo submodule)
        {
            if (!IsFeatureEnabledInSubmodule(module, submodule, Feature.PropagateFeatures))
            {
                // This submodule doesn't support feature propagation, so we pass no arguments.
                return string.Empty;
            }

            if ((_featuresEnabledFromCommandLine == null && _featuresEnabledFromModules == null) || _parentPropagatesFullFeatureSet)
            {
                return "--features full ";
            }

            var features = GetAllEnabledFeatures();
            if (features.Length == 0)
            {
                return "--features \"\" ";
            }

            return "--features \"" + features.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b) + "\" ";
        }
Exemple #32
0
 public DefinitionSynchroniser(ModuleInfo moduleInfo, DefinitionInfo info, CSharpProject project)
 {
     this.m_ModuleInfo     = moduleInfo;
     this.m_DefinitionInfo = info;
     this.m_CSharpProject  = project;
 }
 public virtual void StartNewProject(ModuleInfo module, string name)
 {
 }
        public Tuple <int, string, string> RunProtobuild(ModuleInfo module, string args, bool capture = false)
        {
            var invokeInline = false;
            var myHash       = ExecEnvironment.GetProgramHash();
            var targetHash   = ExecEnvironment.GetProgramHash(Path.Combine(module.Path, "Protobuild.exe"));

            if (myHash == targetHash)
            {
                invokeInline = true;
            }

            if (ExecEnvironment.RunProtobuildInProcess || invokeInline)
            {
                var oldBuffer = RedirectableConsole.TargetBuffer;
                var ourBuffer = new RedirectableBuffer();
                RedirectableConsole.TargetBuffer = ourBuffer;
                var needsEndSelfInvoke = true;
                try
                {
                    var exitCode = ExecEnvironment.InvokeSelf(module.Path, args.SplitCommandLine().ToArray());
                    RedirectableConsole.TargetBuffer = oldBuffer;
                    needsEndSelfInvoke = false;
                    if (capture)
                    {
                        return(new Tuple <int, string, string>(
                                   exitCode,
                                   ourBuffer.Stdout,
                                   ourBuffer.Stderr));
                    }
                    else
                    {
                        return(new Tuple <int, string, string>(
                                   exitCode,
                                   string.Empty,
                                   string.Empty));
                    }
                }
                finally
                {
                    if (needsEndSelfInvoke)
                    {
                        RedirectableConsole.TargetBuffer = oldBuffer;
                    }
                }
            }

            var protobuildPath = Path.Combine(module.Path, "Protobuild.exe");

            PathUtils.MakePathExecutable(protobuildPath, true);

            var stdout = string.Empty;
            var stderr = string.Empty;

            for (var attempt = 0; attempt < 3; attempt++)
            {
                if (File.Exists(protobuildPath))
                {
                    var pi = new ProcessStartInfo
                    {
                        FileName               = protobuildPath,
                        Arguments              = args,
                        WorkingDirectory       = module.Path,
                        CreateNoWindow         = capture,
                        RedirectStandardError  = capture,
                        RedirectStandardInput  = capture,
                        RedirectStandardOutput = capture,
                        UseShellExecute        = false
                    };
                    var p = new Process {
                        StartInfo = pi
                    };
                    if (capture)
                    {
                        p.OutputDataReceived += (sender, eventArgs) =>
                        {
                            if (!string.IsNullOrEmpty(eventArgs.Data))
                            {
                                if (capture)
                                {
                                    stdout += eventArgs.Data + "\n";
                                }
                                else
                                {
                                    RedirectableConsole.WriteLine(eventArgs.Data);
                                }
                            }
                        };
                        p.ErrorDataReceived += (sender, eventArgs) =>
                        {
                            if (!string.IsNullOrEmpty(eventArgs.Data))
                            {
                                if (capture)
                                {
                                    stderr += eventArgs.Data + "\n";
                                }
                                else
                                {
                                    RedirectableConsole.ErrorWriteLine(eventArgs.Data);
                                }
                            }
                        };
                    }
                    try
                    {
                        p.Start();
                    }
                    catch (System.ComponentModel.Win32Exception ex)
                    {
                        if (ex.Message.Contains("Cannot find the specified file"))
                        {
                            // Mono sometimes throws this error even though the
                            // file does exist on disk.  The best guess is there's
                            // a race condition between performing chmod on the
                            // file and Mono actually seeing it as an executable file.
                            // Show a warning and sleep for a bit before retrying.
                            if (attempt != 2)
                            {
                                RedirectableConsole.WriteLine("WARNING: Unable to execute Protobuild.exe, will retry again...");
                                System.Threading.Thread.Sleep(2000);
                                continue;
                            }
                            else
                            {
                                RedirectableConsole.WriteLine("ERROR: Still unable to execute Protobuild.exe.");
                                throw;
                            }
                        }
                    }
                    if (capture)
                    {
                        p.BeginOutputReadLine();
                        p.BeginErrorReadLine();
                    }
                    p.WaitForExit();
                    return(new Tuple <int, string, string>(p.ExitCode, stdout, stderr));
                }
            }

            return(new Tuple <int, string, string>(1, string.Empty, string.Empty));
        }