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
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
internal static class LockFileReader
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
public static LockFile Read(string filePath)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
using (var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
return Read(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
|
|
|
{
|
2015-10-15 15:09:37 -07:00
|
|
|
throw ex.WithFilePath(filePath);
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
throw FileFormatException.Create(ex, filePath);
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
internal static LockFile Read(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)
|
|
|
|
{
|
|
|
|
return ReadLockFile(jobject);
|
|
|
|
}
|
|
|
|
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
|
|
|
|
return new LockFile
|
|
|
|
{
|
|
|
|
Version = int.MinValue
|
|
|
|
};
|
|
|
|
}
|
2015-10-13 14:31:29 -07:00
|
|
|
}
|
|
|
|
|
2015-10-15 15:09:37 -07:00
|
|
|
private static LockFile ReadLockFile(JsonObject cursor)
|
2015-10-13 14:31:29 -07:00
|
|
|
{
|
|
|
|
var lockFile = new LockFile();
|
|
|
|
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);
|
2015-10-13 14:31:29 -07:00
|
|
|
|
|
|
|
return library;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|