设为首页 收藏本站
查看: 684|回复: 0

[经验分享] 【C#】纯托管实现一个Git服务端

[复制链接]

尚未签到

发表于 2018-1-14 20:35:34 | 显示全部楼层 |阅读模式
  有传闻说,这年头不用Git就不是个程序员。传闻归传闻,近些年来Git的发展是如火如荼。除了一些公共的Git平台外,大多的Git服务端都是在Linux上的,Windows的可选方案实在甚少。作为一个.Net码农,当然希望能有个纯托管代码的Git服务端。经过一晚上的学习,用纯托管代码写了个Git服务端供大家参考。
  学习资料:暂无。
  接下来开始码代码。首先加入引用:GitSharp.Core,GitSharp。可以从git://github.com/henon/GitSharp.git获取。然后,
   1:  using GitSharp.Core.Transport;  

  

   2:  using System;  

  

   3:  using System.IO;  

  

   4:  using System.Net;  

  

   5:  using System.Text;  

  

   6:  using System.Text.RegularExpressions;  

  

   7:     

  

   8:  namespace SampleGitServer  

  

   9:  {  

  

  10:     >  

  

  11:      {  

  

  12:          const string PREFIX = @"http://localhost:2034/";  

  

  13:          const string REPOSITORY_PATH = @"F:\Repositories\git-debug-ONLY";  

  

  14:     

  

  15:          readonly static Regex GetInfoRefsRegex = new Regex(PREFIX + @"\w{3,10}/info/refs\?service=.*");  

  

  16:          readonly static Regex GitUploadPackRegex = new Regex(PREFIX + @"\w{3,10}/git-upload-pack");  

  

  17:          readonly static Regex GitRecivePackRegex = new Regex(PREFIX + @"\w{3,10}/git-receive-pack");  

  

  18:     

  

  19:          static void Main(string[] args)  

  

  20:          {  

  

  21:              var listener = new HttpListener();  

  

  22:              listener.Prefixes.Add(PREFIX);  

  

  23:     

  

  24:              Console.WriteLine("Listening: " + PREFIX);  

  

  25:              listener.Start();  

  

  26:     

  

  27:              while (true)  

  

  28:              {  

  

  29:                  var context = listener.GetContext();  

  

  30:                  var url = context.Request.Url.ToString();  

  

  31:     

  

  32:                  Console.WriteLine(url);  

  

  33:     

  

  34:                  if (GetInfoRefsRegex.Match(url).Success)  

  

  35:                      GetInfoRefs(context);  

  

  36:                  else if (GitUploadPackRegex.Match(url).Success)  

  

  37:                      GitUploadPack(context);  

  

  38:                  else if (GitRecivePackRegex.Match(url).Success)  

  

  39:                      GitRecivePack(context);  

  

  40:              }  

  

  41:          }  

  

  42:     

  

  43:          private static void GetInfoRefs(HttpListenerContext context)  

  

  44:          {  

  

  45:              var Request = context.Request;  

  

  46:              var Response = context.Response;  

  

  47:              var project = Request.Url.PathAndQuery.Split('/')[1];  

  

  48:              var service = Request.QueryString["service"];  

  

  49:     

  

  50:              var directory = GetDirectoryInfo(project);  

  

  51:              if (GitSharp.Repository.IsValid(directory.FullName, true))  

  

  52:              {  

  

  53:                  Response.StatusCode = 200;  

  

  54:                  Response.ContentType = String.Format("application/x-{0}-advertisement", service);  

  

  55:                  SetNoCache(Response);  

  

  56:     

  

  57:                  var sb = new StringBuilder();  

  

  58:                  sb.Append(FormatMessage(String.Format("# service={0}\n", service)));  

  

  59:                  sb.Append(FlushMessage());  

  

  60:                  var bytes = Encoding.ASCII.GetBytes(sb.ToString());  

  

  61:                  Response.OutputStream.Write(bytes, 0, bytes.Length);  

  

  62:     

  

  63:                  using (var repository = new GitSharp.Repository(directory.FullName))  

  

  64:                  {  

  

  65:                      if (String.Equals("git-receive-pack", service, StringComparison.InvariantCultureIgnoreCase))  

  

  66:                      {  

  

  67:                          using (var pack = new ReceivePack(repository))  

  

  68:                          {  

  

  69:                              pack.SendAdvertisedRefs(new RefAdvertiser.PacketLineOutRefAdvertiser(new PacketLineOut(Response.OutputStream)));  

  

  70:                          }  

  

  71:     

  

  72:                      }  

  

  73:                      else if (String.Equals("git-upload-pack", service, StringComparison.InvariantCultureIgnoreCase))  

  

  74:                      {  

  

  75:                          using (var pack = new UploadPack(repository))  

  

  76:                          {  

  

  77:                              pack.SendAdvertisedRefs(new RefAdvertiser.PacketLineOutRefAdvertiser(new PacketLineOut(Response.OutputStream)));  

  

  78:                          }  

  

  79:                      }  

  

  80:                  }  

  

  81:              }  

  

  82:              else  

  

  83:              {  

  

  84:                  Response.StatusCode = 404;  

  

  85:              }  

  

  86:              Response.Close();  

  

  87:          }  

  

  88:     

  

  89:          private static void GitUploadPack(HttpListenerContext context)  

  

  90:          {  

  

  91:              var Request = context.Request;  

  

  92:              var Response = context.Response;  

  

  93:              var project = Request.Url.PathAndQuery.Split('/')[1];  

  

  94:     

  

  95:              Response.ContentType = "application/x-git-upload-pack-result";  

  

  96:              SetNoCache(Response);  

  

  97:     

  

  98:              var directory = GetDirectoryInfo(project);  

  

  99:              if (GitSharp.Repository.IsValid(directory.FullName, true))  

  

100:              {  

  

101:                  using (var repository = new GitSharp.Repository(directory.FullName))  

  

102:                  using (var pack = new UploadPack(repository))  

  

103:                  {  

  

104:                      pack.setBiDirectionalPipe(false);  

  

105:                      pack.Upload(Request.InputStream, Response.OutputStream, Response.OutputStream);  

  

106:                  }  

  

107:              }  

  

108:              else  

  

109:              {  

  

110:                  Response.StatusCode = 404;  

  

111:              }  

  

112:              Response.Close();  

  

113:          }  

  

114:     

  

115:          private static void GitRecivePack(HttpListenerContext context)  

  

116:          {  

  

117:              var Request = context.Request;  

  

118:              var Response = context.Response;  

  

119:              var project = Request.Url.PathAndQuery.Split('/')[1];  

  

120:     

  

121:              Response.ContentType = "application/x-git-receive-pack-result";  

  

122:              SetNoCache(Response);  

  

123:     

  

124:              var directory = GetDirectoryInfo(project);  

  

125:              if (GitSharp.Repository.IsValid(directory.FullName, true))  

  

126:              {  

  

127:                  using (var repository = new GitSharp.Repository(directory.FullName))  

  

128:                  using (var pack = new ReceivePack(repository))  

  

129:                  {  

  

130:                      pack.setBiDirectionalPipe(false);  

  

131:                      pack.receive(Request.InputStream, Response.OutputStream, Response.OutputStream);  

  

132:                  }  

  

133:              }  

  

134:              else  

  

135:              {  

  

136:                  Response.StatusCode = 404;  

  

137:              }  

  

138:              Response.Close();  

  

139:          }  

  

140:     

  

141:          private static String FormatMessage(String input)  

  

142:          {  

  

143:              return (input.Length + 4).ToString("X").PadLeft(4, '0') + input;  

  

144:          }  

  

145:     

  

146:          private static String FlushMessage()  

  

147:          {  

  

148:              return "0000";  

  

149:          }  

  

150:     

  

151:          private static DirectoryInfo GetDirectoryInfo(String project)  

  

152:          {  

  

153:              return new DirectoryInfo(Path.Combine(REPOSITORY_PATH, project));  

  

154:          }  

  

155:     

  

156:          private static void SetNoCache(HttpListenerResponse Response)  

  

157:          {  

  

158:              Response.AddHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");  

  

159:              Response.AddHeader("Pragma", "no-cache");  

  

160:              Response.AddHeader("Cache-Control", "no-cache, max-age=0, must-revalidate");  

  

161:          }  

  

162:      }  

  

163:  }  

  好吧,你看完代码会有一种上当的感觉。我必须承认我只是实现了服务端的接口而已。PS,我不会告诉你这点代码都是抄来的。
  重点是,所有的代码都是托管代码。
  

  .Net 托管实现的Git平台可以选择使用Git Candy了,功能比Bonobo更强大,速度更快、更稳定!
  
欢迎你的使用!
  源码在:http://github.com/Aimeast/GitCandy
  演示在:http://gitcandy.com
  Bonobo到GitCandy数据库转换程序:http://gitcandy.com/Repository/Tree/Bonobo2Candy/

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-435126-1-1.html 上篇帖子: GIT 使用小结 下篇帖子: git使用教程(二) 基础
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表