Skip to content

Commit b603e16

Browse files
Merge pull request #752 from jimmylewis/latest
Rework support for @latest version
2 parents 22dab05 + 4351103 commit b603e16

File tree

6 files changed

+47
-13
lines changed

6 files changed

+47
-13
lines changed

src/LibraryManager/ManifestConstants.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,10 @@ public static class ManifestConstants
4848
/// libman.json files element
4949
/// </summary>
5050
public const string Files = "files";
51+
52+
/// <summary>
53+
/// For providers that support versioned libraries, this represents the evergreen latest version
54+
/// </summary>
55+
public const string LatestVersion = "latest";
5156
}
5257
}

src/LibraryManager/Providers/BaseProvider.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,18 @@ public virtual async Task<ILibraryOperationResult> UpdateStateAsync(ILibraryInst
9898
try
9999
{
100100
ILibraryCatalog catalog = GetCatalog();
101+
102+
if (string.Equals(desiredState.Version, ManifestConstants.LatestVersion, StringComparison.Ordinal))
103+
{
104+
// replace the @latest version with the latest version from the catalog. This redirect
105+
// ensures that as new versions are released, we will not reuse stale "latest" assets
106+
// from the cache.
107+
string latestVersion = await catalog.GetLatestVersion(libraryId, includePreReleases: false, cancellationToken).ConfigureAwait(false);
108+
LibraryInstallationState newState = LibraryInstallationState.FromInterface(desiredState);
109+
newState.Version = latestVersion;
110+
desiredState = newState;
111+
}
112+
101113
ILibrary library = await catalog.GetLibraryAsync(desiredState.Name, desiredState.Version, cancellationToken).ConfigureAwait(false);
102114

103115
if (library == null)

src/LibraryManager/Providers/Cdnjs/CdnjsCatalog.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ internal class CdnjsCatalog : ILibraryCatalog
2020
// TO DO: These should become Provider properties to be passed to CacheService
2121
private const string FileName = "cache.json";
2222
public const string CatalogUrl = "https://api.cdnjs.com/libraries?fields=name,description,version";
23-
public const string MetaPackageUrlFormat = "https://api.cdnjs.com/libraries/{0}?fields=filename,versions"; // {libraryName}
23+
public const string MetaPackageUrlFormat = "https://api.cdnjs.com/libraries/{0}?fields=filename,versions"; // {libraryName}
2424
public const string PackageVersionUrlFormat = "https://api.cdnjs.com/libraries/{0}/{1}?fields=files"; // {libraryName}/{version}
2525

2626
private readonly string _cacheFile;
@@ -150,7 +150,13 @@ public async Task<ILibrary> GetLibraryAsync(string libraryName, string version,
150150
throw new InvalidLibraryException(libraryId, _provider.Id);
151151
}
152152

153-
if (!(await GetLibraryVersionsAsync(libraryName, cancellationToken)).Contains(version))
153+
if (string.Equals(version, ManifestConstants.LatestVersion, StringComparison.Ordinal))
154+
{
155+
version = await GetLatestVersion(libraryName, includePreReleases: false, cancellationToken);
156+
}
157+
158+
IEnumerable<string> enumerable = await GetLibraryVersionsAsync(libraryName, cancellationToken);
159+
if (!enumerable.Contains(version))
154160
{
155161
throw new InvalidLibraryException(libraryId, _provider.Id);
156162
}
@@ -160,7 +166,7 @@ public async Task<ILibrary> GetLibraryAsync(string libraryName, string version,
160166
JObject groupMetadata = await GetLibraryGroupMetadataAsync(libraryName, cancellationToken);
161167
string defaultFile = groupMetadata?["filename"].Value<string>() ?? string.Empty;
162168

163-
IEnumerable<string> libraryFiles= await GetLibraryFilesAsync(libraryName, version, cancellationToken).ConfigureAwait(false);
169+
IEnumerable<string> libraryFiles = await GetLibraryFilesAsync(libraryName, version, cancellationToken).ConfigureAwait(false);
164170

165171
return new CdnjsLibrary
166172
{

src/LibraryManager/Providers/Unpkg/UnpkgCatalog.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ internal class UnpkgCatalog : ILibraryCatalog
2020
public const string CacheFileName = "cache.json";
2121
public const string LibraryFileListUrlFormat = "https://unpkg.com/{0}@{1}/?meta"; // e.g. https://unpkg.com/[email protected]/?meta
2222
public const string LatestLibraryVersonUrl = "https://unpkg.com/{0}/package.json"; // e.g. https://unpkg.com/jquery/package.json
23-
public const string LatestVersionTag = "latest";
2423

2524
private readonly INpmPackageInfoFactory _packageInfoFactory;
2625
private readonly INpmPackageSearch _packageSearch;
@@ -58,7 +57,7 @@ public async Task<string> GetLatestVersion(string libraryName, bool includePreRe
5857
try
5958
{
6059
string latestLibraryVersionUrl = string.Format(LatestLibraryVersonUrl, libraryName);
61-
string latestCacheFile = Path.Combine(_cacheFolder, libraryName, $"{LatestVersionTag}.json");
60+
string latestCacheFile = Path.Combine(_cacheFolder, libraryName, $"{ManifestConstants.LatestVersion}.json");
6261

6362
string latestJson = await _cacheService.GetContentsFromUriWithCacheFallbackAsync(latestLibraryVersionUrl,
6463
latestCacheFile,
@@ -88,7 +87,7 @@ public async Task<ILibrary> GetLibraryAsync(string libraryName, string version,
8887
}
8988

9089
string libraryId = _libraryNamingScheme.GetLibraryId(libraryName, version);
91-
if (string.Equals(version, LatestVersionTag, StringComparison.Ordinal))
90+
if (string.Equals(version, ManifestConstants.LatestVersion, StringComparison.Ordinal))
9291
{
9392
string latestVersion = await GetLatestVersion(libraryId, includePreReleases: false, cancellationToken).ConfigureAwait(false);
9493
libraryId = _libraryNamingScheme.GetLibraryId(libraryName, latestVersion);
@@ -263,8 +262,8 @@ public async Task<CompletionSet> GetLibraryCompletionSetAsync(string libraryName
263262
// support @latest version
264263
completions.Add(new CompletionItem
265264
{
266-
DisplayText = LatestVersionTag,
267-
InsertionText = _libraryNamingScheme.GetLibraryId(name, LatestVersionTag),
265+
DisplayText = ManifestConstants.LatestVersion,
266+
InsertionText = _libraryNamingScheme.GetLibraryId(name, ManifestConstants.LatestVersion),
268267
});
269268

270269
completionSet.CompletionType = CompletionSortOrder.Version;

src/LibraryManager/Providers/jsDelivr/JsDelivrCatalog.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ internal class JsDelivrCatalog : ILibraryCatalog
2323
public const string LatestLibraryVersionUrl = "https://data.jsdelivr.com/v1/package/npm/{0}";
2424
public const string LibraryFileListUrlFormatGH = "https://data.jsdelivr.com/v1/package/gh/{0}/flat";
2525
public const string LatestLibraryVersionUrlGH = "https://data.jsdelivr.com/v1/package/gh/{0}";
26-
public const string LatestVersionTag = "latest";
2726

2827
private readonly INpmPackageInfoFactory _packageInfoFactory;
2928
private readonly INpmPackageSearch _packageSearch;
@@ -61,7 +60,7 @@ public async Task<string> GetLatestVersion(string libraryId, bool includePreRele
6160
bool isGitHub = IsGitHub(libraryId);
6261
string latestLibraryVersionUrl = string.Format(isGitHub ? LatestLibraryVersionUrlGH : LatestLibraryVersionUrl, name);
6362
string cacheFileType = isGitHub ? "github" : "npm";
64-
string latestLibraryVersionCacheFile = Path.Combine(_cacheFolder, name, $"{cacheFileType}-{LatestVersionTag}.json");
63+
string latestLibraryVersionCacheFile = Path.Combine(_cacheFolder, name, $"{cacheFileType}-{ManifestConstants.LatestVersion}.json");
6564

6665
string latestVersionContent = await _cacheService.GetContentsFromUriWithCacheFallbackAsync(latestLibraryVersionUrl,
6766
latestLibraryVersionCacheFile,
@@ -116,7 +115,7 @@ public async Task<ILibrary> GetLibraryAsync(string name, string version, Cancell
116115
}
117116

118117
string libraryId = _libraryNamingScheme.GetLibraryId(name, version);
119-
if (string.Equals(version, LatestVersionTag, StringComparison.Ordinal))
118+
if (string.Equals(version, ManifestConstants.LatestVersion, StringComparison.Ordinal))
120119
{
121120
string latestVersion = await GetLatestVersion(libraryId, includePreReleases: false, cancellationToken).ConfigureAwait(false);
122121
libraryId = _libraryNamingScheme.GetLibraryId(name, latestVersion);
@@ -288,8 +287,8 @@ public async Task<CompletionSet> GetLibraryCompletionSetAsync(string libraryName
288287
// support @latest version
289288
completions.Add(new CompletionItem
290289
{
291-
DisplayText = LatestVersionTag,
292-
InsertionText = _libraryNamingScheme.GetLibraryId(name, LatestVersionTag),
290+
DisplayText = ManifestConstants.LatestVersion,
291+
InsertionText = _libraryNamingScheme.GetLibraryId(name, ManifestConstants.LatestVersion),
293292
});
294293

295294
completionSet.CompletionType = CompletionSortOrder.Version;

test/LibraryManager.Test/Providers/Cdnjs/CdnjsCatalogTest.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,19 @@ public async Task GetLibraryAsync_Success()
134134
Assert.IsNotNull(library.Files);
135135
}
136136

137+
[TestMethod]
138+
public async Task GetLibraryAsync_LatestVersion_Success()
139+
{
140+
CdnjsCatalog sut = SetupCatalog();
141+
142+
ILibrary library = await sut.GetLibraryAsync("sampleLibrary", "latest", CancellationToken.None);
143+
144+
Assert.IsNotNull(library);
145+
Assert.AreEqual("sampleLibrary", library.Name);
146+
Assert.AreEqual("3.1.4", library.Version);
147+
Assert.IsNotNull(library.Files);
148+
}
149+
137150
[TestMethod]
138151
public async Task GetLibraryAsync_InvalidLibraryId()
139152
{

0 commit comments

Comments
 (0)