[xa-prep-tasks] Improve <DownloadUri/> behavior (#302)

The `<DownloadUri/>` Task had two problems:

1. It used `HttpClient.GetAsync()`, not `HttpClient.GetStreamAsync()`.
    It *looks* like a minor difference, but the former would
    apparently attempt to store the *entire* source URI contents
    *in memory*, which would fail if the URI contents are "big".

2. Exceptions leaving `Task.Execute()` are "uglier" than exceptions
    logged via `TaskLoggingHelper.LogErrorFromException()`.

Improve the `<DownloadUri/>` task so that
`HttpClient.GetStreamAsync()` is used, removing the "download to
in-memory" behavior, and use
`TaskLoggingHelper.LogErrorFromException()` so that error messages are
nicer.

Additionally, `xa-prep-tasks.targets`
*wasn't supposed to surface errors* from the `_DownloadBundle` target.
The bundle which is downloaded *may not exist*. The build shouldn't
fail if the specified URI can't be found.

What's odd is that this *used* to work for me, in that if the target
URI -- the bundle -- didn't exist, `<DownloadTask/>` wouldn't report
an error, and execution would continue.

I suspect, but have not tested or verified, that Azure had changed
it's handling here: previously, it would return an XML document
containing a "404" error, even when the URL didn't exist.
This is *still the case* now [^0], so I'm not sure why I was *ever*
getting an error in the first place! (Very odd...)

"Sanitize" the behavior here: since the `_DownloadBundle` task can be
expected to "fail" -- in that the target URI may not exist, even if
Azure/etc. doesn't give a 404 for it -- then the `<DownloadUri/>` task
invocation should contain a `ContinueOnError="True"` attribute so that
errors are ignored.

Additionally, there is no need for the `_ExtractBundle` target to
execute unless the downloaded file exists, so make `_ExtractBundle`
conditional on the file existing, and update the
`_DownloadAndExtractBundle` target so that it explicitly orders the
dependent targets, so that `_ExtractBundle` doesn't need to depend on
the `_DownloadBundle` target.

[^0]: For example:

    $ curl -o x.txt https://xamjenkinsartifact.blob.core.windows.net/xamarin-android/xamarin-android/bin/does-not-exist
    $ $ cat x.txt
    <?xml version="1.0" encoding="utf-8"?><Error><Code>BlobNotFound</Code><Message>The specified blob does not exist.
    RequestId:d54a8d4a-0001-007d-1a0e-415487000000
    Time:2016-11-17T20:12:32.8482654Z</Message></Error>
This commit is contained in:
Jonathan Pryor 2016-11-18 09:49:08 -05:00 коммит произвёл Dean Ellis
Родитель 94b3f706a8
Коммит cfb82e4378
2 изменённых файлов: 14 добавлений и 8 удалений

Просмотреть файл

@ -62,13 +62,18 @@ namespace Xamarin.Android.BuildTools.PrepTasks {
var dn = Path.GetFileName (destinationFile);
var tempPath = Path.Combine (dp, "." + dn + ".download");
Log.LogMessage (MessageImportance.Low, $"Downloading `{uri}` to `{tempPath}`.");
using (var r = await client.GetAsync (uri))
using (var o = File.OpenWrite (tempPath)) {
await r.Content.CopyToAsync (o);
Log.LogMessage (MessageImportance.Normal, $"Downloading `{uri}` to `{tempPath}`.");
try {
using (var s = await client.GetStreamAsync (uri))
using (var o = File.OpenWrite (tempPath)) {
await s.CopyToAsync (o);
}
Log.LogMessage (MessageImportance.Low, $"mv '{tempPath}' '{destinationFile}'.");
File.Move (tempPath, destinationFile);
}
catch (Exception e) {
Log.LogErrorFromException (e);
}
Log.LogMessage (MessageImportance.Low, $"mv '{tempPath}' '{destinationFile}'.");
File.Move (tempPath, destinationFile);
}
}
}

Просмотреть файл

@ -17,12 +17,13 @@
Inputs=""
Outputs="$(_BundlePath)">
<DownloadUri
ContinueOnError="True"
SourceUris="$(_AzureBaseUri)$(Configuration)/$(XABundleFileName)"
DestinationFiles="$(_BundlePath)"
/>
</Target>
<Target Name="_ExtractBundle"
DependsOnTargets="_DownloadBundle"
Condition=" Exists('$(_BundlePath)') "
Inputs="$(_BundlePath)"
Outputs="$(OutputPath).extracted-$(XABundleFileName)">
<SystemUnzip
@ -38,6 +39,6 @@
</Target>
<Target Name="_DownloadAndExtractBundle"
AfterTargets="Build"
DependsOnTargets="_ExtractBundle">
DependsOnTargets="_GetBundleOutputPath;_DownloadBundle;_ExtractBundle">
</Target>
</Project>