Skip to content

Commit af2e9b6

Browse files
fix: Allow any ref of a Git repo in the fragment (#11147)
This reverses the split of branches and tags from #11127, instead putting all possible references (e.g. also pull requests) in the same map and implements short-hands for looking up unqualified refs. Fixes #11140 Signed-off-by: Marek Kubica <marek@tarides.com>
1 parent 7a2a93b commit af2e9b6

File tree

2 files changed

+51
-65
lines changed

2 files changed

+51
-65
lines changed

src/dune_pkg/rev_store.ml

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ module Remote = struct
3232
type nonrec t =
3333
{ url : string
3434
; default_branch : Object.resolved option Fiber.t
35-
; branches : Object.resolved String.Map.t Fiber.t
36-
; tags : Object.resolved String.Map.t Fiber.t
35+
; refs : Object.resolved String.Map.t Fiber.t
3736
}
3837

3938
let default_branch t = t.default_branch
@@ -733,24 +732,8 @@ end
733732
let remote =
734733
let hash = Re.(rep1 alnum) in
735734
let head_mark, head = Re.mark (Re.str "HEAD") in
736-
let re =
737-
Re.(
738-
compile
739-
@@ seq
740-
[ bol
741-
; group hash
742-
; rep1 space
743-
; alt
744-
[ head
745-
; seq
746-
[ str "refs/"
747-
; group (alt [ str "heads"; str "tags" ])
748-
; str "/"
749-
; group (rep1 any)
750-
]
751-
]
752-
])
753-
in
735+
let ref = Re.(group (seq [ str "refs/"; rep1 any ])) in
736+
let re = Re.(compile @@ seq [ bol; group hash; rep1 space; alt [ head; ref ] ]) in
754737
fun t ~url:(url_loc, url) ->
755738
let f url =
756739
let command = [ "ls-remote"; url ] in
@@ -776,37 +759,24 @@ let remote =
776759
]
777760
| _ -> Git_error.raise_code_error git_error)
778761
in
779-
let default_branch, branches, tags =
780-
List.fold_left
781-
hits
782-
~init:(None, [], [])
783-
~f:(fun (default_branch, branches, tags) line ->
784-
match Re.exec_opt re line with
785-
| None -> default_branch, branches, tags
786-
| Some group ->
787-
let hash = Re.Group.get group 1 |> Object.of_sha1 |> Option.value_exn in
788-
if Re.Mark.test group head_mark
789-
then Some hash, branches, tags
790-
else (
791-
let name = Re.Group.get group 3 in
792-
let entry = name, hash in
793-
match Re.Group.get group 2 with
794-
| "heads" -> default_branch, entry :: branches, tags
795-
| "tags" -> default_branch, branches, entry :: tags
796-
| type_ ->
797-
Code_error.raise
798-
"ls-remote matched unexpected type of ref"
799-
[ "ref", Dyn.string name
800-
; "hash", Object.to_dyn hash
801-
; "type", Dyn.string type_
802-
]))
762+
let default_branch, refs =
763+
List.fold_left hits ~init:(None, []) ~f:(fun (default_branch, refs) line ->
764+
match Re.exec_opt re line with
765+
| None -> default_branch, refs
766+
| Some group ->
767+
let hash = Re.Group.get group 1 |> Object.of_sha1 |> Option.value_exn in
768+
if Re.Mark.test group head_mark
769+
then Some hash, refs
770+
else (
771+
let name = Re.Group.get group 2 in
772+
let entry = name, hash in
773+
default_branch, entry :: refs))
803774
in
804-
default_branch, String.Map.of_list_exn branches, String.Map.of_list_exn tags)
775+
default_branch, String.Map.of_list_exn refs)
805776
in
806777
{ Remote.url
807-
; default_branch = (Fiber_lazy.force refs >>| fun (v, _, _) -> v)
808-
; branches = (Fiber_lazy.force refs >>| fun (_, v, _) -> v)
809-
; tags = (Fiber_lazy.force refs >>| fun (_, _, v) -> v)
778+
; default_branch = Fiber_lazy.force refs >>| fst
779+
; refs = Fiber_lazy.force refs >>| snd
810780
}
811781
in
812782
Table.find_or_add t.remotes ~f url
@@ -818,19 +788,31 @@ let fetch_resolved t (remote : Remote.t) revision =
818788
;;
819789

820790
let resolve_revision t (remote : Remote.t) ~revision =
821-
let* branches = remote.branches in
822-
let* tags = remote.tags in
791+
let* refs = remote.refs in
823792
let obj =
824-
match String.Map.find branches revision, String.Map.find tags revision with
825-
| (Some _ as obj), None -> obj
826-
| None, (Some _ as obj) -> obj
827-
| None, None -> None
828-
| Some branch_obj, Some tag_obj ->
829-
(match Object.equal branch_obj tag_obj with
830-
| true -> Some branch_obj
831-
| false ->
832-
User_error.raise
833-
[ Pp.textf "Reference %S in remote %S is ambiguous" revision remote.url ])
793+
match String.Map.find refs revision with
794+
| Some _ as obj -> obj
795+
| None ->
796+
(* revision was not found as-is, try formatting as branch/tag *)
797+
let lookup_in format = String.Map.find refs (sprintf format revision) in
798+
let as_branch = lookup_in "refs/heads/%s" in
799+
let as_tag = lookup_in "refs/tags/%s" in
800+
(match as_branch, as_tag with
801+
| (Some _ as obj), None -> obj
802+
| None, (Some _ as obj) -> obj
803+
| None, None -> None
804+
| Some branch_obj, Some tag_obj ->
805+
(match Object.equal branch_obj tag_obj with
806+
| true -> Some branch_obj
807+
| false ->
808+
let hints =
809+
[ Pp.textf "If you want to specify a tag use refs/tags/%s" revision
810+
; Pp.textf "If you want to specify a branch use refs/branches/%s" revision
811+
]
812+
in
813+
User_error.raise
814+
~hints
815+
[ Pp.textf "Reference %S in remote %S is ambiguous" revision remote.url ]))
834816
in
835817
match obj with
836818
| Some obj as s ->

test/blackbox-tests/test-cases/pkg/pin-stanza/git-source.t

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ This should work without issue, as we never reference the ambiguous reference:
4343
Solution for dune.lock:
4444
- foo.dev
4545

46-
If we use the duplicate reference in the condig
46+
If we use the duplicate reference in the config
4747

4848
$ cat >dune-project <<EOF
4949
> (lang dune 3.13)
@@ -73,6 +73,8 @@ In this case Dune can't determine which reference to use and will error out:
7373
Error: Reference "duplicated" in remote
7474
"file://$PWD/_repo"
7575
is ambiguous
76+
Hint: If you want to specify a tag use refs/tags/duplicated
77+
Hint: If you want to specify a branch use refs/branches/duplicated
7678

7779
Git also has unambibuous namespaces tags and branches, for tags it is `refs/tags/`.
7880

@@ -88,8 +90,9 @@ Git also has unambibuous namespaces tags and branches, for tags it is `refs/tags
8890

8991
Locking should work, as there are no ambiguous references.
9092

91-
$ dune pkg lock 2>&1 | tr '\n' ' ' | sed 's#/.*/git #git #'
92-
Error: Command returned nothing: cd git rev-parse --verify --quiet refs/tags/duplicated^{commit}
93+
$ dune pkg lock
94+
Solution for dune.lock:
95+
- foo.dev
9396

9497
For branches the namespace is `refs/heads/`:
9598

@@ -105,5 +108,6 @@ For branches the namespace is `refs/heads/`:
105108

106109
Likewise locking a branch this way should work as well:
107110

108-
$ dune pkg lock 2>&1 | tr '\n' ' ' | sed 's#/.*/git #git #'
109-
Error: Command returned nothing: cd git rev-parse --verify --quiet refs/heads/duplicated^{commit}
111+
$ dune pkg lock
112+
Solution for dune.lock:
113+
- foo.dev

0 commit comments

Comments
 (0)