public async Task <List <(string fullFilePath, string fileContent)> > GetMultipleFileContentsAsync(string repositoryOwner, string repositoryName, string gitRef, List <string> fullFilePaths) { var tupleList = new List <(string fullFilePath, string fileContent)>(); var fileContentRequestBuilder = new StringBuilder(); // Build up the list of file content requests. This is needed because GraphQl does not allow // the returning of multiple nodes of the same name. This loop builds up the file request json // aliases on these nodes for (int i = 0; i < fullFilePaths.Count; i++) { var fileContentRequestJson = GetFileContentRequestJson(i + 1, fullFilePaths[i]); fileContentRequestBuilder.Append(fileContentRequestJson); } var query = $@" query ($repoName:String!, $repoOwner:String!){{ repository(name:$repoName, owner: $repoOwner) {{ {fileContentRequestBuilder.ToString()} }} }} "; var variables = new { repoOwner = repositoryOwner, repoName = repositoryName }; var responseBodyString = await graphQLClient.QueryAsync(query, variables).ConfigureAwait(false); var jObject = JObject.Parse(responseBodyString); // Parse the aliased file for (int i = 0; i < fullFilePaths.Count; i++) { var fileJObject = jObject["data"]["repository"][$"file{i + 1}"]; if (fileJObject.HasValues) { var fileContent = fileJObject["text"].Value <string>(); tupleList.Add((fullFilePaths[i], fileContent)); } else { throw new ArgumentException($"File {fullFilePaths[i]} not found when reading file contents for repo {repositoryName}. " + $"This is likely the result of a stale file list cache for the repository"); } } return(tupleList); string GetFileContentRequestJson(int index, string fullFilePath) { return($@" file{index}: object(expression: ""{gitRef}:{fullFilePath}"") {{ ...on Blob {{ text }} }} "); } }