improved program direction and error handling

This commit is contained in:
2024-01-27 13:19:50 -06:00
parent 0861986563
commit 5eb89a953c
8 changed files with 164 additions and 37 deletions

View File

@@ -9,6 +9,7 @@ public abstract class BaseAction {
public virtual async Task<ActivityStatusCode> RunAsync()
{
await Task.Delay(0);
throw new NotImplementedException();
}
}

View File

@@ -69,7 +69,7 @@ public class Create : BaseAction
foreach (Repository newProject in newProjects)
{
GitHub.CloneProjectOptions options = new()
GitHub.GithubRepoOptions options = new()
{
BackupDir = anchorDir,
Repo = newProject,
@@ -91,11 +91,8 @@ public class Create : BaseAction
reporter.Stop();
if (verbose)
{
var report = reporter.ToString();
Console.WriteLine(report);
}
return ActivityStatusCode.Ok;
}

View File

@@ -21,8 +21,6 @@ namespace GitAnchor.Actions
string anchorName = args.FirstOrDefault(arg => arg.StartsWith("--name") || arg.StartsWith("-n"))?.Split("=")[1].Trim()
?? throw new Exception("No anchor name provided");
anchorName = anchorName.Split("=")[1].Trim();
// find (or create) the anchor in question
var anchor = Volumes.GetAnchor(mainBackupDir, anchorName) ?? FileSystemTools.SetUpAnchor(mainBackupDir, anchorName);
var projectDirectories = anchor?.GetDirectories();
@@ -50,7 +48,14 @@ namespace GitAnchor.Actions
if (verbose) Console.WriteLine($"Preparing pull task for {repo.Name}");
Task pullTask = new(() => GitHub.PullExistingRepo(repo, backupDir, verbose));
var options = new GitHub.GithubRepoOptions
{
Repo = repo,
BackupDir = backupDir,
Verbose = verbose,
};
Task pullTask = new(() => GitHub.PullExistingRepo(options));
taskPool.Add(pullTask);
}

View File

@@ -0,0 +1,44 @@
using System.Diagnostics;
using GitAnchor.Lib;
namespace GitAnchor.Actions;
public class Status : BaseAction
{
public new static async Task<ActivityStatusCode> RunAsync()
{
string[] args = Environment.GetCommandLineArgs();
// get main backup directory
var backupLocation = FileSystemTools.MainBackupFile;
var anchorName = CommandLineTools.ReadAnchorName();
var backupDir = new DirectoryInfo(Path.Join(backupLocation, anchorName));
// get all directories in main backup directory
var directories = backupDir.GetDirectories();
List<Task> taskPool = [];
foreach (var dir in directories)
{
GitHub.GithubRepoOptions options = new()
{
AnchorPath = Path.Join(backupDir.FullName, dir.Name),
BackupDir = backupDir,
ProjectPath = dir.Name,
};
taskPool.Add(Task.Run(() => GitHub.QueryStatus(options)));
}
using var reporter = new ProgressReporter();
reporter.Start();
await Parallel.ForEachAsync(taskPool, async(task, cancellationToken) => await task);
reporter.Stop();
Console.WriteLine(reporter.ToString());
return ActivityStatusCode.Ok;
}
}

View File

@@ -3,6 +3,12 @@ using Octokit;
namespace GitAnchor.Lib;
public static class CommandLineTools {
public static string? ReadAnchorName()
{
return Environment.GetCommandLineArgs().FirstOrDefault(arg => arg.StartsWith("--name") || arg.StartsWith("-n"))?
.Split("=")[1].Trim();
}
public static int ReadAsInt()
{
string? input = Console.ReadLine();

View File

@@ -1,3 +1,4 @@
using System.Runtime.InteropServices;
namespace GitAnchor.Lib;
public static class FileSystemTools {
@@ -77,7 +78,38 @@ public static class FileSystemTools {
private static DirectoryInfo? CreateMainWindowsDirectory(DriveInfo volume, string? location = ".git-anchor")
{
bool isSystemDrive = volume.Name == "C:\\";
OSPlatform platform;
if (OperatingSystem.IsWindows())
{
platform = OSPlatform.Windows;
}
else if (OperatingSystem.IsMacOS())
{
platform = OSPlatform.OSX;
}
else if (OperatingSystem.IsLinux())
{
platform = OSPlatform.Linux;
}
else
{
throw new Exception("Unsupported operating system");
}
bool isSystemDrive;
bool isExternalDrive;
if (platform == OSPlatform.Windows)
{
isSystemDrive = volume.Name == "C:\\";
isExternalDrive = volume.DriveType == DriveType.Removable && !isSystemDrive;
}
else
{
isSystemDrive = volume.Name == "/";
isExternalDrive = volume.DriveType == DriveType.Removable && !isSystemDrive;
}
try
{

View File

@@ -1,5 +1,6 @@
using Octokit;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace GitAnchor.Lib
{
@@ -80,23 +81,27 @@ namespace GitAnchor.Lib
return projectsToUpdate;
}
public record CloneProjectOptions
public record GithubRepoOptions
{
public User User { get; init; } = default!;
public Repository Repo { get; init; } = default!;
public DirectoryInfo BackupDir { get; init; } = default!;
public string Token { get; init; } = default!;
public User? User { get; init; } = default!;
public Repository? Repo { get; init; } = default!;
public string? ProjectPath { get; init; }
public string? Token { get; init; }
public string? AnchorPath { get; init; }
public bool Verbose { get; init; } = false;
public bool? Verbose { get; init; } = false;
}
public static void CloneProject(CloneProjectOptions options)
public static void CloneProject(GithubRepoOptions options)
{
if (options.User == null) throw new Exception("User not found");
if (options.Repo == null) throw new Exception("Repository not found");
string cloneString = "";
cloneString += $"clone https://{options.Token}@github.com/";
cloneString += $"{options.User.Login}/{options.Repo.Name} .";
Console.WriteLine($"Cloning {options.Repo.Name}...");
if (options.Verbose ?? false) Console.WriteLine($"Cloning {options.Repo.Name}...");
using (Process process = new())
{
@@ -104,21 +109,22 @@ namespace GitAnchor.Lib
{
FileName = "git",
Arguments = cloneString,
WorkingDirectory = $"{options.BackupDir}/{options.Repo.Name}",
WorkingDirectory = Path.Join(options.BackupDir.FullName, options.Repo.Name),
RedirectStandardOutput = true,
RedirectStandardError = true
};
process.Start();
if (options.Verbose) Console.WriteLine(process.StandardOutput.ReadToEnd());
if (options.Verbose ?? false) Console.WriteLine(process.StandardOutput.ReadToEnd());
process.WaitForExit();
Console.WriteLine($"Clone complete for {options.Repo.Name}");
};
}
public static void PullExistingRepo(Repository repo, DirectoryInfo backupDir, bool verbose = false)
public static void PullExistingRepo(GithubRepoOptions options)
{
Console.WriteLine($"Pulling {repo.Name}...");
if (options.Repo == null) throw new Exception("Repository not found");
Console.WriteLine($"Pulling {options.Repo.Name}...");
using (Process process = new())
{
@@ -126,15 +132,34 @@ namespace GitAnchor.Lib
{
FileName = "git",
Arguments = "pull",
WorkingDirectory = $"{backupDir}/{repo.Name}",
WorkingDirectory = Path.Join(options.BackupDir.FullName, options.Repo.Name),
RedirectStandardOutput = true,
RedirectStandardError = true
};
process.Start();
if (verbose) Console.WriteLine(process.StandardOutput.ReadToEnd());
if (options.Verbose ?? false) Console.WriteLine(process.StandardOutput.ReadToEnd());
process.WaitForExit();
Console.WriteLine($"Pull complete for {options.Repo.Name}");
};
}
public static void QueryStatus(GithubRepoOptions options)
{
using (Process process = new())
{
process.StartInfo = new()
{
FileName = "git",
Arguments = "status",
WorkingDirectory = Path.Join(options.BackupDir.FullName, options.Repo?.Name ?? options.ProjectPath ?? throw new Exception("Unable to determine working directory")),
RedirectStandardOutput = true,
RedirectStandardError = true
};
process.Start();
Console.WriteLine(process.StandardOutput.ReadToEnd());
process.WaitForExit();
Console.WriteLine($"Pull complete for {repo.Name}");
};
}
}

View File

@@ -1,25 +1,42 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Collections;
using System.Diagnostics;
using System.Reflection;
using GitAnchor.Actions;
using GitAnchor.Lib;
string[] inputArgs = Environment.GetCommandLineArgs();
// create pointers for entrypoints for each action
var createFn = typeof(Create).GetMethod("RunAsync", BindingFlags.Static | BindingFlags.Public);
var pullFn = typeof(Pull).GetMethod("RunAsync", BindingFlags.Static | BindingFlags.Public);
var statusFn = typeof(Status).GetMethod("RunAsync", BindingFlags.Static | BindingFlags.Public);
var listFn = typeof(List).GetMethod("Run", BindingFlags.Static | BindingFlags.Public);
var helpFn = typeof(Help).GetMethod("Run", BindingFlags.Static | BindingFlags.Public);
var AllOptions = new Hashtable()
{
{ "create", createFn },
{ "pull", pullFn },
{ "status", statusFn },
{ "list", listFn },
{ "help", helpFn },
};
try
{
foreach (string a in inputArgs)
{
string[] options = ["create", "pull", "list", "help"];
if (options.Contains(a))
var titleCase = a.ToUpperInvariant();
if (AllOptions.ContainsKey(a))
{
return a switch
var func = (MethodInfo)AllOptions[a];
var result = func?.Invoke(null, null);
if (result is Task<ActivityStatusCode> task)
{
"create" => (int)await Create.RunAsync(),
"pull" => (int)await Pull.RunAsync(),
"list" => (int)List.Run(),
"help" => (int)Help.Run(),
_ => (int)Help.Run(),
};
return (int)task.Result;
}
};
}