diff --git a/.editorconfig b/.editorconfig
index e7128c76..9cac4b23 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,6 +10,7 @@ indent_style = space
# ReSharper properties
resharper_csharp_wrap_after_invocation_lpar = true
resharper_csharp_wrap_arguments_style = chop_if_long
+resharper_indent_raw_literal_string = indent
# MSBuild files
[*.{csproj,targets,props}]
@@ -138,6 +139,19 @@ dotnet_diagnostic.il3000.severity = error
dotnet_diagnostic.il3001.severity = error
dotnet_diagnostic.il3002.severity = error
dotnet_diagnostic.il3003.severity = error
+
+# Resharper
+resharper_place_accessorholder_attribute_on_same_line = false
+resharper_place_accessor_attribute_on_same_line = false
+resharper_place_event_attribute_on_same_line = false
+resharper_place_field_attribute_on_same_line = false
+resharper_place_method_attribute_on_same_line = false
+resharper_place_property_attribute_on_same_line = false
+resharper_place_record_field_attribute_on_same_line = false
+resharper_place_type_attribute_on_same_line = false
+csharp_max_attribute_length_for_same_line = 0
+
+
###############################
# VB Coding Conventions #
###############################
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index c7a92d42..966c9f32 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -17,16 +17,15 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+ - uses: dotnet/nbgv@master
+ with:
+ setAllVars: true
- uses: Swatinem/rust-cache@v2
with:
key: "rust-test-${{ matrix.os }}"
workspaces: "src/Rust -> target"
- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov
- - name: Install NBGV
- run: dotnet tool install -g nbgv
- if: startsWith(matrix.os, 'macos-')
- continue-on-error: true
- name: Test Rust
working-directory: src/Rust
run: cargo llvm-cov ${{ matrix.rust_flags }} --cobertura --output-path ../../test/coverage.rust.${{ matrix.os }}.xml
@@ -42,6 +41,9 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+ - uses: dotnet/nbgv@master
+ with:
+ setAllVars: true
- uses: Swatinem/rust-cache@v2
with:
key: "rust-build-windows"
@@ -70,20 +72,33 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+ - uses: dotnet/nbgv@master
+ id: nbgv
+ with:
+ setAllVars: true
- uses: Swatinem/rust-cache@v2
with:
key: "rust-build-linux"
workspaces: "src/Rust -> target"
- - name: Build Rust
+ - name: Build Rust (x64)
working-directory: src/Rust
run: |
cargo build --release --target x86_64-unknown-linux-gnu
- cp ./target/x86_64-unknown-linux-gnu/release/update ./target/release/UpdateNix
+ cp ./target/x86_64-unknown-linux-gnu/release/update ./target/release/UpdateNix_x64
+ - name: Build Rust (arm64)
+ working-directory: src/Rust
+ env:
+ CROSS_NuGetPackageVersion: ${{ steps.nbgv.outputs.NuGetPackageVersion }}
+ run: |
+ curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
+ cargo binstall cross --no-confirm
+ cross build --release --target aarch64-unknown-linux-gnu
+ cp ./target/aarch64-unknown-linux-gnu/release/update ./target/release/UpdateNix_arm64
- name: Upload Rust Build Artifacts
uses: actions/upload-artifact@v4
with:
name: rust-ubuntu-latest
- path: src/Rust/target/release/UpdateNix
+ path: src/Rust/target/release/UpdateNix*
- name: Cancel workflow if failed
uses: andymckay/cancel-action@0.4
if: ${{ failure() }}
@@ -97,13 +112,13 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+ - uses: dotnet/nbgv@master
+ with:
+ setAllVars: true
- uses: Swatinem/rust-cache@v2
with:
key: "rust-build-${{ matrix.os }}"
workspaces: "src/Rust -> target"
- - name: Install NBGV
- run: dotnet tool install -g nbgv
- continue-on-error: true
- name: Build Rust
working-directory: src/Rust
run: |
@@ -170,10 +185,6 @@ jobs:
key: ${{ runner.os }}-nuget-${{ hashFiles('**/packages.lock.json') }}
restore-keys: |
${{ runner.os }}-nuget-
- - name: Install NBGV
- run: dotnet tool install -g nbgv
- if: ${{ matrix.os == 'macos-latest' }}
- continue-on-error: true
- name: Install FUSE
run: |
sudo add-apt-repository universe
diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets
index 4e85e5bd..954b8a39 100644
--- a/src/Directory.Build.targets
+++ b/src/Directory.Build.targets
@@ -43,7 +43,8 @@
-
+
+
diff --git a/src/Rust/Cross.toml b/src/Rust/Cross.toml
new file mode 100644
index 00000000..0c1033a0
--- /dev/null
+++ b/src/Rust/Cross.toml
@@ -0,0 +1,5 @@
+[target.aarch64-unknown-linux-gnu]
+pre-build = [
+ "dpkg --add-architecture $CROSS_DEB_ARCH",
+ "apt-get update && apt-get install -y libssl-dev:$CROSS_DEB_ARCH",
+]
diff --git a/src/Rust/build.rs b/src/Rust/build.rs
index dd1c538a..4495bf03 100644
--- a/src/Rust/build.rs
+++ b/src/Rust/build.rs
@@ -1,6 +1,7 @@
#![allow(unused_variables)]
+
use semver;
-use std::process::Command;
+use std::env;
#[cfg(target_os = "windows")]
extern crate winres;
@@ -12,9 +13,7 @@ fn main() {
#[cfg(target_os = "windows")]
delay_load();
- let ver_output = Command::new("nbgv").args(&["get-version", "-v", "NuGetPackageVersion"]).output().expect("Failed to execute nbgv get-version");
- let version = String::from_utf8(ver_output.stdout).expect("Unable to convert ngbv output to string");
- let version = version.trim();
+ let version = get_package_version();
let ver = semver::Version::parse(&version).expect("Unable to parse ngbv output as semver version");
let ver: u64 = ver.major << 48 | ver.minor << 32 | ver.patch << 16;
let desc = format!("Velopack {}", version);
@@ -28,13 +27,32 @@ fn main() {
.set_version_info(winres::VersionInfo::FILEVERSION, ver)
.set("CompanyName", "Velopack")
.set("ProductName", "Velopack")
- .set("ProductVersion", version)
+ .set("ProductVersion", &version)
.set("FileDescription", &desc)
.set("LegalCopyright", "Caelan Sayler (c) 2023, Velopack Ltd. (c) 2024")
.compile()
.unwrap();
}
+fn get_package_version() -> String {
+ if let Ok(version) = env::var("NuGetPackageVersion") {
+ // NuGetPackageVersion is set, return it trimmed
+ return version.trim().to_string();
+ } else if let Ok(version) = env::var("NBGV_NuGetPackageVersion") {
+ // NBGV_NuGetPackageVersion is set, return it trimmed
+ return version.trim().to_string();
+ } else if let Ok(version) = env::var("CROSS_NuGetPackageVersion") {
+ // NBGV_NuGetPackageVersion is set, return it trimmed
+ return version.trim().to_string();
+ } else if env::var("CI").is_ok() {
+ // CI is set, NuGetPackageVersion should be set always in CI
+ panic!("Error: NuGetPackageVersion must be set in CI");
+ } else {
+ // CI is not set, return "v0.0.0-local"
+ return "0.0.0-local".to_string();
+ }
+}
+
#[cfg(target_os = "windows")]
fn delay_load() {
delay_load_exe("update");
diff --git a/src/Rust/src/shared/runtime_arch.rs b/src/Rust/src/shared/runtime_arch.rs
index 03a67a33..3018b574 100644
--- a/src/Rust/src/shared/runtime_arch.rs
+++ b/src/Rust/src/shared/runtime_arch.rs
@@ -1,5 +1,3 @@
-use anyhow::Result;
-
#[derive(PartialEq, Debug, Clone, strum::IntoStaticStr)]
pub enum RuntimeArch {
X86,
@@ -86,7 +84,7 @@ type IsWow64Process2Fn = unsafe extern "system" fn(
) -> windows::Win32::Foundation::BOOL;
#[cfg(target_os = "windows")]
-unsafe fn is_wow64_process2(handle: windows::Win32::Foundation::HANDLE) -> Result {
+unsafe fn is_wow64_process2(handle: windows::Win32::Foundation::HANDLE) -> anyhow::Result {
use windows::Win32::Foundation::TRUE;
use windows::Win32::System::SystemInformation::IMAGE_FILE_MACHINE;
diff --git a/src/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs b/src/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs
index f8ab224c..7e04db42 100644
--- a/src/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs
+++ b/src/Velopack.Packaging.Unix/Commands/LinuxPackCommandRunner.cs
@@ -35,18 +35,18 @@ public class LinuxPackCommandRunner : PackageBuilder
: Options.Categories.TrimEnd(';');
File.WriteAllText(appRunPath, $$"""
-#!/bin/sh
-if [ ! -z "$APPIMAGE" ] && [ ! -z "$APPDIR" ]; then
- MD5=$(echo -n "file://$APPIMAGE" | md5sum | cut -d' ' -f1)
- cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/normal/$MD5.png" >/dev/null 2>&1
- cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/large/$MD5.png" >/dev/null 2>&1
- xdg-icon-resource forceupdate >/dev/null 2>&1
-fi
-HERE="$(dirname "$(readlink -f "${0}")")"
-export PATH="${HERE}"/usr/bin/:"${PATH}"
-EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1 | sed 's/\\s/ /g')
-exec "${EXEC}" "$@"
-""".Replace("\r", ""));
+ #!/bin/sh
+ if [ ! -z "$APPIMAGE" ] && [ ! -z "$APPDIR" ]; then
+ MD5=$(echo -n "file://$APPIMAGE" | md5sum | cut -d' ' -f1)
+ cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/normal/$MD5.png" >/dev/null 2>&1
+ cp "$APPDIR/{{iconFilename}}" "$HOME/.cache/thumbnails/large/$MD5.png" >/dev/null 2>&1
+ xdg-icon-resource forceupdate >/dev/null 2>&1
+ fi
+ HERE="$(dirname "$(readlink -f "${0}")")"
+ export PATH="${HERE}"/usr/bin/:"${PATH}"
+ EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1 | sed 's/\\s/ /g')
+ exec "${EXEC}" "$@"
+ """.Replace("\r", ""));
Chmod.ChmodFileAsExecutable(appRunPath);
var mainExeName = Options.EntryExecutableName ?? Options.PackId;
@@ -59,23 +59,28 @@ exec "${EXEC}" "$@"
mainExeName = mainExeName.Replace(" ", "\\s");
File.WriteAllText(Path.Combine(dir.FullName, Options.PackId + ".desktop"), $"""
-[Desktop Entry]
-Type=Application
-Name={Options.PackTitle ?? Options.PackId}
-Comment={Options.PackTitle ?? Options.PackId} {Options.PackVersion}
-Icon={Options.PackId}
-Exec={mainExeName}
-StartupWMClass={Options.PackId}
-Categories={categories};
-""".Replace("\r", ""));
+ [Desktop Entry]
+ Type=Application
+ Name={Options.PackTitle ?? Options.PackId}
+ Comment={Options.PackTitle ?? Options.PackId} {Options.PackVersion}
+ Icon={Options.PackId}
+ Exec={mainExeName}
+ StartupWMClass={Options.PackId}
+ Categories={categories};
+ """.Replace("\r", ""));
// copy existing app files
CopyFiles(new DirectoryInfo(packDir), bin, progress, true);
}
+ Options.TargetRuntime.Architecture = Options.TargetRuntime.HasArchitecture
+ ? Options.TargetRuntime.Architecture
+ : GetMachineForBinary(MainExePath);
+
+
// velopack required files
File.WriteAllText(Path.Combine(bin.FullName, "sq.version"), GenerateNuspecContent());
- File.Copy(HelperFile.GetUpdatePath(RuntimeOs.Linux), Path.Combine(bin.FullName, "UpdateNix"), true);
+ File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), Path.Combine(bin.FullName, "UpdateNix"), true);
progress(100);
return Task.FromResult(dir.FullName);
}
@@ -91,10 +96,7 @@ Categories={categories};
protected override Task CreatePortablePackage(Action progress, string packDir, string outputPath)
{
progress(-1);
- var machine = Options.TargetRuntime.HasArchitecture
- ? Options.TargetRuntime.Architecture
- : GetMachineForBinary(MainExePath);
- AppImageTool.CreateLinuxAppImage(packDir, outputPath, machine, Log);
+ AppImageTool.CreateLinuxAppImage(packDir, outputPath, Options.TargetRuntime.Architecture, Log);
PortablePackagePath = outputPath;
progress(100);
return Task.CompletedTask;
@@ -126,4 +128,4 @@ Categories={categories};
progress(-1); // there is only one "file", so progress will not work
return base.CreateDeltaPackage(progress, releasePkg, prevReleasePkg, outputPkg, mode);
}
-}
+}
\ No newline at end of file
diff --git a/src/Velopack.Packaging.Unix/Commands/OsxPackCommandRunner.cs b/src/Velopack.Packaging.Unix/Commands/OsxPackCommandRunner.cs
index aee11b5e..2254d681 100644
--- a/src/Velopack.Packaging.Unix/Commands/OsxPackCommandRunner.cs
+++ b/src/Velopack.Packaging.Unix/Commands/OsxPackCommandRunner.cs
@@ -32,7 +32,7 @@ public class OsxPackCommandRunner : PackageBuilder
var structure = new OsxStructureBuilder(dir.FullName);
var macosdir = structure.MacosDirectory;
File.WriteAllText(Path.Combine(macosdir, "sq.version"), GenerateNuspecContent());
- File.Copy(HelperFile.GetUpdatePath(RuntimeOs.OSX), Path.Combine(macosdir, "UpdateMac"), true);
+ File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), Path.Combine(macosdir, "UpdateMac"), true);
foreach (var f in Directory.GetFiles(macosdir, "*", SearchOption.AllDirectories)) {
if (BinDetect.IsMachOImage(f)) {
diff --git a/src/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs b/src/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs
index 0db992c2..3cdafa59 100644
--- a/src/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs
+++ b/src/Velopack.Packaging.Windows/Commands/WindowsPackCommandRunner.cs
@@ -46,7 +46,7 @@ public class WindowsPackCommandRunner : PackageBuilder
packDir = dir.FullName;
var updatePath = Path.Combine(TempDir.FullName, "Update.exe");
- File.Copy(HelperFile.GetUpdatePath(RuntimeOs.Windows), updatePath, true);
+ File.Copy(HelperFile.GetUpdatePath(Options.TargetRuntime, Log), updatePath, true);
// check for and delete clickonce manifest
var clickonceManifests = Directory.EnumerateFiles(packDir, "*.application")
diff --git a/src/Velopack.Packaging/HelperFile.cs b/src/Velopack.Packaging/HelperFile.cs
index 8a4b48f4..013a6df2 100644
--- a/src/Velopack.Packaging/HelperFile.cs
+++ b/src/Velopack.Packaging/HelperFile.cs
@@ -1,12 +1,13 @@
using System.Runtime.Versioning;
+using Microsoft.Extensions.Logging;
namespace Velopack.Packaging;
public static class HelperFile
{
- public static string GetUpdateExeName(RuntimeOs os)
+ private static string GetUpdateExeName(RID target, ILogger log)
{
- switch (os) {
+ switch (target.BaseRID) {
case RuntimeOs.Windows:
return FindHelperFile("update.exe");
#if DEBUG
@@ -16,16 +17,25 @@ public static class HelperFile
return FindHelperFile("update");
#else
case RuntimeOs.Linux:
- return FindHelperFile("UpdateNix");
+ if (!target.HasArchitecture) {
+ log.Warn("No architecture specified with --runtime, defaulting to x64. If this was not intended please specify via the --runtime parameter");
+ return FindHelperFile("UpdateNix_x64");
+ }
+
+ return target.Architecture switch {
+ RuntimeCpu.arm64 => FindHelperFile("UpdateNix_arm64"),
+ RuntimeCpu.x64 => FindHelperFile("UpdateNix_x64"),
+ _ => throw new PlatformNotSupportedException($"Update binary is not available for this platform ({target}).")
+ };
case RuntimeOs.OSX:
return FindHelperFile("UpdateMac");
#endif
- default:
- throw new PlatformNotSupportedException("Update binary is not available for this platform.");
}
+
+ throw new PlatformNotSupportedException($"Update binary is not available for this platform ({target}).");
}
- public static string GetUpdatePath(RuntimeOs os) => FindHelperFile(GetUpdateExeName(os));
+ public static string GetUpdatePath(RID target, ILogger log) => FindHelperFile(GetUpdateExeName(target, log));
public static string GetZstdPath()
{
@@ -73,7 +83,7 @@ public static class HelperFile
}
}
- private static List _searchPaths = new List();
+ private static readonly List _searchPaths = new List();
static HelperFile()
{
@@ -123,4 +133,4 @@ public static class HelperFile
return result;
}
-}
+}
\ No newline at end of file
diff --git a/src/Velopack.Packaging/PackageBuilder.cs b/src/Velopack.Packaging/PackageBuilder.cs
index 983b3b34..d30fdb6c 100644
--- a/src/Velopack.Packaging/PackageBuilder.cs
+++ b/src/Velopack.Packaging/PackageBuilder.cs
@@ -67,7 +67,6 @@ public abstract class PackageBuilder : ICommand
var packId = options.PackId;
var packDirectory = options.PackDirectory;
var packVersion = options.PackVersion;
- var semVer = SemanticVersion.Parse(packVersion);
// check that entry exe exists
var mainExeName = options.EntryExecutableName ?? options.PackId;