【C#】純託管實現一個Git服務端

來源:互聯網
上載者:User

      有傳聞說,這年頭不用Git就不是個程式員。傳聞歸傳聞,近些年來Git的發展是如火如荼。除了一些公用的Git平台外,大多的Git服務端都是在Linux上的,Windows的可選方案實在甚少。作為一個.Net碼農,當然希望能有個純Managed 程式碼的Git服務端。經過一晚上的學習,用純Managed 程式碼寫了個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,我不會告訴你這點代碼都是抄來的。

 

      重點是,所有的代碼都是Managed 程式碼。在Github.com上有個正在發展中的ASP.NET MVC + EF + Sqlite實現的Git服務端(Dudu推薦:用開源 ASP.NET MVC 程式 Bonobo Git Server 搭建 Git 伺服器)。經過幾天的試用之後覺得比較穩定。重點的重點是此服務端正處在發展初期,你完全可以根據自己需求打造一個最適合自己的Git服務端。PS,此repo的主人最近很活躍。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.