ASP.NET Core 2.0 开源Git HTTP Server,实现类似 GitHub、GitLab。
GitHub:https://github.com/linezero/GitServer
设置
"GitSettings": {
"BasePath": "D:\Git",
"GitPath": "git"
}
需要先安装Git,并确保git 命令可以执行,GitPath 可以是 git 的绝对路径。
目前实现的功能
- 创建仓库
- 浏览仓库
- git客户端push pull
- 数据库支持 SQLite、MSSQL、MySQL
- 支持用户管理仓库
更多功能可以查看readme,也欢迎大家贡献支持。
Git交互
LibGit2Sharp 用于操作Git库,实现创建读取仓库信息及删除仓库。
以下是主要代码:
public Repository CreateRepository(string name) { string path = Path.Combine(Settings.BasePath, name); Repository repo = new Repository(Repository.Init(path, true)); return repo; } public Repository CreateRepository(string name, string remoteUrl) { var path = Path.Combine(Settings.BasePath, name); try { using (var repo = new Repository(Repository.Init(path, true))) { repo.Config.Set("core.logallrefupdates", true); repo.Network.Remotes.Add("origin", remoteUrl, "+refs/*:refs/*"); var logMessage = ""; foreach (var remote in repo.Network.Remotes) { IEnumerable<string> refSpecs = remote.FetchRefSpecs.Select(x => x.Specification); Commands.Fetch(repo, remote.Name, refSpecs, null, logMessage); } return repo; } } catch { try { Directory.Delete(path, true); } catch { } return null; } } public void DeleteRepository(string name) { Exception e = null; for(int i = 0; i < 3; i++) { try { string path = Path.Combine(Settings.BasePath, name); Directory.Delete(path, true); } catch(Exception ex) { e = ex; } } if (e != null) throw new GitException("Failed to delete repository", e); }
执行Git命令
git-upload-pack
git-receive-pack
主要代码 GitCommandResult 实现IActionResult
public async Task ExecuteResultAsync(ActionContext context) { HttpResponse response = context.HttpContext.Response; Stream responseStream = GetOutputStream(context.HttpContext); string contentType = $"application/x-{Options.Service}"; if (Options.AdvertiseRefs) contentType += "-advertisement"; response.ContentType = contentType; response.Headers.Add("Expires", "Fri, 01 Jan 1980 00:00:00 GMT"); response.Headers.Add("Pragma", "no-cache"); response.Headers.Add("Cache-Control", "no-cache, max-age=0, must-revalidate"); ProcessStartInfo info = new ProcessStartInfo(_gitPath, Options.ToString()) { UseShellExecute = false, CreateNoWindow = true, RedirectStandardInput = true, RedirectStandardOutput = true, RedirectStandardError = true }; using (Process process = Process.Start(info)) { GetInputStream(context.HttpContext).CopyTo(process.StandardInput.BaseStream); if (Options.EndStreamWithNull) process.StandardInput.Write('