Пример #1
0
        public IPackageContent GetSourcePackage(string url, string gitHash)
        {
            var sourceName = Path.Combine(
                _packageCacheConfiguration.GetCacheDirectory(),
                this.GetPackageName(url, string.Empty, "Source", string.Empty));

            if (this.HasSourcePackage(url, gitHash))
            {
                try
                {
                    GitUtils.RunGitAbsolute(sourceName, "fetch origin +refs/heads/*:refs/heads/*");
                }
                catch (InvalidOperationException)
                {
                    // Ignore exceptions here in case the user is offline.
                }

                return(new SourcePackageContent(this)
                {
                    SourcePath = sourceName,
                    GitRef = gitHash,
                    OriginalGitUri = url,
                });
            }

            Directory.CreateDirectory(sourceName);
            GitUtils.RunGit(null, "clone --bare " + url + " " + sourceName);

            return(new SourcePackageContent(this)
            {
                SourcePath = sourceName,
                GitRef = gitHash,
                OriginalGitUri = url,
            });
        }
Пример #2
0
        private static string GetGitExcludePath(string folder)
        {
            var root = GitUtils.GetGitRootPath(folder);

            if (root == null)
            {
                return(null);
            }
            else
            {
                return(Path.Combine(root, ".git", "info", "exclude"));
            }
        }
Пример #3
0
        public static void MarkIgnored(string folder)
        {
            var excludePath = GitUtils.GetGitExcludePath(Path.Combine(folder, ".."));

            if (excludePath == null)
            {
                return;
            }

            var contents = GitUtils.GetFileStringList(excludePath).ToList();

            contents.Add(folder);
            GitUtils.SetFileStringList(excludePath, contents);
        }
Пример #4
0
        public void DownloadSourcePackage(string gitUrl, string targetPath)
        {
            if (Directory.Exists(targetPath))
            {
                throw new Exception("Unable to download source package; target path already exists!");
            }

            if (File.Exists(targetPath))
            {
                throw new Exception("Target path already exists (but is not a directory)");
            }

            Directory.CreateDirectory(targetPath);
            GitUtils.RunGit(targetPath, "git clone --bare " + gitUrl + " .");
        }
Пример #5
0
        private static string GetGitExcludePath(string folder)
        {
            var root = GitUtils.GetGitRootPath(folder);

            if (root == null)
            {
                return(null);
            }
            else
            {
                var path = Path.Combine(root, ".git", "info", "exclude");
                Directory.CreateDirectory(Path.GetDirectoryName(path));
                return(path);
            }
        }
Пример #6
0
        private void InitializeSubmodulesFromCache(string workingDirectory, string path)
        {
            GitUtils.RunGit(workingDirectory, path, "submodule init");
            var submodules = GitUtils.RunGitAndCapture(workingDirectory, path, "config --local --list");

            foreach (Match match in new Regex(@"submodule\.(?<name>.*)\.url=(?<url>.*)").Matches(submodules))
            {
                var name = match.Groups["name"].Value;
                var url  = match.Groups["url"].Value;

                var submodule = GetSourcePackage(workingDirectory, url);
                GitUtils.RunGit(workingDirectory, path, "config --local submodule." + name + ".url " + submodule);
                GitUtils.RunGit(workingDirectory, path, "submodule update " + name);
                this.InitializeSubmodulesFromCache(workingDirectory, Path.Combine(path ?? "", name));
                GitUtils.RunGit(workingDirectory, path, "config --local submodule." + name + ".url " + url);
            }
        }
Пример #7
0
        private void ExtractGitSourceTo(string workingDirectory, string sourcePath, string gitRef, string path)
        {
            // FIXME: This assumes packages are being extracted underneath the current
            // working directory (i.e. the module root).
            if (GitUtils.IsGitRepository())
            {
                GitUtils.UnmarkIgnored(path);
            }

            GitUtils.RunGit(workingDirectory, null, "clone --progress " + sourcePath + " \"" + path + "\"");
            GitUtils.RunGit(workingDirectory, path, "checkout -f " + gitRef);
            this.InitializeSubmodulesFromCache(workingDirectory, path);

            if (GitUtils.IsGitRepository())
            {
                GitUtils.MarkIgnored(path);
            }
        }
Пример #8
0
        public void ExtractTo(string path)
        {
            // FIXME: This assumes packages are being extracted underneath the current
            // working directory (i.e. the module root).
            if (GitUtils.IsGitRepository())
            {
                GitUtils.UnmarkIgnored(path);
            }

            GitUtils.RunGit(null, "clone " + this.SourcePath + " " + path);
            GitUtils.RunGit(path, "checkout -f " + this.GitRef);
            this.InitializeSubmodulesFromCache(path);

            if (GitUtils.IsGitRepository())
            {
                GitUtils.MarkIgnored(path);
            }
        }
Пример #9
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);
        }
Пример #10
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");
        }
Пример #11
0
        public int Execute(object handle)
        {
            var instructions = (List <ParsedInstruction>)handle;

            var protobuild       = Assembly.GetEntryAssembly().Location;
            var workingDirectory = _workingDirectoryProvider.GetPath();

            var    targets              = string.Empty;
            var    buildTarget          = string.Empty;
            var    buildProcessArch     = string.Empty;
            var    buildProperties      = new Dictionary <string, string>();
            string executeConfiguration = null;

            var predicates = new Stack <ParsedInstruction>();

            foreach (var inst in instructions)
            {
                if (inst.Predicate != null)
                {
                    predicates.Push(inst);
                }
                else if (inst.EndPredicate)
                {
                    predicates.Pop();
                }
                else if (predicates.All(x => x.Predicate()))
                {
                    if (inst.Command == "native-execute")
                    {
                        var components = inst.Arguments.Split(new[] { ' ' }, 2);

                        string path;
                        try
                        {
                            path = FindNativeProgram(components[0]);
                        }
                        catch (ApplicationException ex)
                        {
                            Console.Error.WriteLine(ex);
                            return(1);
                        }

                        var args = components.Length == 2 ? components[1] : string.Empty;

                        Console.WriteLine("+ native-execute " + path + " " + args);
                        var process =
                            Process.Start(new ProcessStartInfo(path, args)
                        {
                            WorkingDirectory = workingDirectory,
                            UseShellExecute  = false
                        });
                        if (process == null)
                        {
                            Console.Error.WriteLine("ERROR: Process did not start when running " + path + " " +
                                                    args);
                            return(1);
                        }
                        process.WaitForExit();
                        if (process.ExitCode != 0)
                        {
                            Console.Error.WriteLine(
                                "ERROR: Non-zero exit code " + process.ExitCode);
                            return(process.ExitCode);
                        }
                    }
                    else if (inst.Command == "nuget")
                    {
                        // See if we have a copy of NuGet available for use.
                        var cachedNuget =
                            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                                         "NuGet.exe");
                        if (!File.Exists(cachedNuget))
                        {
                            var client = new RetryableWebClient();
                            client.DownloadFile("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", cachedNuget);
                        }

                        string runtime      = null;
                        var    hostPlatform = _hostPlatformDetector.DetectPlatform();
                        if (hostPlatform != "Windows")
                        {
                            try
                            {
                                runtime = FindNativeProgram("mono");
                            }
                            catch (ApplicationException ex)
                            {
                                Console.Error.WriteLine(ex);
                                return(1);
                            }
                        }

                        Process process;

                        if (hostPlatform != "Windows" && runtime != null)
                        {
                            Console.WriteLine("+ " + runtime + " \"" + cachedNuget + "\" " + inst.Arguments);
                            process =
                                Process.Start(new ProcessStartInfo(runtime, "\"" + cachedNuget + "\" " + inst.Arguments)
                            {
                                WorkingDirectory = workingDirectory,
                                UseShellExecute  = false
                            });
                        }
                        else
                        {
                            Console.WriteLine("+ " + cachedNuget + " " + inst.Arguments);
                            process =
                                Process.Start(new ProcessStartInfo(cachedNuget, inst.Arguments)
                            {
                                WorkingDirectory = workingDirectory,
                                UseShellExecute  = false
                            });
                        }

                        if (process == null)
                        {
                            Console.Error.WriteLine(
                                "ERROR: Process did not start when running NuGet with arguments " + inst.Arguments);
                            return(1);
                        }
                        process.WaitForExit();
                        if (process.ExitCode != 0)
                        {
                            Console.Error.WriteLine(
                                "ERROR: Non-zero exit code " + process.ExitCode);
                            return(process.ExitCode);
                        }
                    }
                    else if (inst.Command != null)
                    {
                        var args = string.Empty;
                        switch (inst.Command)
                        {
                        case "execute":
                            if (executeConfiguration != null)
                            {
                                args = "--execute-configuration " + executeConfiguration + " --" + inst.Command +
                                       " " + inst.Arguments;
                            }
                            else
                            {
                                args = "--" + inst.Command + " " + inst.Arguments;
                            }
                            break;

                        case "build":
                            args = "--" + inst.Command + " " + targets + " ";

                            if (buildTarget != string.Empty)
                            {
                                args += "--build-target " + buildTarget + " ";
                            }

                            if (buildProcessArch != string.Empty)
                            {
                                args += "--build-process-arch " + buildProcessArch + " ";
                            }

                            args = buildProperties.Aggregate(args,
                                                             (current, prop) =>
                                                             current + ("--build-property " + prop.Key + " " + prop.Value + " "));
                            args += " " + inst.Arguments;
                            break;

                        case "pack":
                        case "push":
                        case "repush":
                            args = "--" + inst.Command + " " + inst.Arguments;
                            break;

                        default:
                            args = "--" + inst.Command + " " + targets + " " + inst.Arguments;
                            break;
                        }

                        var runSets = new List <string>();
                        if (args.Contains("$TARGET_PLATFORM"))
                        {
                            var targetsSplit = targets.Split(',');
                            if (targetsSplit.Length < 1 || string.IsNullOrWhiteSpace(targetsSplit[0]))
                            {
                                runSets.Add(_hostPlatformDetector.DetectPlatform());
                            }
                            else
                            {
                                runSets.AddRange(targetsSplit);
                            }
                        }
                        else
                        {
                            runSets.Add(_hostPlatformDetector.DetectPlatform());
                        }

                        if (args.Contains("$GIT_COMMIT") || args.Contains("$GIT_BRANCH"))
                        {
                            string commit;
                            string branch;

                            try
                            {
                                Console.WriteLine("+ git rev-parse HEAD");
                                commit = GitUtils.RunGitAndCapture(workingDirectory, "rev-parse HEAD").Trim();

                                try
                                {
                                    Console.WriteLine("+ git show-ref --heads");
                                    var branchesText = GitUtils.RunGitAndCapture(workingDirectory, "show-ref --heads");
                                    var branches     = branchesText.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries);
                                    var branchRaw    = branches.FirstOrDefault(x => x.StartsWith(commit, StringComparison.Ordinal));
                                    branch = string.Empty;
                                    if (branchRaw != null)
                                    {
                                        var branchComponents = branchRaw.Trim().Split(' ');
                                        if (branchComponents.Length >= 2)
                                        {
                                            if (branchComponents[1].StartsWith("refs/heads/", StringComparison.Ordinal))
                                            {
                                                branch = branchComponents[1].Substring("refs/heads/".Length);
                                            }
                                        }
                                    }
                                }
                                catch (InvalidOperationException)
                                {
                                    branch = string.Empty;
                                }
                            }
                            catch (InvalidOperationException)
                            {
                                commit = string.Empty;
                                branch = string.Empty;
                            }

                            args = args.Replace("$GIT_COMMIT", commit);
                            args = args.Replace("$GIT_BRANCH", branch);
                        }

                        string runtime      = null;
                        var    hostPlatform = _hostPlatformDetector.DetectPlatform();
                        if (hostPlatform != "Windows")
                        {
                            try
                            {
                                runtime = FindNativeProgram("mono");
                            }
                            catch (ApplicationException ex)
                            {
                                Console.Error.WriteLine(ex);
                                return(1);
                            }
                        }

                        foreach (var run in runSets)
                        {
                            var runArgs = args
                                          .Replace("$TARGET_PLATFORM", run);

                            Process process;

                            if (hostPlatform != "Windows" && runtime != null)
                            {
                                Console.WriteLine("+ " + runtime + " \"" + protobuild + "\" " + runArgs);
                                process =
                                    Process.Start(new ProcessStartInfo(runtime, "\"" + protobuild + "\" " + runArgs)
                                {
                                    WorkingDirectory = workingDirectory,
                                    UseShellExecute  = false
                                });
                            }
                            else
                            {
                                Console.WriteLine("+ " + protobuild + " " + runArgs);
                                process =
                                    Process.Start(new ProcessStartInfo(protobuild, runArgs)
                                {
                                    WorkingDirectory = workingDirectory,
                                    UseShellExecute  = false
                                });
                            }

                            if (process == null)
                            {
                                Console.Error.WriteLine(
                                    "ERROR: Process did not start when running Protobuild with arguments " + args);
                                return(1);
                            }
                            process.WaitForExit();
                            if (process.ExitCode != 0)
                            {
                                Console.Error.WriteLine(
                                    "ERROR: Non-zero exit code " + process.ExitCode);
                                return(process.ExitCode);
                            }
                        }
                    }
                    else if (inst.Key != null)
                    {
                        Console.WriteLine("+ set " + inst.Key + " -> " + inst.Values.Aggregate((a, b) => a + ", " + b));
                        switch (inst.Key)
                        {
                        case "target-platforms":
                            targets = inst.Values.Aggregate((a, b) => a + "," + b);
                            break;

                        case "build-target":
                            buildTarget = inst.Values.First();
                            break;

                        case "build-process-arch":
                            buildProcessArch = inst.Values.First();
                            break;

                        case "build-property":
                            buildProperties.Add(inst.Values[0],
                                                inst.Values.Length >= 2 ? inst.Values[1] : string.Empty);
                            break;

                        case "execute-configuration":
                            executeConfiguration = inst.Values.First();
                            break;
                        }
                    }
                    else if (inst.Echo != null)
                    {
                        Console.WriteLine(inst.Echo);
                    }
                }
            }

            Console.WriteLine("Automated build script completed successfully.");
            return(0);
        }
Пример #12
0
        private void ResolveLibraryBinary(PackageRef reference, string platform, string source, bool forceUpgrade)
        {
            if (File.Exists(Path.Combine(reference.Folder, platform, ".pkg")))
            {
                if (!forceUpgrade)
                {
                    Console.WriteLine("Protobuild binary package already present at " + Path.Combine(reference.Folder, platform));
                    return;
                }
            }

            var folder = Path.Combine(reference.Folder, platform);

            Console.WriteLine("Creating and emptying " + folder);

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

            Directory.CreateDirectory(folder);

            Console.WriteLine("Marking " + reference.Folder + " as ignored for Git");
            GitUtils.MarkIgnored(reference.Folder);

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

            if (package == null)
            {
                this.ResolveLibrarySource(reference, source, forceUpgrade);
                return;
            }

            package.ExtractTo(folder);

            // 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(folder, "Build", "Projects")) &&
                File.Exists(Path.Combine(folder, "Build", "Module.xml")))
            {
                var sourceProtobuild = Assembly.GetEntryAssembly().Location;
                File.Copy(sourceProtobuild, Path.Combine(folder, "Protobuild.exe"), true);

                try
                {
                    var chmodStartInfo = new ProcessStartInfo
                    {
                        FileName         = "chmod",
                        Arguments        = "a+x Protobuild.exe",
                        WorkingDirectory = folder,
                        CreateNoWindow   = true,
                        UseShellExecute  = false
                    };
                    Process.Start(chmodStartInfo);
                }
                catch (ExecEnvironment.SelfInvokeExitException)
                {
                    throw;
                }
                catch
                {
                }
            }

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

            file.Close();

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

            Console.WriteLine("Binary resolution complete");
        }