Skip to content

Commit

Permalink
Added restore progress bar
Browse files Browse the repository at this point in the history
  • Loading branch information
GPhMbe committed Feb 18, 2024
1 parent af9c83f commit 0edecb7
Show file tree
Hide file tree
Showing 6 changed files with 288 additions and 32 deletions.
8 changes: 3 additions & 5 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@


# To do
- Selectable config
- Selectable config (Exist on command line)
- Replace SaveDialog by Treeview for directories
- Wiki documentation

## Delayed
- Add information when restoring (restic didn't give information for now, but in progress : https://github.com/restic/restic/issues/3413#event-9556227439)

## Done
- ~~For local repo, show real used space~~
- ~~Add repo migration to V2 for using compression~~
- ~~Command line options : for config location, for help~~
- ~~Add cache for summary when no action made in submenu~~
- ~~Adding extra parameters in setup form for pass to restic~~
-
- ~~Add information when restoring (restic didn't give information for now, but in progress : https://github.com/restic/restic/issues/3413#event-9556227439)~~

# Ideas
- Clipboard use
- Cached summary
Expand Down
12 changes: 6 additions & 6 deletions resticterm/Models/Restore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@

namespace resticterm.Models
{
class Restore
public class Restore
{
// Common
public string message_type { get; set; }
public int total_files { get; set; }
public int total_bytes { get; set; }
public ulong total_files { get; set; }
public ulong total_bytes { get; set; }

// Only "message_type":"status"
public int percent_done { get; set; }
public float percent_done { get; set; }

// Only "message_type":"summary"
public int files_restored { get; set; }
public int bytes_restored { get; set; }
public ulong files_restored { get; set; }
public ulong bytes_restored { get; set; }
}

}
52 changes: 34 additions & 18 deletions resticterm/Restic/Restic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using resticterm.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Text.Json;
Expand Down Expand Up @@ -31,7 +32,7 @@ public class Restic
/// Report the current state of backup
/// </summary>
/// <param name="message">Action or message</param>
/// <param name="percent">0 to 1 = Progress bar ans current action. -1 = information message</param>
/// <param name="percent">0 to 1 = Progress bar and current action. -1 = information message</param>
protected void OnProgress(String message, float percent)
{
if (Progress != null) Progress(message, percent);
Expand All @@ -44,7 +45,7 @@ public Restic(String repoPath, String encryptedPassword)
_run = new Run(repoPath, encryptedPassword);
}


public void ForceRefreshSummaryCache()
{
_CacheRefreshNeeded = true;
Expand Down Expand Up @@ -181,21 +182,26 @@ public void Backup()
return files;
}

public String Restore(String snapshotID, String filepath, String filenameToRestore)
public void Restore(String snapshotID, String filepath, String filenameToRestore)
{
var command = "restore ";
command += " --target \"" + filepath + "\"";
command += " --include \"" + filenameToRestore + "\"";
command += " -v";
command += " " + snapshotID;
_run.RestoreStatus += RestoreStatus;

//var command = "dump " + currentSnapshotId;
//command += " \"" +filenameToRestore+ "\"";
//command += " --archive \"zip\"";
////command += " > " + Path.Combine(saveDialog.FilePath.ToString(), saveDialog.FileName.ToString());
OnProgress("\nStart", -1);
OnProgress("Started", 0);

// TODO : Event for each line
return Program.restic._run.Start(command);

var summary = _run.StartRestore(snapshotID, filepath, filenameToRestore);
OnProgress("Done", 100);
OnProgress("End\n", -1);
if (summary.message_type == "error")
{
OnProgress("Error !" , -1);
}
else
{
OnProgress("Files restored : " + summary.files_restored.ToString(), -1);
}
_run.RestoreStatus -= RestoreStatus;
}

public String Remove(String snapshotID)
Expand Down Expand Up @@ -229,7 +235,7 @@ public String Create()

var uncryptedPassword = Program.dataManager.config.GetRepoPassword();
rep = Run.RemoveESC(_run.Start("init", -1, uncryptedPassword + "\n" + uncryptedPassword));
_CacheRefreshNeeded = true;
_CacheRefreshNeeded = true;
return rep.Replace("\r", "");
}

Expand All @@ -238,7 +244,7 @@ public String Purge()
String rep;
//forget--keep - last 1--prune
rep = Run.RemoveESC(_run.Start("forget --keep-last " + Program.dataManager.config.KeepLastSnapshots.ToString() + " --prune"));
_CacheRefreshNeeded = true;
_CacheRefreshNeeded = true;
return rep.Replace("\r", "");
}

Expand All @@ -247,7 +253,7 @@ public String Prune()
String rep;
//forget--keep - last 1--prune
rep = "\n" + Run.RemoveESC(_run.Start("prune"));
_CacheRefreshNeeded = true;
_CacheRefreshNeeded = true;
return rep.Replace("\r", "");
}

Expand All @@ -257,7 +263,7 @@ public String UpgradeV2()
var uncryptedPassword = Program.dataManager.config.GetRepoPassword();

rep = "\n" + Run.RemoveESC(_run.Start("migrate upgrade_repo_v2", -1, uncryptedPassword + "\n" + uncryptedPassword));
_CacheRefreshNeeded = true;
_CacheRefreshNeeded = true;
return rep.Replace("\r", "");
}

Expand Down Expand Up @@ -298,6 +304,16 @@ private void BackupStatus(Status status)
OnProgress(ms, status.percent_done);
}


private void RestoreStatus(Models.Restore status)
{
String ms = String.Empty;

// File count
ms += "Files: " + status.files_restored.ToString() + " / " + status.total_files.ToString();
OnProgress(ms, status.percent_done);
}

public static string RemoveFirstLines(string text, int linesCount)
{
var lines = System.Text.RegularExpressions.Regex.Split(text, "\r\n|\r|\n").Skip(linesCount);
Expand Down
114 changes: 113 additions & 1 deletion resticterm/Restic/Run.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using resticterm.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
Expand All @@ -14,6 +15,7 @@
namespace resticterm.Restic
{
public delegate void BackupStatusHandler(Status status);
public delegate void RestoreStatusHandler(Restore status);

/// <summary>
/// Running restic binary
Expand All @@ -27,11 +29,17 @@ public class Run

#region "Events"
public event BackupStatusHandler BackupStatus;
public event RestoreStatusHandler RestoreStatus;

protected void OnBackupStatus(Status status)
{
if (BackupStatus != null) BackupStatus(status);
}

protected void OnRestoreStatus(Models.Restore status)
{
if (RestoreStatus != null) RestoreStatus(status);
}
#endregion

public Run(String repoPath, String encryptedPassword)
Expand Down Expand Up @@ -213,6 +221,110 @@ public Summary StartBackup(String source, String flags = "")

}

/// <summary>
/// Do restore with events
/// </summary>
/// <param name="snapshotID">source snapshot</param>
/// <param name="filepath">Target</param>
/// <param name="filenameToRestore">filname or folder to restore</param>
/// <returns>Summary of restore. If error, message_type = "error"</returns>
public Models.Restore StartRestore(String snapshotID, String filepath, String filenameToRestore)
{
var p = new Process();
var psi = new ProcessStartInfo();
Models.Restore ret;

// Binary
psi.WorkingDirectory = Path.Combine(Directory.GetCurrentDirectory(), "Restic");
if (OperatingSystem.IsWindows())
{
psi.FileName = Path.Combine(psi.WorkingDirectory, "restic.exe");
}
else
{
psi.FileName = Path.Combine(psi.WorkingDirectory, "restic");
}
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.UseShellExecute = false;
psi.EnvironmentVariables.Add("RESTIC_PASSWORD", Libs.Cryptography.Decrypt(_EncryptedPassword, Program.dataManager.config.MasterPassword));

var command = "restore ";
command += " --target \"" + filepath + "\"";
command += " --include \"" + filenameToRestore + "\"";
//command += " -v";
command += " " + snapshotID;
command += GetRepo() + " --json ";
psi.Arguments = command;

p.StartInfo = psi;
p.Start();

// Running
String summary = String.Empty;
var errorTask = p.StandardError.ReadLineAsync();
var statusTask = p.StandardOutput.ReadLineAsync();
while (!p.HasExited)
{
// Outpout
if (statusTask.IsCompleted)
{
var line = statusTask.Result;
statusTask = p.StandardOutput.ReadLineAsync();
if (!String.IsNullOrWhiteSpace(line))
{
if (line.Contains("\"message_type\":\"status\""))
{
var status = JsonSerializer.Deserialize<Restore>(RemoveESC(line));
OnRestoreStatus(status);
}
else if (line.Contains("\"message_type\":\"summary\""))
{
summary = line;
}
}
}

// Error
if (errorTask.IsCompleted)
{
var error = errorTask.Result;
errorTask = p.StandardError.ReadLineAsync();
if (!String.IsNullOrWhiteSpace(error))
{
if (error.Contains("error,"))
{
if (Views.DialogBackupError.AskQuitOnError(error))
{
p.Kill(true);
}
}
}
}
}

// End
if (p.ExitCode == 0)
{
if (String.IsNullOrWhiteSpace(summary))
summary = statusTask.Result;

if (!String.IsNullOrWhiteSpace(summary) && summary.Contains("\"message_type\":\"summary\""))
ret = JsonSerializer.Deserialize<Restore>(RemoveESC(summary));
else
ret = new Restore { message_type = "error"}; // TODO : return error message
}
else
{
var error = errorTask.Result;
ret = new Restore { message_type = "error"};
}
p.Close();
p.Dispose();
return ret;

}

/// <summary>
/// Remove VT100 escape code from string
/// </summary>
Expand Down
9 changes: 7 additions & 2 deletions resticterm/Views/UI_Files.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,13 @@ void FileRestore()
Application.Run(openDialog);
if (!openDialog.Canceled)
{
var ret = Program.restic.Restore(currentSnapshotId, openDialog.FilePaths[0].ToString(), filenameToRestore);
MessageBox.Query("File(s) save", ret, "Ok");
//var ret = Program.restic.Restore(currentSnapshotId, openDialog.FilePaths[0].ToString(), filenameToRestore);
//MessageBox.Query("File(s) restored", ret, "Ok");
if (Application.Top.IsCurrentTop)
{
var rest = new Views.UI_Restore();
rest.ShowModal(currentSnapshotId, openDialog.FilePaths[0].ToString(), filenameToRestore);
}
}
}

Expand Down
Loading

0 comments on commit 0edecb7

Please sign in to comment.