defined some more functions and their cli flags
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GitAnchor.Actions;
|
||||
delegate Task<ActivityStatusCode> CallableAction();
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10
git-anchor/Lib/Callable.cs
Normal file
10
git-anchor/Lib/Callable.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace GitAnchor.Lib;
|
||||
|
||||
public partial class ActionResult
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
delegate Task<T> Callable<T>();
|
||||
@@ -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:\\";
|
||||
|
||||
21
git-anchor/Lib/ProgressReporter.cs
Normal file
21
git-anchor/Lib/ProgressReporter.cs
Normal 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
5
git-anchor/Lib/Union.cs
Normal file
@@ -0,0 +1,5 @@
|
||||
namespace GitAnchor.Lib;
|
||||
|
||||
public class Union<T1, T2>
|
||||
{
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user