static async Task<string> getBuildScriptPath(BuildQueueItem queueItem, string target) { var filename = queueItem.BuildScriptUrl.Substring(queueItem.BuildScriptUrl.LastIndexOf('/') + 1); // If the build script is in the same repo, just return it if (GitHubUrl.NameWithOwner(queueItem.RepoUrl) == GitHubUrl.NameWithOwner(queueItem.BuildScriptUrl)) { return Path.Combine(target, Regex.Replace(queueItem.BuildScriptUrl, @".*/master/blob/", "").Replace('/', Path.DirectorySeparatorChar)); } var buildScriptPath = Path.Combine(target, filename); var wc = new WebClient(); var buildScriptUrl = queueItem.BuildScriptUrl.Replace("/blob/", "/raw/").Replace("/master/", "/" + queueItem.SHA1 + "/"); await wc.DownloadFileTaskAsync(buildScriptUrl, buildScriptPath); return buildScriptPath; }
static async Task cloneOrResetRepo(BuildQueueItem queueItem, string target, LibGit2Sharp.Repository repo, LibGit2Sharp.Credentials creds) { if (repo == null) { await Task.Run(() => { LibGit2Sharp.Repository.Clone(queueItem.RepoUrl, target, credentials: creds); repo = new LibGit2Sharp.Repository(target); }); } else { repo.Network.Fetch(repo.Network.Remotes["origin"], credentials: creds); } await Task.Run(() => { var sha = default(LibGit2Sharp.ObjectId); LibGit2Sharp.ObjectId.TryParse(queueItem.SHA1, out sha); var commit = (LibGit2Sharp.Commit)repo.Lookup(sha, LibGit2Sharp.ObjectType.Commit); if (commit == null) { throw new Exception(String.Format("Commit {0} in Repo {1} doesn't exist", queueItem.SHA1, queueItem.RepoUrl)); } repo.Reset(LibGit2Sharp.ResetOptions.Hard, commit); // NB: Unlike git clean, RemoveUntrackedFiles respects // .gitignore, we need to squelch it var gitignorePath = Path.Combine(target, ".gitignore"); if (File.Exists(gitignorePath)) { var contents = File.ReadAllBytes(gitignorePath); File.Delete(gitignorePath); repo.RemoveUntrackedFiles(); File.WriteAllBytes(gitignorePath, contents); } else { repo.RemoveUntrackedFiles(); } }); }
public async Task<int> ProcessSingleBuild(BuildQueueItem queueItem, IObserver<string> stdout = null) { var target = queueItem.GetBuildDirectory(); var repo = default(LibGit2Sharp.Repository); try { repo = new LibGit2Sharp.Repository(target); var dontcare = repo.Info.IsHeadUnborn; // NB: We just want to test if the repo is valid } catch (Exception) { repo = null; } var creds = new LibGit2Sharp.Credentials() { Username = client.Credentials.Login, Password = client.Credentials.Password }; await cloneOrResetRepo(queueItem, target, repo, creds); // XXX: This needs to be way more secure await validateBuildUrl(queueItem.BuildScriptUrl); var buildScriptPath = await getBuildScriptPath(queueItem, target); var process = new ObservableProcess(createStartInfoForScript(buildScriptPath, target)); if (stdout != null) { process.Output.Subscribe(stdout); } var exitCode = await process; if (exitCode != 0) { var ex = new Exception("Build failed with code: " + exitCode.ToString()); ex.Data["ExitCode"] = exitCode; throw ex; } return exitCode; }