class ChefCLI::Policyfile::UndoStack

def delete(id)

def delete(id)
  undo_file = undo_file_for(id)
  unless File.exist?(undo_file)
    raise UndoRecordNotFound, "No undo record for id '#{id}' exists at #{undo_file}"
  end
  record = load_undo_record(undo_file)
  yield record if block_given?
  File.unlink(undo_file)
  record
end

def each_with_id

def each_with_id
  undo_record_files.each do |filename|
    yield File.basename(filename), load_undo_record(filename)
  end
end

def empty?

def empty?
  size == 0
end

def ensure_undo_dir_exists

def ensure_undo_dir_exists
  return false if File.directory?(undo_dir)
  FileUtils.mkdir_p(undo_dir)
end

def has_id?(id)

def has_id?(id)
  File.exist?(undo_file_for(id))
end

def load_undo_record(file)

def load_undo_record(file)
  data = FFI_Yajl::Parser.parse(IO.read(file))
  UndoRecord.new.load(data)
end

def pop

def pop
  file_to_pop = undo_record_files.last
  if file_to_pop.nil?
    raise CantUndo, "No undo records exist in #{undo_dir}"
  end
  record = load_undo_record(file_to_pop)
  # if this hits an exception, we skip unlink
  yield record if block_given?
  File.unlink(file_to_pop)
  record
end

def push(undo_record)

def push(undo_record)
  ensure_undo_dir_exists
  record_id = Time.new.utc.strftime("%Y%m%d%H%M%S")
  path = File.join(undo_dir, record_id)
  with_file(path) do |f|
    f.print(FFI_Yajl::Encoder.encode(undo_record.for_serialization, pretty: true))
  end
  records_to_delete = undo_record_files.size - MAX_SIZE
  if records_to_delete > 0
    undo_record_files.take(records_to_delete).each do |file|
      File.unlink(file)
    end
  end
  self
end

def size

def size
  undo_record_files.size
end

def undo_dir

def undo_dir
  File.join(Helpers.package_home, "undo")
end

def undo_file_for(id)

def undo_file_for(id)
  File.join(undo_dir, id)
end

def undo_record_files

def undo_record_files
  Dir[File.join(undo_dir, "*")].sort
end

def undo_records

def undo_records
  undo_record_files.map { |f| load_undo_record(f) }
end