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, }); }
private static string GetGitExcludePath(string folder) { var root = GitUtils.GetGitRootPath(folder); if (root == null) { return(null); } else { return(Path.Combine(root, ".git", "info", "exclude")); } }
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); }
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 + " ."); }
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); } }
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); } }
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); } }
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); } }
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); }
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"); }
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); }
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"); }