@@ -34,23 +34,57 @@ let node_sep = "/"
34
34
let node_parent = " .."
35
35
let node_current = " ."
36
36
37
+ type t =
38
+ [ `File of string
39
+ | `Dir of string ]
40
+
41
+ let cwd = lazy (Sys. getcwd () )
42
+
43
+ let (// ) = Filename. concat
44
+
45
+ let combine path1 path2 =
46
+ if path1 = " " then
47
+ path2
48
+ else if path2 = " " then path1
49
+ else
50
+ if Filename. is_relative path2 then
51
+ path1// path2
52
+ else
53
+ path2
54
+
55
+ (* Note that [.//] is the same as [./] *)
56
+ let path_as_directory x =
57
+ if x = " " then x
58
+ else
59
+ if Ext_string. ends_with x Filename. dir_sep then
60
+ x
61
+ else
62
+ x ^ Filename. dir_sep
63
+
37
64
let absolute_path s =
38
- let s = if Filename. is_relative s then Filename. concat (Sys. getcwd () ) s else s in
39
- (* Now simplify . and .. components *)
40
- let rec aux s =
41
- let base = Filename. basename s in
42
- let dir = Filename. dirname s in
43
- if dir = s then dir
44
- else if base = Filename. current_dir_name then aux dir
45
- else if base = Filename. parent_dir_name then Filename. dirname (aux dir)
46
- else Filename. concat (aux dir) base
47
- in
48
- aux s
65
+ let process s =
66
+ let s =
67
+ if Filename. is_relative s then
68
+ Lazy. force cwd // s
69
+ else s in
70
+ (* Now simplify . and .. components *)
71
+ let rec aux s =
72
+ let base,dir = Filename. basename s, Filename. dirname s in
73
+ if dir = s then dir
74
+ else if base = Filename. current_dir_name then aux dir
75
+ else if base = Filename. parent_dir_name then Filename. dirname (aux dir)
76
+ else aux dir // base
77
+ in aux s in
78
+ match s with
79
+ | `File x -> `File (process x )
80
+ | `Dir x -> `Dir (process x)
81
+
49
82
50
83
let chop_extension ?(loc =" " ) name =
51
84
try Filename. chop_extension name
52
85
with Invalid_argument _ ->
53
- invalid_arg (" Filename.chop_extension (" ^ loc ^ " :" ^ name ^ " )" )
86
+ Ext_pervasives. invalid_argf
87
+ " Filename.chop_extension ( %s : %s )" loc name
54
88
55
89
let try_chop_extension s = try Filename. chop_extension s with _ -> s
56
90
@@ -74,9 +108,18 @@ let try_chop_extension s = try Filename.chop_extension s with _ -> s
74
108
/c/d
75
109
]}
76
110
*)
77
- let relative_path file1 file2 =
78
- let dir1 = Ext_string. split (Filename. dirname file1) (Filename. dir_sep.[0 ]) in
79
- let dir2 = Ext_string. split (Filename. dirname file2) (Filename. dir_sep.[0 ]) in
111
+ let relative_path file_or_dir_1 file_or_dir_2 =
112
+ let sep_char = Filename. dir_sep.[0 ] in
113
+ let relevant_dir1 =
114
+ (match file_or_dir_1 with
115
+ | `Dir x -> x
116
+ | `File file1 -> Filename. dirname file1) in
117
+ let relevant_dir2 =
118
+ (match file_or_dir_2 with
119
+ | `Dir x -> x
120
+ | `File file2 -> Filename. dirname file2 ) in
121
+ let dir1 = Ext_string. split relevant_dir1 sep_char in
122
+ let dir2 = Ext_string. split relevant_dir2 sep_char in
80
123
let rec go (dir1 : string list ) (dir2 : string list ) =
81
124
match dir1, dir2 with
82
125
| x::xs , y :: ys when x = y
@@ -95,20 +138,29 @@ let relative_path file1 file2 =
95
138
96
139
let node_modules = " node_modules"
97
140
let node_modules_length = String. length " node_modules"
141
+ let package_json = " package.json"
142
+
143
+
144
+
145
+
98
146
(* * path2: a/b
99
147
path1: a
100
148
result: ./b
101
149
TODO: [Filename.concat] with care
150
+
151
+ [file1] is currently compilation file
152
+ [file2] is the dependency
102
153
*)
103
- let node_relative_path path1 path2 =
104
- let v = Ext_string. find path2 ~sub: node_modules in
105
- let len = String. length path2 in
154
+ let node_relative_path (file1 : t )
155
+ (`File file2 as dep_file : [`File of string] ) =
156
+ let v = Ext_string. find file2 ~sub: node_modules in
157
+ let len = String. length file2 in
106
158
if v > = 0 then
107
159
let rec skip i =
108
160
if i > = len then
109
- failwith ( " invalid path: " ^ path2)
161
+ Ext_pervasives. failwithf " invalid path: %s " file2
110
162
else
111
- match path2 .[i] with
163
+ match file2 .[i] with
112
164
| '/'
113
165
| '.' -> skip (i + 1 )
114
166
| _ -> i
@@ -121,21 +173,22 @@ let node_relative_path path1 path2 =
121
173
This seems weird though
122
174
*)
123
175
in
124
- Ext_string. tail_from path2
176
+ Ext_string. tail_from file2
125
177
(skip (v + node_modules_length))
126
178
else
127
- (relative_path
128
- (try_chop_extension (absolute_path path2))
129
- (try_chop_extension (absolute_path path1))
130
- ) ^ node_sep ^
131
- (try_chop_extension (Filename. basename path2))
179
+ relative_path
180
+ (absolute_path dep_file)
181
+ (absolute_path file1)
182
+ ^ node_sep ^
183
+ try_chop_extension (Filename. basename file2)
184
+
132
185
133
186
134
187
(* * [resolve cwd module_name], [cwd] is current working directory, absolute path
135
188
*)
136
189
let resolve ~cwd module_name =
137
190
let rec aux origin cwd module_name =
138
- let v = Filename. concat ( Filename. concat cwd node_modules) module_name
191
+ let v = ( cwd // node_modules) // module_name
139
192
in
140
193
if Sys. is_directory v then v
141
194
else
@@ -145,3 +198,18 @@ let resolve ~cwd module_name =
145
198
else Ext_pervasives. failwithf " %s not found in %s" module_name origin
146
199
in
147
200
aux cwd cwd module_name
201
+
202
+
203
+ let resolve_package cwd =
204
+ let rec aux cwd =
205
+ if Sys. file_exists (cwd // package_json) then cwd
206
+ else
207
+ let cwd' = Filename. dirname cwd in
208
+ if String. length cwd' < String. length cwd then
209
+ aux cwd'
210
+ else
211
+ Ext_pervasives. failwithf " package.json not found from %s" cwd
212
+ in
213
+ aux cwd
214
+
215
+ let package_dir = lazy (resolve_package (Lazy. force cwd))
0 commit comments