Skip to content

Commit 08da442

Browse files
committed
Protocol: support error messages from the remote
Recognize the error messages from the remote and throw an exception with the message if we receive an error. The code is messy, but a networ stream doesn't support peeking, so we need to read the first four bytes to see if they contain "ERR " and pass them to PktRef() if they don't, because we just removed part of the commit's hash from the stream. References libgit2#210
1 parent 340cfd8 commit 08da442

File tree

4 files changed

+59
-6
lines changed

4 files changed

+59
-6
lines changed

LibGit2Sharp/GitProtocolException.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System;
2+
namespace LibGit2Sharp
3+
{
4+
public class GitProtocolException : Exception
5+
{
6+
public GitProtocolException()
7+
{
8+
}
9+
10+
public GitProtocolException(string message)
11+
: base(message)
12+
{
13+
}
14+
15+
public GitProtocolException(string message, Exception innerException)
16+
: base(message, innerException)
17+
{
18+
}
19+
}
20+
}
21+

LibGit2Sharp/GitTransport.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ public void Connect()
4545

4646
if (pkt is PktRef)
4747
Refs.Add(pkt as PktRef);
48+
49+
if (pkt is PktError)
50+
throw new GitProtocolException((pkt as PktError).Error);
4851
}
4952
}
5053

LibGit2Sharp/LibGit2Sharp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@
166166
<Compile Include="ITransport.cs" />
167167
<Compile Include="GitTransport.cs" />
168168
<Compile Include="Refspec.cs" />
169+
<Compile Include="GitProtocolException.cs" />
169170
</ItemGroup>
170171
<ItemGroup>
171172
<CodeAnalysisDictionary Include="CustomDictionary.xml" />

LibGit2Sharp/Pkt.cs

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,39 @@ static public Pkt Parse(BinaryReader reader)
1515

1616
len -= 4;
1717

18-
return new PktRef(reader, len);
18+
return NewPkt(reader, len);
19+
}
20+
21+
/*
22+
* We can't seek on a NetworkStream, which means that we can't use
23+
* reader.PeekChar() to see if we got an error (which starts with
24+
* "ERR " instead of a hash) so we need this new function that chooses
25+
* which type to create
26+
*/
27+
public static Pkt NewPkt(BinaryReader reader, int len)
28+
{
29+
var mayerr = Encoding.ASCII.GetString(reader.ReadBytes(4));
30+
len -= 4;
31+
if (mayerr.Equals("ERR "))
32+
return new PktError(reader, len);
33+
34+
return new PktRef(reader, len, mayerr);
1935
}
2036
}
2137

38+
2239
public class PktRef : Pkt
2340
{
2441
public readonly ObjectId Id;
2542
public readonly string Name;
2643
public readonly string CapString;
2744

28-
public PktRef(BinaryReader reader, int len)
45+
public PktRef(BinaryReader reader, int len, string pre)
2946
{
30-
var buf = reader.ReadBytes(40);
31-
len -= 40; /* The hash */
32-
var hash = Encoding.ASCII.GetString(buf);
33-
ObjectId.TryParse(hash, out Id);
47+
int toread = 40 - pre.Length;
48+
var hash = Encoding.ASCII.GetString(reader.ReadBytes(toread));
49+
len -= toread; /* The hash */
50+
ObjectId.TryParse(pre + hash, out Id);
3451
reader.ReadByte(); /* Skip the SP */
3552
len -= 1; /* The SP */
3653

@@ -55,6 +72,17 @@ public PktRef(BinaryReader reader, int len)
5572
}
5673
}
5774

75+
public class PktError : Pkt
76+
{
77+
public readonly string Error;
78+
79+
public PktError(BinaryReader reader, int len)
80+
{
81+
/* NewPkt() has already removed "ERR " from the stream */
82+
Error = Encoding.UTF8.GetString(reader.ReadBytes(len));
83+
}
84+
}
85+
5886
public class PktFlush : Pkt
5987
{
6088
}

0 commit comments

Comments
 (0)