improved program direction and error handling
This commit is contained in:
@@ -9,6 +9,7 @@ public abstract class BaseAction {
|
||||
|
||||
public virtual async Task<ActivityStatusCode> RunAsync()
|
||||
{
|
||||
await Task.Delay(0);
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
var report = reporter.ToString();
|
||||
Console.WriteLine(report);
|
||||
|
||||
return ActivityStatusCode.Ok;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
44
git-anchor/Actions/Status.cs
Normal file
44
git-anchor/Actions/Status.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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}");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user