Пример #1
0
        private void ResolveTemplateBinary(PackageRef reference, string templateName, string platform, string sourceUri)
        {
            if (reference.Folder != string.Empty)
            {
                throw new InvalidOperationException("Reference folder must be empty for template type.");
            }

            if (Directory.Exists(".staging"))
            {
                PathUtils.AggressiveDirectoryDelete(".staging");
            }

            Directory.CreateDirectory(".staging");

            var package = m_PackageCache.GetBinaryPackage(reference.Uri, reference.GitRef, platform);

            if (package == null)
            {
                this.ResolveTemplateSource(reference, templateName, sourceUri);
                return;
            }

            package.ExtractTo(".staging");

            ApplyProjectTemplateFromStaging(templateName);
        }
Пример #2
0
        private void ResolveTemplateBinary(string workingDirectory, ICachableBinaryPackageMetadata protobuildMetadata, string folder, string templateName, bool forceUpgrade)
        {
            if (folder != string.Empty)
            {
                throw new InvalidOperationException("Reference folder must be empty for template type.");
            }

            // The template is a reference to a Git repository.
            if (Directory.Exists(Path.Combine(workingDirectory, ".staging")))
            {
                PathUtils.AggressiveDirectoryDelete(Path.Combine(workingDirectory, ".staging"));
            }

            Directory.CreateDirectory(Path.Combine(workingDirectory, ".staging"));

            var package = GetBinaryPackage(protobuildMetadata);

            if (package == null)
            {
                _sourcePackageResolve.Resolve(workingDirectory, protobuildMetadata, folder, templateName, forceUpgrade);
                return;
            }

            ExtractTo(workingDirectory, protobuildMetadata.PackageName, protobuildMetadata.BinaryFormat, package, Path.Combine(workingDirectory, ".staging"), "Template");

            _projectTemplateApplier.Apply(Path.Combine(workingDirectory, ".staging"), templateName);
            PathUtils.AggressiveDirectoryDelete(Path.Combine(workingDirectory, ".staging"));
        }
        public int Execute(Execution execution)
        {
            var url    = execution.PackageUrl;
            var module = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml"));

            if (module.Packages == null)
            {
                module.Packages = new List <PackageRef>();
            }

            var packageRef = _packageUrlParser.Parse(url);

            foreach (var package in module.Packages.ToArray())
            {
                if (package.Uri == packageRef.Uri)
                {
                    RedirectableConsole.WriteLine("Removing " + package.Uri + "...");
                    module.Packages.Remove(package);

                    // Save after each package remove in case something goes wrong deleting
                    // the directory.
                    module.Save(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml"));

                    if (Directory.Exists(Path.Combine(module.Path, package.Folder)))
                    {
                        RedirectableConsole.WriteLine("Deleting folder '" + package.Folder + "'...");
                        PathUtils.AggressiveDirectoryDelete(Path.Combine(module.Path, package.Folder));
                    }
                }
            }

            return(0);
        }
Пример #4
0
        private void ResolveTemplateSource(PackageRef reference, string templateName, string source)
        {
            if (reference.Folder != string.Empty)
            {
                throw new InvalidOperationException("Reference folder must be empty for template type.");
            }

            if (Directory.Exists(".staging"))
            {
                PathUtils.AggressiveDirectoryDelete(".staging");
            }

            var package = m_PackageCache.GetSourcePackage(source, reference.GitRef);

            package.ExtractTo(".staging");

            this.ApplyProjectTemplateFromStaging(templateName);
        }
Пример #5
0
        private void ApplyProjectTemplateFromStaging(string name)
        {
            foreach (var pathToFile in GetFilesFromStaging())
            {
                var path = pathToFile.Key;
                var file = pathToFile.Value;

                var replacedPath = path.Replace("{PROJECT_NAME}", name);
                var dirSeperator = replacedPath.LastIndexOfAny(new[] { '/', '\\' });
                if (dirSeperator != -1)
                {
                    var replacedDir = replacedPath.Substring(0, dirSeperator);
                    if (!Directory.Exists(replacedDir))
                    {
                        Directory.CreateDirectory(replacedDir);
                    }
                }

                string contents;
                using (var reader = new StreamReader(file.FullName))
                {
                    contents = reader.ReadToEnd();
                }

                if (contents.Contains("{PROJECT_NAME}") || contents.Contains("{PROJECT_XML_NAME}"))
                {
                    contents = contents.Replace("{PROJECT_NAME}", name);
                    contents = contents.Replace("{PROJECT_XML_NAME}", System.Security.SecurityElement.Escape(name));
                    using (var writer = new StreamWriter(replacedPath))
                    {
                        writer.Write(contents);
                    }
                }
                else
                {
                    // If we don't see {PROJECT_NAME} or {PROJECT_XML_NAME}, use a straight
                    // file copy so that we don't break binary files.
                    File.Copy(file.FullName, replacedPath, true);
                }
            }

            PathUtils.AggressiveDirectoryDelete(".staging");
        }
Пример #6
0
        private void ResolveGlobalToolBinary(string workingDirectory, ICachableBinaryPackageMetadata protobuildMetadata, bool forceUpgrade)
        {
            var toolFolder = _packageGlobalTool.GetGlobalToolInstallationPath(protobuildMetadata.CanonicalURI);

            if (File.Exists(Path.Combine(toolFolder, ".pkg")))
            {
                if (!forceUpgrade)
                {
                    RedirectableConsole.WriteLine("Protobuild binary package already present at " + toolFolder);
                    return;
                }
            }

            RedirectableConsole.WriteLine("Creating and emptying " + toolFolder);
            PathUtils.AggressiveDirectoryDelete(toolFolder);
            Directory.CreateDirectory(toolFolder);

            RedirectableConsole.WriteLine("Installing " + protobuildMetadata.CanonicalURI + " at version " + protobuildMetadata.GitCommitOrRef);
            var package = GetBinaryPackage(protobuildMetadata);

            if (package == null)
            {
                RedirectableConsole.WriteLine("The specified global tool package is not available for this platform.");
                return;
            }

            ExtractTo(workingDirectory, protobuildMetadata.PackageName, protobuildMetadata.BinaryFormat, package, toolFolder, protobuildMetadata.Platform);

            var file = File.Create(Path.Combine(toolFolder, ".pkg"));

            file.Close();

            if (_knownToolProvider == null)
            {
                // We must delay load this because of a circular dependency :(
                _knownToolProvider = _lightweightKernel.Get <IKnownToolProvider>();
            }

            _packageGlobalTool.ScanPackageForToolsAndInstall(toolFolder, _knownToolProvider);

            RedirectableConsole.WriteLine("Binary resolution complete");
        }
Пример #7
0
        private string GetSourcePackage(string workingDirectory, string url)
        {
            var sourcePath = Path.Combine(
                _packageCacheConfiguration.GetCacheDirectory(),
                this.GetPackageName(url));

            if (this.HasSourcePackage(url))
            {
                if (Directory.Exists(Path.Combine(sourcePath, "objects")) &&
                    File.Exists(Path.Combine(sourcePath, "config")))
                {
                    try
                    {
                        GitUtils.RunGitAbsolute(sourcePath, "fetch origin +refs/heads/*:refs/heads/*");
                    }
                    catch (InvalidOperationException)
                    {
                        // Ignore exceptions here in case the user is offline.
                    }

                    return(sourcePath);
                }
                else
                {
                    RedirectableConsole.ErrorWriteLine("WARNING: Source package cache is corrupt, removing and cloning again...");
                    try
                    {
                        PathUtils.AggressiveDirectoryDelete(sourcePath);
                    }
                    catch (Exception)
                    {
                        RedirectableConsole.ErrorWriteLine("WARNING: Unable to delete invalid source package from cache!");
                    }
                }
            }

            Directory.CreateDirectory(sourcePath);
            GitUtils.RunGit(workingDirectory, null, "clone --progress --bare " + url + " \"" + sourcePath + "\"");

            return(sourcePath);
        }
Пример #8
0
        private void ResolveGit(string workingDirectory, GitPackageMetadata gitMetadata, string folder, string templateName, bool forceUpgrade)
        {
            switch (gitMetadata.PackageType)
            {
            case PackageManager.PACKAGE_TYPE_LIBRARY:
                if (File.Exists(Path.Combine(workingDirectory, folder, ".git")) || Directory.Exists(Path.Combine(workingDirectory, folder, ".git")))
                {
                    if (!forceUpgrade)
                    {
                        RedirectableConsole.WriteLine("Git submodule / repository already present at " + folder);
                        return;
                    }
                }

                PathUtils.AggressiveDirectoryDelete(Path.Combine(workingDirectory, folder));

                var packageLibrary = GetSourcePackage(workingDirectory, gitMetadata.CloneURI);
                ExtractGitSourceTo(workingDirectory, packageLibrary, gitMetadata.GitRef, folder);
                break;

            case PackageManager.PACKAGE_TYPE_TEMPLATE:
                if (Directory.Exists(".staging"))
                {
                    PathUtils.AggressiveDirectoryDelete(Path.Combine(workingDirectory, ".staging"));
                }

                var packageTemplate = GetSourcePackage(workingDirectory, gitMetadata.CloneURI);
                ExtractGitSourceTo(workingDirectory, packageTemplate, gitMetadata.GitRef, Path.Combine(workingDirectory, ".staging"));

                _projectTemplateApplier.Apply(Path.Combine(workingDirectory, ".staging"), templateName);
                PathUtils.AggressiveDirectoryDelete(Path.Combine(workingDirectory, ".staging"));
                break;

            default:
                throw new InvalidOperationException("Unable to resolve source package with type '" + gitMetadata.PackageType + "' using Git-based package.");
            }
        }
Пример #9
0
        public int Execute(Execution execution)
        {
            var platforms = execution.Platform ?? this._hostPlatformDetector.DetectPlatform();

            var package = _packageUrlParser.Parse(execution.PackageUrl);

            foreach (var platform in platforms.Split(','))
            {
                // Create a temporary working directory where we can precache files.
                var tempDir = Path.Combine(Path.GetTempPath(), "precache-" + HashString(execution.PackageUrl + "|" + platform + "|" + (execution.PrecacheSource == null ? "null" : execution.PrecacheSource.Value ? "true" : "false")));
                if (Directory.Exists(tempDir))
                {
                    PathUtils.AggressiveDirectoryDelete(tempDir);
                }
                Directory.CreateDirectory(tempDir);

                try
                {
                    RedirectableConsole.WriteLine("Precaching " + package.Uri + "...");
                    var metadata = _packageManager.Lookup(tempDir, null, package, platform, null, execution.PrecacheSource, true, false);
                    _packageManager.Resolve(tempDir, metadata, package, "PRECACHE", execution.PrecacheSource, true, false);

                    // Also precache dependencies.
                    if (File.Exists(Path.Combine(tempDir, "Build", "Module.xml")))
                    {
                        var moduleInfo = ModuleInfo.Load(Path.Combine(tempDir, "Build", "Module.xml"));
                        _packageManager.ResolveAll(tempDir, moduleInfo, platform, execution.UseTaskParallelisation, true, false, execution.PrecacheSource);
                    }
                }
                finally
                {
                    PathUtils.AggressiveDirectoryDelete(tempDir);
                }
            }

            return(0);
        }
Пример #10
0
        private void ResolveGlobalToolBinary(ProtobuildPackageMetadata protobuildMetadata, bool forceUpgrade)
        {
            var toolFolder = _packageGlobalTool.GetGlobalToolInstallationPath(protobuildMetadata.ReferenceURI);

            if (File.Exists(Path.Combine(toolFolder, ".pkg")))
            {
                if (!forceUpgrade)
                {
                    Console.WriteLine("Protobuild binary package already present at " + toolFolder);
                    return;
                }
            }

            Console.WriteLine("Creating and emptying " + toolFolder);
            PathUtils.AggressiveDirectoryDelete(toolFolder);
            Directory.CreateDirectory(toolFolder);

            Console.WriteLine("Installing " + protobuildMetadata.ReferenceURI + " at version " + protobuildMetadata.GitCommit);
            var package = GetProtobuildBinaryPackage(protobuildMetadata);

            if (package == null)
            {
                Console.WriteLine("The specified global tool package is not available for this platform.");
                return;
            }

            ExtractTo(protobuildMetadata.BinaryFormat, package, toolFolder);

            var file = File.Create(Path.Combine(toolFolder, ".pkg"));

            file.Close();

            _packageGlobalTool.ScanPackageForToolsAndInstall(toolFolder);

            Console.WriteLine("Binary resolution complete");
        }
Пример #11
0
        public byte[] Transform(string workingDirectory, string url, string gitReference, string platform, string format)
        {
            var urlAndPackageName = url.Split(new[] { '|' }, 2);

            if (urlAndPackageName.Length != 2)
            {
                RedirectableConsole.ErrorWriteLine(
                    "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);

            if (Directory.Exists(Path.Combine(originalFolder, "protobuild")))
            {
                // This is a Protobuild-aware NuGet package.  In this case, we just use the contents of the
                // "protobuild" folder as the content of our package, and ignore everything else.
                RedirectableConsole.WriteLine("Detected Protobuild-aware package...");

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

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

                filter.ApplyInclude("protobuild/(.*)");
                filter.ApplyRewrite("protobuild/(.*)", "$1");

                filter.ImplyDirectories();

                _packageCreator.Create(
                    target,
                    filter,
                    originalFolder,
                    format,
                    platform);

                RedirectableConsole.WriteLine("Package conversion complete.");
                var bytes2 = new byte[target.Position];
                target.Seek(0, SeekOrigin.Begin);
                target.Read(bytes2, 0, bytes2.Length);
                return(bytes2);
            }

            var folder = Path.GetTempFileName();

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

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

                RedirectableConsole.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) =>
                                RedirectableConsole.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 = _nuGetPlatformMapping.GetFrameworkNamesForRead(workingDirectory, platform);

                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)
                {
                    RedirectableConsole.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")");
                }

                RedirectableConsole.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"));

                RedirectableConsole.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"));

                RedirectableConsole.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,
                    platform);

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

            return(bytes);
        }
Пример #12
0
        private void ConvertNuGetOnlyPackage(Reduplicator reduplicator, ZipStorer zipStorer, string path, string packageName, string workingDirectory, string platform)
        {
            var folder = Path.GetTempFileName();

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

            try
            {
                reduplicator.UnpackZipToFolder(
                    zipStorer,
                    folder,
                    candidatePath => true,
                    outputPath => outputPath);

                var references          = new List <string>();
                var libraryReferences   = new Dictionary <string, string>();
                var packageDependencies = new Dictionary <string, string>();

                // Load NuGet specification file.
                var specFile = Directory.GetFiles(folder, "*.nuspec").FirstOrDefault();
                if (specFile != null)
                {
                    specFile = Path.Combine(folder, specFile);
                    if (File.Exists(specFile))
                    {
                        var packageDoc = new XmlDocument();
                        packageDoc.Load(specFile);

                        if (packageDoc?.DocumentElement != null)
                        {
                            // If we have an id in the package, that forms the package name.
                            if (packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>()
                                .Count(x => x.Name == "id") > 0)
                            {
                                var newName = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>()
                                              .First(x => x.Name == "id").InnerText.Trim();
                                if (!string.IsNullOrWhiteSpace(newName))
                                {
                                    packageName = newName;
                                }
                            }

                            // 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) =>
                                        RedirectableConsole.WriteLine("WARNING: More than one dependency on " +
                                                                      c +
                                                                      " in NuGet package."));
                            }
                        }
                    }
                }

                if (string.IsNullOrWhiteSpace(packageName))
                {
                    throw new InvalidOperationException("Expected package name when converting NuGet-only package!");
                }

                // Determine the priority of the frameworks that we want to target
                // out of the available versions.
                string[] clrNames = _nugetPlatformMapping.GetFrameworkNamesForRead(workingDirectory, platform);

                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)
                {
                    RedirectableConsole.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")");
                }

                RedirectableConsole.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);
                }
                Directory.CreateDirectory(Path.Combine(path, "Build", "Projects"));
                document.Save(Path.Combine(path, "Build", "Projects", packageName + ".definition"));

                RedirectableConsole.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    = "https-nuget-v3://api.nuget.org/v3/index.json|" + package.Key,
                        GitRef = package.Value.TrimStart('[').TrimEnd(']'),
                        Folder = package.Key
                    });
                }

                generatedModule.Save(Path.Combine(path, "Build", "Module.xml"));

                foreach (var kv in libraryReferences)
                {
                    var targetFile =
                        new FileInfo(Path.Combine(path,
                                                  kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-")));
                    targetFile.Directory.Create();
                    File.Copy(kv.Value, targetFile.FullName);
                }
            }
            finally
            {
                PathUtils.AggressiveDirectoryDelete(folder);
            }
        }
Пример #13
0
        private void ResolveLibraryBinary(string workingDirectory, ICachableBinaryPackageMetadata protobuildMetadata, string folder, bool forceUpgrade, Func <byte[]> getBinaryPackage)
        {
            var platformFolder = Path.Combine(folder, protobuildMetadata.Platform);

            if (File.Exists(Path.Combine(platformFolder, ".pkg")))
            {
                if (!forceUpgrade)
                {
                    RedirectableConsole.WriteLine("Protobuild binary package already present at " + platformFolder);
                    return;
                }
            }

            RedirectableConsole.WriteLine("Creating and emptying " + platformFolder);

            if (File.Exists(Path.Combine(folder, ".pkg")))
            {
                if (Directory.Exists(platformFolder))
                {
                    // Only clear out the target's folder if the reference folder
                    // already contains binary packages (for other platforms)
                    PathUtils.AggressiveDirectoryDelete(platformFolder);
                }
            }
            else
            {
                // The reference folder is holding source code, so clear it
                // out entirely.
                PathUtils.AggressiveDirectoryDelete(folder);
            }

            Directory.CreateDirectory(platformFolder);

            RedirectableConsole.WriteLine("Marking " + folder + " as ignored for Git");
            GitUtils.MarkIgnored(folder);

            var package = getBinaryPackage();

            if (package == null)
            {
                return;
            }

            ExtractTo(workingDirectory, protobuildMetadata.PackageName, protobuildMetadata.BinaryFormat, package, platformFolder, protobuildMetadata.Platform);

            // Only copy ourselves to the binary folder if both "Build/Module.xml" and
            // "Build/Projects" exist in the binary package's folder.  This prevents us
            // from triggering the "create new module?" logic if the package hasn't been
            // setup correctly.
            if (Directory.Exists(Path.Combine(platformFolder, "Build", "Projects")) &&
                File.Exists(Path.Combine(platformFolder, "Build", "Module.xml")))
            {
                var sourceProtobuild = Assembly.GetEntryAssembly().Location;
                File.Copy(sourceProtobuild, Path.Combine(platformFolder, "Protobuild.exe"), true);
                PathUtils.MakePathExecutable(Path.Combine(platformFolder, "Protobuild.exe"), true);
            }

            var file = File.Create(Path.Combine(platformFolder, ".pkg"));

            file.Close();

            file = File.Create(Path.Combine(folder, ".pkg"));
            file.Close();

            RedirectableConsole.WriteLine("Binary resolution complete");
        }
Пример #14
0
        /// <summary>
        /// Returns the required JSIL directories, downloading and building JSIL if necessary.
        /// </summary>
        /// <remarks>
        /// If this returns <c>false</c>, then an error was encountered while downloading or
        /// building JSIL.
        /// </remarks>
        /// <returns><c>true</c>, if JSIL was available or was installed successfully, <c>false</c> otherwise.</returns>
        /// <param name="jsilDirectory">The runtime directory of JSIL.</param>
        /// <param name="jsilCompilerFile">The JSIL compiler executable.</param>
        public bool GetJSIL(out string jsilDirectory, out string jsilCompilerFile)
        {
            if (File.Exists(this.GetJSILCompilerPath()))
            {
                jsilDirectory    = this.GetJSILRuntimeDirectory();
                jsilCompilerFile = this.GetJSILCompilerPath();
                return(true);
            }

            if (this.BuggyMonoDetected())
            {
                Console.WriteLine("=============== Please update Mono ===============");
                Console.WriteLine("Mono 3.2.6 is known to be buggy when building ");
                Console.WriteLine("JSIL.  To update Mono, upgrade via your package ");
                Console.WriteLine("manager on Linux, or if you are on Mac update Mono ");
                Console.WriteLine("by downloading the latest version from: ");
                Console.WriteLine();
                Console.WriteLine("  http://www.go-mono.com/mono-downloads/download.html");
                Console.WriteLine();
                Console.WriteLine("=============================================================");
                jsilDirectory    = null;
                jsilCompilerFile = null;
                return(false);
            }

            Console.WriteLine("=============== JSIL runtime is not installed ===============");
            Console.WriteLine("I will now download and build JSIL for the Web platform.");
            Console.WriteLine("Installing into: " + this.GetJSILRuntimeDirectory());

            Console.Write("Removing existing JSIL runtime... ");
            try
            {
                PathUtils.AggressiveDirectoryDelete(this.GetJSILSourceDirectory());
                PathUtils.AggressiveDirectoryDelete(this.GetJSILRuntimeDirectory());
                Console.WriteLine("done.");
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("error!");
                Console.WriteLine("Unable to remove existing JSIL runtime or source.  Remove");
                Console.WriteLine("the files and directories located in the following directory:");
                Console.WriteLine();
                Console.WriteLine("  " + this.GetJSILDirectory(string.Empty));
                Console.WriteLine();
                Console.WriteLine("and then try again.");
                Console.WriteLine();
                Console.WriteLine("=============================================================");
                jsilDirectory    = null;
                jsilCompilerFile = null;
                return(false);
            }

            Console.WriteLine("Downloading JSIL source code via Git... ");

            try
            {
                this.ExecuteGit("clone https://github.com/sq/JSIL.git .");
            }
            catch (InvalidOperationException)
            {
                Console.WriteLine("error!");
                Console.WriteLine("You don't have Git installed or it currently isn't in your PATH.");
                Console.WriteLine("JSIL has to be downloaded via Git due to the use of submodules.");
                Console.WriteLine("=============================================================");
                jsilDirectory    = null;
                jsilCompilerFile = null;
                return(false);
            }

            Console.WriteLine("Updating JSIL submodules... ");
            this.ExecuteGit("submodule update --init --recursive");
            Console.WriteLine("done.");

            Console.WriteLine("Patching JSIL project files... ");
            this.PatchFile(
                Path.Combine(this.GetJSILSourceDirectory(), "Compiler", "Compiler.csproj"),
                x =>
                Regex.Replace(
                    Regex.Replace(
                        x,
                        "\\<PreBuildEvent\\>[^\\<]+\\<\\/PreBuildEvent\\>",
                        string.Empty),
                    "\\<PostBuildEvent\\>[^\\<]+\\<\\/PostBuildEvent\\>",
                    string.Empty));
            this.PatchFile(
                Path.Combine(
                    this.GetJSILSourceDirectory(),
                    "Upstream",
                    "ILSpy",
                    "ICSharpCode.Decompiler",
                    "ICSharpCode.Decompiler.csproj"),
                x =>
                Regex.Replace(
                    Regex.Replace(
                        x,
                        "<Compile Include=\"Properties\\\\AssemblyInfo\\.cs\" />",
                        string.Empty),
                    "<Target Name=\"BeforeBuild\">(.+?)</Target>",
                    string.Empty,
                    RegexOptions.Singleline));
            Console.WriteLine("done.");

            Console.WriteLine("Building JSIL compiler... ");
            string builderOrError;

            if (!this.DetectBuilder(out builderOrError))
            {
                Console.WriteLine("error!");
                Console.WriteLine("Unable to locate the tool to build C# projects.  The exact ");
                Console.WriteLine("error is: ");
                Console.WriteLine();
                Console.WriteLine("  " + builderOrError);
                Console.WriteLine();
                Console.WriteLine("If you are running on Windows, make sure you are running ");
                Console.WriteLine("Protobuild under the Visual Studio command prompt.");
                Console.WriteLine();
                Console.WriteLine("=============================================================");
                jsilDirectory    = null;
                jsilCompilerFile = null;
                return(false);
            }

            if (!this.ExecuteProgram(builderOrError, "Compiler" + Path.DirectorySeparatorChar + "Compiler.csproj"))
            {
                Console.WriteLine("error!");
                Console.WriteLine("Unable to build the JSIL compiler.  This may be caused by an ");
                Console.WriteLine("incompatible change made in the upstream codebase.  Things you ");
                Console.WriteLine("can try:");
                Console.WriteLine();
                Console.WriteLine(" 1) Make sure you have the latest version of Protobuild");
                Console.WriteLine(" 2) If the problem still persists, file an issue at");
                Console.WriteLine("    https://github.com/hach-que/Protobuild/issues");
                Console.WriteLine("    with a copy of the above output.");
                Console.WriteLine();
                Console.WriteLine("=============================================================");
                jsilDirectory    = null;
                jsilCompilerFile = null;
                return(false);
            }

            Console.WriteLine("Copying resulting binaries... ");
            foreach (var file in new DirectoryInfo(Path.Combine(this.GetJSILSourceDirectory(), "bin")).GetFiles())
            {
                Console.WriteLine("> " + file.Name);
                file.CopyTo(Path.Combine(this.GetJSILRuntimeDirectory(), file.Name));
            }

            Console.WriteLine("done.");

            Console.WriteLine("Creating runtime libraries... ");
            Directory.CreateDirectory(Path.Combine(this.GetJSILRuntimeDirectory(), "Libraries"));
            Console.WriteLine("done.");

            Console.WriteLine("Copying runtime libraries... ");
            this.RecursiveCopy(
                Path.Combine(this.GetJSILSourceDirectory(), "Libraries"),
                Path.Combine(this.GetJSILRuntimeDirectory(), "Libraries"));
            Console.WriteLine("done.");

            Console.Write("Removing temporary build directory... ");
            try
            {
                PathUtils.AggressiveDirectoryDelete(this.GetJSILSourceDirectory());
            }
            catch (UnauthorizedAccessException)
            {
                // Ignore
            }

            Console.WriteLine("done.");

            if (File.Exists(this.GetJSILCompilerPath()))
            {
                jsilDirectory    = this.GetJSILRuntimeDirectory();
                jsilCompilerFile = this.GetJSILCompilerPath();
                return(true);
            }
            else
            {
                Console.WriteLine("error.");
                Console.WriteLine("The build did not result in a JSILc.exe file being present ");
                Console.WriteLine("at: " + this.GetJSILCompilerPath());
                Console.WriteLine();
                Console.WriteLine("=============================================================");
                jsilDirectory    = null;
                jsilCompilerFile = null;
                return(false);
            }
        }
Пример #15
0
        private void InstallToolIntoUserApplicationFolder(string toolName, string toolPath)
        {
            var appToolPath = toolPath.Replace(".exe", ".app");

            if (!Directory.Exists(appToolPath))
            {
                return;
            }

            var basename        = Path.GetFileName(appToolPath);
            var applicationPath = Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder.UserProfile),
                "Applications");

            Directory.CreateDirectory(applicationPath);
            var installPath = Path.Combine(applicationPath, basename);

            try
            {
                var stat = System.Diagnostics.Process.Start(new ProcessStartInfo
                {
                    FileName               = "/usr/bin/stat",
                    Arguments              = "-f %T '" + installPath + "'",
                    UseShellExecute        = false,
                    CreateNoWindow         = true,
                    RedirectStandardOutput = true
                });
                var type = stat.StandardOutput.ReadToEnd().Trim();
                if (type == "@")
                {
                    // The file is a symbolic link.
                    File.Delete(installPath);
                }
                else
                {
                    if (Directory.Exists(installPath))
                    {
                        // Recursive delete.
                        PathUtils.AggressiveDirectoryDelete(installPath);
                    }
                    else
                    {
                        File.Delete(installPath);
                    }
                }
            }
            catch
            {
            }

            // Make sure we don't create a symbolic link inside a symbolically linked directory.
            if (!File.Exists(installPath) && !Directory.Exists(installPath))
            {
                var install = System.Diagnostics.Process.Start("ln", "-s '" + appToolPath + "' '" + installPath + "'");
                if (install != null)
                {
                    install.WaitForExit();

                    RedirectableConsole.WriteLine("Global tool '" + toolName + "' is now available in the application menu");
                }
                else
                {
                    RedirectableConsole.WriteLine("Unable to install global tool '" + toolName + "' into the application menu (unable to create link)");
                }
            }
        }
Пример #16
0
 private void EmptyReferenceFolder(string folder)
 {
     PathUtils.AggressiveDirectoryDelete(folder);
 }