我从
测试了自定义的Git HTTP SmartTransport扩展克隆命令有效,但通过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;
}
}
}