class Textrepo::FileSystemRepository

A concrete class which implements Repository interfaces. This repository uses the default file system of the operating system as a text storage.

Constants

FAVORITE_EXTNAME

Default extension of notes which uses when no extname is specified in the configuration settings.

FAVORITE_REPOSITORY_NAME

Default name for the repository which uses when no name is specified in the configuration settings.

FAVORITE_SEARCHER

Default searcher program to search text in the repository.

Attributes

extname[R]

Extension of notes sotres in the repository.

path[R]

Repository root.

searcher[R]

Searcher program name.

searcher_options[R]

An array of options to pass to the searcher program.

Public Class Methods

new(Hash or Hash like object) → FileSystemRepository click to toggle source

Creates a new repository object. The argument, `conf` must be a Hash object. It should hold the follwoing values:

  • MANDATORY:

    • :repository_type => `:file_system`

    • :repository_base => the parent directory path for the repository

  • OPTIONAL: (if not specified, default values are used)

    • :repository_name => basename of the root path for the repository

    • :default_extname => extname for a file stored into in the repository

    • :searcher => a program to search like `grep`

    • :searcher_options => an Array of option to pass to the searcher

The root path of the repository looks like the following:

Default values are set when `:repository_name` and `:default_extname` were not defined in `conf`.

Be careful to set `:searcher_options`, it must be to specify the searcher behavior equivalent to `grep` with “-inRE”. The default values for the searcher options is defined for BSD grep (default grep on macOS), GNU grep, and ripgrep (aka rg). They are:

"grep"   => ["-i", "-n", "-R", "-E"]
"egrep"  => ["-i", "-n", "-R"]
"ggrep"  => ["-i", "-n", "-R", "-E"]
"gegrep" => ["-i", "-n", "-R"]
"rg"     => ["-S", "-n", "--no-heading", "--color", "never"]

If use those searchers, it is not recommended to set `:searcher_options`. The default value works well in `textrepo`.

Calls superclass method
# File lib/textrepo/file_system_repository.rb, line 88
def initialize(conf)
  super
  base = conf[:repository_base]
  @name ||= FAVORITE_REPOSITORY_NAME
  @path = File.expand_path(name, base)
  FileUtils.mkdir_p(@path)
  @extname = conf[:default_extname] || FAVORITE_EXTNAME
  @searcher = find_searcher(conf[:searcher])
  @searcher_options = conf[:searcher_options]
end

Public Instance Methods

create(Timestamp, Array) → Timestamp click to toggle source

Creates a file into the repository, which contains the specified text and is associated to the timestamp.

# File lib/textrepo/file_system_repository.rb, line 106
def create(timestamp, text)
  abs = abspath(timestamp)
  raise DuplicateTimestampError, timestamp if FileTest.exist?(abs)
  raise EmptyTextError if text.nil? || text.empty?

  write_text(abs, text)
  timestamp
end
delete(Timestamp) → Array click to toggle source

Deletes the file in the repository.

# File lib/textrepo/file_system_repository.rb, line 167
def delete(timestamp)
  abs = abspath(timestamp)
  raise MissingTimestampError, timestamp unless FileTest.exist?(abs)
  content = read(timestamp)

  FileUtils.remove_file(abs)

  content
end
entries(String = nil) → Array of Timestamp instances click to toggle source

Finds entries of text those timestamp matches the specified pattern.

# File lib/textrepo/file_system_repository.rb, line 183
def entries(stamp_pattern = nil)
  size = stamp_pattern.to_s.size
  return [] if size > 0 and !(/\A[\d_]+\Z/ === stamp_pattern)

  results = []

  case size
  when "yyyymoddhhmiss_lll".size
    stamp = Timestamp.parse_s(stamp_pattern)
    if exist?(stamp)
      results << stamp
    end
  when 0, "yyyymoddhhmiss".size, "yyyymodd".size, "yyyymo".size
    results += find_entries("#{stamp_pattern}*")
  when 4                    # "yyyy" or "modd"
    pat = nil
    # The following distinction is practically correct, but not
    # perfect.  It simply assumes that a year is greater than
    # 1231.  For, a year before 1232 is too old for us to create
    # any text (I believe...).
    if stamp_pattern.to_i > 1231
      # yyyy
      pat = "#{stamp_pattern}*"
    else
      # modd
      pat = "????#{stamp_pattern}*"
    end
    results += find_entries(pat)
  end

  results
end
exist?(Timestamp) → true or false click to toggle source

Check the existence of text which is associated with the given timestamp.

# File lib/textrepo/file_system_repository.rb, line 223
def exist?(timestamp)
  FileTest.exist?(abspath(timestamp))
end
read(Timestamp) → Array click to toggle source

Reads the file content in the repository. Then, returns its content.

# File lib/textrepo/file_system_repository.rb, line 122
def read(timestamp)
  abs = abspath(timestamp)
  raise MissingTimestampError, timestamp unless FileTest.exist?(abs)
  content = nil
  File.open(abs, 'r') { |f|
    content = f.readlines(chomp: true)
  }
  content
end
update(Timestamp, Array, true or false) → Timestamp click to toggle source

Updates the file content in the repository. A new Timestamp object will be attached to the text. Then, returns the new Timestamp object.

When true is passed as the third argument, keeps the Timestamp unchanged, though updates the content. Then, returns the given Timestamp object.

See the documentation of Repository#update to know about errors and constraints of this method.

# File lib/textrepo/file_system_repository.rb, line 147
def update(timestamp, text, keep_stamp = false)
  raise EmptyTextError if text.empty?
  raise MissingTimestampError, timestamp unless exist?(timestamp)

  # does nothing if given text is the same in the repository one
  return timestamp if read(timestamp) == text

  stamp = keep_stamp ? timestamp : Timestamp.new(Time.now)
  write_text(abspath(stamp), text)
  FileUtils.remove_file(abspath(timestamp)) unless keep_stamp

  stamp
end