@@ -8,20 +8,33 @@ impl From<InternalRef> for Ref {
8
8
InternalRef :: Symbolic {
9
9
path,
10
10
target : Some ( target) ,
11
+ tag,
11
12
object,
12
13
} => Ref :: Symbolic {
13
14
full_ref_name : path,
14
15
target,
16
+ tag,
15
17
object,
16
18
} ,
17
19
InternalRef :: Symbolic {
18
20
path,
19
21
target : None ,
22
+ tag : None ,
20
23
object,
21
24
} => Ref :: Direct {
22
25
full_ref_name : path,
23
26
object,
24
27
} ,
28
+ InternalRef :: Symbolic {
29
+ path,
30
+ target : None ,
31
+ tag : Some ( tag) ,
32
+ object,
33
+ } => Ref :: Peeled {
34
+ full_ref_name : path,
35
+ tag,
36
+ object,
37
+ } ,
25
38
InternalRef :: Peeled { path, tag, object } => Ref :: Peeled {
26
39
full_ref_name : path,
27
40
tag,
@@ -56,6 +69,7 @@ pub(crate) enum InternalRef {
56
69
///
57
70
/// The latter is more of an edge case, please [this issue][#205] for details.
58
71
target : Option < BString > ,
72
+ tag : Option < gix_hash:: ObjectId > ,
59
73
object : gix_hash:: ObjectId ,
60
74
} ,
61
75
/// extracted from V1 capabilities, which contain some important symbolic refs along with their targets
@@ -155,6 +169,7 @@ pub(in crate::handshake::refs) fn parse_v1(
155
169
Some ( position) => match out_refs. swap_remove ( position) {
156
170
InternalRef :: SymbolicForLookup { path : _, target } => out_refs. push ( InternalRef :: Symbolic {
157
171
path : path. into ( ) ,
172
+ tag : None , // TODO: figure out how annotated tags work here.
158
173
object,
159
174
target,
160
175
} ) ,
@@ -172,7 +187,7 @@ pub(in crate::handshake::refs) fn parse_v1(
172
187
173
188
pub ( in crate :: handshake:: refs) fn parse_v2 ( line : & BStr ) -> Result < Ref , Error > {
174
189
let trimmed = line. trim_end ( ) ;
175
- let mut tokens = trimmed. splitn ( 3 , |b| * b == b' ' ) ;
190
+ let mut tokens = trimmed. splitn ( 4 , |b| * b == b' ' ) ;
176
191
match ( tokens. next ( ) , tokens. next ( ) ) {
177
192
( Some ( hex_hash) , Some ( path) ) => {
178
193
let id = if hex_hash == b"unborn" {
@@ -183,40 +198,22 @@ pub(in crate::handshake::refs) fn parse_v2(line: &BStr) -> Result<Ref, Error> {
183
198
if path. is_empty ( ) {
184
199
return Err ( Error :: MalformedV2RefLine ( trimmed. to_owned ( ) . into ( ) ) ) ;
185
200
}
186
- Ok ( if let Some ( attribute) = tokens. next ( ) {
201
+ let mut symref_target = None ;
202
+ let mut peeled = None ;
203
+ for attribute in tokens. by_ref ( ) . take ( 2 ) {
187
204
let mut tokens = attribute. splitn ( 2 , |b| * b == b':' ) ;
188
205
match ( tokens. next ( ) , tokens. next ( ) ) {
189
206
( Some ( attribute) , Some ( value) ) => {
190
207
if value. is_empty ( ) {
191
208
return Err ( Error :: MalformedV2RefLine ( trimmed. to_owned ( ) . into ( ) ) ) ;
192
209
}
193
210
match attribute {
194
- b"peeled" => Ref :: Peeled {
195
- full_ref_name : path. into ( ) ,
196
- object : gix_hash:: ObjectId :: from_hex ( value. as_bytes ( ) ) ?,
197
- tag : id. ok_or ( Error :: InvariantViolation {
198
- message : "got 'unborn' as tag target" ,
199
- } ) ?,
200
- } ,
201
- b"symref-target" => match value {
202
- b"(null)" => Ref :: Direct {
203
- full_ref_name : path. into ( ) ,
204
- object : id. ok_or ( Error :: InvariantViolation {
205
- message : "got 'unborn' while (null) was a symref target" ,
206
- } ) ?,
207
- } ,
208
- name => match id {
209
- Some ( id) => Ref :: Symbolic {
210
- full_ref_name : path. into ( ) ,
211
- object : id,
212
- target : name. into ( ) ,
213
- } ,
214
- None => Ref :: Unborn {
215
- full_ref_name : path. into ( ) ,
216
- target : name. into ( ) ,
217
- } ,
218
- } ,
219
- } ,
211
+ b"peeled" => {
212
+ peeled = Some ( gix_hash:: ObjectId :: from_hex ( value. as_bytes ( ) ) ?) ;
213
+ }
214
+ b"symref-target" => {
215
+ symref_target = Some ( value) ;
216
+ }
220
217
_ => {
221
218
return Err ( Error :: UnknownAttribute {
222
219
attribute : attribute. to_owned ( ) . into ( ) ,
@@ -227,13 +224,53 @@ pub(in crate::handshake::refs) fn parse_v2(line: &BStr) -> Result<Ref, Error> {
227
224
}
228
225
_ => return Err ( Error :: MalformedV2RefLine ( trimmed. to_owned ( ) . into ( ) ) ) ,
229
226
}
230
- } else {
231
- Ref :: Direct {
227
+ }
228
+ if tokens. next ( ) . is_some ( ) {
229
+ return Err ( Error :: MalformedV2RefLine ( trimmed. to_owned ( ) . into ( ) ) ) ;
230
+ }
231
+ Ok ( match ( symref_target, peeled) {
232
+ ( Some ( target_name) , peeled) => match target_name {
233
+ b"(null)" => match peeled {
234
+ None => Ref :: Direct {
235
+ full_ref_name : path. into ( ) ,
236
+ object : id. ok_or ( Error :: InvariantViolation {
237
+ message : "got 'unborn' while (null) was a symref target" ,
238
+ } ) ?,
239
+ } ,
240
+ Some ( peeled) => Ref :: Peeled {
241
+ full_ref_name : path. into ( ) ,
242
+ object : peeled,
243
+ tag : id. ok_or ( Error :: InvariantViolation {
244
+ message : "got 'unborn' while (null) was a symref target" ,
245
+ } ) ?,
246
+ } ,
247
+ } ,
248
+ name => match id {
249
+ Some ( id) => Ref :: Symbolic {
250
+ full_ref_name : path. into ( ) ,
251
+ tag : peeled. map ( |_| id) ,
252
+ object : peeled. unwrap_or ( id) ,
253
+ target : name. into ( ) ,
254
+ } ,
255
+ None => Ref :: Unborn {
256
+ full_ref_name : path. into ( ) ,
257
+ target : name. into ( ) ,
258
+ } ,
259
+ } ,
260
+ } ,
261
+ ( None , Some ( peeled) ) => Ref :: Peeled {
262
+ full_ref_name : path. into ( ) ,
263
+ object : peeled,
264
+ tag : id. ok_or ( Error :: InvariantViolation {
265
+ message : "got 'unborn' as tag target" ,
266
+ } ) ?,
267
+ } ,
268
+ ( None , None ) => Ref :: Direct {
232
269
object : id. ok_or ( Error :: InvariantViolation {
233
270
message : "got 'unborn' as object name of direct reference" ,
234
271
} ) ?,
235
272
full_ref_name : path. into ( ) ,
236
- }
273
+ } ,
237
274
} )
238
275
}
239
276
_ => Err ( Error :: MalformedV2RefLine ( trimmed. to_owned ( ) . into ( ) ) ) ,
0 commit comments