@@ -107,8 +107,8 @@ defmodule Path do
107
107
"""
108
108
def type ( name ) when is_list ( name ) or is_binary ( name ) do
109
109
case :os . type ( ) do
110
- { :unix , _ } -> unix_pathtype ( name )
111
110
{ :win32 , _ } -> win32_pathtype ( name )
111
+ _ -> unix_pathtype ( name )
112
112
end |> elem ( 0 )
113
113
end
114
114
@@ -131,8 +131,8 @@ defmodule Path do
131
131
"""
132
132
def relative ( name ) do
133
133
case :os . type ( ) do
134
- { :unix , _ } -> unix_pathtype ( name )
135
134
{ :win32 , _ } -> win32_pathtype ( name )
135
+ _ -> unix_pathtype ( name )
136
136
end |> elem ( 1 )
137
137
end
138
138
@@ -194,11 +194,12 @@ defmodule Path do
194
194
195
195
"""
196
196
def relative_to ( path , from ) when is_list ( path ) and is_binary ( from ) do
197
- relative_to ( FN . split ( list_to_binary ( path ) ) , FN . split ( from ) , list_to_binary ( path ) )
197
+ path = filename_string_to_binary ( path )
198
+ relative_to ( FN . split ( path ) , FN . split ( from ) , path )
198
199
end
199
200
200
201
def relative_to ( path , from ) when is_binary ( path ) and is_list ( from ) do
201
- relative_to ( FN . split ( path ) , FN . split ( list_to_binary ( from ) ) , path )
202
+ relative_to ( FN . split ( path ) , FN . split ( filename_string_to_binary ( from ) ) , path )
202
203
end
203
204
204
205
def relative_to ( path , from ) do
@@ -329,9 +330,12 @@ defmodule Path do
329
330
#=> "/foo/bar"
330
331
331
332
"""
332
- def join ( paths ) do
333
- FN . join ( paths )
334
- end
333
+ def join ( [ name1 , name2 | rest ] ) , do:
334
+ join ( [ join ( name1 , name2 ) | rest ] )
335
+ def join ( [ name ] ) when is_list ( name ) , do:
336
+ binary_to_filename_string ( do_join ( filename_string_to_binary ( name ) , << >> , [ ] , major_os_type ( ) ) )
337
+ def join ( [ name ] ) when is_binary ( name ) , do:
338
+ do_join ( name , << >> , [ ] , major_os_type ( ) )
335
339
336
340
@ doc """
337
341
Joins two paths.
@@ -342,10 +346,59 @@ defmodule Path do
342
346
#=> "foo/bar"
343
347
344
348
"""
345
- def join ( left , right ) do
346
- FN . join ( left , right )
349
+ def join ( left , right ) when is_binary ( left ) and is_binary ( right ) , do:
350
+ do_join ( left , Path . relative ( right ) , [ ] , major_os_type ( ) )
351
+
352
+ def join ( left , right ) when is_binary ( left ) and is_list ( right ) , do:
353
+ join ( left , filename_string_to_binary ( right ) )
354
+
355
+ def join ( left , right ) when is_list ( left ) and is_binary ( right ) , do:
356
+ join ( filename_string_to_binary ( left ) , right )
357
+
358
+ def join ( left , right ) when is_list ( left ) and is_list ( right ) , do:
359
+ binary_to_filename_string join ( filename_string_to_binary ( left ) , filename_string_to_binary ( right ) )
360
+
361
+ def join ( left , right ) when is_atom ( left ) , do:
362
+ join ( atom_to_binary ( left ) , right )
363
+
364
+ def join ( left , right ) when is_atom ( right ) , do:
365
+ join ( left , atom_to_binary ( right ) )
366
+
367
+ defp major_os_type do
368
+ case :os . type do
369
+ { maj , _ } -> maj
370
+ maj -> maj
371
+ end
347
372
end
348
373
374
+ defp do_join ( << uc_letter , ?: , rest :: binary >> , relativename , [ ] , :win32 ) when uc_letter in ?A .. ?Z , do:
375
+ do_join ( rest , relativename , [ ?: , uc_letter + ?a - ?A ] , :win32 )
376
+ defp do_join ( << ?\\ , rest :: binary >> , relativename , result , :win32 ) , do:
377
+ do_join ( << ?/ , rest :: binary >> , relativename , result , :win32 )
378
+ defp do_join ( << ?/ , rest :: binary >> , relativename , [ ?. , ?/ | result ] , os_type ) , do:
379
+ do_join ( rest , relativename , [ ?/ | result ] , os_type )
380
+ defp do_join ( << ?/ , rest :: binary >> , relativename , [ ?/ | result ] , os_type ) , do:
381
+ do_join ( rest , relativename , [ ?/ | result ] , os_type )
382
+ defp do_join ( << >> , << >> , result , os_type ) , do:
383
+ list_to_binary ( maybe_remove_dirsep ( result , os_type ) )
384
+ defp do_join ( << >> , relativename , [ ?: | rest ] , :win32 ) , do:
385
+ do_join ( relativename , << >> , [ ?: | rest ] , :win32 )
386
+ defp do_join ( << >> , relativename , [ ?/ | result ] , os_type ) , do:
387
+ do_join ( relativename , << >> , [ ?/ | result ] , os_type )
388
+ defp do_join ( << >> , relativename , result , os_type ) , do:
389
+ do_join ( relativename , << >> , [ ?/ | result ] , os_type )
390
+ defp do_join ( << char , rest :: binary >> , relativename , result , os_type ) when is_integer ( char ) , do:
391
+ do_join ( rest , relativename , [ char | result ] , os_type )
392
+
393
+ defp maybe_remove_dirsep ( [ ?/ , ?: , letter ] , :win32 ) , do:
394
+ [ letter , ?: , ?/ ]
395
+ defp maybe_remove_dirsep ( [ ?/ ] , _ ) , do:
396
+ [ ?/ ]
397
+ defp maybe_remove_dirsep ( [ ?/ | name ] , _ ) , do:
398
+ :lists . reverse ( name )
399
+ defp maybe_remove_dirsep ( name , _ ) , do:
400
+ :lists . reverse ( name )
401
+
349
402
@ doc """
350
403
Returns a list with the path splitted by the path separator.
351
404
If an empty string is given, then it returns the root path.
@@ -411,6 +464,24 @@ defmodule Path do
411
464
defp get_cwd ( path ) when is_list ( path ) , do: System . cwd! |> binary_to_list
412
465
defp get_cwd ( _ ) , do: System . cwd!
413
466
467
+ defp binary_to_filename_string ( binary ) do
468
+ case :unicode . characters_to_list ( binary ) do
469
+ { :error , _ , _ } ->
470
+ :erlang . error ( :badarg )
471
+ list when is_list ( list ) ->
472
+ list
473
+ end
474
+ end
475
+
476
+ defp filename_string_to_binary ( list ) do
477
+ case :unicode . characters_to_binary ( :filename . flatten ( list ) , :unicode , :file . native_name_encoding ( ) ) do
478
+ { :error , _ , _ } ->
479
+ :erlang . error ( :badarg )
480
+ bin when is_binary ( bin ) ->
481
+ bin
482
+ end
483
+ end
484
+
414
485
# Normalize the given path by expanding "..", "." and "~".
415
486
416
487
defp normalize ( path ) , do: do_normalize ( FN . split ( path ) )
0 commit comments