【C#】纯托管实现一个Git服务端

      有传闻说,这年头不用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:      class Program
  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/

转载于:https://www.cnblogs.com/Aimeast/archive/2013/03/28/2987499.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值