defined some more functions and their cli flags

This commit is contained in:
2024-01-27 12:04:21 -06:00
parent 29643ae86d
commit ed03194471
12 changed files with 199 additions and 55 deletions

View File

@@ -1,9 +1,18 @@
using System.Diagnostics;
using GitAnchor.Lib;
namespace GitAnchor.Actions;
/** represent a function type matching either of the below class members */
// public delegate Task<ActivityStatusCode> Callable();
public abstract class BaseAction {
public virtual async Task<ActivityStatusCode> Run()
public virtual void Run()
{
throw new NotImplementedException();
}
public virtual async Task<ActivityStatusCode> RunAsync()
{
throw new NotImplementedException();
}

View File

@@ -1,4 +0,0 @@
using System.Diagnostics;
namespace GitAnchor.Actions;
delegate Task<ActivityStatusCode> CallableAction();

View File

@@ -5,11 +5,11 @@ using System.Diagnostics;
namespace GitAnchor.Actions;
public class Create : BaseAction
{
public new static async Task<ActivityStatusCode> Run()
public new static async Task<ActivityStatusCode> RunAsync()
{
string[] args = Environment.GetCommandLineArgs();
string? backupName = args.FirstOrDefault(arg => arg.StartsWith("--name"));
string? backupName = args.FirstOrDefault(arg => arg.StartsWith("--name") || arg.StartsWith("-n"));
string? token = args.FirstOrDefault(arg => arg.StartsWith("--token"));
bool verbose = args.Any(arg => arg.StartsWith("--verbose")
|| arg.StartsWith("-v"));
@@ -18,7 +18,7 @@ public class Create : BaseAction
DirectoryInfo backupDir = FileSystemTools.SetUpMainBackupFile() ?? throw new Exception("Encountered a problem creating main backup directory");
// create backup file
DirectoryInfo? anchorDir = SetUpAnchor(backupDir, backupName);
DirectoryInfo? anchorDir = FileSystemTools.SetUpAnchor(backupDir, backupName);
if (anchorDir == null)
{
@@ -68,40 +68,20 @@ public class Create : BaseAction
Console.WriteLine($"Preparing to clone {taskPool.Count} repositories. Starting...");
// start a timer to track progress
Stopwatch stopwatch = new();
stopwatch.Start();
ProgressReporter reporter = new();
reporter.Start();
// execute all tasks
Parallel.ForEach(taskPool, task => task.Start());
Task.WaitAll([.. taskPool]);
stopwatch.Stop();
long elapsed = stopwatch.ElapsedMilliseconds < 1000
? stopwatch.ElapsedMilliseconds
: stopwatch.ElapsedMilliseconds / 1000;
reporter.Stop();
string unit = stopwatch.ElapsedMilliseconds < 1000 ? "ms" : "s";
Console.WriteLine($"All tasks completed in {elapsed}{unit}. Exiting...");
if (verbose)
{
var report = reporter.ToString();
Console.WriteLine(report);
}
return ActivityStatusCode.Ok;
}
private static DirectoryInfo? SetUpAnchor(DirectoryInfo backupDir, string? initialInput)
{
string defaultName = FileSystemTools.DefaultAnchorPath;
string? backupName = initialInput;
if (backupName == null)
{
Console.WriteLine($"Enter a name for this backup: (default {defaultName})");
backupName = Console.ReadLine();
if (backupName == "") backupName = defaultName;
}
if (backupName == null || backupName == "") throw new Exception("No backup name provided");
// create backup file
return Volumes.CreateAnchor(backupDir, backupName);
}
}

View File

@@ -4,7 +4,7 @@ namespace GitAnchor.Actions;
public class Help : BaseAction
{
public static async new Task<ActivityStatusCode> Run()
public static new ActivityStatusCode Run()
{
Console.WriteLine("\nGitAnchor - a tool for performing scoped backups of GitHub repositories based on credentials and configuration.");
Console.WriteLine("Usage:\n");

View File

@@ -1,10 +1,34 @@
using System.Diagnostics;
using GitAnchor.Lib;
namespace GitAnchor.Actions;
class List : BaseAction
{
static async new Task<ActivityStatusCode> Run()
public static new ActivityStatusCode Run()
{
// get main backup directory
var backupLocation = FileSystemTools.MainBackupFile;
var backupDir = new DirectoryInfo(backupLocation ?? throw new Exception("No main backup found"));
string first = "";
// get all directories in main backup directory
var directories = backupDir.GetDirectories();
Console.WriteLine("Found the following backups:\n");
// print all directories
foreach (var dir in directories)
{
if (first == "") first = dir.Name;
long size = FileSystemTools.GetBackupSize(dir);
long sizeInGBs = Volumes.GetSizeInGB(size);
long sizeInMBs = Volumes.GetSizeInMB(size);
Console.WriteLine($"{dir.Name} - {(sizeInGBs > 0 ? sizeInGBs : sizeInMBs)}{(sizeInGBs > 0 ? "GB" : "MB")}");
}
Console.WriteLine("\nUse git-anchor pull --name=<name> to pull a backup.");
Console.WriteLine($"Example: git-anchor pull --name={first} -v\n");
return ActivityStatusCode.Ok;
}

View File

@@ -1,12 +1,73 @@
using System.Diagnostics;
using GitAnchor.Lib;
using GitAnchor.Actions;
using Octokit;
namespace GitAnchor.Actions
{
internal class Pull : BaseAction
{
public static async new Task<ActivityStatusCode> Run()
public new static async Task<ActivityStatusCode> RunAsync()
{
throw new NotImplementedException();
string[] args = Environment.GetCommandLineArgs();
// get main backup
var backupLocation = FileSystemTools.MainBackupFile;
var mainBackupDir = new DirectoryInfo(backupLocation ?? throw new Exception("No main backup found"));
// act on provided arguments
string? token = args.FirstOrDefault(arg => arg.StartsWith("--token"));
bool verbose = args.Any(arg => arg.StartsWith("--verbose") || arg.StartsWith("-v"));
string? anchorName = args.FirstOrDefault(arg => arg.StartsWith("--name") || arg.StartsWith("-n"))
?? throw new Exception("No anchor name provided");
// find (or create) the anchor in question
var anchor = Volumes.GetAnchor(mainBackupDir, anchorName) ?? FileSystemTools.SetUpAnchor(mainBackupDir, anchorName);
var projectDirectories = anchor?.GetDirectories();
if (projectDirectories == null)
{
Console.WriteLine("No projects found in anchor.");
return ActivityStatusCode.Error;
}
// set up our github connection
GitHubClient github = GitHub.CreateClient();
token = GitHub.Authenticate(github, token);
var repoList = await GitHub.GetRepos(github);
// set up a task pool for all pull jobs
List<Task> taskPool = [];
// iterate through all projects and prepare jobs
foreach (DirectoryInfo backupDir in projectDirectories)
{
var repo = repoList?.Where(r => r.Name == backupDir.Name).FirstOrDefault();
if (repo == null) continue;
if (verbose) Console.WriteLine($"Preparing pull task for {repo.Name}");
Task pullTask = new(() => GitHub.PullExistingRepo(repo, backupDir, verbose));
taskPool.Add(pullTask);
}
// start progress tracker
ProgressReporter reporter = new();
reporter.Start();
Parallel.ForEach(taskPool, task => task.Start());
Task.WaitAll([.. taskPool]);
reporter.Stop();
if (verbose)
{
var report = reporter.ToString();
Console.WriteLine(report);
}
return ActivityStatusCode.Ok;
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Diagnostics;
namespace GitAnchor.Lib;
public partial class ActionResult
{
}
delegate Task<T> Callable<T>();

View File

@@ -21,6 +21,17 @@ public static class FileSystemTools {
get => Volumes.FindMainBackupFile();
}
public static long GetBackupSize(DirectoryInfo dir)
{
long size = 0;
foreach (FileInfo fi in dir.GetFiles("*", SearchOption.AllDirectories))
{
size += fi.Length;
}
return size;
}
public static DirectoryInfo? SetUpMainBackupFile()
{
IEnumerable<DriveInfo> volumes = Volumes.GetVolumes();
@@ -46,6 +57,24 @@ public static class FileSystemTools {
throw new Exception("Unsupported operating system");
}
public static DirectoryInfo? SetUpAnchor(DirectoryInfo backupDir, string? initialInput)
{
string defaultName = FileSystemTools.DefaultAnchorPath;
string? backupName = initialInput;
if (backupName == null)
{
Console.WriteLine($"Enter a name for this backup: (default {defaultName})");
backupName = Console.ReadLine();
if (backupName == "") backupName = defaultName;
}
if (backupName == null || backupName == "") throw new Exception("No backup name provided");
// create backup file
return Volumes.CreateAnchor(backupDir, backupName);
}
private static DirectoryInfo? CreateMainWindowsDirectory(DriveInfo volume, string? location = ".git-anchor")
{
bool isSystemDrive = volume.Name == "C:\\";

View File

@@ -0,0 +1,21 @@
using System.Diagnostics;
namespace GitAnchor.Lib;
public class ProgressReporter : Stopwatch
{
public ProgressReporter()
{
}
public override string ToString()
{
var elapsed = this.ElapsedMilliseconds < 1000
? this.ElapsedMilliseconds
: this.ElapsedMilliseconds / 1000;
string unit = this.ElapsedMilliseconds < 1000 ? "ms" : "s";
return $"All tasks completed in {elapsed}{unit}. Exiting...";
}
}

5
git-anchor/Lib/Union.cs Normal file
View File

@@ -0,0 +1,5 @@
namespace GitAnchor.Lib;
public class Union<T1, T2>
{
}

View File

@@ -72,6 +72,11 @@ public static class Volumes
return backupDir.CreateSubdirectory(anchorName);
}
public static DirectoryInfo? GetAnchor(DirectoryInfo backupDir, string anchorName)
{
return backupDir.GetDirectories().FirstOrDefault(dir => dir.Name == anchorName);
}
public static string? FindMainBackupFile()
{
// find a folder entitled `.ghbackups`
@@ -92,7 +97,10 @@ public static class Volumes
return null;
}
public static double GetSizeInGB(DriveInfo volume) => volume.TotalSize / 1024 / 1024 / 1024;
public static long GetSizeInMB(long bytes) => bytes / 1024 / 1024;
public static long GetSizeInGB(long bytes) => bytes / 1024 / 1024 / 1024;
public static long GetSizeInGB(DriveInfo volume) => volume.TotalSize / 1024 / 1024 / 1024;
public static HashSet<Repository> PopulateBackupDirectories(HashSet<Repository> repos, DirectoryInfo backupDir)
{

View File

@@ -1,28 +1,29 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using GitAnchor.Actions;
using GitAnchor.Lib;
string[] inputArgs = Environment.GetCommandLineArgs();
SortedDictionary<string, CallableAction> options = new()
{
{ "create", Create.Run },
{ "pull", Pull.Run },
{ "help", Help.Run }
};
try
{
foreach (string a in inputArgs)
{
if (a == "") continue;
var result = options.TryGetValue(a, out CallableAction? action);
if (!result) continue;
if (action != null) return (int)await action();
string[] options = ["create", "pull", "list", "help"];
if (options.Contains(a))
{
return a switch
{
"create" => (int)await Create.RunAsync(),
"pull" => (int)await Pull.RunAsync(),
"list" => (int)List.Run(),
"help" => (int)Help.Run(),
_ => (int)Help.Run(),
};
};
}
return (int)await Help.Run();
return (int)Help.Run();
}
catch (Exception ex)
{