manageiq-smartstate 0.3.10 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/lib/MiqVm/MiqRhevmVm.rb +1 -1
- data/lib/fs/modules/LinuxMount.rb +14 -18
- data/lib/fs/ntfs/data_run.rb +1 -1
- data/lib/manageiq/smartstate/version.rb +1 -1
- data/lib/metadata/VmConfig/VmConfig.rb +2 -2
- data/lib/metadata/linux/LinuxPackages.rb +1 -1
- data/lib/metadata/linux/MiqRpmPackages.rb +7 -1
- data/lib/metadata/util/md5deep.rb +43 -59
- metadata +2 -3
- data/lib/metadata/util/find_class_methods.rb +0 -133
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d63431a0219ca739a68bc15b1c5856beeb3a08a5
|
4
|
+
data.tar.gz: b16b3f96b811e2d3cb75d0991a19b2dee837ec70
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '08d5cc7d71aea21a889af06207aff8df129a2f8917efc8cf7fe67b47e7ecf5cb7214ab91c274ec1a7fb16a2bbec6c42681715121e5a5c7b60c0f41faf269aca5'
|
7
|
+
data.tar.gz: c8222c9952bae19d739975849261812f9aebc29f7728c1a4d641cac30577feede0cd422bc5e2ba1a5a15b0315d0183376f75b0711942e3eadd550ca7a83672a2
|
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
|
|
3
3
|
# Specify your gem's dependencies in manageiq-smartstate.gemspec
|
4
4
|
gemspec
|
5
5
|
|
6
|
-
gem "manageiq-gems-pending", :git => "https://github.com/ManageIQ/manageiq-gems-pending.git", :branch => "
|
6
|
+
gem "manageiq-gems-pending", :git => "https://github.com/ManageIQ/manageiq-gems-pending.git", :branch => "master"
|
7
7
|
|
8
8
|
# Modified gems for vmware_web_service. Setting sources here since they are git references
|
9
9
|
gem "handsoap", "~>0.2.5", :require => false, :git => "https://github.com/ManageIQ/handsoap.git", :tag => "v0.2.5-5"
|
data/lib/MiqVm/MiqRhevmVm.rb
CHANGED
@@ -42,7 +42,7 @@ class MiqRhevmVm < MiqVm
|
|
42
42
|
disks = @rhevm.collect_vm_disks(@rhevmVm)
|
43
43
|
disks.each_with_index do |disk, idx|
|
44
44
|
$log.debug "MiqRhevmVm#getCfg: disk = #{disk.inspect}"
|
45
|
-
storage_domain = disk.storage_domains
|
45
|
+
storage_domain = disk.storage_domains.first
|
46
46
|
if storage_domain.nil?
|
47
47
|
$log.info("Disk <#{disk.name}> is skipped due to unassigned storage domain")
|
48
48
|
next
|
@@ -309,27 +309,23 @@ module LinuxMount
|
|
309
309
|
#
|
310
310
|
components.each do |c|
|
311
311
|
ncp = File.join(cp, c)
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
filesys, tmp_link_ptr = getFsPathBase(link_ptr)
|
325
|
-
if filesys.fileSymLink?(tmp_link_ptr)
|
326
|
-
symlink = getSymLink(filesys, tmp_link_ptr)
|
327
|
-
link_ptr = symlink[0, 1] == '/' ? symlink : File.join(File.dirname(link_ptr), symlink)
|
312
|
+
#
|
313
|
+
# Each file system know how to check for,
|
314
|
+
# and read its own links.
|
315
|
+
#
|
316
|
+
fs, lp = getFsPathBase(ncp)
|
317
|
+
if fs.fileSymLink?(lp)
|
318
|
+
sl = getSymLink(fs, lp)
|
319
|
+
if sl[0, 1] == '/'
|
320
|
+
cp = sl
|
321
|
+
else
|
322
|
+
cp = File.join(cp, sl)
|
323
|
+
end
|
328
324
|
else
|
329
|
-
|
325
|
+
cp = ncp
|
330
326
|
end
|
331
327
|
end
|
332
|
-
|
328
|
+
(cp)
|
333
329
|
end
|
334
330
|
|
335
331
|
def getSymLink(fs, p)
|
data/lib/fs/ntfs/data_run.rb
CHANGED
@@ -282,7 +282,7 @@ module NTFS
|
|
282
282
|
|
283
283
|
@runSpec.each_slice(2) do |lcn, len|
|
284
284
|
total_clusters += len
|
285
|
-
next unless
|
285
|
+
next unless total_clusters > start_vcn
|
286
286
|
|
287
287
|
start = lcn + (vcn - (total_clusters - len))
|
288
288
|
count = len - (start - lcn)
|
@@ -498,7 +498,7 @@ class VmConfig
|
|
498
498
|
end
|
499
499
|
|
500
500
|
def rhevm_disk_file_entry(disk)
|
501
|
-
storage_id = disk.storage_domains
|
501
|
+
storage_id = disk.storage_domains.first&.id
|
502
502
|
disk_id = disk.image_id || disk.id
|
503
503
|
full_path = storage_id && File.join('/dev', storage_id, disk_id)
|
504
504
|
{:path => full_path, :name => disk_id, :size => disk.actual_size.to_i}
|
@@ -550,7 +550,7 @@ class VmConfig
|
|
550
550
|
elsif miqvm.rhevmVm
|
551
551
|
disks = miqvm.rhevm.collect_vm_disks(miqvm.rhevmVm)
|
552
552
|
disks.each do |disk|
|
553
|
-
storage_id = disk.storage_domains
|
553
|
+
storage_id = disk.storage_domains.first&.id
|
554
554
|
disk_id = disk.image_id || disk.id
|
555
555
|
full_path = storage_id && File.join('/dev', storage_id, disk_id)
|
556
556
|
d = {:path => full_path, :name => disk.name.to_s, :size => disk.actual_size.to_i}
|
@@ -175,7 +175,7 @@ module MiqLinux
|
|
175
175
|
pkgs = doc.add_element 'applications'
|
176
176
|
@packages.each do |p|
|
177
177
|
next unless p.installed
|
178
|
-
pkgs.add_element('application', {"name" => p.name, "version" => p.version, "description" => p.description, "typename" => p.category, "arch" => p.arch, "release" => p.release, "install_time" => p.installtime})
|
178
|
+
pkgs.add_element('application', {"name" => p.name, "version" => p.version, "description" => p.description, "typename" => p.category, "arch" => p.arch, "release" => p.release, "install_time" => p.installtime, "build_time" => p.buildtime, "url" => p.url})
|
179
179
|
# "status" => p.status, "depends" => p.depends
|
180
180
|
end
|
181
181
|
doc
|
@@ -22,9 +22,11 @@ class MiqRpmPackages
|
|
22
22
|
RELEASE = 1002
|
23
23
|
SUMMARY = 1004
|
24
24
|
DESCRIPTION = 1005
|
25
|
+
BUILDTIME = 1006
|
25
26
|
INSTALLTIME = 1008
|
26
27
|
VENDOR = 1011
|
27
28
|
GROUP = 1016
|
29
|
+
URL = 1020
|
28
30
|
ARCH = 1022
|
29
31
|
REQUIRES = 1049
|
30
32
|
|
@@ -34,9 +36,11 @@ class MiqRpmPackages
|
|
34
36
|
1002 => "release",
|
35
37
|
1004 => "summary",
|
36
38
|
1005 => "description",
|
39
|
+
1006 => "buildtime",
|
37
40
|
1008 => "installtime",
|
38
41
|
1011 => "vendor",
|
39
42
|
1016 => "category", # group
|
43
|
+
1020 => "url",
|
40
44
|
1022 => "arch",
|
41
45
|
1049 => "depends", # requires
|
42
46
|
}
|
@@ -101,7 +105,7 @@ class MiqRpmPackages
|
|
101
105
|
private
|
102
106
|
|
103
107
|
def time_tag?(tag)
|
104
|
-
tag
|
108
|
+
['installtime', 'buildtime'].include?(tag)
|
105
109
|
end
|
106
110
|
|
107
111
|
def convert(tag, val)
|
@@ -148,6 +152,7 @@ if __FILE__ == $0
|
|
148
152
|
rpmPkgs.each do |pkg|
|
149
153
|
puts "Package: #{pkg.name}"
|
150
154
|
puts "\tInstall Time: #{pkg.installtime}"
|
155
|
+
puts "\tBuild Time: #{pkg.buildtime}"
|
151
156
|
puts "\tVersion: #{pkg.version}"
|
152
157
|
puts "\tRelease: #{pkg.release}"
|
153
158
|
puts "\tSummary: #{pkg.summary}"
|
@@ -155,6 +160,7 @@ if __FILE__ == $0
|
|
155
160
|
puts "\tArchitecture: #{pkg.arch}"
|
156
161
|
puts "\tCategory: #{pkg.category}"
|
157
162
|
puts "\tDescription: #{pkg.description}"
|
163
|
+
puts "\tURL: #{pkg.url}"
|
158
164
|
puts "\tDepends: #{pkg.depends}"
|
159
165
|
end
|
160
166
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'time'
|
2
2
|
require 'metadata/util/win32/peheader'
|
3
3
|
require 'metadata/util/win32/versioninfo'
|
4
|
-
require 'metadata/util/find_class_methods'
|
5
4
|
require 'util/miq-xml'
|
6
5
|
require 'ostruct'
|
7
6
|
require 'util/miq-encode'
|
@@ -55,35 +54,29 @@ class MD5deep
|
|
55
54
|
def scan_glob(filename)
|
56
55
|
filename.tr!("\\", "/")
|
57
56
|
startDir = File.dirname(filename)
|
57
|
+
globPattern = File.basename(filename)
|
58
58
|
@xml.root.add_attribute("base_path", startDir)
|
59
|
-
|
60
|
-
@drive_letter = path_prefix.match?(/^\w\:/) ? path_prefix : ""
|
59
|
+
@fs.chdir(startDir)
|
61
60
|
|
62
61
|
# First check if we are passed a fully qualifed file name
|
63
62
|
if @fs.fileExists?(filename)
|
64
|
-
|
65
|
-
isDir?(filename) ? process_dir_as_file(startDir, base_file, @xml.root) : processFile(startDir, base_file, @xml.root)
|
63
|
+
isDir?(filename) ? process_dir_as_file(startDir, globPattern, @xml.root) : processFile(startDir, globPattern, @xml.root)
|
66
64
|
else
|
67
65
|
# If the file is not found then process the data as a glob pattern.
|
68
|
-
|
66
|
+
@fs.dirGlob(globPattern) do |f|
|
67
|
+
# $log.info "Glob file found: [#{f}]"
|
68
|
+
# Passing "startDir" as the first parameter is a work-around for issues
|
69
|
+
# when scanning Win VMs from Linux where the path returned from dirGlob
|
70
|
+
# do not include the drive letter.
|
71
|
+
# Below is the original line
|
72
|
+
# processFile(File.dirname(f), File.basename(f), @xml.root)
|
73
|
+
processFile(startDir, File.basename(f), @xml.root)
|
74
|
+
end
|
69
75
|
end
|
70
76
|
@xml
|
71
77
|
end
|
72
78
|
|
73
|
-
def process_each_glob_file(file_name)
|
74
|
-
FindClassMethods.glob(file_name, @fs) do |f|
|
75
|
-
# Passing "startDir" as the first parameter is a work-around for issues
|
76
|
-
# when scanning Win VMs from Linux where the path returned from dirGlob
|
77
|
-
# do not include the drive letter.
|
78
|
-
processFile(File.dirname(f), File.basename(f), @xml.root)
|
79
|
-
end
|
80
|
-
rescue => err
|
81
|
-
$log.error "process_each_glob_file: Exception #{err} rescued"
|
82
|
-
$log.debug err.backtrace.join("\n")
|
83
|
-
end
|
84
|
-
|
85
79
|
def read_fs(path, xmlNode)
|
86
|
-
@drive_letter = @drive_letter.nil? ? "" : @drive_letter
|
87
80
|
if @fs
|
88
81
|
@fs.dirForeach(path) { |x| processFile(path, x, xmlNode) }
|
89
82
|
@fs.dirForeach(path) { |x| processDir(path, x, xmlNode) }
|
@@ -98,7 +91,7 @@ class MD5deep
|
|
98
91
|
|
99
92
|
def processDir(path, x, xmlNode)
|
100
93
|
if x != "." && x != ".."
|
101
|
-
currFile = File.join(
|
94
|
+
currFile = File.join(path, x)
|
102
95
|
|
103
96
|
begin
|
104
97
|
if File.directory?(currFile)
|
@@ -117,7 +110,7 @@ class MD5deep
|
|
117
110
|
|
118
111
|
def process_dir_as_file(path, x, xml_node)
|
119
112
|
if x != "." && x != ".."
|
120
|
-
curr_dir = File.join(
|
113
|
+
curr_dir = File.join(path, x)
|
121
114
|
if isDir?(curr_dir)
|
122
115
|
xml_file_node = xml_node.add_element("file", "name" => x, "fqname" => curr_dir)
|
123
116
|
stat_hash = {}
|
@@ -129,43 +122,39 @@ class MD5deep
|
|
129
122
|
|
130
123
|
def processFile(path, x, xmlNode)
|
131
124
|
if (@opts.exclude.include?(x) == false) && x[0..0] != "$"
|
132
|
-
currFile = File.join(
|
125
|
+
currFile = File.join(path, x)
|
133
126
|
|
134
127
|
begin
|
135
128
|
# unless File.directory?(currFile) then
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
129
|
+
unless isDir?(currFile)
|
130
|
+
# File we have an exclusion list and the current file is in it, skip to the next file
|
131
|
+
@fullFileCount += 1
|
132
|
+
fh = fileOpen(currFile)
|
133
|
+
|
134
|
+
xmlFileNode = xmlNode.add_element("file", "name" => x, "fqname" => currFile)
|
135
|
+
statHash = {}
|
136
|
+
statHash.merge!(getFileStats(fh))
|
137
|
+
statHash.merge!(calculate_digest(fh))
|
138
|
+
xmlFileNode.add_attributes(statHash)
|
139
|
+
|
140
|
+
ext = File.extname(currFile).downcase
|
141
|
+
if @opts.winVerList.include?(ext)
|
142
|
+
if @opts.versioninfo || @opts.imports
|
143
|
+
peHdr = PEheader.new(fh) rescue nil
|
144
|
+
unless peHdr.nil?
|
145
|
+
xmlFileNode.add_element("versioninfo", peHdr.versioninfo) if @opts.versioninfo && !peHdr.versioninfo.blank?
|
146
|
+
xmlFileNode.add_element("libraries", "imports" => peHdr.getImportList) if @opts.imports && !peHdr.imports.blank?
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
getFileContents(fh, xmlFileNode) if @opts.contents == true
|
152
|
+
fh.close
|
152
153
|
end
|
153
|
-
|
154
|
-
getFileContents(fh, xmlFileNode) if @opts.contents == true
|
155
|
-
fh.close
|
156
154
|
rescue Errno::EACCES, RuntimeError, SystemCallError
|
157
155
|
fh.close if fh.kind_of?(File) && !fh.closed?
|
158
156
|
end
|
159
157
|
end
|
160
|
-
$log.debug "processFile: finished @xml is #{@xml}"
|
161
|
-
end
|
162
|
-
|
163
|
-
def process_pe_header(pe_hdr, xml_file_node)
|
164
|
-
xml_file_node.add_element("versioninfo", pe_hdr.versioninfo) if @opts.versioninfo && pe_hdr.versioninfo.present?
|
165
|
-
xml_file_node.add_element("libraries", "imports" => pe_hdr.getImportList) if @opts.imports && pe_hdr.imports.present?
|
166
|
-
rescue TypeError => err
|
167
|
-
$log.info "process_pe_header: TypeError handling PEheader; skipping PEheader info"
|
168
|
-
$log.debug err.backtrace.join("\n")
|
169
158
|
end
|
170
159
|
|
171
160
|
def isDir?(currFile)
|
@@ -226,15 +215,10 @@ class MD5deep
|
|
226
215
|
# Create hash for requested digests
|
227
216
|
digest = create_digest_hash
|
228
217
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
digest.each_pair { |_k, v| v << buf }
|
234
|
-
end
|
235
|
-
rescue => err
|
236
|
-
$log.error "Error #{err} reading file to calculate digest"
|
237
|
-
$log.debug err.backtrace.join("\n")
|
218
|
+
fileName.seek(0, IO::SEEK_SET)
|
219
|
+
# Loop over each digest and add the file contents
|
220
|
+
while buf = fileName.read(10240000)
|
221
|
+
digest.each_pair { |_k, v| v << buf }
|
238
222
|
end
|
239
223
|
end
|
240
224
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manageiq-smartstate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- ManageIQ Developers
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-12-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: azure-armrest
|
@@ -525,7 +525,6 @@ files:
|
|
525
525
|
- lib/metadata/linux/MiqConaryPackages.rb
|
526
526
|
- lib/metadata/linux/MiqRpmPackages.rb
|
527
527
|
- lib/metadata/util/event_log_filter.rb
|
528
|
-
- lib/metadata/util/find_class_methods.rb
|
529
528
|
- lib/metadata/util/md5deep.rb
|
530
529
|
- lib/metadata/util/win32/Win32Accounts.rb
|
531
530
|
- lib/metadata/util/win32/Win32EventLog.rb
|
@@ -1,133 +0,0 @@
|
|
1
|
-
module FindClassMethods
|
2
|
-
# Return directory entries matching specified glob pattern
|
3
|
-
#
|
4
|
-
# @param glob_pattern [String] pattern to match
|
5
|
-
# @param flags [Integer] file match flags
|
6
|
-
# @yield block invoked with each match if specified
|
7
|
-
#
|
8
|
-
# @see VfsRealFile.fnmatch
|
9
|
-
# @see FindClassMethods#dir_and_glob which does most of the work regarding globbing
|
10
|
-
# @see FindClassMethods#find which retrieves stats information & dir entries for found files
|
11
|
-
#
|
12
|
-
def self.glob(glob_pattern, filesys, flags = 0)
|
13
|
-
@fs = filesys
|
14
|
-
return [] unless (glob = dir_and_glob(glob_pattern))
|
15
|
-
|
16
|
-
ra = []
|
17
|
-
find(@search_path, glob_depth(glob)) do |p|
|
18
|
-
if (p = check_file(p, glob, flags))
|
19
|
-
block_given? ? yield(p) : ra << p
|
20
|
-
end
|
21
|
-
end
|
22
|
-
ra.sort_by(&:downcase)
|
23
|
-
end
|
24
|
-
|
25
|
-
#
|
26
|
-
# Determine if the file returned from "find" will be used or skipped.
|
27
|
-
#
|
28
|
-
def self.check_file(file, glob, flags)
|
29
|
-
return nil if file == @search_path
|
30
|
-
|
31
|
-
if @search_path == File::SEPARATOR
|
32
|
-
file.sub!(File::SEPARATOR, "")
|
33
|
-
else
|
34
|
-
file.sub!("#{@search_path}#{File::SEPARATOR}", "")
|
35
|
-
end
|
36
|
-
|
37
|
-
return nil if file == "" || !File.fnmatch(glob, file, flags)
|
38
|
-
|
39
|
-
@specified_path ? File.join(@specified_path, file) : file
|
40
|
-
end
|
41
|
-
|
42
|
-
#
|
43
|
-
# Modified version of Find.find:
|
44
|
-
# - Accepts only a single path.
|
45
|
-
# - Can be restricted by depth - optimization for glob searches.
|
46
|
-
#
|
47
|
-
# @param path [String] starting directory of the find
|
48
|
-
# @param max_depth [Integer] max number of levels to decend befroelookup
|
49
|
-
# @yield files found
|
50
|
-
#
|
51
|
-
def self.find(path, max_depth = nil)
|
52
|
-
block_given? || (return enum_for(__method__, path, max_depth))
|
53
|
-
|
54
|
-
depths = [0]
|
55
|
-
paths = [path.dup]
|
56
|
-
|
57
|
-
while (file = paths.shift)
|
58
|
-
depth = depths.shift
|
59
|
-
yield file.dup.taint
|
60
|
-
next if max_depth && depth + 1 > max_depth
|
61
|
-
|
62
|
-
get_dir_entries(file).each do |f|
|
63
|
-
f = File.join(file, f)
|
64
|
-
paths.unshift f.untaint
|
65
|
-
depths.unshift depth + 1
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def self.get_dir_entries(directory)
|
71
|
-
return [] unless @fs.fileExists?(directory) && @fs.fileDirectory?(directory)
|
72
|
-
|
73
|
-
files = @fs.dirEntries(directory)
|
74
|
-
files -= [".", ".."]
|
75
|
-
files.sort!
|
76
|
-
files.reverse_each
|
77
|
-
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
78
|
-
$log.info "find: while-loop @fs.dirEntries #{directory} returned an error"
|
79
|
-
[]
|
80
|
-
end
|
81
|
-
|
82
|
-
GLOB_CHARS = '*?[{'.freeze
|
83
|
-
def self.glob_str?(str)
|
84
|
-
str.gsub(/\\./, "X").count(GLOB_CHARS) != 0
|
85
|
-
end
|
86
|
-
|
87
|
-
# Returns files matching glob pattern
|
88
|
-
#
|
89
|
-
# @api private
|
90
|
-
# @param glob_pattern [String,Regex] pattern to search for
|
91
|
-
# @return [String] paths to files found
|
92
|
-
#
|
93
|
-
def self.dir_and_glob(glob_pattern)
|
94
|
-
stripped_path = glob_pattern.sub(/^[a-zA-Z]:/, "")
|
95
|
-
glob_path = Pathname.new(stripped_path)
|
96
|
-
@search_path = File::SEPARATOR
|
97
|
-
@specified_path = File::SEPARATOR
|
98
|
-
|
99
|
-
unless glob_path.absolute?
|
100
|
-
@search_path = Dir.getwd
|
101
|
-
@specified_path = nil
|
102
|
-
end
|
103
|
-
|
104
|
-
components = path_components(glob_path)
|
105
|
-
@search_path = File.expand_path(@search_path, "/")
|
106
|
-
@fs.fileExists?(@search_path) ? File.join(components) : nil
|
107
|
-
end
|
108
|
-
|
109
|
-
def self.path_components(glob_path, search_path = @search_path)
|
110
|
-
components = glob_path.each_filename.to_a
|
111
|
-
while (comp = components.shift)
|
112
|
-
if glob_str?(comp)
|
113
|
-
components.unshift(comp)
|
114
|
-
break
|
115
|
-
end
|
116
|
-
@search_path = File.join(search_path, comp)
|
117
|
-
@specified_path = @specified_path ? File.join(@specified_path, comp) : comp
|
118
|
-
end
|
119
|
-
components
|
120
|
-
end
|
121
|
-
|
122
|
-
# Return max levels which glob pattern may resolve to
|
123
|
-
#
|
124
|
-
# @api private
|
125
|
-
# @param glob_pattern [String,Regex] pattern to search for
|
126
|
-
# @return [Integer] max levels which pattern may match
|
127
|
-
def self.glob_depth(glob_pattern)
|
128
|
-
path_components = Pathname(glob_pattern).each_filename.to_a
|
129
|
-
return nil if path_components.include?('**')
|
130
|
-
|
131
|
-
path_components.length
|
132
|
-
end
|
133
|
-
end
|