Skip to content

Commit

Permalink
Add variable expansion in defaultDestination
Browse files Browse the repository at this point in the history
This implements #68, except I used [Name] instead of [LibraryName].  It felt like LibraryName should be matched with LibraryVersion and that felt verbose, so I took the shorter versions.

This expansion is applied when we expand the ManifestOnDisk (which is either read from disk or from a raw JSON) into LibraryInstallationState.  This is where we determine to use the defaultDestination or a library-specific destination, so it should be the only place this expansion needs to occur.
  • Loading branch information
jimmylewis committed Jun 1, 2024
1 parent 6a3fb4c commit c929c6b
Show file tree
Hide file tree
Showing 2 changed files with 145 additions and 4 deletions.
40 changes: 36 additions & 4 deletions src/LibraryManager/Json/LibraryStateToFileConverter.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
using Microsoft.Web.LibraryManager.Contracts;
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Diagnostics.CodeAnalysis;
using System.Text;
using Microsoft.Web.LibraryManager.Contracts;
using Microsoft.Web.LibraryManager.LibraryNaming;

namespace Microsoft.Web.LibraryManager.Json
Expand All @@ -22,22 +27,49 @@ public ILibraryInstallationState ConvertToLibraryInstallationState(LibraryInstal
}

string provider = string.IsNullOrEmpty(stateOnDisk.ProviderId) ? _defaultProvider : stateOnDisk.ProviderId;
string destination = string.IsNullOrEmpty(stateOnDisk.DestinationPath) ? _defaultDestination : stateOnDisk.DestinationPath;

(string name, string version) = LibraryIdToNameAndVersionConverter.Instance.GetLibraryNameAndVersion(stateOnDisk.LibraryId, provider);
string destination = string.IsNullOrEmpty(stateOnDisk.DestinationPath) ? ExpandDestination(_defaultDestination, name, version) : stateOnDisk.DestinationPath;

var state = new LibraryInstallationState()
{
Name = name,
Version = version,
IsUsingDefaultDestination = string.IsNullOrEmpty(stateOnDisk.DestinationPath),
IsUsingDefaultProvider = string.IsNullOrEmpty(stateOnDisk.ProviderId),
ProviderId = provider,
DestinationPath = destination,
Files = stateOnDisk.Files
};

(state.Name, state.Version) = LibraryIdToNameAndVersionConverter.Instance.GetLibraryNameAndVersion(stateOnDisk.LibraryId, provider);

return state;
}

/// <summary>
/// Expands [Name] and [Version] tokens in the DefaultDestination
/// </summary>
/// <param name="destination">The default destination string</param>
/// <param name="name">Package name</param>
/// <param name="version">Package version</param>
/// <returns></returns>
[SuppressMessage("Globalization", "CA1307:Specify StringComparison for clarity", Justification = "Not available on net481, not needed here (caseless)")]
private string ExpandDestination(string destination, string name, string version)
{
if (!destination.Contains("["))
{
return destination;
}

// if the name contains a slash (either filesystem or scoped packages),
// trim that and only take the last segment.
int cutIndex = name.LastIndexOfAny(['/', '\\']);

StringBuilder stringBuilder = new StringBuilder(destination);
stringBuilder.Replace("[Name]", cutIndex == -1 ? name : name.Substring(cutIndex + 1));
stringBuilder.Replace("[Version]", version);
return stringBuilder.ToString();
}

public LibraryInstallationStateOnDisk ConvertToLibraryInstallationStateOnDisk(ILibraryInstallationState state)
{
if (state == null)
Expand Down
109 changes: 109 additions & 0 deletions test/LibraryManager.Test/Json/LibraryStateToFileConverterTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Web.LibraryManager.Contracts;
using Microsoft.Web.LibraryManager.Json;
using Microsoft.Web.LibraryManager.LibraryNaming;
using Microsoft.Web.LibraryManager.Mocks;
using Microsoft.Web.LibraryManager.Providers.Cdnjs;

namespace Microsoft.Web.LibraryManager.Test.Json
{
[TestClass]
public class LibraryStateToFileConverterTests
{
[TestInitialize]
public void Setup()
{
string cacheFolder = Environment.ExpandEnvironmentVariables(@"%localappdata%\Microsoft\Library\");
string projectFolder = Path.Combine(Path.GetTempPath(), "LibraryManager");
var hostInteraction = new HostInteraction(projectFolder, cacheFolder);
var dependencies = new Dependencies(hostInteraction, new CdnjsProviderFactory());
IProvider provider = dependencies.GetProvider("cdnjs");
LibraryIdToNameAndVersionConverter.Instance.EnsureInitialized(dependencies);
}

[TestMethod]
public void ConvertToLibraryInstallationState_NullStateOnDisk()
{
LibraryStateToFileConverter converter = new LibraryStateToFileConverter("provider", "destination");

ILibraryInstallationState result = converter.ConvertToLibraryInstallationState(null);

Assert.IsNull(result);
}

[TestMethod]
public void ConvertToLibraryInstallationState_UseDefaultProviderAndDestination()
{
LibraryStateToFileConverter converter = new LibraryStateToFileConverter("defaultProvider", "defaultDestination");

var stateOnDisk = new LibraryInstallationStateOnDisk
{
LibraryId = "libraryId",
};

ILibraryInstallationState result = converter.ConvertToLibraryInstallationState(stateOnDisk);

Assert.AreEqual("defaultProvider", result.ProviderId);
Assert.AreEqual("defaultDestination", result.DestinationPath);
}

[TestMethod]
public void ConvertToLibraryInstallationState_OverrideProviderAndDestination()
{
LibraryStateToFileConverter converter = new LibraryStateToFileConverter("defaultProvider", "defaultDestination");

var stateOnDisk = new LibraryInstallationStateOnDisk
{
LibraryId = "libraryId",
ProviderId = "provider",
DestinationPath = "destination",
};

ILibraryInstallationState result = converter.ConvertToLibraryInstallationState(stateOnDisk);

Assert.AreEqual("provider", result.ProviderId);
Assert.AreEqual("destination", result.DestinationPath);
}

[TestMethod]
public void ConvertToLibraryInstallationState_ExpandTokensInDefaultDestination()
{
LibraryStateToFileConverter converter = new LibraryStateToFileConverter("defaultProvider", "lib/[Name]/[Version]");

var stateOnDisk = new LibraryInstallationStateOnDisk
{
LibraryId = "testLibraryId@1.0",
// it needs to be a provider that uses the versioned naming scheme
ProviderId = "cdnjs",
};

ILibraryInstallationState result = converter.ConvertToLibraryInstallationState(stateOnDisk);

Assert.AreEqual("lib/testLibraryId/1.0", result.DestinationPath);
}

[TestMethod]
[DataRow("filesystem", "c:\\path\\to\\library")]
[DataRow("filesystem", "/path/to/library")]
[DataRow("cdnjs", "@scope/library@1.0.0")]
public void ConvertToLibraryInstallationState_ExpandTokensInDefaultDestination_NamesWithSlashes(string provider, string libraryId)
{
LibraryStateToFileConverter converter = new LibraryStateToFileConverter("defaultProvider", "lib/[Name]");

var stateOnDisk = new LibraryInstallationStateOnDisk
{
LibraryId = libraryId,
ProviderId = provider,
};

ILibraryInstallationState result = converter.ConvertToLibraryInstallationState(stateOnDisk);

Assert.AreEqual("lib/library", result.DestinationPath);
}
}
}

0 comments on commit c929c6b

Please sign in to comment.