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



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

def self.canonize_path(aPath,aRootPath=nil)
	path = path_combine(aRootPath,aPath)
	path = real_path(path) if path
	path
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



188
189
190
191
192
193
194
195
# File 'lib/buzzcore/misc_utils.rb', line 188

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



228
229
230
# File 'lib/buzzcore/misc_utils.rb', line 228

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



217
218
219
220
221
# File 'lib/buzzcore/misc_utils.rb', line 217

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)



320
321
322
323
324
325
326
327
328
329
330
# File 'lib/buzzcore/misc_utils.rb', line 320

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



223
224
225
226
# File 'lib/buzzcore/misc_utils.rb', line 223

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

.filelist_from_patterns(aPatterns, aBasePath) ⇒ Object



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

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



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

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



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

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



350
351
352
353
354
355
356
# File 'lib/buzzcore/misc_utils.rb', line 350

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)


248
249
250
251
252
253
254
# File 'lib/buzzcore/misc_utils.rb', line 248

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

.is_uri?(aString) ⇒ Boolean

Returns:

  • (Boolean)


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

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

.is_windows?Boolean

Returns:

  • (Boolean)


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

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



256
257
258
# File 'lib/buzzcore/misc_utils.rb', line 256

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”



345
346
347
# File 'lib/buzzcore/misc_utils.rb', line 345

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

.path_absolute?(aPath) ⇒ Boolean

Returns:

  • (Boolean)


266
267
268
# File 'lib/buzzcore/misc_utils.rb', line 266

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



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

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



158
159
160
161
162
# File 'lib/buzzcore/misc_utils.rb', line 158

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’ ‘/’,‘/’ = ”



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

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



332
333
334
335
336
337
338
339
340
341
# File 'lib/buzzcore/misc_utils.rb', line 332

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



197
198
199
200
# File 'lib/buzzcore/misc_utils.rb', line 197

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



212
213
214
215
# File 'lib/buzzcore/misc_utils.rb', line 212

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

.path_rebase(aPath, aOldBase, aNewBase) ⇒ Object



153
154
155
156
# File 'lib/buzzcore/misc_utils.rb', line 153

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)


260
261
262
263
264
# File 'lib/buzzcore/misc_utils.rb', line 260

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



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

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

.platformObject



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

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

.real_path(aPath) ⇒ Object

make path real according to file system



165
166
167
# File 'lib/buzzcore/misc_utils.rb', line 165

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



301
302
303
# File 'lib/buzzcore/misc_utils.rb', line 301

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



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

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

.send_email(aArgs) ⇒ Object

send an email via an SMTP server



383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
# File 'lib/buzzcore/misc_utils.rb', line 383

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



202
203
204
# File 'lib/buzzcore/misc_utils.rb', line 202

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

.simple_file_name(aPath) ⇒ Object



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

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



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

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