Skip to content

Commit

Permalink
Supports downloading multiple files with curl
Browse files Browse the repository at this point in the history
  • Loading branch information
ecampidoglio committed Jan 8, 2017
1 parent 360e0ee commit 9f07228
Show file tree
Hide file tree
Showing 6 changed files with 463 additions and 1 deletion.
219 changes: 219 additions & 0 deletions src/Cake.Curl.Tests/CurlDownloadMultipleFilesTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
using System;
using Cake.Core;
using Cake.Core.IO;
using Cake.Curl.Tests.Fixtures;
using Cake.Testing;
using Xunit;

namespace Cake.Curl.Tests
{
public sealed class CurlDownloadMultipleFilesTests
{
public sealed class TheExecutable
{
[Fact]
public void Should_Throw_If_Hosts_Is_Null()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture();
fixture.Hosts = null;

// When
var result = Record.Exception(() => fixture.Run());

// Then
Assert.IsType<ArgumentNullException>(result);
Assert.Equal("hosts", ((ArgumentNullException)result).ParamName);
}

[Fact]
public void Should_Throw_If_Hosts_Is_Empty()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture();
fixture.Hosts = new Uri[0];

// When
var result = Record.Exception(() => fixture.Run());

// Then
Assert.IsType<ArgumentException>(result);
Assert.Equal("hosts", ((ArgumentException)result).ParamName);
Assert.Contains("Hosts cannot be empty", ((ArgumentException)result).Message);
}

[Fact]
public void Should_Throw_If_Settings_Is_Null()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture();
fixture.Settings = null;

// When
var result = Record.Exception(() => fixture.Run());

// Then
Assert.IsType<ArgumentNullException>(result);
Assert.Equal("settings", ((ArgumentNullException)result).ParamName);
}

[Fact]
public void Should_Throw_If_Curl_Executable_Was_Not_Found()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture();
fixture.GivenDefaultToolDoNotExist();

// When
var result = Record.Exception(() => fixture.Run());

// Then
Assert.IsType<CakeException>(result);
Assert.Equal("curl: Could not locate executable.", result.Message);
}

[Theory]
[InlineData("/bin/curl", "/bin/curl")]
[InlineData("./tools/curl", "/Working/tools/curl")]
public void Should_Use_Curl_Runner_From_Tool_Path_If_Provided(
string toolPath,
string expected)
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture
{
Settings = { ToolPath = toolPath }
};
fixture.GivenSettingsToolPathExist();

// When
var result = fixture.Run();

// Then
Assert.Equal(expected, result.Path.FullPath);
}

#if NETFX
[Theory]
[InlineData(@"C:\bin\curl.exe", "C:/bin/curl.exe")]
[InlineData(@".\tools\curl.exe", "/Working/tools/curl.exe")]
public void Should_Use_Curl_Runner_From_Tool_Path_If_Provided_On_Windows(
string toolPath,
string expected)
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture
{
Settings = { ToolPath = toolPath }
};
fixture.GivenSettingsToolPathExist();

// When
var result = fixture.Run();

// Then
Assert.Equal(expected, result.Path.FullPath);
}
#endif

[Fact]
public void Should_Find_Curl_Runner_If_Tool_Path_Not_Provided()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture();

// When
var result = fixture.Run();

// Then
Assert.Equal("/Working/tools/curl", result.Path.FullPath);
}

[Fact]
public void Should_Set_The_Remote_Name_Switches_And_The_Urls_Of_The_Hosts_As_Arguments()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture
{
Hosts = new[]
{
new Uri("protocol://host/path"),
new Uri("protocol://anotherhost/path")
}
};

// When
var result = fixture.Run();

// Then
Assert.Contains("-O protocol://host/path", result.Args);
Assert.Contains("-O protocol://anotherhost/path", result.Args);
}

[Fact]
public void Should_Set_The_Absolute_Output_File_Paths_In_Quotes_And_The_Urls_Of_The_Hosts_As_Arguments()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture
{
Hosts = new[]
{
new Uri("protocol://host/path"),
new Uri("protocol://anotherhost/path")
},
Settings =
{
OutputPaths = new FilePath[]
{
"output/file",
"output/anotherfile"
}
}
};

// When
var result = fixture.Run();

// Then
Assert.Contains(
"-o \"/Working/output/file\" protocol://host/path",
result.Args);
Assert.Contains(
"-o \"/Working/output/anotherfile\" protocol://anotherhost/path",
result.Args);
}

[Fact]
public void Should_Set_The_User_Credentials_In_Quotes_As_Argument()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture
{
Settings = { Username = "user", Password = "password" }
};

// When
var result = fixture.Run();

// Then
Assert.Contains("--user \"user:password\"", result.Args);
}

[Fact]
public void Should_Not_Set_The_User_Credentials_As_Argument_If_Username_Is_Null()
{
// Given
var fixture = new CurlDownloadMultipleFilesFixture
{
Settings = { Username = null, Password = "password" }
};

// When
var result = fixture.Run();

// Then
Assert.DoesNotContain($"--user", result.Args);
}
}
}
}
32 changes: 32 additions & 0 deletions src/Cake.Curl.Tests/Fixtures/CurlDownloadMultipleFilesFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;
using Cake.Testing.Fixtures;

namespace Cake.Curl.Tests.Fixtures
{
internal sealed class CurlDownloadMultipleFilesFixture
: ToolFixture<CurlDownloadSettings>
{
public CurlDownloadMultipleFilesFixture()
: base("curl")
{
Hosts = new[]
{
new Uri("protocol://host/path"),
new Uri("protocol://anotherhost/path")
};
}

public IEnumerable<Uri> Hosts { get; set; }

protected override void RunTool()
{
var tool = new CurlDownloadRunner(
FileSystem,
Environment,
ProcessRunner,
Tools);
tool.DownloadFiles(Hosts, Settings);
}
}
}
72 changes: 72 additions & 0 deletions src/Cake.Curl/CurlAliases.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Cake.Core;
using Cake.Core.Annotations;
using Cake.Core.IO;
Expand All @@ -23,6 +24,77 @@ namespace Cake.Curl
[CakeAliasCategory("Curl")]
public static class CurlAliases
{
/// <summary>
/// Downloads the files from the specified remote URLs to the working directory.
/// </summary>
/// <param name="context">The Cake context.</param>
/// <param name="hosts">The URLs of the files to download.</param>
/// <example>
/// <code>
/// CurlDownloadFiles(new Uri[]
/// {
/// new Uri("http://host/file"),
/// new Uri("http://host/anotherfile")
/// });
/// </code>
/// </example>
[CakeMethodAlias]
public static void CurlDownloadFiles(
this ICakeContext context,
IEnumerable<Uri> hosts)
{
CurlDownloadFiles(context, hosts, new CurlDownloadSettings());
}

/// <summary>
/// Downloads the files from the specified remote URLs.
/// </summary>
/// <remarks>
/// By default, curl is going to download the files to the working directory
/// using the same names as on the remote host.
/// If you want to put the files into a different directory, you can set the
/// <see cref="P:CurlDownloadSettings.WorkingDirectory"/> property accordingly.
/// If you want to rename the downloaded files, you can do so by specifying the
/// output paths for each of the files at the remote URLs in the
/// <see cref="P:CurlDownloadSettings.OutputPaths"/> property.
/// In that case, the order of the output paths is going to be matched with
/// the order of the remote URLs.
/// </remarks>
/// <param name="context">The Cake context.</param>
/// <param name="hosts">The URLs of the files to download.</param>
/// <param name="settings">The settings.</param>
/// <example>
/// <code>
/// CurlDownloadFiles(
/// new Uri[]
/// {
/// new Uri("http://host/file"),
/// new Uri("http://host/anotherfile")
/// },
/// new CurlDownloadSettings
/// {
/// OutputPaths = new FilePath[]
/// {
/// "output/path",
/// "another/output/path"
/// }
/// });
/// </code>
/// </example>
[CakeMethodAlias]
public static void CurlDownloadFiles(
this ICakeContext context,
IEnumerable<Uri> hosts,
CurlDownloadSettings settings)
{
var runner = new CurlDownloadRunner(
context.FileSystem,
context.Environment,
context.ProcessRunner,
context.Tools);
runner.DownloadFiles(hosts, settings);
}

/// <summary>
/// Uploads the specified file to a remote host using the specified URL.
/// </summary>
Expand Down
Loading

0 comments on commit 9f07228

Please # to comment.