Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/Sleet/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Sleet
{
public class Program
{
public static int Main(string[] args)
public static async Task<int> Main(string[] args)
{
var logLevel = Util.DefaultLogLevel;

Expand All @@ -19,8 +19,7 @@ public static int Main(string[] args)

using (var log = new ConsoleLogger(logLevel))
{
var task = MainCore(args, log);
return task.Result;
return await MainCore(args, log).ConfigureAwait(false);
}
}

Expand Down
44 changes: 28 additions & 16 deletions src/SleetLib/AssemblyVersionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,51 @@ namespace Sleet
{
public static class AssemblyVersionHelper
{
private static volatile SemanticVersion _versionOverride;
private static volatile SemanticVersion _version;
private static readonly object _lock = new object();

/// <summary>
/// Set this to override the assembly version.
/// </summary>
public static SemanticVersion VersionOverride { get; set; }

private static SemanticVersion _version;
public static SemanticVersion VersionOverride
{
get => _versionOverride;
set => _versionOverride = value;
}

/// <summary>
/// Read the assembly version or override.
/// </summary>
/// <returns></returns>
public static SemanticVersion GetVersion()
{
if (VersionOverride != null)
if (_versionOverride != null)
{
return VersionOverride;
return _versionOverride;
}

if (_version == null)
{
// Read the assembly
var assemblyVersion = typeof(AssemblyVersionHelper).GetTypeInfo().Assembly.GetName().Version;

// Avoid going lower than 3.0.0. This can happen in some build environments and will fail tests.
var lowestPossible = new SemanticVersion(3, 0, 0);
var tempVersion = new SemanticVersion(Math.Max(0, assemblyVersion.Major), Math.Max(0, assemblyVersion.Minor), Math.Max(0, assemblyVersion.Build));

if (tempVersion < lowestPossible)
lock (_lock)
{
tempVersion = lowestPossible;
if (_version == null)
{
// Read the assembly
var assemblyVersion = typeof(AssemblyVersionHelper).GetTypeInfo().Assembly.GetName().Version;

// Avoid going lower than 3.0.0. This can happen in some build environments and will fail tests.
var lowestPossible = new SemanticVersion(3, 0, 0);
var tempVersion = new SemanticVersion(Math.Max(0, assemblyVersion.Major), Math.Max(0, assemblyVersion.Minor), Math.Max(0, assemblyVersion.Build));

if (tempVersion < lowestPossible)
{
tempVersion = lowestPossible;
}

_version = tempVersion;
}
}

_version = tempVersion;
}

return _version;
Expand Down
4 changes: 2 additions & 2 deletions src/SleetLib/ExternalSearchHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ public Task UnSet()
private async Task SetSearchUri(string value)
{
var indexFile = _context.Source.Get("index.json");
var json = await indexFile.GetJson(_context.Log, _context.Token);
var json = await indexFile.GetJson(_context.Log, _context.Token).ConfigureAwait(false);
var searchEntry = GetSearchEntry(json);
searchEntry["@id"] = value;
await indexFile.Write(json, _context.Log, _context.Token);
await indexFile.Write(json, _context.Log, _context.Token).ConfigureAwait(false);
}

private JObject GetSearchEntry(JObject serviceIndex)
Expand Down
19 changes: 15 additions & 4 deletions src/SleetLib/FileSystem/AmazonS3File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
{
Stream writeStream = cache;
string contentType = null, contentEncoding = null;
bool disposeWriteStream = false;

if (key.EndsWith(".nupkg", StringComparison.Ordinal))
{
contentType = "application/zip";
Expand All @@ -121,6 +123,7 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
{
contentEncoding = "gzip";
writeStream = await JsonUtility.GZipAndMinifyAsync(cache);
disposeWriteStream = true;
}
}
else if (key.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)
Expand All @@ -141,10 +144,18 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
log.LogWarning($"Unknown file type: {absoluteUri}");
}

await UploadFileAsync(client, bucketName, key, contentType, contentEncoding, writeStream, serverSideEncryptionMethod, acl, disablePayloadSigning, token)
.ConfigureAwait(false);

writeStream.Dispose();
try
{
await UploadFileAsync(client, bucketName, key, contentType, contentEncoding, writeStream, serverSideEncryptionMethod, acl, disablePayloadSigning, token)
.ConfigureAwait(false);
}
finally
{
if (disposeWriteStream && writeStream != cache)
{
writeStream.Dispose();
}
}
}
}

Expand Down
16 changes: 13 additions & 3 deletions src/SleetLib/FileSystem/AzureFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
using (var cache = LocalCacheFile.OpenRead())
{
Stream writeStream = cache;
bool disposeWriteStream = false;
var blobHeaders = new BlobHttpHeaders
{
CacheControl = "no-store"
Expand Down Expand Up @@ -85,6 +86,7 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
{
blobHeaders.ContentEncoding = "gzip";
writeStream = await JsonUtility.GZipAndMinifyAsync(cache);
disposeWriteStream = true;
}
}
else if (_blob.Uri.AbsoluteUri.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)
Expand All @@ -105,9 +107,17 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
log.LogWarning($"Unknown file type: {_blob.Uri.AbsoluteUri}");
}

await _blob.UploadAsync(writeStream, blobHeaders, cancellationToken: token);

writeStream.Dispose();
try
{
await _blob.UploadAsync(writeStream, blobHeaders, cancellationToken: token);
}
finally
{
if (disposeWriteStream && writeStream != cache)
{
writeStream.Dispose();
}
}
}
}
else if (await _blob.ExistsAsync(token))
Expand Down
2 changes: 1 addition & 1 deletion src/SleetLib/FileSystem/FileSystemFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static async Task<ISleetFileSystem> CreateFileSystemAsync(LocalSettings s
{
var sourceName = JsonUtility.GetValueCaseInsensitive(sourceEntry, "name");

if (source.Equals(sourceName, StringComparison.OrdinalIgnoreCase))
if (source?.Equals(sourceName, StringComparison.OrdinalIgnoreCase) == true)
{
var path = JsonUtility.GetValueCaseInsensitive(sourceEntry, "path");
var baseURIString = JsonUtility.GetValueCaseInsensitive(sourceEntry, "baseURI");
Expand Down
2 changes: 1 addition & 1 deletion src/SleetLib/TemplateUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static async Task<string> LoadTemplate(string name, DateTimeOffset now, U
{
using (var reader = new StreamReader(GetResource($"template{name}.json")))
{
var data = await reader.ReadToEndAsync();
var data = await reader.ReadToEndAsync().ConfigureAwait(false);

return data
.Replace("$SLEETVERSION$", AssemblyVersionHelper.GetVersion().ToFullVersionString())
Expand Down
178 changes: 178 additions & 0 deletions test/SleetLib.Tests/CreateConfigCommandTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
using System;
using System.IO;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json.Linq;
using NuGet.Common;
using NuGet.Test.Helpers;
using Sleet;
using Xunit;

namespace SleetLib.Tests
{
public class CreateConfigCommandTests
{
[Fact]
public async Task CreateConfigCommand_WithLocalStorageType_CreatesValidConfig()
{
using (var testDir = new TestFolder())
{
var configPath = Path.Combine(testDir.Root, "sleet.json");
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, testDir.Root, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(configPath).Should().BeTrue();

var json = JObject.Parse(File.ReadAllText(configPath));
json["username"].Value<string>().Should().Be("");
json["useremail"].Value<string>().Should().Be("");
json["sources"].Should().NotBeNull();
json["sources"].Count().Should().Be(1);

var source = json["sources"][0];
source["name"].Value<string>().Should().Be("myLocalFeed");
source["type"].Value<string>().Should().Be("local");
source["path"].Value<string>().Should().NotBeNullOrEmpty();
source["baseURI"].Value<string>().Should().Be("https://example.com/feed/");
}
}

[Fact]
public async Task CreateConfigCommand_WithAzureStorageType_CreatesValidConfig()
{
using (var testDir = new TestFolder())
{
var configPath = Path.Combine(testDir.Root, "sleet.json");
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Azure, testDir.Root, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(configPath).Should().BeTrue();

var json = JObject.Parse(File.ReadAllText(configPath));
var source = json["sources"][0];
source["name"].Value<string>().Should().Be("myAzureFeed");
source["type"].Value<string>().Should().Be("azure");
source["container"].Value<string>().Should().Be("myfeed");
source["connectionString"].Value<string>().Should().Be(AzureFileSystem.AzureEmptyConnectionString);
}
}

[Fact]
public async Task CreateConfigCommand_WithS3StorageType_CreatesValidConfig()
{
using (var testDir = new TestFolder())
{
var configPath = Path.Combine(testDir.Root, "sleet.json");
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.S3, testDir.Root, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(configPath).Should().BeTrue();

var json = JObject.Parse(File.ReadAllText(configPath));
var source = json["sources"][0];
source["name"].Value<string>().Should().Be("myAmazonS3Feed");
source["type"].Value<string>().Should().Be("s3");
source["bucketName"].Value<string>().Should().Be("bucketname");
source["region"].Value<string>().Should().Be("us-east-1");
source["profileName"].Value<string>().Should().Be("credentialsFileProfileName");
}
}

[Fact]
public async Task CreateConfigCommand_WithUnspecifiedStorageType_CreatesValidConfig()
{
using (var testDir = new TestFolder())
{
var configPath = Path.Combine(testDir.Root, "sleet.json");
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Unspecified, testDir.Root, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(configPath).Should().BeTrue();

var json = JObject.Parse(File.ReadAllText(configPath));
var source = json["sources"][0];
source["name"].Value<string>().Should().Be("myFeed");
source["type"].Value<string>().Should().Be("");
}
}

[Fact]
public async Task CreateConfigCommand_WithSpecificFileName_CreatesConfigAtPath()
{
using (var testDir = new TestFolder())
{
var configPath = Path.Combine(testDir.Root, "custom-config.json");
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, configPath, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(configPath).Should().BeTrue();
}
}

[Fact]
public async Task CreateConfigCommand_WithExistingFile_ReturnsFalse()
{
using (var testDir = new TestFolder())
{
var configPath = Path.Combine(testDir.Root, "sleet.json");
File.WriteAllText(configPath, "existing content");

var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, testDir.Root, NullLogger.Instance);

result.Should().BeFalse();
}
}

[Fact]
public async Task CreateConfigCommand_WithNonExistentDirectory_ReturnsFalse()
{
var nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "config.json");

var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, nonExistentPath, NullLogger.Instance);

result.Should().BeFalse();
}

[Fact]
public async Task CreateConfigCommand_WithNullOutput_UsesCurrentDirectory()
{
using (var testDir = new TestFolder())
{
var originalDir = Directory.GetCurrentDirectory();
try
{
Directory.SetCurrentDirectory(testDir.Root);
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, null, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(Path.Combine(testDir.Root, "sleet.json")).Should().BeTrue();
}
finally
{
Directory.SetCurrentDirectory(originalDir);
}
}
}

[Fact]
public async Task CreateConfigCommand_WithEmptyOutput_UsesCurrentDirectory()
{
using (var testDir = new TestFolder())
{
var originalDir = Directory.GetCurrentDirectory();
try
{
Directory.SetCurrentDirectory(testDir.Root);
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, string.Empty, NullLogger.Instance);

result.Should().BeTrue();
File.Exists(Path.Combine(testDir.Root, "sleet.json")).Should().BeTrue();
}
finally
{
Directory.SetCurrentDirectory(originalDir);
}
}
}
}
}
Loading