2015-11-16 11:21:57 -08:00
|
|
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2015-11-27 16:19:54 -08:00
|
|
|
using Microsoft.DotNet.ProjectModel.Utilities;
|
2015-10-15 15:09:37 -07:00
|
|
|
using Microsoft.Extensions.JsonParser.Sources;
|
2015-10-13 14:31:29 -07:00
|
|
|
using NuGet.Frameworks;
|
|
|
|
using NuGet.Packaging.Core;
|
|
|
|
using NuGet.Versioning;
|
|
|
|
|
2015-11-27 16:19:54 -08:00
|
|
|
namespace Microsoft.DotNet.ProjectModel.Graph
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-04 12:36:46 -08:00
|
|
|
public static class LockFileReader
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-14 11:52:03 -08:00
|
|
|
public static LockFile Read(string lockFilePath)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-03-10 00:47:13 -08:00
|
|
|
using (var stream = ResilientFileStreamOpener.OpenFile(lockFilePath))
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2016-01-14 11:52:03 -08:00
|
|
|
return Read(lockFilePath, stream);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
2015-10-15 15:09:37 -07:00
|
|
|
catch (FileFormatException ex)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-14 11:52:03 -08:00
|
|
|
throw ex.WithFilePath(lockFilePath);
|
2015-10-15 15:09:37 -07:00
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
2016-01-14 11:52:03 -08:00
|
|
|
throw FileFormatException.Create(ex, lockFilePath);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-10 00:47:13 -08:00
|
|
|
public static LockFile Read(string lockFilePath, Stream stream)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
try
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var reader = new StreamReader(stream);
|
|
|
|
var jobject = JsonDeserializer.Deserialize(reader) as JsonObject;
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
if (jobject != null)
|
|
|
|
{
|
2016-01-14 11:52:03 -08:00
|
|
|
return ReadLockFile(lockFilePath, jobject);
|
2015-10-15 15:09:37 -07:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw new InvalidDataException();
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
2015-10-15 15:09:37 -07:00
|
|
|
catch
|
|
|
|
{
|
|
|
|
// Ran into parsing errors, mark it as unlocked and out-of-date
|
2016-01-14 11:52:03 -08:00
|
|
|
return new LockFile(lockFilePath)
|
2015-10-15 15:09:37 -07:00
|
|
|
{
|
|
|
|
Version = int.MinValue
|
|
|
|
};
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2016-01-14 11:52:03 -08:00
|
|
|
private static LockFile ReadLockFile(string lockFilePath, JsonObject cursor)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2016-01-14 11:52:03 -08:00
|
|
|
var lockFile = new LockFile(lockFilePath);
|
2015-10-13 14:31:29 -07:00
|
|
|
lockFile.Version = ReadInt(cursor, "version", defaultValue: int.MinValue);
|
2015-10-15 15:09:37 -07:00
|
|
|
lockFile.Targets = ReadObject(cursor.ValueAsJsonObject("targets"), ReadTarget);
|
|
|
|
lockFile.ProjectFileDependencyGroups = ReadObject(cursor.ValueAsJsonObject("projectFileDependencyGroups"), ReadProjectFileDependencyGroup);
|
|
|
|
ReadLibrary(cursor.ValueAsJsonObject("libraries"), lockFile);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
return lockFile;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static void ReadLibrary(JsonObject json, LockFile lockFile)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
if (json == null)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
foreach (var key in json.Keys)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var value = json.ValueAsJsonObject(key);
|
2015-10-13 14:31:29 -07:00
|
|
|
if (value == null)
|
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
throw FileFormatException.Create("The value type is not object.", json.Value(key));
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
var parts = key.Split(new[] { '/' }, 2);
|
2015-10-13 14:31:29 -07:00
|
|
|
var name = parts[0];
|
|
|
|
var version = parts.Length == 2 ? NuGetVersion.Parse(parts[1]) : null;
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
var type = value.ValueAsString("type")?.Value;
|
2015-10-13 14:31:29 -07:00
|
|
|
|
2015-10-24 04:32:26 -07:00
|
|
|
if (type == null || string.Equals(type, "package", StringComparison.OrdinalIgnoreCase))
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
lockFile.PackageLibraries.Add(new LockFilePackageLibrary
|
|
|
|
{
|
|
|
|
Name = name,
|
|
|
|
Version = version,
|
|
|
|
IsServiceable = ReadBool(value, "serviceable", defaultValue: false),
|
2015-10-15 15:09:37 -07:00
|
|
|
Sha512 = ReadString(value.Value("sha512")),
|
|
|
|
Files = ReadPathArray(value.Value("files"), ReadString)
|
2015-10-13 14:31:29 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
else if (type == "project")
|
|
|
|
{
|
|
|
|
lockFile.ProjectLibraries.Add(new LockFileProjectLibrary
|
|
|
|
{
|
|
|
|
Name = name,
|
|
|
|
Version = version,
|
2015-10-15 15:09:37 -07:00
|
|
|
Path = ReadString(value.Value("path"))
|
2015-10-13 14:31:29 -07:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static LockFileTarget ReadTarget(string property, JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var jobject = json as JsonObject;
|
|
|
|
if (jobject == null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
throw FileFormatException.Create("The value type is not an object.", json);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
var target = new LockFileTarget();
|
|
|
|
var parts = property.Split(new[] { '/' }, 2);
|
|
|
|
target.TargetFramework = NuGetFramework.Parse(parts[0]);
|
|
|
|
if (parts.Length == 2)
|
|
|
|
{
|
|
|
|
target.RuntimeIdentifier = parts[1];
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
target.Libraries = ReadObject(jobject, ReadTargetLibrary);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
return target;
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static LockFileTargetLibrary ReadTargetLibrary(string property, JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var jobject = json as JsonObject;
|
|
|
|
if (jobject == null)
|
|
|
|
{
|
|
|
|
throw FileFormatException.Create("The value type is not an object.", json);
|
|
|
|
}
|
|
|
|
|
2015-10-13 14:31:29 -07:00
|
|
|
var library = new LockFileTargetLibrary();
|
|
|
|
|
|
|
|
var parts = property.Split(new[] { '/' }, 2);
|
|
|
|
library.Name = parts[0];
|
|
|
|
if (parts.Length == 2)
|
|
|
|
{
|
|
|
|
library.Version = NuGetVersion.Parse(parts[1]);
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
library.Type = jobject.ValueAsString("type");
|
|
|
|
var framework = jobject.ValueAsString("framework");
|
2015-10-13 14:31:29 -07:00
|
|
|
if (framework != null)
|
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
library.TargetFramework = NuGetFramework.Parse(framework);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
library.Dependencies = ReadObject(jobject.ValueAsJsonObject("dependencies"), ReadPackageDependency);
|
|
|
|
library.FrameworkAssemblies = new HashSet<string>(ReadArray(jobject.Value("frameworkAssemblies"), ReadFrameworkAssemblyReference), StringComparer.OrdinalIgnoreCase);
|
|
|
|
library.RuntimeAssemblies = ReadObject(jobject.ValueAsJsonObject("runtime"), ReadFileItem);
|
|
|
|
library.CompileTimeAssemblies = ReadObject(jobject.ValueAsJsonObject("compile"), ReadFileItem);
|
|
|
|
library.ResourceAssemblies = ReadObject(jobject.ValueAsJsonObject("resource"), ReadFileItem);
|
|
|
|
library.NativeLibraries = ReadObject(jobject.ValueAsJsonObject("native"), ReadFileItem);
|
2016-02-17 10:08:27 -08:00
|
|
|
library.ContentFiles = ReadObject(jobject.ValueAsJsonObject("contentFiles"), ReadContentFile);
|
2016-03-08 16:46:50 -08:00
|
|
|
library.RuntimeTargets = ReadObject(jobject.ValueAsJsonObject("runtimeTargets"), ReadRuntimeTarget);
|
2015-10-13 14:31:29 -07:00
|
|
|
return library;
|
|
|
|
}
|
|
|
|
|
2016-03-07 10:51:40 -08:00
|
|
|
private static LockFileRuntimeTarget ReadRuntimeTarget(string property, JsonValue json)
|
|
|
|
{
|
|
|
|
var jsonObject = json as JsonObject;
|
|
|
|
if (jsonObject == null)
|
|
|
|
{
|
|
|
|
throw FileFormatException.Create("The value type is not an object.", json);
|
|
|
|
}
|
|
|
|
|
|
|
|
return new LockFileRuntimeTarget(
|
|
|
|
path: property,
|
2016-03-08 16:46:50 -08:00
|
|
|
runtime: jsonObject.ValueAsString("rid"),
|
2016-03-07 10:51:40 -08:00
|
|
|
assetType: jsonObject.ValueAsString("assetType")
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2016-02-17 10:08:27 -08:00
|
|
|
private static LockFileContentFile ReadContentFile(string property, JsonValue json)
|
|
|
|
{
|
|
|
|
var contentFile = new LockFileContentFile()
|
|
|
|
{
|
|
|
|
Path = property
|
|
|
|
};
|
|
|
|
|
|
|
|
var jsonObject = json as JsonObject;
|
|
|
|
if (jsonObject != null)
|
|
|
|
{
|
|
|
|
|
|
|
|
BuildAction action;
|
|
|
|
BuildAction.TryParse(jsonObject.ValueAsString("buildAction"), out action);
|
|
|
|
|
|
|
|
contentFile.BuildAction = action;
|
|
|
|
var codeLanguage = jsonObject.ValueAsString("codeLanguage");
|
|
|
|
if (codeLanguage == "any")
|
|
|
|
{
|
|
|
|
codeLanguage = null;
|
|
|
|
}
|
|
|
|
contentFile.CodeLanguage = codeLanguage;
|
|
|
|
contentFile.OutputPath = jsonObject.ValueAsString("outputPath");
|
|
|
|
contentFile.PPOutputPath = jsonObject.ValueAsString("ppOutputPath");
|
|
|
|
contentFile.CopyToOutput = ReadBool(jsonObject, "copyToOutput", false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return contentFile;
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static ProjectFileDependencyGroup ReadProjectFileDependencyGroup(string property, JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
return new ProjectFileDependencyGroup(
|
2015-10-17 07:20:56 -07:00
|
|
|
string.IsNullOrEmpty(property) ? null : NuGetFramework.Parse(property),
|
2015-10-15 15:09:37 -07:00
|
|
|
ReadArray(json, ReadString));
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static PackageDependency ReadPackageDependency(string property, JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var versionStr = ReadString(json);
|
2015-10-13 14:31:29 -07:00
|
|
|
return new PackageDependency(
|
|
|
|
property,
|
|
|
|
versionStr == null ? null : VersionRange.Parse(versionStr));
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static LockFileItem ReadFileItem(string property, JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
var item = new LockFileItem { Path = PathUtility.GetPathWithDirectorySeparator(property) };
|
2015-10-15 15:09:37 -07:00
|
|
|
var jobject = json as JsonObject;
|
|
|
|
|
|
|
|
if (jobject != null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
foreach (var subProperty in jobject.Keys)
|
|
|
|
{
|
|
|
|
item.Properties[subProperty] = jobject.ValueAsString(subProperty);
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static string ReadFrameworkAssemblyReference(JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
return ReadString(json);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static IList<TItem> ReadArray<TItem>(JsonValue json, Func<JsonValue, TItem> readItem)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
if (json == null)
|
|
|
|
{
|
|
|
|
return new List<TItem>();
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
var jarray = json as JsonArray;
|
|
|
|
if (jarray == null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
throw FileFormatException.Create("The value type is not array.", json);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
var items = new List<TItem>();
|
|
|
|
for (int i = 0; i < jarray.Length; ++i)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
items.Add(readItem(jarray[i]));
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
2015-10-15 15:09:37 -07:00
|
|
|
return items;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static IList<string> ReadPathArray(JsonValue json, Func<JsonValue, string> readItem)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
return ReadArray(json, readItem).Select(f => PathUtility.GetPathWithDirectorySeparator(f)).ToList();
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static IList<TItem> ReadObject<TItem>(JsonObject json, Func<string, JsonValue, TItem> readItem)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
if (json == null)
|
|
|
|
{
|
|
|
|
return new List<TItem>();
|
|
|
|
}
|
|
|
|
var items = new List<TItem>();
|
2015-10-15 15:09:37 -07:00
|
|
|
foreach (var childKey in json.Keys)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
items.Add(readItem(childKey, json.Value(childKey)));
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
return items;
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static bool ReadBool(JsonObject cursor, string property, bool defaultValue)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var valueToken = cursor.Value(property) as JsonBoolean;
|
|
|
|
if (valueToken == null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
return defaultValue;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
return valueToken.Value;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static int ReadInt(JsonObject cursor, string property, int defaultValue)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var number = cursor.Value(property) as JsonNumber;
|
|
|
|
if (number == null)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
return defaultValue;
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
try
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
var resultInInt = Convert.ToInt32(number.Raw);
|
|
|
|
return resultInInt;
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
2015-10-15 15:09:37 -07:00
|
|
|
catch (Exception ex)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
// FormatException or OverflowException
|
|
|
|
throw FileFormatException.Create(ex, cursor);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static string ReadString(JsonValue json)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
if (json is JsonString)
|
|
|
|
{
|
|
|
|
return (json as JsonString).Value;
|
|
|
|
}
|
|
|
|
else if (json is JsonNull)
|
|
|
|
{
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
throw FileFormatException.Create("The value type is not string.", json);
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
2015-10-15 15:09:37 -07:00
|
|
|
}
|