Add project files.

This commit is contained in:
2024-01-21 14:50:44 -06:00
parent 6b79cee2f1
commit 9fc8818cc1
6 changed files with 178 additions and 0 deletions

13
README.md Normal file
View File

@@ -0,0 +1,13 @@
# GitHub Repository Bookup Tool
This is a lightweight command line interface for backing up a GitHub user's repositories. Depending on permissions provided
during authentication, the tool can backup public and private repositories.
The tool is writting in C# and uses the Octokit.net library to interact with the GitHub API.
## Usage
The tool is a command line interface. It can be run from the command line or from a batch file. The tool requires a GitHub
Personal Access Token to be provided as a command line argument. The token can be generated from the GitHub website. It is
recommended that the user only provide the minimum permissions required to backup the repositories. GitHub provides a fine-grained
access token generator that makes this very simple.

25
repo-backup-util.sln Normal file
View File

@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34309.116
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "repo-backup-util", "repo-backup-util\repo-backup-util.csproj", "{352652F3-958B-416B-B5F5-CDC36B0AA0C4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{352652F3-958B-416B-B5F5-CDC36B0AA0C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{352652F3-958B-416B-B5F5-CDC36B0AA0C4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{352652F3-958B-416B-B5F5-CDC36B0AA0C4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{352652F3-958B-416B-B5F5-CDC36B0AA0C4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {46CA2A1B-A03D-4D97-9DDF-4BCABF53C54A}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,30 @@
// See https://aka.ms/new-console-template for more information
using Octokit;
using RepoBackupUtil.Lib;
static async Task Main()
{
// initialize our github client
ProductHeaderValue productHeaderValue = new("repo-backup-util");
GitHubClient github = new(productHeaderValue);
// check for user with received input
string username = GitHub.SetCredentialsToken(github);
User user = await GitHub.GetUser(username, github);
// get all repos for user
IEnumerable<Repository> repos = await GitHub.GetRepos(github) ?? throw new Exception("No repos found");
// organize and ensure all repositories are unique
HashSet<Repository> uniqueRepos = GitHub.GetUniqueRepos(repos);
// derive repository count and clone urls
var privateRepos = uniqueRepos.Where(r => r.Private);
var publicRepos = uniqueRepos.Where(r => !r.Private);
Console.WriteLine($"Found {privateRepos.Count()} private repos and {publicRepos.Count()} public repos.");
var cloneUrls = uniqueRepos.Select(r => r.CloneUrl);
}
await Main();

View File

@@ -0,0 +1,85 @@
using Octokit;
namespace RepoBackupUtil.Lib
{
public static class GitHub
{
public static string SetCredentialsToken(GitHubClient github)
{
Console.WriteLine("Please enter your Github Personal Access Token: ");
string? token = Console.ReadLine();
if (token == null)
{
Console.WriteLine("Received invalid input. Try again:");
return SetCredentialsToken(github);
}
else
{
AuthenticationType authType = AuthenticationType.Bearer;
Credentials auth = new(token, authType);
github.Credentials = auth;
Console.WriteLine("Successfully authenticated with GitHub.");
return github.User.Current().Result.Login;
}
}
public static string SetOAuthCredentials(GitHubClient github)
{
Console.WriteLine("Provide OAuth Client Secret: ");
string? clientSecret = Console.ReadLine();
if (clientSecret == null)
{
Console.WriteLine("Received invalid input. Try again:");
return SetOAuthCredentials(github);
}
else
{
Credentials auth = new(clientSecret, AuthenticationType.Oauth);
github.Credentials = auth;
Console.WriteLine("Successfully authenticated with GitHub.");
return github.User.Current().Result.Login;
}
}
public static async Task<User> GetUser(string username, GitHubClient github)
{
Console.WriteLine("Checking for user...");
User? user = await github.User.Get(username);
if (user == null)
{
Console.WriteLine("User does not exist");
string newUsername = SetCredentialsToken(github);
return await GetUser(newUsername, github);
}
else
{
Console.WriteLine($"Found user {user.Login}. Loading repos...");
return user;
}
}
public static async Task<IReadOnlyList<Repository>?> GetRepos(GitHubClient github)
{
Console.WriteLine("Loading repos...");
var repos = await github.Repository.GetAllForCurrent();
return repos;
}
public static HashSet<Repository> GetUniqueRepos(IEnumerable<Repository> repos)
{
HashSet<Repository> uniqueRepos = [];
int i = 0;
foreach (var repo in repos)
{
bool added = uniqueRepos.Add(repo);
Console.WriteLine($"{++i} - {(added ? "added" : null)}{repo.Name} - {(repo.Private ? "Private" : "Public")}");
}
return uniqueRepos;
}
}
}

View File

@@ -0,0 +1,10 @@
namespace RepoBackupUtil.Lib
{
public static class Volumes
{
public static IEnumerable<DriveInfo> GetVolumes()
{
return DriveInfo.GetDrives();
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>RepoBackupUtil</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Octokit" Version="9.1.0" />
</ItemGroup>
</Project>