diff --git a/src/lib-csharp/Internal/CompiledJson.cs b/src/lib-csharp/Internal/CompiledJson.cs
index 8a278469..f5028d3d 100644
--- a/src/lib-csharp/Internal/CompiledJson.cs
+++ b/src/lib-csharp/Internal/CompiledJson.cs
@@ -114,7 +114,7 @@ namespace Velopack.Json
internal static class CompiledJson
{
- public static readonly JsonSerializerSettings Options = new JsonSerializerSettings {
+ private static readonly JsonSerializerSettings Options = new JsonSerializerSettings {
Converters = { new StringEnumConverter(), new SemanticVersionConverter() },
ContractResolver = new JsonNameContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
diff --git a/src/lib-csharp/Internal/SymbolicLink.cs b/src/lib-csharp/Internal/SymbolicLink.cs
index a52ee850..4aa80d8a 100644
--- a/src/lib-csharp/Internal/SymbolicLink.cs
+++ b/src/lib-csharp/Internal/SymbolicLink.cs
@@ -39,14 +39,30 @@ namespace Velopack
: targetPath;
if (Directory.Exists(targetPath)) {
-#if NETFRAMEWORK || NETSTANDARD
+#if NETSTANDARD
+ if (VelopackRuntimeInfo.IsWindows) {
+ if (!CreateSymbolicLink(linkPath, finalTarget, SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE))
+ ThrowLastWin32Error("Unable to create junction point / symlink.");
+ } else {
+ var linkInfo = new Mono.Unix.UnixSymbolicLinkInfo(linkPath);
+ linkInfo.CreateSymbolicLinkTo(targetPath);
+ }
+#elif NETFRAMEWORK
if (!CreateSymbolicLink(linkPath, finalTarget, SYMBOLIC_LINK_FLAG_DIRECTORY | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE))
ThrowLastWin32Error("Unable to create junction point / symlink.");
#else
Directory.CreateSymbolicLink(linkPath, finalTarget);
#endif
} else if (File.Exists(targetPath)) {
-#if NETFRAMEWORK || NETSTANDARD
+#if NETSTANDARD
+ if (VelopackRuntimeInfo.IsWindows) {
+ if (!CreateSymbolicLink(linkPath, finalTarget, SYMBOLIC_LINK_FLAG_FILE | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE))
+ ThrowLastWin32Error("Unable to create junction point / symlink.");
+ } else {
+ var fileInfo = new Mono.Unix.UnixFileInfo(targetPath);
+ fileInfo.CreateSymbolicLink(linkPath);
+ }
+#elif NETFRAMEWORK
if (!CreateSymbolicLink(linkPath, finalTarget, SYMBOLIC_LINK_FLAG_FILE | SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE))
ThrowLastWin32Error("Unable to create junction point / symlink.");
#else
@@ -74,7 +90,7 @@ namespace Velopack
{
var isLink = TryGetLinkFsi(linkPath, out var fsi);
if (fsi != null && !isLink) {
- throw new IOException("Path is not a junction point.");
+ throw new IOException("Path is not a junction point / symlink.");
} else {
fsi?.Delete();
}
@@ -106,13 +122,19 @@ namespace Velopack
private static string GetUnresolvedTarget(string linkPath)
{
if (TryGetLinkFsi(linkPath, out var fsi)) {
-#if NETFRAMEWORK || NETSTANDARD
-
+#if NETSTANDARD
+ if (VelopackRuntimeInfo.IsWindows) {
+ return GetTargetWin32(linkPath);
+ } else {
+ return Mono.Unix.UnixPath.ReadLink(linkPath);
+ }
+#elif NETFRAMEWORK
return GetTargetWin32(linkPath);
#else
return fsi.LinkTarget!;
#endif
}
+
throw new IOException("Path does not exist or is not a junction point / symlink.");
}
@@ -140,6 +162,67 @@ namespace Velopack
}
#if NETFRAMEWORK || NETSTANDARD
+ private static string ToggleRelative(string basePath, string toggledPath)
+ {
+ // from https://github.com/RT-Projects/RT.Util/blob/master/RT.Util.Core/Paths/PathUtil.cs#L297
+ if (basePath.Length == 0)
+ throw new Exception("InvalidBasePath");
+ if (toggledPath.Length == 0)
+ throw new Exception("InvalidToggledPath");
+ if (!Path.IsPathRooted(basePath))
+ throw new Exception("BasePathNotAbsolute");
+
+ try { basePath = Path.GetFullPath(basePath + "\\"); } catch { throw new Exception("InvalidBasePath"); }
+
+ if (!Path.IsPathRooted(toggledPath)) {
+ try {
+ return StripTrailingSeparator(Path.GetFullPath(Path.Combine(basePath, toggledPath)));
+ } catch {
+ throw new Exception("InvalidToggledPath");
+ }
+ }
+
+ // Both basePath and toggledPath are absolute. Need to relativize toggledPath.
+ try { toggledPath = Path.GetFullPath(toggledPath + "\\"); } catch { throw new Exception("InvalidToggledPath"); }
+
+ int prevPos = -1;
+ int pos = toggledPath.IndexOf(Path.DirectorySeparatorChar);
+ while (pos != -1 && pos < basePath.Length &&
+ basePath.Substring(0, pos + 1).Equals(toggledPath.Substring(0, pos + 1), StringComparison.OrdinalIgnoreCase)) {
+ prevPos = pos;
+ pos = toggledPath.IndexOf(Path.DirectorySeparatorChar, pos + 1);
+ }
+
+ if (prevPos == -1)
+ throw new Exception("PathsOnDifferentDrives");
+ var piece = basePath.Substring(prevPos + 1);
+ var result = StripTrailingSeparator(
+ (".." + Path.DirectorySeparatorChar).Repeat(piece.Count(ch => ch == Path.DirectorySeparatorChar))
+ + toggledPath.Substring(prevPos + 1));
+ return result.Length == 0 ? "." : result;
+ }
+
+ private static string Repeat(this string input, int numTimes)
+ {
+ if (numTimes == 0) return "";
+ if (numTimes == 1) return input;
+ if (numTimes == 2) return input + input;
+ var sb = new StringBuilder();
+ for (int i = 0; i < numTimes; i++)
+ sb.Append(input);
+ return sb.ToString();
+ }
+
+ private static string StripTrailingSeparator(string path)
+ {
+ if (path.Length < 1)
+ return path;
+ if (path[path.Length - 1] == '/' || path[path.Length - 1] == '\\')
+ return (path.Length == 3 && path[1] == ':') ? path : path.Substring(0, path.Length - 1);
+ else
+ return path;
+ }
+
[Flags]
private enum EFileAttributes : uint
{
@@ -194,7 +277,8 @@ namespace Velopack
private const uint IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003;
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- private static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags);
+ private static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath,
+ uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
@@ -281,63 +365,6 @@ namespace Velopack
{
throw new IOException(message, Marshal.GetExceptionForHR(Marshal.GetHRForLastWin32Error()));
}
-
- private static string ToggleRelative(string basePath, string toggledPath)
- {
- // from https://github.com/RT-Projects/RT.Util/blob/master/RT.Util.Core/Paths/PathUtil.cs#L297
- if (basePath.Length == 0)
- throw new Exception("InvalidBasePath");
- if (toggledPath.Length == 0)
- throw new Exception("InvalidToggledPath");
- if (!Path.IsPathRooted(basePath))
- throw new Exception("BasePathNotAbsolute");
-
- try { basePath = Path.GetFullPath(basePath + "\\"); } catch { throw new Exception("InvalidBasePath"); }
-
- if (!Path.IsPathRooted(toggledPath)) {
- try {
- return StripTrailingSeparator(Path.GetFullPath(Path.Combine(basePath, toggledPath)));
- } catch {
- throw new Exception("InvalidToggledPath");
- }
- }
-
- // Both basePath and toggledPath are absolute. Need to relativize toggledPath.
- try { toggledPath = Path.GetFullPath(toggledPath + "\\"); } catch { throw new Exception("InvalidToggledPath"); }
- int prevPos = -1;
- int pos = toggledPath.IndexOf(Path.DirectorySeparatorChar);
- while (pos != -1 && pos < basePath.Length && basePath.Substring(0, pos + 1).Equals(toggledPath.Substring(0, pos + 1), StringComparison.OrdinalIgnoreCase)) {
- prevPos = pos;
- pos = toggledPath.IndexOf(Path.DirectorySeparatorChar, pos + 1);
- }
- if (prevPos == -1)
- throw new Exception("PathsOnDifferentDrives");
- var piece = basePath.Substring(prevPos + 1);
- var result = StripTrailingSeparator((".." + Path.DirectorySeparatorChar).Repeat(piece.Count(ch => ch == Path.DirectorySeparatorChar))
- + toggledPath.Substring(prevPos + 1));
- return result.Length == 0 ? "." : result;
- }
-
- private static string Repeat(this string input, int numTimes)
- {
- if (numTimes == 0) return "";
- if (numTimes == 1) return input;
- if (numTimes == 2) return input + input;
- var sb = new StringBuilder();
- for (int i = 0; i < numTimes; i++)
- sb.Append(input);
- return sb.ToString();
- }
-
- private static string StripTrailingSeparator(string path)
- {
- if (path.Length < 1)
- return path;
- if (path[path.Length - 1] == '/' || path[path.Length - 1] == '\\')
- return (path.Length == 3 && path[1] == ':') ? path : path.Substring(0, path.Length - 1);
- else
- return path;
- }
#endif
}
-}
+}
\ No newline at end of file
diff --git a/src/lib-csharp/Velopack.csproj b/src/lib-csharp/Velopack.csproj
index 4a15cc98..c977d9ab 100644
--- a/src/lib-csharp/Velopack.csproj
+++ b/src/lib-csharp/Velopack.csproj
@@ -32,6 +32,7 @@
+
diff --git a/src/vpk/Velopack.Packaging/SimpleJson.cs b/src/vpk/Velopack.Packaging/SimpleJson.cs
index 6f11b8ad..8d9a22d2 100644
--- a/src/vpk/Velopack.Packaging/SimpleJson.cs
+++ b/src/vpk/Velopack.Packaging/SimpleJson.cs
@@ -1,36 +1,43 @@
-namespace Velopack.Json;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Converters;
+using NuGet.Versioning;
+
+namespace Velopack.Packaging;
public class SimpleJson
{
-#if NET6_0_OR_GREATER
- private static readonly System.Text.Json.JsonSerializerOptions Options = new System.Text.Json.JsonSerializerOptions {
- AllowTrailingCommas = true,
- ReadCommentHandling = System.Text.Json.JsonCommentHandling.Skip,
- PropertyNameCaseInsensitive = true,
- WriteIndented = true,
- DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
- Converters = {
- new System.Text.Json.Serialization.JsonStringEnumConverter(),
- new SemanticVersionConverter(),
- },
+ private static readonly JsonSerializerSettings Options = new JsonSerializerSettings {
+ Converters = { new StringEnumConverter(), new SemanticVersionConverter() },
+ NullValueHandling = NullValueHandling.Ignore,
};
-#endif
public static T DeserializeObject(string json)
{
-#if NET6_0_OR_GREATER
- return System.Text.Json.JsonSerializer.Deserialize(json, Options);
-#else
- return Newtonsoft.Json.JsonConvert.DeserializeObject(json, CompiledJson.Options);
-#endif
+ return JsonConvert.DeserializeObject(json, Options);
}
public static string SerializeObject(T obj)
{
-#if NET6_0_OR_GREATER
- return System.Text.Json.JsonSerializer.Serialize(obj, Options);
-#else
- return Newtonsoft.Json.JsonConvert.SerializeObject(obj, CompiledJson.Options);
-#endif
+ return JsonConvert.SerializeObject(obj, Options);
}
-}
+
+ private class SemanticVersionConverter : JsonConverter
+ {
+ public override SemanticVersion ReadJson(JsonReader reader, Type objectType, SemanticVersion existingValue, bool hasExistingValue,
+ JsonSerializer serializer)
+ {
+ string s = reader.Value as string;
+ if (s == null) return null;
+ return SemanticVersion.Parse(s);
+ }
+
+ public override void WriteJson(JsonWriter writer, SemanticVersion value, JsonSerializer serializer)
+ {
+ if (value != null) {
+ writer.WriteValue(value.ToFullString());
+ } else {
+ writer.WriteNull();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
index 7e66f7d4..0db84bf9 100644
--- a/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
+++ b/src/vpk/Velopack.Packaging/Velopack.Packaging.csproj
@@ -12,6 +12,7 @@
+
diff --git a/test/Velopack.Packaging.Tests/SimpleJsonTests.cs b/test/Velopack.Packaging.Tests/SimpleJsonTests.cs
index 1e2ecd31..60f470e5 100644
--- a/test/Velopack.Packaging.Tests/SimpleJsonTests.cs
+++ b/test/Velopack.Packaging.Tests/SimpleJsonTests.cs
@@ -2,6 +2,7 @@
using System.Text.Json;
using NuGet.Versioning;
using Velopack.Json;
+using Velopack.Packaging;
using Velopack.Sources;
using JsonPropertyNameAttribute = System.Text.Json.Serialization.JsonPropertyNameAttribute;
diff --git a/test/Velopack.Tests/ShortcutTests.cs b/test/Velopack.Tests/ShortcutTests.cs
index 3177988e..658167b9 100644
--- a/test/Velopack.Tests/ShortcutTests.cs
+++ b/test/Velopack.Tests/ShortcutTests.cs
@@ -5,7 +5,6 @@ using Velopack.Windows;
namespace Velopack.Tests;
-[SupportedOSPlatform("windows")]
public class ShortcutTests
{
private readonly ITestOutputHelper _output;
diff --git a/test/Velopack.Tests/SymbolicLinkTests.cs b/test/Velopack.Tests/SymbolicLinkTests.cs
index 7ea003c9..bff4264e 100644
--- a/test/Velopack.Tests/SymbolicLinkTests.cs
+++ b/test/Velopack.Tests/SymbolicLinkTests.cs
@@ -74,8 +74,8 @@ public class SymbolicLinkTests
SymbolicLink.Create(symFile, tmpFile, true);
- Assert.True(File.Exists(symFile), "Symfile point exists now.");
- Assert.True(SymbolicLink.Exists(symFile), "Junction point exists now.");
+ Assert.True(File.Exists(symFile), "Symlink should exist now.");
+ Assert.True(SymbolicLink.Exists(symFile), "Symlink should exist now.");
Assert.Equal(tmpFile, SymbolicLink.GetTarget(symFile));
diff --git a/test/Velopack.Tests/TestHelpers/FakeFixtureRepository.cs b/test/Velopack.Tests/TestHelpers/FakeFixtureRepository.cs
index 676b0bb8..611d43ee 100644
--- a/test/Velopack.Tests/TestHelpers/FakeFixtureRepository.cs
+++ b/test/Velopack.Tests/TestHelpers/FakeFixtureRepository.cs
@@ -1,7 +1,7 @@
#pragma warning disable CS0618 // Type or member is obsolete
#pragma warning disable CS0612 // Type or member is obsolete
using System.Text;
-using Velopack.Json;
+using Velopack.Packaging;
using Velopack.Sources;
namespace Velopack.Tests.TestHelpers;
diff --git a/test/Velopack.Tests/UpdateManagerTests.cs b/test/Velopack.Tests/UpdateManagerTests.cs
index 0396d3d4..9fcfc8e2 100644
--- a/test/Velopack.Tests/UpdateManagerTests.cs
+++ b/test/Velopack.Tests/UpdateManagerTests.cs
@@ -1,7 +1,7 @@
using System.Text;
using NuGet.Versioning;
using Velopack.Compression;
-using Velopack.Json;
+using Velopack.Packaging;
using Velopack.Locators;
using Velopack.Sources;
using Velopack.Tests.TestHelpers;
diff --git a/test/Velopack.Tests/UtilityTests.cs b/test/Velopack.Tests/UtilityTests.cs
index 51e1c8b7..98900553 100644
--- a/test/Velopack.Tests/UtilityTests.cs
+++ b/test/Velopack.Tests/UtilityTests.cs
@@ -48,7 +48,6 @@ public class UtilityTests
}
[SkippableFact]
- [SupportedOSPlatform("windows")]
public void SetAppIdOnShortcutTest()
{
Skip.IfNot(VelopackRuntimeInfo.IsWindows);
diff --git a/test/Velopack.Tests/Velopack.Tests.csproj b/test/Velopack.Tests/Velopack.Tests.csproj
index 8f01bee2..5662d354 100644
--- a/test/Velopack.Tests/Velopack.Tests.csproj
+++ b/test/Velopack.Tests/Velopack.Tests.csproj
@@ -1,15 +1,19 @@
+
+
+ $(NoWarn);CA1416
+
- net8.0;net48
+ net6.0;net8.0;net48
- net8.0
+ net6.0;net8.0
@@ -20,7 +24,6 @@
-
@@ -30,8 +33,17 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+