Module: LibPath::Util::Windows::LibPath_Util_Windows_Methods
- Included in:
- LibPath::Util::Windows, LibPath::Util::Windows
- Defined in:
- lib/libpath/util/windows.rb
Overview
Module defining instance functions that will be included and extended into any class or module including/extending module LibPath::Util::Windows
Instance Method Summary collapse
-
#combine_paths(*args, **options) ⇒ Object
Combines a number of path parts into a single path, ignoring any parts that are preceded by an absolute part.
-
#derive_relative_path(origin, path, **options) ⇒ Object
Obtains the form of the given
path
relative to the givenorigin
. -
#make_compare_path(path, **options) ⇒ Object
Returns a “compare path” for the given absolute path.
-
#make_path_absolute(path, **options) ⇒ Object
NOTE: The behaviour of this method is undefined if any of the parts are malformed.
-
#make_path_canonical(path, **options) ⇒ Object
Converts a path into canonical form, which is to say that all possible dots directory parts are removed:.
Instance Method Details
#combine_paths(*args, **options) ⇒ Object
Combines a number of path parts into a single path, ignoring any parts that are preceded by an absolute part
Because Windows paths’ absolute nature comprises two elements - the volume(/drive) and the root directory - it is possible to combine elements where either the volume or the root directory is missing.
NOTE: The behaviour of this method is undefined if any of the parts are malformed. See ::LibPath::Form::Windows::name_is_malformed?
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/libpath/util/windows.rb', line 74 def combine_paths *args, ** _Form_Windows = Form::Windows _Internal_Windows_Form = Internal_::Windows::Form args.each_with_index { |arg, index| Diagnostics.check_string_parameter(arg, "arg#{index}", allow_nil: true) } if $DEBUG first = [] dirs = [] last = [] if [:elide_single_dots] args = args.map do |arg| case arg when '.', './' nil else arg end end end args = args.reject { |arg| arg.nil? || arg.empty? } rix_abs = nil rix_drv = nil rix_dir = nil args.each_with_index do |arg, index| vol, rem, _ = _Internal_Windows_Form.get_windows_volume arg rem = nil unless rem && _Internal_Windows_Form.char_is_path_name_separator?(rem[0]) if vol if rem rix_abs = index else rix_drv = index end elsif rem rix_dir = index end end rix_drv = nil if (rix_drv || -1) <= (rix_abs || -1) rix_dir = nil if (rix_dir || -1) <= (rix_abs || -1) if rix_drv && rix_dir && rix_abs if rix_abs < rix_drv && rix_abs < rix_dir rix_abs += 1 args = args[rix_abs..-1] rix_drv -= rix_abs rix_dir -= rix_abs rix_abs = nil end end if rix_drv.nil? && rix_dir.nil? if rix_abs args = args[rix_abs..-1] end dirs = args last << args.pop unless args.empty? else if false ; elsif rix_drv if rix_dir drv = args.delete_at rix_drv rix_dir -= 1 if rix_drv < rix_dir dir = args.delete_at rix_dir args = args[rix_dir..-1] if dir.size > 1 args.unshift dir[1..-1] dir = dir[0] end root = _Internal_Windows_Form.append_trailing_slash("#{drv}#{dir}") first << root last << args.pop unless args.empty? dirs = args elsif rix_abs drv = args.delete_at rix_drv rix_abs -= 1 if rix_drv < rix_abs abs = args.delete_at rix_abs _, _, dir, bas, _, _, _, _ = _Internal_Windows_Form.split_path abs args = args[rix_abs..-1] if dir.size > 1 args.unshift dir[1..-1] dir = dir[0] end root = _Internal_Windows_Form.append_trailing_slash("#{drv}#{dir}#{bas}") first << root last << args.pop unless args.empty? dirs = args else first << args.delete_at(rix_drv) last << args.pop unless args.empty? dirs = args end elsif rix_dir if rix_abs abs = args.delete_at rix_abs rix_dir -= 1 if rix_abs < rix_dir dir = args.delete_at rix_dir _, vol, _, _, _, _, _, _ = _Internal_Windows_Form.split_path abs args = args[rix_dir..-1] root = _Internal_Windows_Form.append_trailing_slash("#{vol}#{dir}") first << root last << args.pop unless args.empty? dirs = args else args = args[rix_dir..-1] last << args.pop unless args.empty? dirs = args end else ; end end dirs = dirs.map { |el| _Internal_Windows_Form.append_trailing_slash el } (first + dirs + last).join('') end |
#derive_relative_path(origin, path, **options) ⇒ Object
Obtains the form of the given path
relative to the given origin
NOTE: The behaviour of this method is undefined if any of the parts are malformed. See ::LibPath::Form::Windows::name_is_malformed?
Signature
-
Options:
+:home+:: (String)
+:locator+:: (boolean)
+:make_canonical+:: (boolean)
+:pwd+:: (String)
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/libpath/util/windows.rb', line 251 def derive_relative_path origin, path, ** return path if origin.nil? || origin.empty? return path if path.nil? || path.empty? _Form_Windows = Form::Windows _Util_Windows = Util::Windows _Internal_Windows_Form = Internal_::Windows::Form _MPA_COMMON_OPTIONS = %i{ home locator pwd } tr_sl = _Internal_Windows_Form.get_trailing_slash(path) # Possibly naive home-correction return derive_relative_path(absolute_path(origin), path, **) if _Form_Windows.path_is_homed?(origin) return derive_relative_path(origin, absolute_path(path), **) if _Form_Windows.path_is_homed?(path) o_vol, o_rem, _ = _Internal_Windows_Form.get_windows_volume origin p_vol, p_rem, _ = _Internal_Windows_Form.get_windows_volume path if o_vol && p_vol # always give absolute answer when 'volume's are different if o_vol != p_vol if [:make_path_canonical] path = _Util_Windows.make_path_canonical(path, make_slashes_canonical: true) else path = path.tr('/', '\\') end return path end end o_is_rooted = o_rem && _Internal_Windows_Form.char_is_path_name_separator?(o_rem[0]) p_is_rooted = p_rem && _Internal_Windows_Form.char_is_path_name_separator?(p_rem[0]) o_is_abs = o_vol && o_is_rooted p_is_abs = p_vol && p_is_rooted mpa_opts = .select { |k| _MPA_COMMON_OPTIONS.include?(k) } if o_is_abs != p_is_abs || o_is_rooted != p_is_rooted origin = _Util_Windows.make_path_absolute(origin, **mpa_opts) unless o_is_abs path = _Util_Windows.make_path_absolute(path, **mpa_opts) unless p_is_abs return derive_relative_path(origin, path, **) end origin = _Util_Windows.make_path_canonical(origin, make_slashes_canonical: true) path = _Util_Windows.make_path_canonical(path, make_slashes_canonical: true) return '.' + tr_sl.to_s if origin == path return path if '.\\' == origin if o_is_abs != p_is_abs || '.\\' == path origin = _Util_Windows.make_path_absolute(origin, make_canonical: true, **.select { |k| _MPA_COMMON_OPTIONS.include?(k) }) path = _Util_Windows.make_path_absolute(path, make_canonical: true, **.select { |k| _MPA_COMMON_OPTIONS.include?(k) }) end _, _, _, o3_basename, _, _, o6_parts, _ = _Internal_Windows_Form.split_path(origin) _, _, _, p3_basename, _, _, p6_parts, _ = _Internal_Windows_Form.split_path(path) o_parts = o6_parts o_parts << o3_basename if o3_basename && '.' != o3_basename p_parts = p6_parts p_parts << p3_basename if p3_basename && '.' != p3_basename while true break if o_parts.empty? break if p_parts.empty? o_part = o_parts[0] p_part = p_parts[0] if 1 == o_parts.size || 1 == p_parts.size o_part = _Internal_Windows_Form.append_trailing_slash o_part p_part = _Internal_Windows_Form.append_trailing_slash p_part end parts_equal = false if o_part.size == p_part.size o_part = o_part.tr('/', '\\') if o_part.include? '/' p_part = p_part.tr('/', '\\') if p_part.include? '/' parts_equal = o_part == p_part end if parts_equal o_parts.shift p_parts.shift else break end end return '.' + tr_sl.to_s if 0 == (o_parts.size + p_parts.size) return o_parts.map { |rp| '..' }.join('\\') + (tr_sl || (o_parts.size > 0 ? '\\' : nil)).to_s if p_parts.empty? ar = [ '..' ] * o_parts.size + p_parts last = ar.pop ar = ar.map { |el| _Internal_Windows_Form.append_trailing_slash(el) } last[-1] = '\\' if '/' == last[-1] ar.join + last.to_s end |
#make_compare_path(path, **options) ⇒ Object
Returns a “compare path” for the given absolute path
A compare path is one that would refer definitely to a given entry, regardless of such operating system-specific issues such as case-insensitivity
NOTE: the function does not make path
absolute. That is up to the caller if required
NOTE: The behaviour of this method is undefined if any of the parts are malformed. See ::LibPath::Form::Windows::name_is_malformed?
Signature
-
Parameters:
path
-
(String) The path whose definitive equivalent is to be
obtained
options
-
(Hash) options
-
Options:
:splits
-
([ String ]) An array of string-like objects. If the
object at index 1 exists and supports the +form+ attribute and that returns one of { +:form_2+, +:form_3+, +:form_4+, +:form_5+, +:form_6+ } then it is assumed to be the volume, and the objects at indexes 2 and 3 are assumed to be the directory and the basename, respectively. In this case, the compare path is constructed from a UNC-respecting form
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 |
# File 'lib/libpath/util/windows.rb', line 408 def make_compare_path path, ** if splits = [:splits] if volume = splits[1] if volume.respond_to?(:form) case volume.form when :form_2, :form_3, :form_4, :form_5, :form_6 directory = splits[2] || '' basename = splits[3] || '' return "#{volume}#{directory.upcase}#{basename.upcase}" else end end end end path.upcase end |
#make_path_absolute(path, **options) ⇒ Object
NOTE: The behaviour of this method is undefined if any of the parts are malformed. See ::LibPath::Form::Windows::name_is_malformed?
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/libpath/util/windows.rb', line 436 def make_path_absolute path, ** _Form_Windows = Form::Windows _Internal_Windows_Form = Internal_::Windows::Form Diagnostics.check_string_parameter(path, "path") if $DEBUG Diagnostics.(, known: %i{ home locator make_canonical pwd }) if $DEBUG return path if path.nil? || path.empty? r = nil if false ; elsif _Form_Windows.path_is_homed? path home = nil home ||= [:home] home ||= [:locator].home if .has_key?(:locator) home ||= Dir.home unless _Internal_Windows_Form.has_trailing_slash? home home = home + path[1].to_s end r = combine_paths(home, path[2..-1]) elsif _Form_Windows.path_is_UNC? path r = path elsif _Form_Windows.path_is_absolute? path r = path elsif _Form_Windows.path_is_rooted? path pwd = nil pwd ||= [:pwd] pwd ||= [:locator].pwd if .has_key?(:locator) pwd ||= Dir.pwd r = pwd[0..1] + path else pwd = nil pwd ||= [:pwd] pwd ||= [:locator].pwd if .has_key?(:locator) pwd ||= Dir.pwd r = combine_paths(pwd, path, elide_single_dots: false) end if [:make_canonical] r = make_path_canonical r else vol, rem, _ = _Internal_Windows_Form.get_windows_volume r _Internal_Windows_Form.elide_redundant_path_name_separators! rem r = "#{vol}#{rem}" end return r end |
#make_path_canonical(path, **options) ⇒ Object
Converts a path into canonical form, which is to say that all possible dots directory parts are removed:
-
single-dot parts - ‘./’ or ‘.\’ - are all removed
-
double-dot parts - ‘../’ or ‘..\’ - are removed where they follow a
non-dots directory part, or where they follow the root
NOTE: The behaviour of this method is undefined if any of the parts are malformed. See ::LibPath::Form::Windows::name_is_malformed?
Signature
-
Parameters:
path
-
(String) The path to be evaluated. May not be
nil
-
Options:
:make_slashes_canonical
-
(boolean) Determines whether to
additionally convert all forward slashes to backslashes
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 |
# File 'lib/libpath/util/windows.rb', line 521 def make_path_canonical path, ** Diagnostics.check_string_parameter(path, "path") if $DEBUG if path.include?('/') && [:make_slashes_canonical] path = path.tr '/', '\\' end return path unless '.' == path[-1] || path =~ /[.\\\/][\\\/]/ _Form = ::LibPath::Internal_::Windows::Form _Array = ::LibPath::Internal_::Array path = path[0...-1] if '.' == path[-1] && _Form.char_is_path_name_separator?(path[-2]) f0_path, f1_volume, f2_directory, f3_basename, _, _, f6_dir_parts, _ = _Form.split_path path if f6_dir_parts.empty? case f3_basename when '.' return "#{f1_volume}.\\" when '..' return "#{f1_volume}..\\" else return f0_path end end last_slash = nil case f3_basename when '.', '..' f6_dir_parts << f3_basename + '\\' basename = nil when nil last_slash = _Form.get_trailing_slash(f2_directory) || '\\' else basename = f3_basename end is_rooted = _Form.char_is_path_name_separator?(f2_directory[0]) new_parts = f6_dir_parts.dup new_parts.reject! { |p| '.\\' == p || './' == p } ix_nodots = new_parts.index { |p| '../' != p && '..\\' != p } || new_parts.size ix_2dots = _Array.index2(new_parts, '../', '..\\', ix_nodots) return "#{f1_volume}#{new_parts.join}#{basename}" unless new_parts.size != f6_dir_parts.size || ix_2dots while (ix_2dots || 0) > 0 new_parts.delete_at(ix_2dots - 0) new_parts.delete_at(ix_2dots - 1) if ix_2dots != 1 || !is_rooted ix_nodots = new_parts.index { |p| '../' != p && '..\\' != p } or break ix_2dots = _Array.index2(new_parts, '../', '..\\', ix_nodots) end if new_parts.empty? && (basename || '').empty? case f3_basename when nil, '.', '..' return '.' + (last_slash || '\\').to_s else return '.' end return '.' + last_slash.to_s end return f1_volume.to_s + new_parts.join('') + basename.to_s end |