diff --git a/Bindle.Tests/Integration.cs b/Bindle.Tests/Integration.cs index 0401e03..4c8da92 100644 --- a/Bindle.Tests/Integration.cs +++ b/Bindle.Tests/Integration.cs @@ -129,5 +129,14 @@ public async Task CanCreateParcel() var fetched = await client.GetParcel("mybindle/0.1.0", "460d5965e4d1909e8c7a3748a414956b7038ab5fd79937c9fcb2b214e6b0160a"); Assert.Equal("The front fell off", await fetched.ReadAsStringAsync()); } + + [Fact] + public async Task CanListMissingParcels() + { + var client = new BindleClient(DEMO_SERVER_URL); + var missing = await client.ListMissingParcels("mybindle/0.3.0"); + Assert.Contains(missing, (label) => label.Sha256 == "e1706ab0a39ac88094b6d54a3f5cdba41fe5a901"); + Assert.DoesNotContain(missing, (label) => label.Sha256 == "f7f3b33707fb76d208f5839a40e770452dcf9f348bfd7faf2c524e0fa6710ed6"); + } } } diff --git a/Bindle/BindleClient.cs b/Bindle/BindleClient.cs index b2176c8..000cbb9 100644 --- a/Bindle/BindleClient.cs +++ b/Bindle/BindleClient.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -18,6 +19,9 @@ string baseUri } private const string INVOICE_PATH = "_i"; + private const string QUERY_PATH = "_q"; + private const string RELATIONSHIP_PATH = "_r"; + private readonly Uri _baseUri; public async Task GetInvoice(string invoiceId, GetInvoiceOptions options = GetInvoiceOptions.None) @@ -113,6 +117,23 @@ public async Task CreateParcel(string invoiceId, string parcelId, HttpContent co await httpClient.PostAsync(uri, content); } + public async Task> ListMissingParcels(string invoiceId) + { + var httpClient = new HttpClient(); + var uri = new Uri(_baseUri, $"{RELATIONSHIP_PATH}/missing/{invoiceId}"); + var response = await httpClient.GetAsync(uri); + if (response == null) + { + throw new Exception("No response from Bindle server"); + } + if (response.StatusCode != HttpStatusCode.OK) + { + throw new System.Net.WebException($"Bindle server returned status code {response.StatusCode}"); + } + var toml = await ReadResponseToml(response); + return Parser.ParseMissingLabels(toml); + } + private static string SlashSafe(string uri) { if (uri.EndsWith('/')) diff --git a/Bindle/Parser.cs b/Bindle/Parser.cs index 73e0ab0..7ed0910 100644 --- a/Bindle/Parser.cs +++ b/Bindle/Parser.cs @@ -137,6 +137,11 @@ internal static CreateInvoiceResult ParseCreateInvoiceResult(TomlTable toml) var missingParcels = (toml.TryGetTomlTables("missing") ?? new TomlTable[0]).Select(ParseLabel); return new CreateInvoiceResult(invoice, missingParcels); } + + internal static IEnumerable