-
-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add caching for popular parts of git repositories
Add infrastructure for apps to speed up loading artifacts from paths into git repositories + Implement a method using a git program from the environment to perform a partial clone of a repository. + Provide a global switch to enable a cache for partial git files by commit. + Add an HTTP server for zip archives of partial git clone by commit.
- Loading branch information
Showing
9 changed files
with
604 additions
and
143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using System.IO; | ||
|
||
namespace Pine; | ||
|
||
public class CacheByFileName | ||
{ | ||
public string CacheDirectory { init; get; } | ||
|
||
public byte[] GetOrUpdate(string fileName, System.Func<byte[]> getNew) | ||
{ | ||
var cacheFilePath = Path.Combine(CacheDirectory, fileName); | ||
|
||
if (File.Exists(cacheFilePath)) | ||
{ | ||
try | ||
{ | ||
return File.ReadAllBytes(cacheFilePath); | ||
} | ||
catch { } | ||
} | ||
|
||
var file = getNew(); | ||
|
||
try | ||
{ | ||
Directory.CreateDirectory(Path.GetDirectoryName(cacheFilePath)); | ||
|
||
File.WriteAllBytes(cacheFilePath, file); | ||
} | ||
catch (System.Exception e) | ||
{ | ||
System.Console.WriteLine("Failed to write cache entry: " + e.ToString()); | ||
} | ||
|
||
return file; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
using Microsoft.AspNetCore.Builder; | ||
using Microsoft.AspNetCore.Http; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace Pine; | ||
|
||
/// <summary> | ||
/// This server packages popular parts of git repositories into zip archives and caches them. | ||
/// | ||
/// https://github.blog/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone/ | ||
/// </summary> | ||
public class GitPartialForCommitServer | ||
{ | ||
static public string ZipArchivePathPrefix => "/git/partial-for-commit/zip/"; | ||
|
||
static public string ZipArchivePathFromCommit(string commit) => ZipArchivePathPrefix + commit; | ||
|
||
static public Task Run( | ||
IReadOnlyList<string> urls, | ||
IReadOnlyList<string> gitCloneUrlPrefixes, | ||
string fileCacheDirectory) | ||
{ | ||
var builder = WebApplication.CreateBuilder(); | ||
var app = builder.Build(); | ||
|
||
app.Urls.Clear(); | ||
urls.ToList().ForEach(app.Urls.Add); | ||
|
||
var fileCache = new CacheByFileName | ||
{ | ||
CacheDirectory = Path.Combine(fileCacheDirectory, ZipArchivePathPrefix.TrimStart('/')) | ||
}; | ||
|
||
/* | ||
* https://docs.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0 | ||
* */ | ||
|
||
app.MapGet(ZipArchivePathPrefix + "{commitId}", (string commitId, HttpRequest httpRequest) => | ||
{ | ||
using var bodyReader = new StreamReader(httpRequest.Body); | ||
|
||
var bodyString = bodyReader.ReadToEndAsync().Result; | ||
|
||
var cloneUrls = bodyString.Split(new[] { '\n', '\r' }, System.StringSplitOptions.RemoveEmptyEntries); | ||
|
||
var supportedCloneUrls = | ||
cloneUrls | ||
.Where(c => gitCloneUrlPrefixes.Any(prefix => c.ToLowerInvariant().StartsWith(prefix.ToLowerInvariant()))) | ||
.ToImmutableList(); | ||
|
||
if (!cloneUrls.Any()) | ||
{ | ||
return Results.BadRequest("Missing clone URL. Use one line in the request body for each clone URL."); | ||
} | ||
|
||
if (!supportedCloneUrls.Any()) | ||
{ | ||
return Results.BadRequest( | ||
"None of the given clone URLs is enabled here. Only URLs with the following " + | ||
gitCloneUrlPrefixes.Count + " prefixes are supported: " + string.Join(", ", gitCloneUrlPrefixes)); | ||
} | ||
|
||
byte[] loadWithFreshClone() | ||
{ | ||
var files = | ||
LoadFromGitHubOrGitLab.GetRepositoryFilesPartialForCommitViaEnvironmentGitCheckout( | ||
cloneUrl: supportedCloneUrls[0], | ||
commit: commitId); | ||
|
||
var zipArchive = ZipArchive.ZipArchiveFromEntries(files); | ||
|
||
System.Console.WriteLine( | ||
"Cloned for commit " + commitId + ": Got " + files.Count + " files. Size of zip archive: " + zipArchive.Length + " bytes."); | ||
|
||
return zipArchive; | ||
} | ||
|
||
return Results.Bytes( | ||
contents: fileCache.GetOrUpdate(commitId, loadWithFreshClone), | ||
contentType: "application/zip", | ||
fileDownloadName: "git-partial-for-commit-" + commitId + ".zip"); | ||
}); | ||
|
||
return app.RunAsync(); | ||
} | ||
} |
Oops, something went wrong.