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()
|
public virtual async Task<ActivityStatusCode> RunAsync()
|
||||||
{
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class Create : BaseAction
|
|||||||
|
|
||||||
foreach (Repository newProject in newProjects)
|
foreach (Repository newProject in newProjects)
|
||||||
{
|
{
|
||||||
GitHub.CloneProjectOptions options = new()
|
GitHub.GithubRepoOptions options = new()
|
||||||
{
|
{
|
||||||
BackupDir = anchorDir,
|
BackupDir = anchorDir,
|
||||||
Repo = newProject,
|
Repo = newProject,
|
||||||
@@ -91,11 +91,8 @@ public class Create : BaseAction
|
|||||||
|
|
||||||
reporter.Stop();
|
reporter.Stop();
|
||||||
|
|
||||||
if (verbose)
|
var report = reporter.ToString();
|
||||||
{
|
Console.WriteLine(report);
|
||||||
var report = reporter.ToString();
|
|
||||||
Console.WriteLine(report);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ActivityStatusCode.Ok;
|
return ActivityStatusCode.Ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ namespace GitAnchor.Actions
|
|||||||
string anchorName = args.FirstOrDefault(arg => arg.StartsWith("--name") || arg.StartsWith("-n"))?.Split("=")[1].Trim()
|
string anchorName = args.FirstOrDefault(arg => arg.StartsWith("--name") || arg.StartsWith("-n"))?.Split("=")[1].Trim()
|
||||||
?? throw new Exception("No anchor name provided");
|
?? throw new Exception("No anchor name provided");
|
||||||
|
|
||||||
anchorName = anchorName.Split("=")[1].Trim();
|
|
||||||
|
|
||||||
// find (or create) the anchor in question
|
// find (or create) the anchor in question
|
||||||
var anchor = Volumes.GetAnchor(mainBackupDir, anchorName) ?? FileSystemTools.SetUpAnchor(mainBackupDir, anchorName);
|
var anchor = Volumes.GetAnchor(mainBackupDir, anchorName) ?? FileSystemTools.SetUpAnchor(mainBackupDir, anchorName);
|
||||||
var projectDirectories = anchor?.GetDirectories();
|
var projectDirectories = anchor?.GetDirectories();
|
||||||
@@ -50,7 +48,14 @@ namespace GitAnchor.Actions
|
|||||||
|
|
||||||
if (verbose) Console.WriteLine($"Preparing pull task for {repo.Name}");
|
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);
|
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;
|
namespace GitAnchor.Lib;
|
||||||
|
|
||||||
public static class CommandLineTools {
|
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()
|
public static int ReadAsInt()
|
||||||
{
|
{
|
||||||
string? input = Console.ReadLine();
|
string? input = Console.ReadLine();
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Runtime.InteropServices;
|
||||||
namespace GitAnchor.Lib;
|
namespace GitAnchor.Lib;
|
||||||
|
|
||||||
public static class FileSystemTools {
|
public static class FileSystemTools {
|
||||||
@@ -77,7 +78,38 @@ public static class FileSystemTools {
|
|||||||
|
|
||||||
private static DirectoryInfo? CreateMainWindowsDirectory(DriveInfo volume, string? location = ".git-anchor")
|
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
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Octokit;
|
using Octokit;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace GitAnchor.Lib
|
namespace GitAnchor.Lib
|
||||||
{
|
{
|
||||||
@@ -80,23 +81,27 @@ namespace GitAnchor.Lib
|
|||||||
return projectsToUpdate;
|
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 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 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 = "";
|
string cloneString = "";
|
||||||
cloneString += $"clone https://{options.Token}@github.com/";
|
cloneString += $"clone https://{options.Token}@github.com/";
|
||||||
cloneString += $"{options.User.Login}/{options.Repo.Name} .";
|
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())
|
using (Process process = new())
|
||||||
{
|
{
|
||||||
@@ -104,21 +109,22 @@ namespace GitAnchor.Lib
|
|||||||
{
|
{
|
||||||
FileName = "git",
|
FileName = "git",
|
||||||
Arguments = cloneString,
|
Arguments = cloneString,
|
||||||
WorkingDirectory = $"{options.BackupDir}/{options.Repo.Name}",
|
WorkingDirectory = Path.Join(options.BackupDir.FullName, options.Repo.Name),
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true
|
RedirectStandardError = true
|
||||||
};
|
};
|
||||||
|
|
||||||
process.Start();
|
process.Start();
|
||||||
if (options.Verbose) Console.WriteLine(process.StandardOutput.ReadToEnd());
|
if (options.Verbose ?? false) Console.WriteLine(process.StandardOutput.ReadToEnd());
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
Console.WriteLine($"Clone complete for {options.Repo.Name}");
|
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())
|
using (Process process = new())
|
||||||
{
|
{
|
||||||
@@ -126,15 +132,34 @@ namespace GitAnchor.Lib
|
|||||||
{
|
{
|
||||||
FileName = "git",
|
FileName = "git",
|
||||||
Arguments = "pull",
|
Arguments = "pull",
|
||||||
WorkingDirectory = $"{backupDir}/{repo.Name}",
|
WorkingDirectory = Path.Join(options.BackupDir.FullName, options.Repo.Name),
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true
|
RedirectStandardError = true
|
||||||
};
|
};
|
||||||
|
|
||||||
process.Start();
|
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();
|
process.WaitForExit();
|
||||||
Console.WriteLine($"Pull complete for {repo.Name}");
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,42 @@
|
|||||||
using System.Diagnostics;
|
using System.Collections;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
using GitAnchor.Actions;
|
using GitAnchor.Actions;
|
||||||
using GitAnchor.Lib;
|
|
||||||
|
|
||||||
string[] inputArgs = Environment.GetCommandLineArgs();
|
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
|
try
|
||||||
{
|
{
|
||||||
foreach (string a in inputArgs)
|
foreach (string a in inputArgs)
|
||||||
{
|
{
|
||||||
string[] options = ["create", "pull", "list", "help"];
|
var titleCase = a.ToUpperInvariant();
|
||||||
if (options.Contains(a))
|
|
||||||
|
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(),
|
return (int)task.Result;
|
||||||
"pull" => (int)await Pull.RunAsync(),
|
}
|
||||||
"list" => (int)List.Run(),
|
|
||||||
"help" => (int)Help.Run(),
|
|
||||||
_ => (int)Help.Run(),
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user