zoukankan      html  css  js  c++  java
  • 【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/

  • 相关阅读:
    i++和++i
    MySQL 5.6 for Windows 解压缩版配置安装-----------有点难看懂
    mysqld install报错:Install/Remove of the Service DeniedMy/Authentication plugin 'caching_sha
    mysql中,执行mysqld –install命令 、net start mysql命令出错的解决办法
    Mysql 服务无法启动 服务没有报告任何错误------------------mysql安装步骤
    mysql数据库安装步骤
    对io进行分流
    JDBC、mybatis、hibernate连接数据库
    当前电商行业的介绍
    MySQL常见常用的SQL优化
  • 原文地址:https://www.cnblogs.com/Aimeast/p/2987499.html
Copyright © 2011-2022 走看看