(GarUpdate): allow multiple versions of formats databases.

This commit is contained in:
morkt 2018-01-22 11:44:45 +04:00
parent 90b5d5f269
commit d4fd642cc7

View File

@ -68,9 +68,7 @@ namespace GARbro.GUI
public Version ReleaseVersion { get; set; } public Version ReleaseVersion { get; set; }
public Uri ReleaseUrl { get; set; } public Uri ReleaseUrl { get; set; }
public string ReleaseNotes { get; set; } public string ReleaseNotes { get; set; }
public int FormatsVersion { get; set; } public IEnumerable<FormatsDbInfo> FormatsData { get; set; }
public Uri FormatsUrl { get; set; }
public IDictionary<string, Version> Assemblies { get; set; }
public static GarUpdateInfo Parse (XmlDocument xml) public static GarUpdateInfo Parse (XmlDocument xml)
{ {
@ -82,14 +80,25 @@ namespace GARbro.GUI
ReleaseVersion = Version.Parse (GetInnerText (root.SelectSingleNode ("Release/Version"))), ReleaseVersion = Version.Parse (GetInnerText (root.SelectSingleNode ("Release/Version"))),
ReleaseUrl = new Uri (GetInnerText (root.SelectSingleNode ("Release/Url"))), ReleaseUrl = new Uri (GetInnerText (root.SelectSingleNode ("Release/Url"))),
ReleaseNotes = GetInnerText (root.SelectSingleNode ("Release/Notes")), ReleaseNotes = GetInnerText (root.SelectSingleNode ("Release/Notes")),
FormatsData = root.SelectNodes ("FormatsData").Cast<XmlNode>()
FormatsVersion = Int32.Parse (GetInnerText (root.SelectSingleNode ("FormatsData/FileVersion"))), .Select (node => new FormatsDbInfo {
FormatsUrl = new Uri (GetInnerText (root.SelectSingleNode ("FormatsData/Url"))), Version = Int32.Parse (GetInnerText (node.SelectSingleNode ("FileVersion"))),
Assemblies = ParseAssemblies (root.SelectNodes ("FormatsData/Requires/Assembly")), Url = new Uri (GetInnerText (node.SelectSingleNode ("Url"))),
Assemblies = ParseAssemblies (node.SelectNodes ("Requires/Assembly")),
}),
}; };
return info; return info;
} }
public FormatsDbInfo FindMatchingFormatsData (int current_version, IEnumerable<Assembly> assemblies)
{
var loaded = assemblies.Select (a => a.GetName()).ToDictionary (a => a.Name, a => a.Version);
// select first formats db that has greater version number and no new assemblies
return FormatsData.Where (f => f.Version > current_version)
.OrderByDescending (f => f.Version)
.FirstOrDefault (f => f.Assemblies.All (a => loaded.ContainsKey (a.Key) && loaded[a.Key] >= a.Value));
}
static string GetInnerText (XmlNode node) static string GetInnerText (XmlNode node)
{ {
// XXX node?.InnerText ?? "" // XXX node?.InnerText ?? ""
@ -111,6 +120,13 @@ namespace GARbro.GUI
} }
} }
public class FormatsDbInfo
{
public int Version { get; set; }
public Uri Url { get; set; }
public IDictionary<string, Version> Assemblies { get; set; }
}
internal sealed class GarUpdate : ICommand, IDisposable internal sealed class GarUpdate : ICommand, IDisposable
{ {
private readonly MainWindow m_main; private readonly MainWindow m_main;
@ -180,20 +196,22 @@ namespace GARbro.GUI
} }
UpdateDialog m_dialog; UpdateDialog m_dialog;
Uri m_formats_url; FormatsDbInfo m_formats_db;
private void ShowUpdateResult (GarUpdateInfo result) private void ShowUpdateResult (GarUpdateInfo result)
{ {
var app_version = Assembly.GetExecutingAssembly().GetName().Version; var app_version = Assembly.GetExecutingAssembly().GetName().Version;
var db_version = FormatCatalog.Instance.CurrentSchemeVersion;
bool has_app_update = app_version < result.ReleaseVersion; bool has_app_update = app_version < result.ReleaseVersion;
bool has_db_update = db_version < result.FormatsVersion && CheckAssemblies (result.Assemblies);
var loaded_assemblies = AppDomain.CurrentDomain.GetAssemblies();
m_formats_db = result.FindMatchingFormatsData (FormatCatalog.Instance.CurrentSchemeVersion, loaded_assemblies);
bool has_db_update = m_formats_db != null;
if (!has_app_update && !has_db_update) if (!has_app_update && !has_db_update)
{ {
m_main.SetStatusText (guiStrings.MsgUpToDate); m_main.SetStatusText (guiStrings.MsgUpToDate);
return; return;
} }
m_formats_url = result.FormatsUrl;
m_dialog = new UpdateDialog (result, has_app_update, has_db_update); m_dialog = new UpdateDialog (result, has_app_update, has_db_update);
m_dialog.Owner = m_main; m_dialog.Owner = m_main;
m_dialog.FormatsDownload.Click += StartFormatsDownload; m_dialog.FormatsDownload.Click += StartFormatsDownload;
@ -202,6 +220,8 @@ namespace GARbro.GUI
private async void StartFormatsDownload (object control, RoutedEventArgs e) private async void StartFormatsDownload (object control, RoutedEventArgs e)
{ {
if (null == m_formats_db || null == m_formats_db.Url)
return;
var dialog = m_dialog; var dialog = m_dialog;
try try
{ {
@ -212,7 +232,7 @@ namespace GARbro.GUI
using (var tmp_file = new GARbro.Shell.TemporaryFile (app_data_folder, Path.GetRandomFileName())) using (var tmp_file = new GARbro.Shell.TemporaryFile (app_data_folder, Path.GetRandomFileName()))
{ {
client.Timeout = RequestTimeout; client.Timeout = RequestTimeout;
await client.DownloadFileTaskAsync (m_formats_url, tmp_file.Name); await client.DownloadFileTaskAsync (m_formats_db.Url, tmp_file.Name);
m_main.App.DeserializeScheme (tmp_file.Name); m_main.App.DeserializeScheme (tmp_file.Name);
var local_formats_dat = Path.Combine (app_data_folder, App.FormatsDat); var local_formats_dat = Path.Combine (app_data_folder, App.FormatsDat);
@ -248,14 +268,7 @@ namespace GARbro.GUI
{ {
var loaded = AppDomain.CurrentDomain.GetAssemblies().Select (a => a.GetName()) var loaded = AppDomain.CurrentDomain.GetAssemblies().Select (a => a.GetName())
.ToDictionary (a => a.Name, a => a.Version); .ToDictionary (a => a.Name, a => a.Version);
foreach (var item in assemblies) return assemblies.All (a => loaded.ContainsKey (a.Key) && loaded[a.Key] >= a.Value);
{
if (!loaded.ContainsKey (item.Key))
return false;
if (loaded[item.Key] < item.Value)
return false;
}
return true;
} }
GarUpdateInfo Check (Uri version_url) GarUpdateInfo Check (Uri version_url)