-
Notifications
You must be signed in to change notification settings - Fork 414
/
Copy pathworkspace_root.ml
93 lines (86 loc) · 2.44 KB
/
workspace_root.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
open Stdune
open Dune_engine
open Dune_rules
module Kind = struct
type t =
| Explicit
| Dune_workspace
| Dune_project
| Cwd
let priority = function
| Explicit -> 0
| Dune_workspace -> 1
| Dune_project -> 2
| Cwd -> 3
let of_dir_contents files =
if String.Set.mem files Workspace.filename then
Some Dune_workspace
else if String.Set.mem files Dune_project.filename then
Some Dune_project
else
None
end
type t =
{ dir : string
; to_cwd : string list
; kind : Kind.t
; ancestor_vcs : Dune_engine.Vcs.t option
}
let make kind dir = { kind; dir; to_cwd = []; ancestor_vcs = None }
let find () =
let cwd = Sys.getcwd () in
let rec loop counter ~candidate ~to_cwd dir =
match Sys.readdir dir with
| exception Sys_error msg ->
User_warning.emit
[ Pp.textf
"Unable to read directory %s. Will not look for root in parent \
directories."
dir
; Pp.textf "Reason: %s" msg
; Pp.text
"To remove this warning, set your root explicitly using --root."
];
candidate
| files ->
let files = String.Set.of_list (Array.to_list files) in
let new_candidate =
match Kind.of_dir_contents files with
| Some kind when Kind.priority kind <= Kind.priority candidate.kind ->
Some { kind; dir; to_cwd; ancestor_vcs = None }
| _ -> None
in
let candidate =
match (new_candidate, candidate.ancestor_vcs) with
| Some c, _ -> c
| None, Some _ -> candidate
| None, None -> (
match Vcs.Kind.of_dir_contents files with
| Some kind ->
{ candidate with
ancestor_vcs = Some { kind; root = Path.of_string dir }
}
| None -> candidate )
in
cont counter ~candidate dir ~to_cwd
and cont counter ~candidate ~to_cwd dir =
if counter > String.length cwd then
candidate
else
let parent = Filename.dirname dir in
if parent = dir then
candidate
else
let base = Filename.basename dir in
loop (counter + 1) parent ~candidate ~to_cwd:(base :: to_cwd)
in
loop 0 ~to_cwd:[] cwd
~candidate:{ kind = Cwd; dir = cwd; to_cwd = []; ancestor_vcs = None }
let create ~specified_by_user =
match specified_by_user with
| Some dn -> make Explicit dn
| None ->
if Config.inside_dune then
make Cwd "."
else
find ()