Skip to content

Commit b845a91

Browse files
committed
Change BaseProvider to use a public API for getting goal state.
Also updated Manifest to use the goal state for the uninstall scenario.
1 parent 4b79145 commit b845a91

File tree

6 files changed

+89
-52
lines changed

6 files changed

+89
-52
lines changed

src/LibraryManager.Contracts/IProvider.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,10 @@ public interface IProvider
6666
/// </summary>
6767
/// <param name="library"></param>
6868
string GetSuggestedDestination(ILibrary library);
69+
70+
/// <summary>
71+
/// Gets the goal state of the library installation. Does not imply actual installation.
72+
/// </summary>
73+
Task<OperationResult<LibraryInstallationGoalState>> GetInstallationGoalStateAsync(ILibraryInstallationState installationState, CancellationToken cancellationToken);
6974
}
7075
}

src/LibraryManager/Manifest.cs

Lines changed: 23 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,6 @@ public async Task<ILibraryOperationResult> InstallLibraryAsync(
204204
string destination,
205205
CancellationToken cancellationToken)
206206
{
207-
ILibraryOperationResult result;
208-
209207
var desiredState = new LibraryInstallationState()
210208
{
211209
Name = libraryName,
@@ -236,14 +234,14 @@ public async Task<ILibraryOperationResult> InstallLibraryAsync(
236234
return conflictResults;
237235
}
238236

239-
result = await provider.InstallAsync(desiredState, cancellationToken).ConfigureAwait(false);
237+
ILibraryOperationResult installResult = await provider.InstallAsync(desiredState, cancellationToken);
240238

241-
if (result.Success)
239+
if (installResult.Success)
242240
{
243241
AddLibrary(desiredState);
244242
}
245243

246-
return result;
244+
return installResult;
247245
}
248246

249247
private ILibraryInstallationState SetDefaultProviderIfNeeded(LibraryInstallationState desiredState)
@@ -510,7 +508,7 @@ private async Task<IEnumerable<FileIdentifier>> GetAllManifestFilesWithVersionsA
510508
return allFiles.SelectMany(f => f).Distinct();
511509
}
512510

513-
return new List<FileIdentifier>();
511+
return new List<FileIdentifier>();
514512
}
515513

516514
private async Task<IEnumerable<FileIdentifier>> GetFilesWithVersionsAsync(ILibraryInstallationState state)
@@ -567,41 +565,31 @@ private async Task<ILibraryOperationResult> DeleteLibraryFilesAsync(ILibraryInst
567565
try
568566
{
569567
IProvider provider = _dependencies.GetProvider(state.ProviderId);
570-
ILibraryOperationResult updatedStateResult = await provider.UpdateStateAsync(state, CancellationToken.None).ConfigureAwait(false);
571-
572-
if (updatedStateResult.Success)
568+
OperationResult<LibraryInstallationGoalState> getGoalState = await provider.GetInstallationGoalStateAsync(state, cancellationToken).ConfigureAwait(false);
569+
if (!getGoalState.Success)
573570
{
574-
List<string> filesToDelete = new List<string>();
575-
state = updatedStateResult.InstallationState;
576-
577-
foreach (string file in state.Files)
571+
return new LibraryOperationResult(state, [.. getGoalState.Errors])
578572
{
579-
var url = new Uri(file, UriKind.RelativeOrAbsolute);
580-
581-
if (!url.IsAbsoluteUri)
582-
{
583-
string relativePath = Path.Combine(state.DestinationPath, file).Replace('\\', '/');
584-
filesToDelete.Add(relativePath);
585-
}
586-
}
573+
Cancelled = getGoalState.Cancelled,
574+
};
575+
}
587576

588-
bool success = true;
589-
if (deleteFilesFunction != null)
590-
{
591-
success = await deleteFilesFunction.Invoke(filesToDelete).ConfigureAwait(false);
592-
}
577+
LibraryInstallationGoalState goalState = getGoalState.Result;
593578

594-
if (success)
595-
{
596-
return LibraryOperationResult.FromSuccess(updatedStateResult.InstallationState);
597-
}
598-
else
599-
{
600-
return LibraryOperationResult.FromError(PredefinedErrors.CouldNotDeleteLibrary(libraryId));
601-
}
579+
bool success = true;
580+
if (deleteFilesFunction != null)
581+
{
582+
success = await deleteFilesFunction.Invoke(goalState.InstalledFiles.Keys).ConfigureAwait(false);
602583
}
603584

604-
return updatedStateResult;
585+
if (success)
586+
{
587+
return LibraryOperationResult.FromSuccess(goalState.InstallationState);
588+
}
589+
else
590+
{
591+
return LibraryOperationResult.FromError(PredefinedErrors.CouldNotDeleteLibrary(libraryId));
592+
}
605593
}
606594
catch (OperationCanceledException)
607595
{

src/LibraryManager/Providers/BaseProvider.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public virtual async Task<ILibraryOperationResult> InstallAsync(ILibraryInstalla
8282

8383
if (!IsSourceCacheReady(goalState))
8484
{
85-
ILibraryOperationResult updateCacheResult = await RefreshCacheAsync(desiredState, library, cancellationToken);
85+
ILibraryOperationResult updateCacheResult = await RefreshCacheAsync(desiredState, getLibrary.Result, cancellationToken);
8686
if (!updateCacheResult.Success)
8787
{
8888
return updateCacheResult;
@@ -231,6 +231,18 @@ public virtual async Task<ILibraryOperationResult> UpdateStateAsync(ILibraryInst
231231
return LibraryOperationResult.FromSuccess(desiredState);
232232
}
233233

234+
public async Task<OperationResult<LibraryInstallationGoalState>> GetInstallationGoalStateAsync(ILibraryInstallationState desiredState, CancellationToken cancellationToken)
235+
{
236+
// get the library from the catalog
237+
OperationResult<ILibrary> getLibrary = await GetLibraryForInstallationState(desiredState, cancellationToken).ConfigureAwait(false);
238+
if (!getLibrary.Success)
239+
{
240+
return OperationResult<LibraryInstallationGoalState>.FromErrors([.. getLibrary.Errors]);
241+
}
242+
243+
return GenerateGoalState(desiredState, getLibrary.Result);
244+
}
245+
234246
#endregion
235247

236248
private OperationResult<LibraryInstallationGoalState> GenerateGoalState(ILibraryInstallationState desiredState, ILibrary library)

test/LibraryManager.Mocks/Provider.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public Provider(IHostInteraction hostInteraction)
5858
/// </summary>
5959
public virtual ILibraryOperationResult Result { get; set; }
6060

61+
/// <summary>
62+
/// Gets or sets the goal state to return from <see cref="GetInstallationGoalStateAsync(ILibraryInstallationState, CancellationToken)"/>
63+
/// </summary>
64+
public LibraryInstallationGoalState GoalState { get; set; }
65+
6166
/// <summary>
6267
/// Indicates whether libraries with versions are supported.
6368
/// </summary>
@@ -105,5 +110,13 @@ public string GetSuggestedDestination(ILibrary library)
105110
{
106111
return library?.Name;
107112
}
113+
114+
/// <summary>
115+
/// Returns a stubbed value
116+
/// </summary>
117+
public Task<OperationResult<LibraryInstallationGoalState>> GetInstallationGoalStateAsync(ILibraryInstallationState installationState, CancellationToken cancellationToken)
118+
{
119+
return Task.FromResult(OperationResult<LibraryInstallationGoalState>.FromSuccess(GoalState));
120+
}
108121
}
109122
}

test/LibraryManager.Test/Providers/BaseProviderTest.cs

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
using System;
55
using System.Collections.Generic;
66
using System.IO;
7+
using System.Threading;
8+
using System.Threading.Tasks;
79
using Microsoft.VisualStudio.TestTools.UnitTesting;
810
using Microsoft.Web.LibraryManager.Cache;
911
using Microsoft.Web.LibraryManager.Contracts;
@@ -17,6 +19,7 @@ public class BaseProviderTest
1719
{
1820
private IHostInteraction _hostInteraction;
1921
private ILibrary _library;
22+
private readonly Mocks.LibraryCatalog _catalog;
2023

2124
public BaseProviderTest()
2225
{
@@ -39,10 +42,12 @@ public BaseProviderTest()
3942
},
4043
};
4144

45+
_catalog = new Mocks.LibraryCatalog()
46+
.AddLibrary(_library);
4247
}
4348

4449
[TestMethod]
45-
public void GenerateGoalState_NoFileMapping_SpecifyFilesAtLibraryLevel()
50+
public async Task GenerateGoalState_NoFileMapping_SpecifyFilesAtLibraryLevel()
4651
{
4752
ILibraryInstallationState installState = new LibraryInstallationState
4853
{
@@ -52,20 +57,25 @@ public void GenerateGoalState_NoFileMapping_SpecifyFilesAtLibraryLevel()
5257
DestinationPath = "lib/test",
5358
Files = ["folder/*.txt"],
5459
};
55-
BaseProvider provider = new TestProvider(_hostInteraction, cacheService: null);
60+
BaseProvider provider = new TestProvider(_hostInteraction, cacheService: null)
61+
{
62+
Catalog = _catalog,
63+
};
5664
string expectedDestinationFile1 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.WorkingDirectory, "lib/test/folder/file3.txt"));
5765
string expectedSourceFile1 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.CacheDirectory, "TestProvider/test/1.0/folder/file3.txt"));
5866

59-
LibraryInstallationGoalState goalState = provider.GenerateGoalState(installState, _library);
67+
OperationResult<LibraryInstallationGoalState> getGoalState = await provider.GetInstallationGoalStateAsync(installState, CancellationToken.None);
6068

69+
Assert.IsTrue(getGoalState.Success);
70+
LibraryInstallationGoalState goalState = getGoalState.Result;
6171
Assert.IsNotNull(goalState);
6272
Assert.AreEqual(1, goalState.InstalledFiles.Count);
6373
Assert.IsTrue(goalState.InstalledFiles.TryGetValue(expectedDestinationFile1, out string file1));
6474
Assert.AreEqual(expectedSourceFile1, file1);
6575
}
6676

6777
[TestMethod]
68-
public void GenerateGoalState_NoFileMapping_NoFilesAtLibraryLevel()
78+
public async Task GenerateGoalState_NoFileMapping_NoFilesAtLibraryLevel()
6979
{
7080
ILibraryInstallationState installState = new LibraryInstallationState
7181
{
@@ -74,15 +84,21 @@ public void GenerateGoalState_NoFileMapping_NoFilesAtLibraryLevel()
7484
ProviderId = "TestProvider",
7585
DestinationPath = "lib/test",
7686
};
77-
BaseProvider provider = new TestProvider(_hostInteraction, cacheService: null);
87+
BaseProvider provider = new TestProvider(_hostInteraction, cacheService: null)
88+
{
89+
Catalog = _catalog,
90+
};
7891
string expectedDestinationFile1 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.WorkingDirectory, "lib/test/file1.txt"));
7992
string expectedSourceFile1 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.CacheDirectory, "TestProvider/test/1.0/file1.txt"));
8093
string expectedDestinationFile2 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.WorkingDirectory, "lib/test/file2.txt"));
8194
string expectedSourceFile2 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.CacheDirectory, "TestProvider/test/1.0/file2.txt"));
8295
string expectedDestinationFile3 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.WorkingDirectory, "lib/test/folder/file3.txt"));
8396
string expectedSourceFile3 = FileHelpers.NormalizePath(Path.Combine(provider.HostInteraction.CacheDirectory, "TestProvider/test/1.0/folder/file3.txt"));
8497

85-
LibraryInstallationGoalState goalState = provider.GenerateGoalState(installState, _library);
98+
OperationResult<LibraryInstallationGoalState> getGoalState = await provider.GetInstallationGoalStateAsync(installState, CancellationToken.None);
99+
100+
Assert.IsTrue(getGoalState.Success);
101+
LibraryInstallationGoalState goalState = getGoalState.Result;
86102

87103
Assert.IsNotNull(goalState);
88104
Assert.AreEqual(3, goalState.InstalledFiles.Count);
@@ -105,10 +121,9 @@ public TestProvider(IHostInteraction hostInteraction, CacheService cacheService)
105121

106122
public override string LibraryIdHintText => Text.CdnjsLibraryIdHintText;
107123

108-
public override ILibraryCatalog GetCatalog()
109-
{
110-
throw new NotImplementedException();
111-
}
124+
public ILibraryCatalog Catalog { get; set; }
125+
126+
public override ILibraryCatalog GetCatalog() => Catalog;
112127

113128
public override string GetSuggestedDestination(ILibrary library)
114129
{

test/Microsoft.Web.LibraryManager.Vsix.Test/Shared/LibraryCommandServiceTest.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ public async Task UninstallAsync_DeletesFilesFromDisk()
2828
var mockTaskStatusCenterService = new Mock<ITaskStatusCenterService>();
2929
mockTaskStatusCenterService.Setup(m => m.CreateTaskHandlerAsync(It.IsAny<string>()))
3030
.Returns(Task.FromResult(new Mock<ITaskHandler>().Object));
31+
var testInstallationState = new LibraryInstallationState
32+
{
33+
ProviderId = "testProvider",
34+
Files = new[] { "test.js" },
35+
DestinationPath = "testDestination",
36+
};
37+
var testGoalState = new LibraryInstallationGoalState(testInstallationState);
38+
testGoalState.InstalledFiles.Add(Path.Combine(mockInteraction.WorkingDirectory, "testDestination", "test.js"), Path.Combine(mockInteraction.WorkingDirectory, "test.js"));
3139
var mockDependencies = new Dependencies(mockInteraction, new IProvider[]
3240
{
3341
new Mocks.Provider(mockInteraction)
@@ -36,13 +44,9 @@ public async Task UninstallAsync_DeletesFilesFromDisk()
3644
Catalog = new Mocks.LibraryCatalog(),
3745
Result = new LibraryOperationResult
3846
{
39-
InstallationState = new LibraryInstallationState
40-
{
41-
ProviderId = "testProvider",
42-
Files = new [] { "test.js" },
43-
DestinationPath = "testDestination",
44-
}
47+
InstallationState = testInstallationState
4548
},
49+
GoalState = testGoalState,
4650
SupportsLibraryVersions = true,
4751
}
4852
});

0 commit comments

Comments
 (0)