class Sgfa::Cli::Jacket

Command line interface for {Sgfa::Jacket}. Currently it just supports {Sgfa::JacketFs}.

@todo Needs to be fully implemented. Currently just a shell.

Public Instance Methods

attach(aspec) click to toggle source
# File lib/sgfa/cli/jacket.rb, line 167
def attach(aspec)

  # get attachment spec
  ma = /^\s*(\d+)-(\d+)-(\d+)\s*$/.match(aspec)
  if !ma
    puts "Attachment specification is x-y-z\n" +
      "x = entry number\ny = attachment number\nz = history number"
    return
  end
  enum, anum, hnum = ma[1,3].map{|st| st.to_i }

  # open jacket
  jck = _open_jacket
  return if !jck

  # read attachment
  begin
    fi = jck.read_attach(enum, anum, hnum)
  rescue ::Sgfa::Error::NonExistent => exp
    puts exp.message
    return
  end
  jck.close

  # output
  begin
    out = File.open(options[:output], 'wb')
  rescue
    fi.close
    puts "Unable to open output file"
    return
  end

  # copy
  IO.copy_stream(fi, out)
  fi.close
  out.close

end
backup_s3() click to toggle source
# File lib/sgfa/cli/jacket.rb, line 382
def backup_s3()
  # open jacket
  jck = _open_jacket
  return if !jck

  # read in JSON config
  json = File.read(options[:key])
  creds = JSON.parse(json)
  opts = {
    region: creds['aws_region'],
    access_key_id: creds['aws_id'],
    secret_access_key: creds['aws_key'],
  }
  log = Logger.new(STDOUT)
  case options[:level]
    when 'debug'
      log.level = Logger::DEBUG
    when 'info'
      log.level = Logger::INFO
    when 'warn'
      log.level = Logger::WARN
    else
      log.level = Logger::ERROR
  end

  puts 'id: %s' % creds['aws_id']
  puts 'secret: %s' % creds['aws_key']
  puts 'bucket: %s' % options[:bucket]
  
  # client
  s3 = ::Aws::S3::Client.new(opts)
  sto = ::Sgfa::StoreS3.new
  sto.open(s3, options[:bucket])
  
  # backup
  jck.backup(sto, log: log)
  jck.close

end
check() click to toggle source
# File lib/sgfa/cli/jacket.rb, line 243
def check

  # open jacket
  jck = _open_jacket
  return if !jck

  # options
  opts = {}
  log = Logger.new(STDOUT)
  opts[:log] = log
  case options[:level]
    when 'debug'
      log.level = Logger::DEBUG
    when 'info'
      log.level = Logger::INFO
    when 'warn'
      log.level = Logger::WARN
    else
      log.level = Logger::ERROR
  end
  opts[:hash_entry] = options[:entry]
  opts[:hash_attach] = options[:attach]
  opts[:miss_history] = options[:missing]
  opts[:max_history] = options[:max] if options[:max]
  opts[:min_history] = options[:min] if options[:min]
  opts[:max_hash] = options[:hash] if options[:hash]

  # check
  jck.check(opts)
  jck.close

end
entry(spec) click to toggle source
# File lib/sgfa/cli/jacket.rb, line 68
def entry(spec)

  # get entry and revision nums
  ma = /^\s*(\d+)(-(\d+))?\s*$/.match(spec)
  if !ma
    puts "Entry e-spec must be match format x[-y]\n" +
      "Where x is the entry number and y is the optional revision number."
    return
  end
  enum = ma[1].to_i
  rnum = (ma.length == 4) ? ma[3].to_i : 0

  # open jacket
  jck = _open_jacket
  return if !jck

  # read
  begin
    ent = jck.read_entry(enum, rnum)
  rescue ::Sgfa::Error::NonExistent => exp
    puts exp.message
    return
  end
  jck.close

  # display
  tags = ent.tags.join("\n           ")
  atts = ent.attachments.map{|anum, hnum, hash|
    '%d-%d-%d %s' % [enum, anum, hnum, hash]}.join("\n           ")
  if options[:hash]
    puts "Hash     : %s" % ent.hash
  end
  puts "Title    : %s" % ent.title
  puts "Date/Time: %s" % ent.time.localtime.strftime("%F %T %z")
  puts "Revision : %d" % ent.revision
  puts "History  : %d" % ent.history
  puts "Tags     : %s" % tags
  puts "Files    : %s" % atts
  puts "Body     :\n%s" % ent.body

end
history(hspec='0') click to toggle source
# File lib/sgfa/cli/jacket.rb, line 119
def history(hspec='0')

  # get history num
  ma = /^\s*(\d+)\s*$/.match(hspec)
  if !ma
    hnum = 0
  else
    hnum = ma[1].to_i
  end

  # open jacket
  jck = _open_jacket
  return if !jck

  # read history
  begin
    hst = jck.read_history(hnum)
  rescue ::Sgfa::Error::NonExistent => exp
    puts exp.message
    return
  end
  jck.close

  # display
  hnum = hst.history
  puts "Hash      : %s" % hst.hash if options[:hash]
  puts "Previous  : %s" % hst.previous if options[:hash]
  puts "History   : %d" % hnum
  puts "Date/Time : %s" % hst.time.localtime.strftime("%F %T %z")
  puts "User      : %s" % hst.user
  hst.entries.each do |enum, rnum, hash|
    puts "Entry     : %d-%d %s" % [enum, rnum, hash]
  end
  hst.attachments.each do |enum, anum, hash|
    puts "Attachment: %d-%d-%d %s" % [enum, anum, hnum, hash]
  end

end
info() click to toggle source
# File lib/sgfa/cli/jacket.rb, line 38
def info

  # open jacket
  jck = _open_jacket
  return if !jck

  # print info
  hst = jck.read_history
  puts 'Text ID: %s' % jck.id_text
  puts 'Hash ID: %s' % jck.id_hash
  if hst
    puts 'Entries: %d' % hst.entry_max
    puts 'History: %d' % hst.history
    puts 'Last edit: %s' % hst.time_str
  else
    puts 'No history.'
  end
  jck.close

end
restore_s3() click to toggle source
# File lib/sgfa/cli/jacket.rb, line 441
def restore_s3()
  # open jacket
  jck = _open_jacket
  return if !jck

  # read in JSON config
  json = File.read(options[:key])
  creds = JSON.parse(json)
  opts = {
    region: creds['aws_region'],
    access_key_id: creds['aws_id'],
    secret_access_key: creds['aws_key'],
  }
  log = Logger.new(STDOUT)
  case options[:level]
    when 'debug'
      log.level = Logger::DEBUG
    when 'info'
      log.level = Logger::INFO
    when 'warn'
      log.level = Logger::WARN
    else
      log.level = Logger::ERROR
  end

  puts 'id: %s' % creds['aws_id']
  puts 'secret: %s' % creds['aws_key']
  puts 'bucket: %s' % options[:bucket]

  # client
  s3 = ::Aws::S3::Client.new(opts)
  sto = ::Sgfa::StoreS3.new
  sto.open(s3, options[:bucket])

  # backup
  jck.restore(sto, log: log)
  jck.close
end
stats() click to toggle source
# File lib/sgfa/cli/jacket.rb, line 299
def stats()
  # open jacket
  jck = _open_jacket
  return if !jck

  do_time = options[:time]
  do_title = options[:title]

  # CSV setup
  if options[:output]
    csv = ::CSV.open(options[:output], 'w', :encoding => 'utf-8')
  else
    csv = ::CSV.new(STDOUT, :encoding => 'utf-8')
  end

  # do the header row
  if options[:header]
    ha = [
      'Stat name',
      'Value', 
      'Account',
      'Entry',
      'Revision'
    ]
    ha.push 'Date Time' if do_time
    ha.push 'Title' if do_title
    csv << ha
  end

  # read each entry and provide stats
  hst = jck.read_history
  hst.entry_max.times do |ix|
    enum = ix + 1
    ent = jck.read_entry(enum)
    stats = ent.stats
    next if stats.empty?

    rnum = ent.revision
    time = ent.time_str if do_time
    title = ent.title if do_title

    stats.each do |stat|
      typ, val, accts = stat
      if accts.empty?
        ln = [typ, val, nil, enum, rnum]
        ln.push time if do_time
        ln.push title if do_title
        csv << ln
        next
      end
      accts.each do |acct|
        ln = [typ, val, acct, enum, rnum]
        ln.push time if do_time
        ln.push title if do_title
        csv << ln
      end
    end
  end

  jck.close
  csv.close

end

Private Instance Methods

_open_jacket() click to toggle source

Open the jacket

# File lib/sgfa/cli/jacket.rb, line 485
def _open_jacket()
  if !options[:fs_path]
    puts 'Jacket type and location required.'
    return false
  end

  begin
    jck = ::Sgfa::JacketFs.new(options[:fs_path])
  rescue ::Sgfa::Error::NonExistent, ::Sgfa::Error::Limits => exp
    puts exp.message
    return false
  end

  return jck
end