Skip to content

Commit a787e59

Browse files
committed
Remote: Add support for the sideband
Enable multiplexing if the server supports it. This allows us to give feedback to the user when the server is doing work and we're waiting for the pack data to arrive. References libgit2#221, libgit2#222
1 parent 082ad21 commit a787e59

File tree

5 files changed

+121
-5
lines changed

5 files changed

+121
-5
lines changed

LibGit2Sharp/Indexer.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,28 @@ public ObjectDatabase DatabaseFromPackfile()
3737
return odb;
3838
}
3939

40+
public void Add(byte[] data)
41+
{
42+
unsafe {
43+
var stats = stackalloc byte[Marshal.SizeOf(Stats)];
44+
var statsptr = new IntPtr(stats);
45+
Marshal.StructureToPtr(Stats, statsptr, true);
46+
Ensure.Success(NativeMethods.git_indexer_stream_add(handle, data, new UIntPtr((ulong)data.Length), statsptr));
47+
Stats = (IndexerStats)Marshal.PtrToStructure(statsptr, typeof(IndexerStats));
48+
}
49+
}
50+
51+
public void Finalize()
52+
{
53+
unsafe {
54+
var stats = stackalloc byte[Marshal.SizeOf(Stats)];
55+
var statsptr = new IntPtr(stats);
56+
Marshal.StructureToPtr(Stats, statsptr, true);
57+
Ensure.Success(NativeMethods.git_indexer_stream_finalize(handle, statsptr));
58+
Stats = (IndexerStats)Marshal.PtrToStructure(statsptr, typeof(IndexerStats));
59+
}
60+
}
61+
4062
public void IndexStream(Stream stream)
4163
{
4264
byte[] buffer = new byte[4096];

LibGit2Sharp/Pkt.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@ static public char[] Line(string msg)
1111
return string.Format("{0:x4}{1}\n", 4 + msg.Length + 1, msg).ToCharArray();
1212
}
1313

14-
static public Pkt Parse(BinaryReader reader)
14+
static private int parselen(BinaryReader reader)
1515
{
1616
var buf = reader.ReadBytes(4);
17-
int len = Int32.Parse(Encoding.ASCII.GetString(buf), System.Globalization.NumberStyles.HexNumber);
17+
return Int32.Parse(Encoding.ASCII.GetString(buf), System.Globalization.NumberStyles.HexNumber);
18+
}
19+
20+
static public Pkt Parse(BinaryReader reader)
21+
{
22+
var len = parselen(reader);
1823
if (len == 0)
1924
return new PktFlush();
2025

@@ -23,6 +28,13 @@ static public Pkt Parse(BinaryReader reader)
2328
return NewPkt(reader, len);
2429
}
2530

31+
static public PktDemux Demux(BinaryReader reader)
32+
{
33+
var len = parselen(reader);
34+
len -= 4;
35+
return new PktDemux(reader, len);
36+
}
37+
2638
/*
2739
* We can't seek on a NetworkStream, which means that we can't use
2840
* reader.PeekChar() to see if we got an error (which starts with
@@ -45,6 +57,25 @@ public static Pkt NewPkt(BinaryReader reader, int len)
4557
}
4658
}
4759

60+
public enum Channel
61+
{
62+
PackData = 1,
63+
Progress = 2,
64+
Error = 3,
65+
}
66+
67+
public class PktDemux : Pkt
68+
{
69+
public readonly Channel Channel;
70+
public readonly byte[] Data;
71+
72+
public PktDemux(BinaryReader reader, int len)
73+
{
74+
Channel = (Channel)reader.ReadByte();
75+
len--;
76+
Data = reader.ReadBytes(len);
77+
}
78+
}
4879

4980
public class PktRef : Pkt
5081
{

LibGit2Sharp/PktParser.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,25 @@ public Pkt Next()
2222
return Pkt.Parse(reader);
2323
}
2424
}
25+
26+
public class PktDemultiplexer
27+
{
28+
private BinaryReader reader;
29+
30+
public PktDemultiplexer(Stream stream)
31+
: this(new BinaryReader(stream))
32+
{
33+
}
34+
35+
public PktDemultiplexer(BinaryReader reader)
36+
{
37+
this.reader = reader;
38+
}
39+
40+
public PktDemux Next()
41+
{
42+
return Pkt.Demux(reader);
43+
}
44+
}
2545
}
2646

LibGit2Sharp/ProtocolCapabilities.cs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Linq;
3+
using System.Collections.Generic;
34

45
namespace LibGit2Sharp
56
{
@@ -25,8 +26,16 @@ public ProtocolCapabilities(string str)
2526
public string Common
2627
{
2728
get {
28-
/* Only this one for now */
29-
return OfsDelta ? OfsDeltaStr : "";
29+
var list = new List<string>();
30+
if (OfsDelta)
31+
list.Add(OfsDeltaStr);
32+
33+
if (Sideband64k)
34+
list.Add(Sideband64kStr);
35+
else if (Sideband)
36+
list.Add(SidebandStr);
37+
38+
return string.Join(" ", list.ToArray());
3039
}
3140
}
3241
}

LibGit2Sharp/Remote.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@
88

99
namespace LibGit2Sharp
1010
{
11+
12+
public class ProgressEventArgs : EventArgs
13+
{
14+
public Channel Channel;
15+
public byte[] Data;
16+
17+
public ProgressEventArgs(PktDemux pkt)
18+
{
19+
Channel = pkt.Channel;
20+
Data = pkt.Data;
21+
}
22+
}
23+
24+
public delegate void ProgressHandler(object sender, ProgressEventArgs args);
25+
1126
/// <summary>
1227
/// A remote repository whose branches are tracked.
1328
/// </summary>
@@ -16,6 +31,7 @@ public class Remote : IEquatable<Remote>
1631
private readonly ITransport transport;
1732
public readonly Refspec Refspec;
1833
public List<PktRef> Refs { get; private set; }
34+
public event ProgressHandler Progress;
1935
private Lazy<IEnumerable<string>> refnames;
2036
private Lazy<IEnumerable<string>> matching_refs;
2137
private Indexer indexer;
@@ -128,7 +144,25 @@ public void Download(string path)
128144
if (!(pkt is PktAck || pkt is PktNak))
129145
throw new GitProtocolException("Expected ACK or NAK, got neither");
130146

131-
indexer.IndexStream(stream);
147+
/* If either of these are common, we need to demultiplex it */
148+
149+
if (!caps.Sideband && !caps.Sideband64k) {
150+
indexer.IndexStream(stream);
151+
} else {
152+
var demux = new PktDemultiplexer(stream);
153+
while (true) {
154+
try {
155+
PktDemux p = demux.Next() as PktDemux;
156+
if (p.Channel == Channel.PackData)
157+
indexer.Add(p.Data);
158+
else if (Progress != null)
159+
Progress(this, new ProgressEventArgs(p));
160+
} catch (EndOfStreamException e) {
161+
indexer.Finalize();
162+
break;
163+
}
164+
}
165+
}
132166
}
133167

134168
private static readonly LambdaEqualityHelper<Remote> equalityHelper =

0 commit comments

Comments
 (0)