@@ -338,14 +338,16 @@ async fn do_filter(
338
338
meta : josh_proxy:: MetaConfig ,
339
339
temp_ns : Arc < josh_proxy:: TmpGitNamespace > ,
340
340
filter : josh:: filter:: Filter ,
341
- headref : String ,
341
+ head_ref : & HeadRef ,
342
342
) -> josh:: JoshResult < ( ) > {
343
343
let permit = service. filter_permits . acquire ( ) . await ;
344
344
let heads_map = service. heads_map . clone ( ) ;
345
345
346
- let s = tracing:: span!( tracing:: Level :: TRACE , "do_filter worker" ) ;
347
- let r = tokio:: task:: spawn_blocking ( move || {
348
- let _e = s. enter ( ) ;
346
+ let tracing_span = tracing:: span!( tracing:: Level :: TRACE , "do_filter worker" ) ;
347
+ let head_ref = head_ref. clone ( ) ;
348
+
349
+ tokio:: task:: spawn_blocking ( move || {
350
+ let _span_guard = tracing_span. enter ( ) ;
349
351
tracing:: trace!( "in do_filter worker" ) ;
350
352
let filter_spec = josh:: filter:: spec ( filter) ;
351
353
josh:: housekeeping:: remember_filter ( & meta. config . repo , & filter_spec) ;
@@ -357,57 +359,86 @@ async fn do_filter(
357
359
& josh:: to_ns( & meta. config. repo) ,
358
360
) ) ,
359
361
) ?;
360
- let mut refslist = josh:: housekeeping:: list_refs ( transaction. repo ( ) , & meta. config . repo ) ?;
361
362
362
- let mut headref = headref;
363
-
364
- if headref. starts_with ( "refs/" ) || headref == "HEAD" {
365
- let name = format ! (
363
+ let resolve_ref = |ref_value : & str | {
364
+ let josh_name = format ! (
366
365
"refs/josh/upstream/{}/{}" ,
367
366
& josh:: to_ns( & meta. config. repo) ,
368
- headref
367
+ ref_value
369
368
) ;
370
- if let Ok ( r) = transaction. repo ( ) . revparse_single ( & name) {
371
- refslist. push ( ( headref. clone ( ) , r. id ( ) ) ) ;
369
+
370
+ transaction
371
+ . repo ( )
372
+ . revparse_single ( & josh_name)
373
+ . map_err ( |e| josh_error ( & format ! ( "Could not find ref: {}" , e) ) )
374
+ } ;
375
+
376
+ let ( refs_list, head_ref) = match head_ref {
377
+ HeadRef :: Explicit ( ref_value)
378
+ if ref_value. starts_with ( "refs/" ) || ref_value == "HEAD" =>
379
+ {
380
+ let object = resolve_ref ( & ref_value) ?;
381
+ let list = vec ! [ ( ref_value. clone( ) , object. id( ) ) ] ;
382
+
383
+ ( list, ref_value. clone ( ) )
372
384
}
373
- } else {
374
- // @sha case
375
- refslist . push ( ( headref . clone ( ) , git2 :: Oid :: from_str ( & headref ) ? ) ) ;
376
- headref = format ! ( "refs/heads/_{}" , headref ) ;
377
- }
385
+ HeadRef :: Explicit ( ref_value ) => {
386
+ // When it's not something starting with refs/ or HEAD, it's
387
+ // probably sha1
388
+ let list = vec ! [ ( ref_value . clone ( ) , git2 :: Oid :: from_str ( & ref_value ) ? ) ] ;
389
+ let synthetic_ref = format ! ( "refs/heads/_{}" , ref_value ) ;
378
390
379
- if headref == "HEAD" {
380
- headref = heads_map
391
+ ( list, synthetic_ref)
392
+ }
393
+ HeadRef :: Implicit => {
394
+ // When user did not explicitly request a ref to filter,
395
+ // start with a list of all existing refs
396
+ let mut list =
397
+ josh:: housekeeping:: list_refs ( transaction. repo ( ) , & meta. config . repo ) ?;
398
+
399
+ let head_ref = head_ref. get ( ) . to_string ( ) ;
400
+ if let Ok ( object) = resolve_ref ( & head_ref) {
401
+ list. push ( ( head_ref. clone ( ) , object. id ( ) ) ) ;
402
+ }
403
+
404
+ ( list, head_ref)
405
+ }
406
+ } ;
407
+
408
+ let head_ref = if head_ref == "HEAD" {
409
+ heads_map
381
410
. read ( ) ?
382
411
. get ( & meta. config . repo )
383
412
. unwrap_or ( & "invalid" . to_string ( ) )
384
- . clone ( ) ;
385
- }
413
+ . clone ( )
414
+ } else {
415
+ head_ref
416
+ } ;
386
417
387
418
let t2 = josh:: cache:: Transaction :: open ( & repo_path. join ( "overlay" ) , None ) ?;
388
419
t2. repo ( )
389
420
. odb ( ) ?
390
421
. add_disk_alternate ( repo_path. join ( "mirror" ) . join ( "objects" ) . to_str ( ) . unwrap ( ) ) ?;
391
- let updated_refs = josh:: filter_refs ( & t2, filter, & refslist , josh:: filter:: empty ( ) ) ?;
422
+ let updated_refs = josh:: filter_refs ( & t2, filter, & refs_list , josh:: filter:: empty ( ) ) ?;
392
423
let mut updated_refs = josh_proxy:: refs_locking ( updated_refs, & meta) ;
393
424
josh:: housekeeping:: namespace_refs ( & mut updated_refs, temp_ns. name ( ) ) ;
394
- josh:: update_refs ( & t2, & mut updated_refs, & temp_ns. reference ( & headref ) ) ;
425
+ josh:: update_refs ( & t2, & mut updated_refs, & temp_ns. reference ( & head_ref ) ) ;
395
426
t2. repo ( )
396
427
. reference_symbolic (
397
428
& temp_ns. reference ( "HEAD" ) ,
398
- & temp_ns. reference ( & headref ) ,
429
+ & temp_ns. reference ( & head_ref ) ,
399
430
true ,
400
431
"" ,
401
432
)
402
433
. ok ( ) ;
403
434
404
- Ok ( ( ) )
435
+ Ok :: < _ , JoshError > ( ( ) )
405
436
} )
406
- . await ?;
437
+ . await ?? ;
407
438
408
439
std:: mem:: drop ( permit) ;
409
440
410
- r
441
+ Ok ( ( ) )
411
442
}
412
443
413
444
fn make_response ( body : hyper:: Body , code : hyper:: StatusCode ) -> Response < hyper:: Body > {
@@ -792,15 +823,31 @@ fn is_repo_blocked(meta: &MetaConfig) -> bool {
792
823
false
793
824
}
794
825
795
- fn headref_or_default ( headref : & str ) -> String {
796
- let result = headref
826
+ #[ derive( Clone , Debug ) ]
827
+ enum HeadRef {
828
+ Explicit ( String ) ,
829
+ Implicit ,
830
+ }
831
+
832
+ impl HeadRef {
833
+ // Sometimes we don't care about whether it's implicit or explicit
834
+ fn get ( & self ) -> & str {
835
+ match self {
836
+ HeadRef :: Explicit ( r) => & r,
837
+ HeadRef :: Implicit => "HEAD" ,
838
+ }
839
+ }
840
+ }
841
+
842
+ fn head_ref_or_default ( head_ref : & str ) -> HeadRef {
843
+ let result = head_ref
797
844
. trim_start_matches ( |char| char == '@' || char == '^' )
798
845
. to_owned ( ) ;
799
846
800
847
if result. is_empty ( ) {
801
- "HEAD" . to_string ( )
848
+ HeadRef :: Implicit
802
849
} else {
803
- result
850
+ HeadRef :: Explicit ( result)
804
851
}
805
852
}
806
853
@@ -890,9 +937,9 @@ async fn handle_serve_namespace_request(
890
937
} ;
891
938
892
939
let remote_url = upstream + meta_config. config . repo . as_str ( ) ;
893
- let headref = headref_or_default ( & parsed_url. headref ) ;
940
+ let head_ref = head_ref_or_default ( & parsed_url. headref ) ;
894
941
895
- let remote_refs = [ headref . as_str ( ) ] ;
942
+ let remote_refs = [ head_ref . get ( ) ] ;
896
943
let remote_refs = match ssh_list_refs ( & remote_url, auth_socket, Some ( & remote_refs) ) . await {
897
944
Ok ( remote_refs) => remote_refs,
898
945
Err ( e) => {
@@ -903,7 +950,7 @@ async fn handle_serve_namespace_request(
903
950
}
904
951
} ;
905
952
906
- let resolved_ref = match remote_refs. get ( & headref ) {
953
+ let resolved_ref = match remote_refs. get ( head_ref . get ( ) ) {
907
954
Some ( resolved_ref) => resolved_ref,
908
955
None => {
909
956
return Ok ( make_response (
@@ -918,7 +965,7 @@ async fn handle_serve_namespace_request(
918
965
meta_config. config . repo . to_owned ( ) ,
919
966
& remote_auth,
920
967
remote_url. to_owned ( ) ,
921
- Some ( & headref ) ,
968
+ Some ( head_ref . get ( ) ) ,
922
969
Some ( resolved_ref) ,
923
970
false ,
924
971
)
@@ -977,7 +1024,7 @@ async fn handle_serve_namespace_request(
977
1024
} ,
978
1025
) ;
979
1026
980
- let temp_ns = match prepare_namespace ( serv. clone ( ) , & meta_config, filter, & headref ) . await {
1027
+ let temp_ns = match prepare_namespace ( serv. clone ( ) , & meta_config, filter, & head_ref ) . await {
981
1028
Ok ( ns) => ns,
982
1029
Err ( e) => {
983
1030
return Ok ( make_response (
@@ -1151,13 +1198,13 @@ async fn call_service(
1151
1198
. await ??) ;
1152
1199
}
1153
1200
1154
- let headref = headref_or_default ( & parsed_url. headref ) ;
1201
+ let headref = head_ref_or_default ( & parsed_url. headref ) ;
1155
1202
match fetch_upstream (
1156
1203
serv. clone ( ) ,
1157
1204
meta. config . repo . to_owned ( ) ,
1158
1205
& remote_auth,
1159
1206
remote_url. to_owned ( ) ,
1160
- Some ( & headref) ,
1207
+ Some ( headref. get ( ) ) ,
1161
1208
None ,
1162
1209
false ,
1163
1210
)
@@ -1184,7 +1231,7 @@ async fn call_service(
1184
1231
req. uri ( ) . query ( ) . map ( |x| x. to_string ( ) ) ,
1185
1232
parsed_url. pathinfo . is_empty ( ) ,
1186
1233
) {
1187
- return serve_query ( serv, q, meta. config . repo , filter, headref) . await ;
1234
+ return serve_query ( serv, q, meta. config . repo , filter, headref. get ( ) ) . await ;
1188
1235
}
1189
1236
1190
1237
let temp_ns = prepare_namespace ( serv. clone ( ) , & meta, filter, & headref)
@@ -1265,11 +1312,12 @@ async fn serve_query(
1265
1312
q : String ,
1266
1313
upstream_repo : String ,
1267
1314
filter : josh:: filter:: Filter ,
1268
- headref : String ,
1315
+ head_ref : & str ,
1269
1316
) -> josh:: JoshResult < Response < hyper:: Body > > {
1270
- let s = tracing:: span!( tracing:: Level :: TRACE , "render worker" ) ;
1317
+ let tracing_span = tracing:: span!( tracing:: Level :: TRACE , "render worker" ) ;
1318
+ let head_ref = head_ref. to_string ( ) ;
1271
1319
let res = tokio:: task:: spawn_blocking ( move || -> josh:: JoshResult < _ > {
1272
- let _e = s . enter ( ) ;
1320
+ let _span_guard = tracing_span . enter ( ) ;
1273
1321
1274
1322
let transaction_mirror = josh:: cache:: Transaction :: open (
1275
1323
& serv. repo_path . join ( "mirror" ) ,
@@ -1290,7 +1338,7 @@ async fn serve_query(
1290
1338
1291
1339
let commit_id = transaction_mirror
1292
1340
. repo ( )
1293
- . refname_to_id ( & transaction_mirror. refname ( & headref ) ) ?;
1341
+ . refname_to_id ( & transaction_mirror. refname ( & head_ref ) ) ?;
1294
1342
let commit_id =
1295
1343
josh:: filter_commit ( & transaction, filter, commit_id, josh:: filter:: empty ( ) ) ?;
1296
1344
@@ -1319,7 +1367,7 @@ async fn prepare_namespace(
1319
1367
serv : Arc < JoshProxyService > ,
1320
1368
meta : & josh_proxy:: MetaConfig ,
1321
1369
filter : josh:: filter:: Filter ,
1322
- headref : & str ,
1370
+ head_ref : & HeadRef ,
1323
1371
) -> josh:: JoshResult < std:: sync:: Arc < josh_proxy:: TmpGitNamespace > > {
1324
1372
let temp_ns = Arc :: new ( josh_proxy:: TmpGitNamespace :: new (
1325
1373
& serv. repo_path . join ( "overlay" ) ,
@@ -1334,7 +1382,7 @@ async fn prepare_namespace(
1334
1382
meta. clone ( ) ,
1335
1383
temp_ns. to_owned ( ) ,
1336
1384
filter,
1337
- headref . to_string ( ) ,
1385
+ head_ref ,
1338
1386
)
1339
1387
. await ?;
1340
1388
0 commit comments