Module: LibPath::Util::Unix::LibPath_Util_Unix_Methods

Included in:
LibPath::Util::Unix, LibPath::Util::Unix
Defined in:
lib/libpath/util/unix.rb

Overview

Module defining instance functions that will be included and extended into any class or module including/extending module LibPath::Util::Unix

Instance Method Summary collapse

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

NOTE: The behaviour of this method is undefined if any of the parts are malformed. See ::LibPath::Form::Windows::name_is_malformed?



70
71
72
73
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
# File 'lib/libpath/util/unix.rb', line 70

def combine_paths *args, **options

  _Form_Unix          = Form::Unix
  _Internal_Unix_Form = Internal_::Unix::Form

  args.each_with_index { |arg, index| Diagnostics.check_string_parameter(arg, "arg#{index}", allow_nil: true) } if $DEBUG

  if options[: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? }

  case args.size
  when 0

    ''
  when 1

    args[0]
  else

    rix =   args.rindex { |arg| arg && _Form_Unix.path_is_absolute?(arg) }
    rix ||= 0

    els = args[rix..-1]

    File.join(*els)
  end
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)
+:pwd+:: (String)


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
# File 'lib/libpath/util/unix.rb', line 123

def derive_relative_path origin, path, **options

  return path if origin.nil? || origin.empty?
  return path if path.nil? || path.empty?

  _Form_Unix          = Form::Unix
  _Util_Unix          = Util::Unix
  _Internal_Unix_Form = Internal_::Unix::Form

  _MPA_COMMON_OPTIONS = %i{ home locator pwd }

  tr_sl   = _Internal_Unix_Form.get_trailing_slash(path)

  origin  = _Util_Unix.make_path_canonical(origin)
  path    = _Util_Unix.make_path_canonical(path)

  return '.' + tr_sl.to_s if origin == path
  return path if '.' == origin || './' == origin

  o_is_abs = _Form_Unix.path_is_absolute?(origin)
  p_is_abs = _Form_Unix.path_is_absolute?(path)

  if o_is_abs != p_is_abs || './' == path

    origin  = _Util_Unix.make_path_absolute(origin, make_canonical: true, **options.select { |k| _MPA_COMMON_OPTIONS.include?(k) })
    path    = _Util_Unix.make_path_absolute(path, make_canonical: true, **options.select { |k| _MPA_COMMON_OPTIONS.include?(k) })
  end

  origin  = _Internal_Unix_Form.trim_trailing_slash(origin) unless origin.size < 2
  path    = _Internal_Unix_Form.trim_trailing_slash(path) if tr_sl && path.size > 1


  _, _, _, o3_basename, _, _, o6_parts, _ = _Internal_Unix_Form.split_path(origin)
  _, _, _, p3_basename, _, _, p6_parts, _ = _Internal_Unix_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_Unix_Form.append_trailing_slash o_part
      p_part = _Internal_Unix_Form.append_trailing_slash p_part
    end

    if o_part == p_part

      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_Unix_Form.append_trailing_slash(el) }

  ar.join + last.to_s + tr_sl.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:

For reasons of compatibility (with the Windows version) no options
are currently supported; none are proscribed.


224
225
226
227
# File 'lib/libpath/util/unix.rb', line 224

def make_compare_path path, **options

  path
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?

Signature

  • Parameters:

    • path

      (String) The path to be evaluated. May not be nil

    • options

      (Hash) Options that moderate the behaviour of the

      function
      
  • Options:

    • :home

      (String) A specific home to assume, which means that the

      +locator+'s +home+ method will not be invoked
      
    • :locator

      (object) An object that provides the methods

      +pwd+ and +home+, as needed. This allows for mocking. If not
      given, then the functions +Dir::pwd+ and +Dir::home+ are used
      
    • :make_canonical

      (boolean) Determines whether canonicalisation

      is conducted on the result
      
    • :pwd

      (String) A specific directory to assume, which means that

      the +locator+'s +pwd+ method will not be invoked
      


250
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
# File 'lib/libpath/util/unix.rb', line 250

def make_path_absolute path, **options

  Diagnostics.check_string_parameter(path, "path") if $DEBUG
  Diagnostics.check_options(options, known: %i{ home locator make_canonical pwd }) if $DEBUG

  return path if path.nil? || path.empty?

  r = nil

  case path[0]
  when '/'

    r = path
  when '~'

    case path[1]
    when nil, '/'

      home  =   nil
      home  ||= options[:home]
      home  ||= options[:locator].home if options.has_key?(:locator)
      home  ||= Dir.home

      r = File.join(home, path[2..-1].to_s)
    end
  end

  unless r

    pwd =   nil
    pwd ||= options[:pwd]
    pwd ||= options[:locator].pwd if options.has_key?(:locator)
    pwd ||= Dir.pwd

    r = File.join(pwd, path)
  end

  r ||= path

  r = make_path_canonical r if options[:make_canonical]

  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 (trailing) parts - ‘???/.’ are converted to ‘???/’ (where

    ??? represents 0+ other characters);
    
  • single-dot parts - ‘./’ - are all removed

  • double-dot parts - ‘../’ - 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



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
380
# File 'lib/libpath/util/unix.rb', line 310

def make_path_canonical path, **options

  Diagnostics.check_string_parameter(path, "path") if $DEBUG

  return path unless '.' == path[-1] || path.include?('./') || path.include?('//')

  _Form   = ::LibPath::Internal_::Unix::Form
  _Array  = ::LibPath::Internal_::Array

  path = path[0...-1] if '.' == path[-1] && '/' == path[-2]


  f0_path, _, f2_dir, f3_basename, _, _, f6_dir_parts, _ = _Form.split_path path

  if f6_dir_parts.empty?

    case f3_basename
    when '.'

      return './'
    when '..'

      return '../'
    else

      return f0_path
    end
  end

  case f3_basename
  when '.', '..'

    f6_dir_parts  <<  f3_basename + '/'
    basename      =   nil
  else

    basename = f3_basename
  end

  is_rooted = '/' == f2_dir[0]

  new_parts = f6_dir_parts.dup
  new_parts.reject! { |p| './' == p }
  ix_nodots = new_parts.index { |p| '../' != p } || new_parts.size
  ix_2dots  = _Array.index(new_parts, '../', ix_nodots)

  return "#{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 } or break
    ix_2dots  = _Array.index(new_parts, '../', ix_nodots)
  end

  if new_parts.empty? && (basename || '').empty?

    case f3_basename
    when nil, '.', '..'

      return './'
    else

      return '.'
    end
  end

  return new_parts.join('') + basename.to_s
end