sup

A curses threads-with-tags style email client

sup.git

git clone https://supmua.dev/git/sup/

lib/sup/interactive_lock.rb (2664B) - raw

      1 require 'fileutils'
      2 
      3 module Redwood
      4 
      5 ## wrap a nice interactive layer on top of anything that has a #lock method
      6 ## which throws a LockError which responds to #user, #host, #mtim, #pname, and
      7 ## #pid.
      8 
      9 module InteractiveLock
     10   def pluralize number_of, kind; "#{number_of} #{kind}" + (number_of == 1 ? "" : "s") end
     11 
     12   def time_ago_in_words time
     13     secs = (Time.now - time).to_i
     14     mins = secs / 60
     15     time = if mins == 0
     16       pluralize secs, "second"
     17     else
     18       pluralize mins, "minute"
     19     end
     20   end
     21 
     22   DELAY = 5 # seconds
     23 
     24   def lock_interactively stream=$stderr
     25     begin
     26       Index.lock
     27     rescue Index::LockError => e
     28       begin
     29         Process.kill 0, e.pid.to_i # 0 signal test the existence of PID
     30         stream.puts <<EOS
     31   Error: the index is locked by another process! User '#{e.user}' on
     32   host '#{e.host}' is running #{e.pname} with pid #{e.pid}.
     33   The process was alive as of at least #{time_ago_in_words e.mtime} ago.
     34 
     35 EOS
     36         stream.print "Should I ask that process to kill itself (y/n)? "
     37         stream.flush
     38         if $stdin.gets =~ /^\s*y(es)?\s*$/i
     39           Process.kill "TERM", e.pid.to_i
     40           sleep DELAY
     41           stream.puts "Let's try that again."
     42           begin
     43             Index.lock
     44           rescue Index::LockError => e
     45             stream.puts "I couldn't lock the index. The lockfile might just be stale."
     46             stream.print "Should I just remove it and continue? (y/n) "
     47             stream.flush
     48             if $stdin.gets =~ /^\s*y(es)?\s*$/i
     49               begin
     50                 FileUtils.rm e.path
     51               rescue Errno::ENOENT
     52                 stream.puts "The lockfile doesn't exists. We continue."
     53               end
     54               stream.puts "Let's try that one more time."
     55               begin
     56                 Index.lock
     57               rescue Index::LockError => e
     58                 stream.puts "I couldn't unlock the index."
     59                 return false
     60               end
     61               return true
     62             end
     63           end
     64         end
     65       rescue Errno::ESRCH # no such process
     66         stream.puts "I couldn't lock the index. The lockfile might just be stale."
     67         begin
     68           FileUtils.rm e.path
     69         rescue Errno::ENOENT
     70           stream.puts "The lockfile doesn't exists. We continue."
     71         end
     72         stream.puts "Let's try that one more time."
     73         begin
     74           sleep DELAY
     75           Index.lock
     76         rescue Index::LockError => e
     77           stream.puts "I couldn't unlock the index."
     78           return false
     79         end
     80         return true
     81       end
     82       stream.puts "Sorry, couldn't unlock the index."
     83       return false
     84     end
     85     return true
     86   end
     87 end
     88 
     89 end