Vše, co píše uživatel, míří přes novou třídu UzivatelskaData do profilu uživatele: cad.json, layout.json, error.log, tisk_diag.log. Dosud se zapisovalo vedle .exe, takže .exe v Program Files (složka jen pro čtení) nebo přeinstalace novou verzí uživatele o data připravily. Dodávané podklady (šablona, mustr, loga, mapovani.json) se dál čtou vedle .exe – ty se naopak při každé instalaci obnovují. Hranice mezi tím, co se instaluje, a tím, co patří uživateli, vede přesně tudy. Portable režim zůstává: soubor portable.txt vedle .exe vrátí staré chování (běh z USB, vývoj s jednou složkou). Migrace: Migrace.PrenesStaraData() při startu přenese cad.json a layout.json ze staré polohy, pokud v cíli ještě nejsou; originál označí příponou .migrovano. Nic se nemaže a nic novějšího se nepřepíše. Číselníky přijdou na řadu samostatně (rozpad na dodávanou a uživatelskou vrstvu). Build 0 chyb / 0 varování, 36 testů zelených. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
61 lines
2.8 KiB
C#
61 lines
2.8 KiB
C#
using System.IO;
|
||
|
||
namespace Rozpisky.Data;
|
||
|
||
/// <summary>
|
||
/// Jednorázový přesun dat starších verzí, které zapisovaly vedle .exe, do uživatelské složky
|
||
/// (<see cref="UzivatelskaData"/>). Bez toho by uživatel po aktualizaci našel prázdné číselníky
|
||
/// a přenastavený CAD. Volá se jednou při startu, ještě než si na data sáhne kterýkoli store.
|
||
/// <para>
|
||
/// Zásada: nikdy nic nemazat a nikdy nepřepsat novější data. Soubor se přenese jen tehdy, když
|
||
/// v cíli ještě není; originál zůstane ležet jako <c>*.migrovano</c> (jediná kopie uživatelových dat).
|
||
/// Selhání nesmí shodit start – horší než nepřenesená data je aplikace, která nenaběhne.
|
||
/// </para>
|
||
/// </summary>
|
||
public static class Migrace
|
||
{
|
||
/// <summary>Přípona, kterou dostane původní soubor po přenesení.</summary>
|
||
public const string PriponaHotovo = ".migrovano";
|
||
|
||
/// <summary>Přenese <c>cad.json</c> a <c>layout.json</c> ze složky aplikace do uživatelské.
|
||
/// Číselníky mají vlastní cestu (rozpad na vrstvy) – viz <see cref="CiselnikyStore"/>.</summary>
|
||
public static void PrenesStaraData()
|
||
{
|
||
Prenes(CadEnginesStoreNazev);
|
||
Prenes(LayoutConfigStoreNazev);
|
||
}
|
||
|
||
private const string CadEnginesStoreNazev = "cad.json";
|
||
private const string LayoutConfigStoreNazev = "layout.json";
|
||
|
||
/// <summary>Přesune soubor ze složky aplikace do uživatelské, pokud tam ještě není.
|
||
/// V portable režimu jsou obě složky totožné a neudělá se nic.</summary>
|
||
private static void Prenes(string nazevSouboru)
|
||
{
|
||
try
|
||
{
|
||
var zdroj = Path.Combine(AppContext.BaseDirectory, nazevSouboru);
|
||
var cil = UzivatelskaData.Cesta(nazevSouboru);
|
||
if (string.Equals(zdroj, cil, StringComparison.OrdinalIgnoreCase)) return;
|
||
if (!File.Exists(zdroj) || File.Exists(cil)) return;
|
||
|
||
File.Copy(zdroj, cil);
|
||
OznacJakoPrenesene(zdroj);
|
||
}
|
||
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException)
|
||
{
|
||
// Nezapisovatelná instalační složka apod. – data zůstanou tam, kde jsou, a zkusí se
|
||
// přenést zase příště. Start aplikace to zastavit nesmí.
|
||
}
|
||
}
|
||
|
||
/// <summary>Přejmenuje původní soubor na <c>*.migrovano</c>, aby se přenos neopakoval a aby
|
||
/// starší verze programu (kdyby ji uživatel vrátil) nezmátla už neaktuální data. Nedaří-li se
|
||
/// to (soubor jen pro čtení), nevadí – kopie v cíli už existuje a další běh přenos přeskočí.</summary>
|
||
internal static void OznacJakoPrenesene(string cesta)
|
||
{
|
||
try { File.Move(cesta, cesta + PriponaHotovo, overwrite: true); }
|
||
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException) { }
|
||
}
|
||
}
|