使用自定义HTTP传输对command.fetch进行AccessViolation

时间:2018-06-19 13:44:22

标签: c# git http libgit2sharp

我从

测试了自定义的Git HTTP SmartTransport扩展

https://github.com/gasparnagy/Sample_NtlmGitTest/blob/master/NtlmGitTest/HttpClientSmartSubtransport.cs

克隆命令有效,但通过Commands.Fetch由于AccessViolation无效。我希望任何人都能提供帮助。

LibGit2Sharp版本:0.24.0.0

Callstack:

  

北LibGit2Sharp.Core.NativeMethods.git_remote_fetch(git_remote *   远程,GitStrArray&refspecs,GitFetchOptions fetch_opts,字符串   log_message)北   LibGit2Sharp.Core.Proxy.git_remote_fetch(RemoteHandle远程,   IEnumerable 1 refSpecs, GitFetchOptions fetchOptions, String logMessage) in C:\projects\libgit2sharp\LibGit2Sharp\Core\Proxy.cs:Zeile 2268. bei LibGit2Sharp.Commands.Fetch(Repository repository, String remote, IEnumerable 1 refspecs,FetchOptions选项,String logMessage)   C:\ projects \ libgit2sharp \ LibGit2Sharp \ Commands \ Fetch.cs:Zeile 76.
  bei GitFunction.Test.Beta2.button1_Click(Object sender,EventArgs e)
  bei System.Windows.Forms.Control.OnClick(EventArgs e)   System.Windows.Forms.Button.OnClick(EventArgs e)北   System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)北   System.Windows.Forms.Control.WmMouseUp(Message&m,MouseButtons   按钮,则Int32点击)   System.Windows.Forms.Control.WndProc(Message&m)北   System.Windows.Forms.ButtonBase.WndProc(Message&m)北   System.Windows.Forms.Button.WndProc(Message&m)北   System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&m)   bei System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message&   m)System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr)   hWnd,Int32 msg,IntPtr wparam,IntPtr lparam)bei   System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG&msg)
  i   System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr   dwComponentID,Int32原因,Int32 pvLoopData)bei   System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32   原因,ApplicationContext上下文)bei   System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32   原因,ApplicationContext上下文)bei   System.Windows.Forms.Application.Run(Form mainForm)bei   GitFunction.Test.Program.Main()北   System.AppDomain._nExecuteAssembly(RuntimeAssembly程序集,字符串[]   args)在System.AppDomain.ExecuteAssembly(String assemblyFile,   证据AssemblySecurity,String [] args)bei   Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
  bei System.Threading.ThreadHelper.ThreadStart_Context(对象状态)
  bei System.Threading.ExecutionContext.RunInternal(ExecutionContext   executionContext,ContextCallback回调,对象状态,布尔值   reserveSyncCtx)bei   System.Threading.ExecutionContext.Run(ExecutionContext   executionContext,ContextCallback回调,对象状态,布尔值   reserveSyncCtx)bei   System.Threading.ExecutionContext.Run(ExecutionContext   executionContext,ContextCallback回调,对象状态)bei   System.Threading.ThreadHelper.ThreadStart()

编辑:

如果我从Github获取,则会收到AggregateException。如果从本地Gogs服务器获取,则会收到AccessViolationException!

代码: HttpTransporttest.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using LibGit2Sharp;

namespace AccessViolationTest
{
    //[RpcSmartSubtransport]
    public class HttpClientSmartSubtransport : SmartSubtransport
    {
        private HttpClient httpClient = null;

        protected override SmartSubtransportStream Action(string url, GitSmartSubtransportAction action)
        {
            string postContentType = null;
            Uri serviceUri;
            switch (action)
        {
            case GitSmartSubtransportAction.UploadPackList:
                serviceUri = new Uri(url + "/info/refs?service=git-upload-pack");
                break;
            case GitSmartSubtransportAction.UploadPack:
                serviceUri = new Uri(url + "/git-upload-pack");
                postContentType = "application/x-git-upload-pack-request";
                break;
            case GitSmartSubtransportAction.ReceivePackList:
                serviceUri = new Uri(url + "/info/refs?service=git-receive-pack");
                break;
            case GitSmartSubtransportAction.ReceivePack:
                serviceUri = new Uri(url + "/git-receive-pack");
                postContentType = "application/x-git-receive-pack-request";
                break;
            default:
                throw new InvalidOperationException();
        }
        if (httpClient == null)
        {
            httpClient = BuildHttpClientForUri(serviceUri);
        }

        return new HtppClientSmartSubtransportStream(this, httpClient, serviceUri, postContentType);
    }

    private HttpClient BuildHttpClientForUri(Uri serviceUri)
    {
        //var credentials = new NetworkCredential("##", "##");
        var handler     = new HttpClientHandler { };
        handler.UseDefaultCredentials = true;
        var client = new HttpClient(handler);

        client.Timeout = TimeSpan.FromMinutes(5.0);
        return client;
    }

}

public class HtppClientSmartSubtransportStream : SmartSubtransportStream
{
    private readonly HttpClient httpClient;
    private readonly Uri serviceUri;
    private readonly string postContentType;
    private Stream responseStream;
    private MemoryStream requestSream = null;

    public HtppClientSmartSubtransportStream(SmartSubtransport smartSubtransport, HttpClient httpClient,
        Uri serviceUri, string postContentType)
        : base(smartSubtransport)
    {
        this.httpClient = httpClient;
        this.serviceUri = serviceUri;
        this.postContentType = postContentType;
    }

    private void EnsureResponseStream()
    {
        if (this.responseStream != null)
            return;

        HttpResponseMessage result;
        if (requestSream != null) // we also have something to send
        {
            requestSream.Seek(0, SeekOrigin.Begin);
            var streamContent = new StreamContent(requestSream);

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, serviceUri);
            if (!string.IsNullOrEmpty(postContentType))
                streamContent.Headers.Add("Content-Type", postContentType);
            request.Content = streamContent;
            result = httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
        }
        else
        {
            result = httpClient.GetAsync(serviceUri, HttpCompletionOption.ResponseHeadersRead).Result;
        }

        responseStream = result.EnsureSuccessStatusCode().Content.ReadAsStreamAsync().Result;
    }

    public override int Read(Stream dataStream, long length, out long bytesRead)
    {
        bytesRead = 0L;
        var buffer = new byte[65536];
        this.EnsureResponseStream();

        int count;
        while (length > 0 && (count = this.responseStream.Read(buffer, 0, (int) Math.Min(buffer.Length, length))) >
               0)
        {
            dataStream.Write(buffer, 0, count);
            bytesRead += (long) count;
            length -= (long) count;
        }

        return 0;
    }

    public override int Write(Stream dataStream, long length)
    {
        if (requestSream == null)
            requestSream = new MemoryStream();

        var buffer = new byte[65536];
        int count;
        while (length > 0 && (count = dataStream.Read(buffer, 0, (int) Math.Min(buffer.Length, length))) > 0)
        {
            requestSream.Write(buffer, 0, count);
            length -= (long) count;
        }

        return 0;
    }

    protected override void Free()
    {
        if (httpClient != null)
            httpClient.Dispose();

        if (this.responseStream != null)
            this.responseStream.Close();
        if (this.requestSream != null)
            this.requestSream.Close();

        if (this.responseStream != null)
            this.responseStream.Dispose();


          if (this.requestSream != null)
                this.requestSream.Dispose();

            base.Free();
        }
    }
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LibGit2Sharp;

namespace AccessViolationTest
{
    class Program
    {

        static void Main(string[] args)
        {
            SmartSubtransportRegistration<HttpClientSmartSubtransport> _testTransportRegistration =
                GlobalSettings.RegisterSmartSubtransport<HttpClientSmartSubtransport>("http");

            string str = LibGit2Sharp.Repository.Init(@"C:\Temp\gg");
            Repository repo = new Repository(str);
            AddOrigin(repo, "test", @"http://github.com/libgit2/libgit2sharp.git");


            Remote remote = repo.Network.Remotes["test"];
            IEnumerable<string> refSpecs = remote.FetchRefSpecs.Select(x => x.Specification);
            FetchOptions fetchOptions = new FetchOptions();
            fetchOptions.TagFetchMode = TagFetchMode.Auto;



            Commands.Fetch(repo, "test", refSpecs, fetchOptions, "msg");

        }


        private static bool AddOrigin(Repository repo, string remoteName, string remoteGitAddress)
        {
            foreach (var remote in repo.Network.Remotes)
            {
                if (remote.Name == remoteName)
                {
                    repo.Network.Remotes.Remove(remoteName);
                    Remote newRemote = repo.Network.Remotes.Add(remoteName, remoteGitAddress);
                    Branch branch = repo.Head;
                    Branch updatedBranch = repo.Branches.Update(branch,
                        b => b.Remote = newRemote.Name,
                        b => b.UpstreamBranch = branch.CanonicalName);

                    return true;
                }
            }

            if (!Remote.IsValidName(remoteName))
            {

            }

            if (repo.Network.Remotes != null)
            {
                Remote newRemote = repo.Network.Remotes.Add(remoteName, remoteGitAddress);
                Branch branch = repo.Head;
                Branch updatedBranch = repo.Branches.Update(branch,
                    b => b.Remote = newRemote.Name,
                    b => b.UpstreamBranch = branch.CanonicalName);
            }

            return false;
        }
    }
}

0 个答案:

没有答案