public async Task <List <Build> > ListBuildsAsync(string buildQuery) { var optionSet = new BuildSearchOptionSet(); if (optionSet.Parse(buildQuery.Split(' ', StringSplitOptions.RemoveEmptyEntries)).Count != 0) { throw CreateBadOptionException(); } return(await ListBuildsAsync(optionSet).ConfigureAwait(false)); }
public static bool TryGetBuildId(BuildSearchOptionSet optionSet, string build, [NotNullWhen(true)] out string?project, out int buildId) { var defaultProject = optionSet.Project ?? BuildSearchOptionSet.DefaultProject; return(TryGetBuildId(build, defaultProject, out project, out buildId)); }
public async Task <List <Build> > ListBuildsAsync(BuildSearchOptionSet optionSet) { if (optionSet.BuildIds.Count > 0 && optionSet.Definitions.Count > 0) { OptionFailure("Cannot specify builds and definitions", optionSet); throw CreateBadOptionException(); } var project = optionSet.Project ?? BuildSearchOptionSet.DefaultProject; var searchCount = optionSet.SearchCount ?? BuildSearchOptionSet.DefaultSearchCount; var repository = optionSet.Repository; var branch = optionSet.Branch; var before = optionSet.Before; var after = optionSet.After; if (branch is object && !branch.StartsWith("refs")) { branch = $"refs/heads/{branch}"; } var builds = new List <Build>(); if (optionSet.BuildIds.Count > 0) { if (optionSet.Repository is object) { OptionFailure("Cannot specify builds and repository", optionSet); throw CreateBadOptionException(); } if (optionSet.Branch is object) { OptionFailure("Cannot specify builds and branch", optionSet); throw CreateBadOptionException(); } if (optionSet.SearchCount is object) { OptionFailure("Cannot specify builds and count", optionSet); throw CreateBadOptionException(); } foreach (var buildInfo in optionSet.BuildIds) { if (!TryGetBuildId(optionSet, buildInfo, out var buildProject, out var buildId)) { OptionFailure($"Cannot convert {buildInfo} to build id", optionSet); throw CreateBadOptionException(); } var build = await Server.GetBuildAsync(buildProject, buildId).ConfigureAwait(false); builds.Add(build); } } else if (optionSet.Definitions.Count > 0) { foreach (var definition in optionSet.Definitions) { if (!DotNetUtil.TryGetDefinitionId(definition, defaultProject: project, out var definitionProject, out var definitionId)) { OptionFailureDefinition(definition, optionSet); throw CreateBadOptionException(); } definitionProject ??= project; var collection = await ListBuildsAsync( definitionProject, searchCount, definitions : new[] { definitionId }, repositoryId : repository, branchName : branch, includePullRequests : optionSet.IncludePullRequests); builds.AddRange(collection); } } else { var collection = await ListBuildsAsync( project, searchCount, definitions : null, repositoryId : repository, branchName : branch, includePullRequests : optionSet.IncludePullRequests); builds.AddRange(collection); } // Exclude out the builds that are complicating results foreach (var excludedBuildId in optionSet.ExcludedBuildIds) { builds = builds.Where(x => x.Id != excludedBuildId).ToList(); } // When doing before / after comparisons always use QueueTime. The StartTime parameter // in REST refers to when the latest build attempt started, not the original. Using that // means the jobs returned can violate the before / after constraint. The queue time is // consistent though and can be reliably used for filtering if (before.HasValue) { builds = builds.Where(b => b.GetQueueTime() is DateTimeOffset d && d <= before.Value).ToList(); } if (after.HasValue) { builds = builds.Where(b => b.GetQueueTime() is DateTimeOffset d && d >= after.Value).ToList(); } return(builds); }