Module: MiscUtils

Defined in:
lib/buzzcore/misc_utils.rb

Class Method Summary collapse

Class Method Details

.append_slash(aPath, aSep = nil) ⇒ Object



130
131
132
133
134
135
# File 'lib/buzzcore/misc_utils.rb', line 130

def self.append_slash(aPath,aSep=nil)
	aSep = sniff_seperator(aPath) unless aSep
	last_char = aPath[-1,1]
	aPath += aSep unless last_char=='\\' || last_char=='/'
	return aPath
end

.canonize_path(aPath, aRootPath = nil) ⇒ Object

takes a path and combines it with a root path (which defaults to Dir.pwd) unless it is absolute the final result is then expanded



179
180
181
182
183
# File 'lib/buzzcore/misc_utils.rb', line 179

def self.canonize_path(aPath,aRootPath=nil)
	path = path_combine(aRootPath,aPath)
	path = real_path(path) if path
	path
end

.ensure_prefix(aString, aPrefix) ⇒ Object



143
144
145
# File 'lib/buzzcore/misc_utils.rb', line 143

def self.ensure_prefix(aString,aPrefix)
	aString.begins_with?(aPrefix) ? aString : aPrefix+aString
end

.ensure_suffix(aString, aSuffix) ⇒ Object



147
148
149
# File 'lib/buzzcore/misc_utils.rb', line 147

def self.ensure_suffix(aString,aSuffix)
	aString.ends_with?(aSuffix) ? aString : aString+aSuffix
end

.execute(aCommand, aWorkingDir = nil, aTimeout = nil, aTimeoutClass = nil) ⇒ Object

returns output string if succesful, or integer return code if not, or nil



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/buzzcore/misc_utils.rb', line 41

def self.execute(aCommand,aWorkingDir=nil,aTimeout=nil,aTimeoutClass=nil)
	return nil unless !aWorkingDir || File.exists?(aWorkingDir)
	begin
		orig_wd = Dir.getwd
		pipe = nil
		result = nil
		Dir.chdir(aWorkingDir) if aWorkingDir
		Timeout.timeout(aTimeout,aTimeoutClass || Timeout::Error) do	# nil aTimeout will not time out
			pipe = IO.popen(aCommand)
			logger.debug "command PID:"+pipe.pid.to_s
			result = pipe.read
		end
	ensure
		pipe.close if pipe
		Dir.chdir(orig_wd)
	end
	return result
end

.execute_string(aCmdString, aWorkingDir = nil) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/buzzcore/misc_utils.rb', line 60

def self.execute_string(aCmdString,aWorkingDir=nil)
	result = nil
	begin
		orig_dir = Dir.pwd
		Dir.chdir(aWorkingDir) if aWorkingDir
		result = `#{aCmdString}`
	ensure
		Dir.chdir(orig_dir) if aWorkingDir
	end 
	return result
end

.expand_magic_path(aPath, aBasePath = nil) ⇒ Object

allows special symbols in path currently only … supported, which looks upward in the filesystem for the following relative path from the basepath



196
197
198
199
200
201
202
203
# File 'lib/buzzcore/misc_utils.rb', line 196

def self.expand_magic_path(aPath,aBasePath=nil)
	aBasePath ||= Dir.pwd
	path = aPath
	if path.begins_with?('...')
		rel_part = StringUtils.split3(path,/\.\.\.[\/\\]/)[2]
		path = find_upwards(aBasePath,rel_part)
	end
end

.file_change_ext(aFile, aExt, aExtend = false) ⇒ Object



236
237
238
# File 'lib/buzzcore/misc_utils.rb', line 236

def self.file_change_ext(aFile,aExt,aExtend=false)
	file_no_extension(aFile,false)+(aExtend ? '.'+aExt+'.'+file_extension(aFile,false) : '.'+aExt)
end

.file_extension(aFile, aExtended = true) ⇒ Object



225
226
227
228
229
# File 'lib/buzzcore/misc_utils.rb', line 225

def self.file_extension(aFile,aExtended=true)
	f = File.basename(aFile)
	dot = aExtended ? f.index('.') : f.rindex('.')
	return dot ? f[dot+1..-1] : f
end

.file_list_ancestor(aFiles) ⇒ Object

returns the lowest path containing all files (assumes aFiles contains only absolute paths)



328
329
330
331
332
333
334
335
336
337
338
# File 'lib/buzzcore/misc_utils.rb', line 328

def self.file_list_ancestor(aFiles)
   files = aFiles.is_a?(Hash) ? aFiles.keys : aFiles
	result = File.dirname(files.first)
	files.each do |fp|
		filedir = File.dirname(fp)
		while path_same(result,filedir)==false && path_ancestor(result,filedir)==false
			result = path_parent(result)
		end
	end		
	result
end

.file_no_extension(aFile, aExtended = true) ⇒ Object



231
232
233
234
# File 'lib/buzzcore/misc_utils.rb', line 231

def self.file_no_extension(aFile,aExtended=true)
	ext = file_extension(aFile,aExtended)
	return aFile.chomp('.'+ext)
end

.filelist_from_patterns(aPatterns, aBasePath) ⇒ Object



366
367
368
369
370
371
372
373
374
375
# File 'lib/buzzcore/misc_utils.rb', line 366

def self.filelist_from_patterns(aPatterns,aBasePath)
	return [] unless aPatterns
	aPatterns = [aPatterns] unless aPatterns.is_a? Array

	aPatterns.map do |fp|
		fp = File.expand_path(fp,aBasePath)		# relative to rails root
		fp = FileList[fp] if fp['*'] || fp['?']
		fp
	end.flatten
end

.filter_multilevel_hash(aSource, aInclude = nil, aExclude = nil, &block) ⇒ Object

applies the given block to key/value pairs included/excluded by the given parameters aSource must be a hash, and may contain hashes which will be recursively processed. aInclude/aExclude may be nil, an array of selected keys, or a hash containing arrays of keys for inner hashes of aSource When aInclude/aExclude are a hash, non-hash source values may be selected by passing a value of true. Hash source values will be selected as a whole (all keys) when true is passed. input = { ‘a’ => 1, ‘b’ => => 9, ‘y’ => 8, ‘c’ => 3 } filter_multilevel_hash(input,,href="'y'">b’=>) {|h,k,v| h = true} input now = { ‘a’ => true, ‘b’ => => true, ‘y’ => 8, ‘c’ => 3 }



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/buzzcore/misc_utils.rb', line 21

def self.filter_multilevel_hash(aSource,aInclude=nil,aExclude=nil,&block)
	aSource.each do |key,value|
		next if aInclude.is_a?(Array) and !aInclude.include?(key)		# skip if not in aInclude array
		next if aExclude.is_a?(Array) and aExclude.include?(key)		# skip if in aExclude array
		next if aExclude.is_a?(Hash) and aExclude[key]==true				# skip if in aExclude hash with value=true
		next if aInclude.is_a?(Hash) and !aInclude.include?(key)		# skip if not in aInclude hash at all
		if value.is_a?(Hash)																				# value is hash so recursively apply filter 
			filter_multilevel_hash(
				value,
				aInclude.is_a?(Hash) && (f = aInclude[key]) ? f : nil,	# pass include array if provided for key
				aExclude.is_a?(Hash) && (f = aExclude[key]) ? f : nil,	# pass exclude array if provided for key
				&block
			)
		else
			yield(aSource,key,value)
		end
	end
end

.find_upwards(aStartPath, aPath) ⇒ Object



185
186
187
188
189
190
191
# File 'lib/buzzcore/misc_utils.rb', line 185

def self.find_upwards(aStartPath,aPath)
	curr_path = File.expand_path(aStartPath)
	while curr_path && !(test_path_exists = File.exists?(test_path = File.join(curr_path,aPath))) do
		curr_path = MiscUtils.path_parent(curr_path)
	end
	curr_path && test_path_exists ? test_path : nil
end

.get_files(aArray, aPath, aFullPath = true, aRootPath = nil, &block) ⇒ Object



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
# File 'lib/buzzcore/misc_utils.rb', line 282

def self.get_files(aArray,aPath,aFullPath=true,aRootPath=nil,&block)
	#puts "get_files: aPath='#{aPath}'"
	if aRootPath
		abssrcpath = path_combine(aRootPath,aPath)
	else
		abssrcpath = aRootPath = aPath
		aPath = nil
	end
	return aArray if !File.exists?(abssrcpath)
	#abssrcpath is real path to query
	#aRootPath is highest level path
	#aPath is current path relative to aRootPath
	Dir.new(abssrcpath).to_a.each do |file|
		next if ['.','..'].include? file
		fullpath = File.join(abssrcpath,file)
		resultpath = aFullPath ? fullpath : path_combine(aPath,file)
		if !block_given? || yield(resultpath)
			if FileTest.directory?(fullpath)
				block_given? ? get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath,&block) : get_files(aArray,path_combine(aPath,file),aFullPath,aRootPath)
			else
				aArray << resultpath
			end
		end
	end
	return aArray
end

.hash_to_xml_tag(aName, aHash) ⇒ Object

takes a hash and returns a single closed tag containing the hash pairs as attributes, correctly encoded



358
359
360
361
362
363
364
# File 'lib/buzzcore/misc_utils.rb', line 358

def self.hash_to_xml_tag(aName,aHash)
	atts = ''
	aHash.each do |k,v| 
		atts += ' ' + k.to_s + "=\"#{v.to_s.to_xs}\""
	end
	"<#{aName}#{atts}/>"		
end

.is_root_path?(aPath) ⇒ Boolean

Returns:

  • (Boolean)


256
257
258
259
260
261
262
# File 'lib/buzzcore/misc_utils.rb', line 256

def self.is_root_path?(aPath)
	if is_windows?
		(aPath =~ /^[a-zA-Z]\:[\\\/]$/)==0
	else
		aPath == '/'
	end
end

.is_uri?(aString) ⇒ Boolean

Returns:

  • (Boolean)


252
253
254
# File 'lib/buzzcore/misc_utils.rb', line 252

def self.is_uri?(aString)
	/^[a-zA-Z0-9+_]+\:\/\// =~ aString ? true : false
end

.is_windows?Boolean

Returns:

  • (Boolean)


278
279
280
# File 'lib/buzzcore/misc_utils.rb', line 278

def self.is_windows?
	platform=='mswin32'
end

.loggerObject



9
10
11
# File 'lib/buzzcore/misc_utils.rb', line 9

def self.logger
	@logger || @logger = Logger.new(STDERR)
end

.make_temp_dir(aPrefix = '') ⇒ Object



85
86
87
88
89
90
91
92
# File 'lib/buzzcore/misc_utils.rb', line 85

def self.make_temp_dir(aPrefix='')
	new_dir = nil
   begin
		new_dir = File.join(Dir.tmpdir,aPrefix+("%08X" % rand(0x3FFFFFFF)))
	end until new_dir && !File.exists?(new_dir)
	Dir.mkdir new_dir
	return new_dir
end

.make_temp_file(aName = nil, aDir = nil, aContent = nil) ⇒ Object



77
78
79
80
81
82
83
# File 'lib/buzzcore/misc_utils.rb', line 77

def self.make_temp_file(aName=nil,aDir=nil,aContent=nil)
	filename = aName ? File.expand_path(aName,aDir || Dir.tmpdir) : temp_file(nil,aDir)
   FileUtils.mkdir_p(File.dirname(filename))
	aContent ||= "content of "+filename
	string_to_file(aContent,filename)
   filename
end

.mkdir?(aPath, aPermissions = nil) ⇒ Boolean

Returns:

  • (Boolean)


94
95
96
97
# File 'lib/buzzcore/misc_utils.rb', line 94

def self.mkdir?(aPath,aPermissions=nil)
FileUtils.mkdir_p(aPath) unless File.exists?(aPath)
File.chmod(aPermissions, aPath) if aPermissions
end

.native_path(aPath) ⇒ Object



264
265
266
# File 'lib/buzzcore/misc_utils.rb', line 264

def self.native_path(aPath)
	is_windows? ? windows_path(aPath) : ruby_path(aPath)
end

.neaten_cap_path(aPath) ⇒ Object

for capistrano deployed paths makes “/var/www/logikal.stage/releases/20090911073620/cms/config.xml” into “/var/www/logikal.stage/current/cms/config.xml”



353
354
355
# File 'lib/buzzcore/misc_utils.rb', line 353

def self.neaten_cap_path(aPath)
	aPath.sub(/(\/releases\/[0-9]+\/)/,'/current/')
end

.path_absolute?(aPath) ⇒ Boolean

Returns:

  • (Boolean)


274
275
276
# File 'lib/buzzcore/misc_utils.rb', line 274

def self.path_absolute?(aPath)
	!path_relative(aPath)
end

.path_ancestor(aPathParent, aPath) ⇒ Object

returns true if aPath is under aPathParent both must be absolute or both relative



322
323
324
325
# File 'lib/buzzcore/misc_utils.rb', line 322

def self.path_ancestor(aPathParent,aPath)
	return nil unless path_relative?(aPathParent) == path_relative?(aPath)
	aPath.index(append_slash(aPathParent))==0
end

.path_combine(aBasePath, aPath) ⇒ Object



166
167
168
169
170
# File 'lib/buzzcore/misc_utils.rb', line 166

def self.path_combine(aBasePath,aPath)
	return aBasePath if !aPath
	return aPath if !aBasePath
	return path_relative?(aPath) ? File.join(aBasePath,aPath) : aPath	
end

.path_debase(aPath, aBase) ⇒ Object

Remove base dir from given path. Result will be relative to base dir and not have a leading or trailing slash ‘/a/b/c’,‘/a’ = ‘b/c’ ‘/a/b/c’,‘/’ = ‘a/b/c’ ‘/’,‘/’ = ”



155
156
157
158
159
# File 'lib/buzzcore/misc_utils.rb', line 155

def self.path_debase(aPath,aBase)
	aBase = MiscUtils::append_slash(aBase)
	aPath = MiscUtils::remove_slash(aPath) unless aPath=='/'
	aPath[0,aBase.length]==aBase ? aPath[aBase.length,aPath.length-aBase.length] : aPath
end

.path_match(aPath, aPatterns) ⇒ Object



340
341
342
343
344
345
346
347
348
349
# File 'lib/buzzcore/misc_utils.rb', line 340

def self.path_match(aPath,aPatterns)
	aPatterns = [aPatterns] unless aPatterns.is_a? Array
	aPatterns.any? do |pat|
		case pat
			when String then aPath[0,pat.length] == pat
			when Regexp then aPath =~ pat
			else false
		end
	end
end

.path_parent(aPath) ⇒ Object



205
206
207
208
# File 'lib/buzzcore/misc_utils.rb', line 205

def self.path_parent(aPath)
	return nil if is_root_path?(aPath)
	MiscUtils.append_slash(File.dirname(MiscUtils.remove_slash(File.expand_path(aPath))))
end

.path_parts(aPath) ⇒ Object



220
221
222
223
# File 'lib/buzzcore/misc_utils.rb', line 220

def self.path_parts(aPath)
	sep = sniff_seperator(aPath)
	aPath.split(sep)
end

.path_rebase(aPath, aOldBase, aNewBase) ⇒ Object



161
162
163
164
# File 'lib/buzzcore/misc_utils.rb', line 161

def self.path_rebase(aPath,aOldBase,aNewBase)
	rel_path = path_debase(aPath,aOldBase)
	append_slash(aNewBase)+rel_path
end

.path_relative?(aPath) ⇒ Boolean

Returns:

  • (Boolean)


268
269
270
271
272
# File 'lib/buzzcore/misc_utils.rb', line 268

def self.path_relative?(aPath)
	return false if aPath[0,1]=='/'
	return false if aPath =~ /^[a-zA-Z]:/
	return true
end

.path_same(aPath1, aPath2) ⇒ Object

returns true if aPath1 and aPath2 are the same path (doesn’t query file system) both must be absolute or both relative



315
316
317
318
# File 'lib/buzzcore/misc_utils.rb', line 315

def self.path_same(aPath1,aPath2)
	return nil unless path_relative?(aPath1) == path_relative?(aPath2)
	remove_slash(aPath1) == remove_slash(aPath2)
end

.platformObject



240
241
242
# File 'lib/buzzcore/misc_utils.rb', line 240

def self.platform
	RUBY_PLATFORM.scan(/-(.+)$/).flatten.first
end

.real_path(aPath) ⇒ Object

make path real according to file system



173
174
175
# File 'lib/buzzcore/misc_utils.rb', line 173

def self.real_path(aPath)
	(path = Pathname.new(File.expand_path(aPath))) && path.realpath.to_s
end

.recursive_file_list(aPath, aFullPath = true, &block) ⇒ Object



309
310
311
# File 'lib/buzzcore/misc_utils.rb', line 309

def self.recursive_file_list(aPath,aFullPath=true,&block)
block_given? ? get_files([],aPath,aFullPath,nil,&block) : get_files([],aPath,aFullPath)
end

.remove_slash(aPath) ⇒ Object



137
138
139
140
141
# File 'lib/buzzcore/misc_utils.rb', line 137

def self.remove_slash(aPath)
	last_char = aPath[-1,1]
	aPath = aPath[0..-2] if last_char=='\\' || last_char=='/'
	return aPath
end

.ruby_path(aPath) ⇒ Object



248
249
250
# File 'lib/buzzcore/misc_utils.rb', line 248

def self.ruby_path(aPath)
	aPath.gsub('\\','/')
end

.send_email(aArgs) ⇒ Object

send an email via an SMTP server



391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
# File 'lib/buzzcore/misc_utils.rb', line 391

def self.send_email(aArgs)
  msg = <<END_OF_MESSAGE
From: #{aArgs[:from_alias]} <#{aArgs[:from]}>
To: #{aArgs[:to_alias]} <#{aArgs[:to]}>
Subject: #{aArgs[:subject]}

#{aArgs[:message]}
END_OF_MESSAGE

  Net::SMTP.start(
	aArgs[:host],
	aArgs[:port],
	aArgs[:helodomain],
	aArgs[:user],
	aArgs[:password],
	aArgs[:auth]
) do |smtp|
    smtp.send_message msg, aArgs[:from], aArgs[:to]
  end
end

.set_permissions_cmd(aFilepath, aUser = nil, aGroup = nil, aMode = nil, aSetGroupId = false, aSudo = true) ⇒ Object



99
100
101
102
103
104
105
106
107
108
109
# File 'lib/buzzcore/misc_utils.rb', line 99

def self.set_permissions_cmd(aFilepath,aUser=nil,aGroup=nil,aMode=nil,aSetGroupId=false,aSudo=true)
	cmd = []
	if aGroup
		cmd << (aUser ? "#{aSudo ? sudo : ''} chown #{aUser}:#{aGroup}" : "#{aSudo ? sudo : ''} chgrp #{aGroup}") + " #{aFilepath}"
	else	
		cmd << "#{aSudo ? sudo : ''} chown #{aUser} #{aFilepath}" if aUser
	end
	cmd << "#{aSudo ? sudo : ''} chmod #{aMode.to_s} #{aFilepath}" if aMode
	cmd << "#{aSudo ? sudo : ''} chmod g+s #{aFilepath}" if aSetGroupId
	cmd.join(' && ')
end

.simple_dir_name(aPath) ⇒ Object



210
211
212
# File 'lib/buzzcore/misc_utils.rb', line 210

def self.simple_dir_name(aPath)
	File.basename(remove_slash(aPath))
end

.simple_file_name(aPath) ⇒ Object



214
215
216
217
218
# File 'lib/buzzcore/misc_utils.rb', line 214

def self.simple_file_name(aPath)
	f = File.basename(aPath)
	dot = f.index('.')
	return dot ? f[0,dot] : f
end

.sniff_seperator(aPath) ⇒ Object



121
122
123
124
125
126
127
128
# File 'lib/buzzcore/misc_utils.rb', line 121

def self.sniff_seperator(aPath)
	result = 0.upto(aPath.length-1) do |i|
		char = aPath[i,1]
		break char if char=='\\' || char=='/'
	end
	result = File::SEPARATOR if result==0
	return result
end

.string_from_file(aFilename) ⇒ Object



115
116
117
118
119
# File 'lib/buzzcore/misc_utils.rb', line 115

def self.string_from_file(aFilename)
	result = nil
	File.open(aFilename, "rb") { |f| result = f.read }
	# return result && result[0..-2]  # quick hack to stop returning false \n at end UPDATE: this is causing problems now
end

.string_to_file(aString, aFilename) ⇒ Object



111
112
113
# File 'lib/buzzcore/misc_utils.rb', line 111

def self.string_to_file(aString,aFilename)
	File.open(aFilename,'wb') {|file| file.write aString }
end

.temp_file(aExt = nil, aDir = nil) ⇒ Object



72
73
74
75
# File 'lib/buzzcore/misc_utils.rb', line 72

def self.temp_file(aExt=nil,aDir=nil)
	aExt ||= '.tmp'
	File.expand_path(("%08X" % rand(0x3FFFFFFF)) + aExt, aDir||Dir.tmpdir)
end

.windows_path(aPath) ⇒ Object



244
245
246
# File 'lib/buzzcore/misc_utils.rb', line 244

def self.windows_path(aPath)
	aPath.gsub('/','\\')
end