Module: RUtilAnts::Misc

Defined in:
lib/rUtilAnts/Misc.rb

Constant Summary collapse

FILEMUTEX_NO_LOCK =

Constants used for fileMutex There was no lock on the mutex

0
FILEMUTEX_ZOMBIE_LOCK =

There was a lock on the mutex, but former process did not exist anymore

1
FILEMUTEX_LOCK_TAKEN =

The lock is taken by a running process

2
FILEMUTEX_INVALID_LOCK =

The lock file is invalid

3

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.initializeMiscObject

Set these methods into the Object namespace



11
12
13
# File 'lib/rUtilAnts/Misc.rb', line 11

def self.initializeMisc
  Object.module_eval('include RUtilAnts::Misc')
end

Instance Method Details

#cachedVar(&iCode) ⇒ Object

Cache the access to a given code result, based on the caller ID This can be used to cache variables computation (ex. lVar = cachedVar{ lengthyFctToComputeVar } )

Parameters:

  • *&iCode* (CodeBlock): The code called to compute the result

** Return: *** Object: The computed result Return:

  • Object: The result of the code



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rUtilAnts/Misc.rb', line 24

def cachedVar(&iCode)
  if (defined?(@RUtilAnts_Misc_CachedVars) == nil)
    @RUtilAnts_Misc_CachedVars = {}
  end
  # Compute the hash of this code
  lHash = caller[0].hash
  if (@RUtilAnts_Misc_CachedVars[lHash] == nil)
    @RUtilAnts_Misc_CachedVars[lHash] = iCode.call
  end

  return @RUtilAnts_Misc_CachedVars[lHash]
end

#changeDir(iDir) ⇒ Object

Execute a code block after having changed current directory. Ensure the directory will be changed back at the end of the block, even if exceptions are thrown.

Parameters:

  • iDir (String): The directory to change into

  • CodeBlock: Code called once the current directory has been changed



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/rUtilAnts/Misc.rb', line 158

def changeDir(iDir)
  lOldDir = Dir.getwd
  Dir.chdir(iDir)
  begin
    yield
  rescue Exception
    Dir.chdir(lOldDir)
    raise
  end
  Dir.chdir(lOldDir)
end

#extractZipFile(iZipFileName, iDirName) ⇒ Object

Extract a Zip archive in a given system dependent lib sub-directory

Parameters:

  • iZipFileName (String): The zip file name to extract content from

  • iDirName (String): The name of the directory to store the zip to

Return:

  • Exception: Error, or nil in case of success



58
59
60
61
62
63
64
65
66
67
68
69
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
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
# File 'lib/rUtilAnts/Misc.rb', line 58

def extractZipFile(iZipFileName, iDirName)
  rError = nil

  # Use RDI if possible to ensure the dependencies on zlib.dll and rubyzip
  if (defined?(RDI) != nil)
    lRDIInstaller = RDI::Installer.getMainInstance
    if (lRDIInstaller != nil)
      # First, test that the DLL exists.
      # If it does not exist, we can't install it, because ZLib.dll is downloadable only in ZIP format (kind of stupid ;-) )
      lDLLDep = nil
      case $rUtilAnts_Platform_Info.os
      when OS_WINDOWS
        lDLLDep = RDI::Model::DependencyDescription.new('ZLib DLL').addDescription( {
          :Testers => [
            {
              :Type => 'DynamicLibraries',
              :Content => [ 'zlib.dll' ]
            }
          ],
          # We can't install this one
          :Installers => []
        } )
      else
        logBug "Sorry, installing ZLib on your platform #{$rUtilAnts_Platform_Info.os} is not yet supported."
      end
      if ((lDLLDep != nil) and
          (!lRDIInstaller.testDependency(lDLLDep)))
        # Try adding the default local location for libraries
        lRDIInstaller.ensureLocationInContext('LibraryPath', lRDIInstaller.getDefaultInstallLocation('Download', RDI::DEST_LOCAL))
        # Try again
        if (!lRDIInstaller.testDependency(lDLLDep))
          logErr "zlib.dll is not installed in your system.\nUnfortunately RDI can't help because the only way to install it is to download it through a ZIP file.\nPlease install it manually from http://zlib.net (you can do it now and click OK once it is installed)."
        end
      end
      # Then, ensure the gem dependency
      rError, lCMApplied, lIgnored, lUnresolved = lRDIInstaller.ensureDependencies(
        [
          RDI::Model::DependencyDescription.new('RubyZip').addDescription( {
            :Testers => [
              {
                :Type => 'RubyRequires',
                :Content => [ 'zip/zipfilesystem' ]
              }
            ],
            :Installers => [
              {
                :Type => 'Gem',
                :Content => 'rubyzip',
                :ContextModifiers => [
                  {
                    :Type => 'GemPath',
                    :Content => '%INSTALLDIR%'
                  }
                ]
              }
            ]
          } )
        ]
      )
      if (!lIgnored.empty?)
        rError = RuntimeError.new("Unable to install RubyZip without its dependencies (#{lIgnored.size} ignored dependencies).")
      elsif (!lUnresolved.empty?)
        rError = RuntimeError.new("Unable to install RubyZip without its dependencies (#{lUnresolved.size} unresolved dependencies):\n#{rError}")
      end
    end
  end
  if (rError == nil)
    # Extract content of iFileName to iDirName
    begin
      # We don't put this require in the global scope as it needs first a DLL to be loaded by plugins
      require 'zip/zipfilesystem'
      Zip::ZipInputStream::open(iZipFileName) do |iZipFile|
        while (lEntry = iZipFile.get_next_entry)
          lDestFileName = "#{iDirName}/#{lEntry.name}"
          if (lEntry.directory?)
            FileUtils::mkdir_p(lDestFileName)
          else
            FileUtils::mkdir_p(File.dirname(lDestFileName))
            # If the file already exist, first delete it to replace it with ours
            if (File.exists?(lDestFileName))
              File.unlink(lDestFileName)
            end
            lEntry.extract(lDestFileName)
          end
        end
      end
    rescue Exception
      rError = $!
    end
  end

  return rError
end

#fileMutex(iProcessID) ⇒ Object

Execute a code block protected by a file mutex

Parameters:

  • iProcessID (String): Process ID to be used to identify the mutex

  • CodeBlock: The code called if the mutex is taken

Return:

  • Integer: Error code



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
237
238
239
# File 'lib/rUtilAnts/Misc.rb', line 186

def fileMutex(iProcessID)
  rResult = FILEMUTEX_NO_LOCK

  # Prevent concurrent execution
  require 'tmpdir'
  lLockFile = "#{Dir.tmpdir}/FileMutex_#{iProcessID}.lock"
  if (File.exists?(lLockFile))
    logErr "Another instance of process #{iProcessID} is already running. Delete file #{lLockFile} if it is not."
    begin
      lDetails = nil
      File.open(lLockFile, 'r') do |iFile|
        lDetails = eval(iFile.read)
      end
      logErr "Details of the running instance: #{lDetails.inspect}"
      # If the process does not exist anymore, remove the lock file
      # TODO: Adapt this to non Unix systems
      if (File.exists?("/proc/#{lDetails[:PID]}"))
        rResult = FILEMUTEX_LOCK_TAKEN
      else
        logErr "Process #{lDetails[:PID]} does not exist anymore. Removing lock file."
        File.unlink(lLockFile)
        rResult = FILEMUTEX_ZOMBIE_LOCK
      end
    rescue Exception
      logErr "Invalid lock file #{lLockFile}: #{$!}."
      rResult = FILEMUTEX_INVALID_LOCK
    end
  end
  if ((rResult == FILEMUTEX_NO_LOCK) or
      (rResult == FILEMUTEX_ZOMBIE_LOCK))
    # Create the lock for our process
    File.open(lLockFile, 'w') do |oFile|
      oFile << "
        {
          :ExecutionTime => '#{DateTime.now.strftime('%Y-%m-%d %H:%M:%S')}',
          :PID => '#{Process.pid}'
        }
      "
    end
    begin
      yield
      File.unlink(lLockFile)
    rescue Exception
      begin
        File.unlink(lLockFile)
      rescue Exception
        logErr "Exception while deleting lock file #{lLockFile}: #{$!}"
      end
      raise
    end
  end

  return rResult
end

#getValidFileName(iFileName) ⇒ Object

Get a valid file name, taking into account platform specifically prohibited characters in file names.

Parameters:

  • iFileName (String): The original file name wanted

Return:

  • String: The correct file name



43
44
45
46
47
48
49
# File 'lib/rUtilAnts/Misc.rb', line 43

def getValidFileName(iFileName)
  if ((defined?($rUtilAnts_Platform_Info) != nil))
    return iFileName.gsub(/[#{Regexp.escape($rUtilAnts_Platform_Info.getProhibitedFileNamesCharacters)}]/, '_')
  else
    return iFileName
  end
end