Unverified Commit a74a2d17 authored by Gaétan Lepage's avatar Gaétan Lepage Committed by GitHub
Browse files

tabularis: init at 0.9.12 (#503623)

parents cf511ff7 d33f8692
Loading
Loading
Loading
Loading
+543 −0
Original line number Diff line number Diff line
diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml
index e74f8c5..5333b4a 100644
--- a/src-tauri/Cargo.toml
+++ b/src-tauri/Cargo.toml
@@ -59,8 +59,5 @@ tauri-plugin-clipboard-manager = "2"
 [target.'cfg(target_os = "linux")'.dependencies]
 gtk = "0.18"
 
-[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
-tauri-plugin-updater = "2"
-
 [dev-dependencies]
 tempfile = "3.24.0"
diff --git a/src-tauri/capabilities/desktop.json b/src-tauri/capabilities/desktop.json
index ba6d080..3069583 100644
--- a/src-tauri/capabilities/desktop.json
+++ b/src-tauri/capabilities/desktop.json
@@ -9,6 +9,5 @@
     "main"
   ],
   "permissions": [
-    "updater:default"
   ]
-}
\ No newline at end of file
+}
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index a7a62b7..6010aca 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -21,7 +21,6 @@ pub mod ssh_tunnel;
 pub mod theme_commands;
 pub mod theme_models;
 pub mod task_manager;
-pub mod updater;
 pub mod plugins;
 pub mod drivers {
     pub mod common;
@@ -137,7 +136,6 @@ pub fn run() {
         .plugin(tauri_plugin_opener::init())
         .plugin(tauri_plugin_dialog::init())
         .plugin(tauri_plugin_fs::init())
-        .plugin(tauri_plugin_updater::Builder::new().build())
         .manage(commands::QueryCancellationState::default())
         .manage(export::ExportCancellationState::default())
         .manage(dump_commands::DumpCancellationState::default())
@@ -284,10 +282,6 @@ pub fn run() {
             dump_commands::import_database,
             dump_commands::cancel_import,
             dump_commands::cancel_dump,
-            // Updater
-            updater::check_for_updates,
-            updater::download_and_install_update,
-            updater::get_installation_source,
             // Logs
             log_commands::get_logs,
             log_commands::clear_logs,
diff --git a/src-tauri/src/updater.rs b/src-tauri/src/updater.rs
deleted file mode 100644
index 6351f27..0000000
--- a/src-tauri/src/updater.rs
+++ /dev/null
@@ -1,435 +0,0 @@
-use reqwest::Client;
-use serde::{Deserialize, Serialize};
-use std::fs;
-use std::path::PathBuf;
-use std::time::{SystemTime, UNIX_EPOCH};
-use tauri::Emitter;
-use tauri::{AppHandle, Manager};
-
-// Strutture dati
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct UpdateCheckResult {
-    pub has_update: bool,
-    pub current_version: String,
-    pub latest_version: String,
-    pub release_notes: String,
-    pub release_url: String,
-    pub published_at: String,
-    pub download_urls: Vec<DownloadAsset>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(rename_all = "camelCase")]
-pub struct DownloadAsset {
-    pub name: String,
-    pub url: String,
-    pub size: u64,
-    pub platform: String,
-}
-
-// Cache structure
-#[derive(Serialize, Deserialize, Debug, Clone)]
-struct UpdateCheckCache {
-    last_checked: u64,
-    last_result: Option<UpdateCheckResult>,
-}
-
-// GitHub API response
-#[derive(Deserialize, Debug)]
-struct GitHubRelease {
-    tag_name: String,
-    body: String,
-    html_url: String,
-    published_at: String,
-    assets: Vec<GitHubAsset>,
-}
-
-#[derive(Deserialize, Debug)]
-struct GitHubAsset {
-    name: String,
-    browser_download_url: String,
-    size: u64,
-}
-
-// Constants
-const GITHUB_REPO: &str = "debba/tabularis";
-const CACHE_DURATION_SECS: u64 = 43200; // 12 hours
-/// Returns the installation source: "snap", "aur", or None for direct installs.
-/// Only meaningful on Linux; always returns None on other platforms.
-fn detect_installation_source() -> Option<String> {
-    #[cfg(target_os = "linux")]
-    {
-        // Snap sets the SNAP env var when running inside a snap sandbox
-        if std::env::var("SNAP").is_ok() {
-            return Some("snap".to_string());
-        }
-
-        // Flatpak sets FLATPAK_ID when running inside a Flatpak sandbox
-        if std::env::var("FLATPAK_ID").is_ok() {
-            return Some("flatpak".to_string());
-        }
-
-        // AUR: check if pacman's local database has a tabularis-bin entry
-        if let Ok(entries) = std::fs::read_dir("/var/lib/pacman/local") {
-            let is_aur = entries
-                .filter_map(|e| e.ok())
-                .any(|e| e.file_name().to_string_lossy().starts_with("tabularis-bin-"));
-            if is_aur {
-                return Some("aur".to_string());
-            }
-        }
-    }
-
-    None
-}
-
-/// Returns true when updates should not be managed by the app itself.
-fn is_managed_package() -> bool {
-    detect_installation_source().is_some()
-}
-
-#[tauri::command]
-pub fn get_installation_source() -> Option<String> {
-    detect_installation_source()
-}
-
-// Helper functions
-fn get_cache_path(app: &AppHandle) -> Option<PathBuf> {
-    app.path()
-        .app_config_dir()
-        .ok()
-        .map(|p| p.join("update_check_cache.json"))
-}
-
-fn parse_version(version: &str) -> Option<(u32, u32, u32)> {
-    let clean = version.trim_start_matches('v');
-    let parts: Vec<&str> = clean.split('.').collect();
-    if parts.len() != 3 {
-        return None;
-    }
-
-    let major = parts[0].parse().ok()?;
-    let minor = parts[1].parse().ok()?;
-    let patch = parts[2].parse().ok()?;
-
-    Some((major, minor, patch))
-}
-
-fn is_newer_version(current: &str, latest: &str) -> bool {
-    match (parse_version(current), parse_version(latest)) {
-        (Some(c), Some(l)) => l > c,
-        _ => false,
-    }
-}
-
-async fn fetch_latest_release() -> Result<GitHubRelease, String> {
-    let client = Client::new();
-    let url = format!(
-        "https://api.github.com/repos/{}/releases/latest",
-        GITHUB_REPO
-    );
-
-    let res = client
-        .get(&url)
-        .header("User-Agent", "Tabularis")
-        .header("Accept", "application/vnd.github.v3+json")
-        .send()
-        .await
-        .map_err(|e| format!("Network error: {}", e))?;
-
-    if !res.status().is_success() {
-        return Err(format!("GitHub API error: {}", res.status()));
-    }
-
-    res.json::<GitHubRelease>()
-        .await
-        .map_err(|e| format!("Failed to parse response: {}", e))
-}
-
-fn categorize_asset(name: &str) -> String {
-    if name.ends_with(".dmg") || name.contains("darwin") || name.contains("macos") {
-        "macos".to_string()
-    } else if name.ends_with(".exe") || name.ends_with(".msi") || name.contains("windows") {
-        "windows".to_string()
-    } else if name.ends_with(".AppImage") || name.ends_with(".deb") || name.ends_with(".rpm") {
-        "linux".to_string()
-    } else {
-        "other".to_string()
-    }
-}
-
-// Tauri commands
-#[tauri::command]
-pub async fn check_for_updates(app: AppHandle, force: bool) -> Result<UpdateCheckResult, String> {
-    // Managed packages (AUR, Snap) should not use the built-in updater
-    if is_managed_package() {
-        return Err("Updates are managed by the package manager".to_string());
-    }
-
-    let config = crate::config::load_config_internal(&app);
-
-    // Check if updates are disabled
-    if !force && config.check_for_updates == Some(false) {
-        return Err("Update checks disabled".to_string());
-    }
-
-    // Check cache if not forced
-    if !force {
-        if let Some(cache_path) = get_cache_path(&app) {
-            if cache_path.exists() {
-                if let Ok(content) = fs::read_to_string(&cache_path) {
-                    if let Ok(cache) = serde_json::from_str::<UpdateCheckCache>(&content) {
-                        let now = SystemTime::now()
-                            .duration_since(UNIX_EPOCH)
-                            .unwrap_or_default()
-                            .as_secs();
-
-                        if now - cache.last_checked < CACHE_DURATION_SECS {
-                            if let Some(result) = cache.last_result {
-                                // Invalidate cache if the app was updated since it was written
-                                if result.current_version == env!("CARGO_PKG_VERSION") {
-                                    return Ok(result);
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    // Fetch latest release from GitHub
-    let release = fetch_latest_release().await?;
-
-    let current_version = env!("CARGO_PKG_VERSION");
-    let latest_version = release.tag_name.trim_start_matches('v');
-
-    let download_urls = release
-        .assets
-        .into_iter()
-        .map(|asset| DownloadAsset {
-            name: asset.name.clone(),
-            url: asset.browser_download_url,
-            size: asset.size,
-            platform: categorize_asset(&asset.name),
-        })
-        .collect();
-
-    let result = UpdateCheckResult {
-        has_update: is_newer_version(current_version, &release.tag_name),
-        current_version: current_version.to_string(),
-        latest_version: latest_version.to_string(),
-        release_notes: release.body,
-        release_url: release.html_url,
-        published_at: release.published_at,
-        download_urls,
-    };
-
-    // Save to cache
-    if let Some(cache_path) = get_cache_path(&app) {
-        let timestamp = SystemTime::now()
-            .duration_since(UNIX_EPOCH)
-            .unwrap_or_default()
-            .as_secs();
-
-        let cache = UpdateCheckCache {
-            last_checked: timestamp,
-            last_result: Some(result.clone()),
-        };
-
-        if let Ok(content) = serde_json::to_string(&cache) {
-            let _ = fs::write(cache_path, content);
-        }
-    }
-
-    Ok(result)
-}
-
-#[tauri::command]
-pub async fn download_and_install_update(app: AppHandle) -> Result<(), String> {
-    // Usa tauri-plugin-updater per gestire il download e installazione
-    use tauri_plugin_updater::UpdaterExt;
-
-    let updater = app.updater_builder().build().map_err(|e| e.to_string())?;
-
-    if let Some(update) = updater.check().await.map_err(|e| e.to_string())? {
-        // Emetti eventi per aggiornare la UI sul progresso
-        let mut downloaded = 0;
-
-        update
-            .download_and_install(
-                |chunk_length, content_length| {
-                    downloaded += chunk_length;
-                    let progress = if let Some(total) = content_length {
-                        (downloaded as f64 / total as f64 * 100.0) as u32
-                    } else {
-                        0
-                    };
-
-                    let _ = app.emit("update-progress", progress);
-                },
-                || {
-                    // Pre-installazione: salva stato, chiudi connessioni, etc.
-                    let _ = app.emit("update-installing", ());
-                },
-            )
-            .await
-            .map_err(|e| e.to_string())?;
-
-        app.restart();
-    } else {
-        Err("No update available".to_string())
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    // Version parsing tests
-    #[test]
-    fn test_version_parsing_standard() {
-        assert_eq!(parse_version("0.8.8"), Some((0, 8, 8)));
-        assert_eq!(parse_version("1.2.3"), Some((1, 2, 3)));
-        assert_eq!(parse_version("10.20.30"), Some((10, 20, 30)));
-    }
-
-    #[test]
-    fn test_version_parsing_with_v_prefix() {
-        assert_eq!(parse_version("v0.8.8"), Some((0, 8, 8)));
-        assert_eq!(parse_version("v1.0.0"), Some((1, 0, 0)));
-    }
-
-    #[test]
-    fn test_version_parsing_invalid() {
-        assert_eq!(parse_version("invalid"), None);
-        assert_eq!(parse_version("1.2"), None);
-        assert_eq!(parse_version("1.2.3.4"), None);
-        assert_eq!(parse_version("a.b.c"), None);
-        assert_eq!(parse_version(""), None);
-    }
-
-    #[test]
-    fn test_version_parsing_edge_cases() {
-        assert_eq!(parse_version("0.0.0"), Some((0, 0, 0)));
-        assert_eq!(parse_version("999.999.999"), Some((999, 999, 999)));
-    }
-
-    // Version comparison tests
-    #[test]
-    fn test_version_comparison_newer() {
-        assert!(is_newer_version("0.8.8", "0.9.0"));
-        assert!(is_newer_version("0.8.8", "0.8.9"));
-        assert!(is_newer_version("0.8.8", "1.0.0"));
-        assert!(is_newer_version("1.0.0", "2.0.0"));
-    }
-
-    #[test]
-    fn test_version_comparison_not_newer() {
-        assert!(!is_newer_version("0.8.8", "0.8.8"));
-        assert!(!is_newer_version("0.8.8", "0.8.7"));
-        assert!(!is_newer_version("0.8.8", "0.7.9"));
-        assert!(!is_newer_version("1.0.0", "0.9.9"));
-    }
-
-    #[test]
-    fn test_version_comparison_with_v_prefix() {
-        assert!(is_newer_version("0.8.8", "v0.9.0"));
-        assert!(is_newer_version("v0.8.8", "0.9.0"));
-        assert!(is_newer_version("v0.8.8", "v0.9.0"));
-    }
-
-    #[test]
-    fn test_version_comparison_invalid() {
-        assert!(!is_newer_version("invalid", "0.9.0"));
-        assert!(!is_newer_version("0.8.8", "invalid"));
-        assert!(!is_newer_version("invalid", "invalid"));
-    }
-
-    // Asset categorization tests
-    #[test]
-    fn test_categorize_asset_macos() {
-        assert_eq!(categorize_asset("Tabularis_0.8.8_x64.dmg"), "macos");
-        assert_eq!(categorize_asset("Tabularis_0.8.8_aarch64.dmg"), "macos");
-        assert_eq!(categorize_asset("tabularis-darwin.zip"), "macos");
-        assert_eq!(categorize_asset("app-macos-universal.tar.gz"), "macos");
-    }
-
-    #[test]
-    fn test_categorize_asset_windows() {
-        assert_eq!(categorize_asset("Tabularis_0.8.8_x64_setup.exe"), "windows");
-        assert_eq!(categorize_asset("tabularis.msi"), "windows");
-        assert_eq!(categorize_asset("app-windows-x86_64.zip"), "windows");
-    }
-
-    #[test]
-    fn test_categorize_asset_linux() {
-        assert_eq!(categorize_asset("tabularis_0.8.8_amd64.AppImage"), "linux");
-        assert_eq!(categorize_asset("tabularis_0.8.8_amd64.deb"), "linux");
-        assert_eq!(categorize_asset("tabularis-0.8.8-1.x86_64.rpm"), "linux");
-    }
-
-    #[test]
-    fn test_categorize_asset_other() {
-        assert_eq!(categorize_asset("README.txt"), "other");
-        assert_eq!(categorize_asset("checksums.sha256"), "other");
-        assert_eq!(categorize_asset("unknown-file"), "other");
-    }
-
-    // Cache path tests
-    #[test]
-    fn test_cache_filename() {
-        let expected = "update_check_cache.json";
-        assert!(expected.ends_with(".json"));
-        assert!(expected.contains("cache"));
-    }
-
-    // GitHub repo constant test
-    #[test]
-    fn test_github_repo_constant() {
-        assert_eq!(GITHUB_REPO, "debba/tabularis");
-    }
-
-    // Cache duration test
-    #[test]
-    fn test_cache_duration() {
-        assert_eq!(CACHE_DURATION_SECS, 43200); // 12 hours in seconds
-        assert_eq!(CACHE_DURATION_SECS / 3600, 12); // Verify it's 12 hours
-    }
-
-    // Mutex to serialize env var mutations across parallel tests
-    static ENV_MUTEX: std::sync::LazyLock<std::sync::Mutex<()>> =
-        std::sync::LazyLock::new(|| std::sync::Mutex::new(()));
-
-    // Installation source detection tests
-    #[test]
-    fn test_detect_installation_source_snap() {
-        let _lock = ENV_MUTEX.lock().unwrap();
-        std::env::remove_var("FLATPAK_ID");
-        std::env::set_var("SNAP", "/snap/tabularis/current");
-        let source = detect_installation_source();
-        std::env::remove_var("SNAP");
-        assert_eq!(source.as_deref(), Some("snap"));
-    }
-
-    #[test]
-    fn test_detect_installation_source_flatpak() {
-        let _lock = ENV_MUTEX.lock().unwrap();
-        std::env::remove_var("SNAP");
-        std::env::set_var("FLATPAK_ID", "io.github.debba.tabularis");
-        let source = detect_installation_source();
-        std::env::remove_var("FLATPAK_ID");
-        assert_eq!(source.as_deref(), Some("flatpak"));
-    }
-
-    #[test]
-    fn test_detect_installation_source_direct() {
-        let _lock = ENV_MUTEX.lock().unwrap();
-        std::env::remove_var("SNAP");
-        std::env::remove_var("FLATPAK_ID");
-        let source = detect_installation_source();
-        // On a dev/CI machine without pacman or tabularis-bin installed, must be None
-        assert!(source.is_none() || source.as_deref() == Some("aur"));
-    }
-}
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json
index 86395be..4fbab47 100644
--- a/src-tauri/tauri.conf.json
+++ b/src-tauri/tauri.conf.json
@@ -23,38 +23,5 @@
     "security": {
       "csp": null
     }
-  },
-  "bundle": {
-    "createUpdaterArtifacts": true,
-    "active": true,
-    "targets": "all",
-    "icon": [
-      "icons/32x32.png",
-      "icons/64x64.png",
-      "icons/128x128.png",
-      "icons/128x128@2x.png",
-      "icons/icon.png",
-      "icons/icon.icns",
-      "icons/icon.ico"
-    ],
-    "linux": {
-      "deb": {
-        "depends": [
-          "libwebkit2gtk-4.1-0",
-          "libsecret-1-0"
-        ]
-      },
-      "appimage": {
-        "bundleMediaFramework": false
-      }
-    }
-  },
-  "plugins": {
-    "updater": {
-      "endpoints": [
-        "https://github.com/debba/tabularis/releases/latest/download/latest.json"
-      ],
-      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDY0NzY0QjNEQjI4QjFEQjcKUldTM0hZdXlQVXQyWkRYdmRJOEJhVEpYTit2VXRYS0drTit1bmthSHVzcWlQK09Wb2l5cVpOWXAK"
-    }
   }
-}
\ No newline at end of file
+}
+76 −0
Original line number Diff line number Diff line
{
  lib,
  stdenv,
  rustPlatform,
  fetchFromGitHub,
  fetchPnpmDeps,
  cargo-tauri,
  nodejs,
  pnpm,
  pnpmConfigHook,
  wrapGAppsHook4,
  webkitgtk_4_1,
  pkg-config,
  openssl,
  nix-update-script,
}:
rustPlatform.buildRustPackage (finalAttrs: {
  pname = "tabularis";
  version = "0.9.12";

  src = fetchFromGitHub {
    owner = "debba";
    repo = "tabularis";
    tag = "v${finalAttrs.version}";
    hash = "sha256-kObjJ+C+0d/wLNt902yUPe8Cvss8d0ILeuo98vIiYDU=";
  };

  patches = [
    ./disable-updater.patch
  ];

  strictDeps = true;

  cargoRoot = "src-tauri";
  buildAndTestSubdir = finalAttrs.cargoRoot;

  cargoHash = "sha256-XYvwgZMJXM62kC8+DR06LygtTnL+8TLWyRZAgTQWf3Q=";

  pnpmDeps = fetchPnpmDeps {
    inherit (finalAttrs) pname version src;
    fetcherVersion = 3;
    hash = "sha256-S/XCypKyYlJtuISNiG8NtJzisAejiUwqPVltXEmVlZw=";
  };

  nativeBuildInputs = [
    cargo-tauri.hook

    nodejs
    pnpmConfigHook
    pnpm

    pkg-config
  ]
  ++ lib.optionals stdenv.hostPlatform.isLinux [ wrapGAppsHook4 ];

  buildInputs = [
    openssl
  ]
  ++ lib.optionals stdenv.hostPlatform.isLinux [
    webkitgtk_4_1
  ];

  env.OPENSSL_NO_VENDOR = 1;

  passthru.updateScript = nix-update-script { };

  meta = {
    description = "Lightweight, developer-focused database management tool, built with Tauri and React";
    homepage = "http://tabularis.dev";
    changelog = "https://github.com/debba/tabularis/blob/${finalAttrs.src.tag}/CHANGELOG.md";
    license = lib.licenses.mit;
    inherit (cargo-tauri.hook.meta) platforms;
    maintainers = with lib.maintainers; [ nartsiss ];
    mainProgram = "tabularis";
  };
})