class GitDis

Attributes

dry_run[RW]
redis[RW]
repo_dir[RW]

Public Class Methods

concatenate(filenames) click to toggle source

concatenate file contents into a single string separate by newlines, including CRs if any CRs are detected anywhere include a filetype-specific separator if recognized filenames is an array, and all lengths 0-N are handled

# File lib/gitdis.rb, line 55
def self.concatenate(filenames)
  filetypes = filenames.map { |fname| File.extname(fname) }.uniq
  case filetypes.length
  when 0
    return "" if filenames.length == 0
    raise "filetype detection failure: #{filenames}"
  when 1
    sep = self.separator(filetypes.first)
  else
    raise "refusing to concatenate disparate filetypes: #{filetypes}"
  end

  newline = "\n"

  payload = filenames.map { |fname|
    contents = File.read(fname) || raise("could not read #{fname}")
    newline = "\r\n" if !newline.include?("\r") and contents.include?("\r")
    contents if !contents.empty?
  }.compact
  sep = sep.empty? ? newline : "#{newline}#{sep}#{newline}"
  payload.join(sep)
end
dump(keys, redis_options) click to toggle source
# File lib/gitdis.rb, line 38
def self.dump(keys, redis_options)
  redis = Redis.new(redis_options)
  keys.each { |base_key|
    self.keyset(base_key).each { |rkey|
      val = redis.get(rkey)
      if val and val.include?("\n")
        val = "\n" << val.split("\n").map { |line| "\t#{line}" }.join("\n")
        puts ["[#{rkey}]", val].join(' ')
      end
    }
  }
end
exec(cmd, bytes=1024) click to toggle source

return Process::Status, stream through STDOUT and STDERR

# File lib/gitdis.rb, line 7
def self.exec(cmd, bytes=1024)
  Open3.popen3(cmd) { |sin, sout, serr, thr|
    sin.close_write
    while !sout.eof or !serr.eof
      ready = IO.select [sout, serr]
      if ready
        ready[0].each { |f| # ready for reading
          begin
            (f == sout ? $stdout : $stderr).print f.read_nonblock(bytes)
          rescue EOFError => e
            # ok
          end
        }
      end
    end
    thr.value # Process::Status
  }
end
exec!(cmd) click to toggle source

raise on nonzero exit code

# File lib/gitdis.rb, line 27
def self.exec!(cmd)
  status = self.exec(cmd)
  raise "`#{cmd}` #{status}" unless status.exitstatus == 0
  0
end
keyset(base_key) click to toggle source

file contents, version, md5

# File lib/gitdis.rb, line 34
def self.keyset(base_key)
  [base_key, [base_key, 'version'].join(':'), [base_key, 'md5'].join(':')]
end
new(repo_dir, redis_options = {}) click to toggle source
# File lib/gitdis.rb, line 92
def initialize(repo_dir, redis_options = {})
  @dry_run = false
  @repo_dir = File.expand_path(repo_dir)
  raise "#{@repo_dir} does not exist!" unless Dir.exist? @repo_dir
  @redis = Redis.new(redis_options)
end
separator(filetype) click to toggle source

return a specific separator for known filetypes e.g. yaml document separator: —

# File lib/gitdis.rb, line 80
def self.separator(filetype)
  filetype = filetype[1..-1] if filetype[0] == '.'
  case filetype.downcase
  when 'yaml', 'yml'
    '---'
  else
    ''
  end
end

Public Instance Methods

git_pull(git_branch) click to toggle source
# File lib/gitdis.rb, line 99
def git_pull(git_branch)
  Dir.chdir @repo_dir do
    if self.class.exec("git diff --quiet HEAD").exitstatus != 0
      raise "please stash your local changes"
    end
    self.class.exec! "git checkout #{git_branch}"
    self.class.exec! "git pull"
  end
  self
end
update(base_key, relpath) click to toggle source

e.g. update(‘foo:bar:baz’, ‘foo/bar/*.baz’) return nil # path does not exist

false      # no update needed
true       # update was needed, but just a dry run
[ver, md5] # updated
# File lib/gitdis.rb, line 133
def update(base_key, relpath)
  # handle e.g. "foo/bar/*.yaml"
  files = Dir.glob(File.join(@repo_dir, relpath))
  case files.length
  when 0 then nil
  when 1 then self.update_redis(base_key, File.read(files.first))
  else        self.update_redis(base_key, self.class.concatenate(files))
  end
end
update_redis(base_key, file_contents) click to toggle source

quick false if calculated md5 == redis md5 return true if dry run and update needed otherwise update contents and md5; increment version

# File lib/gitdis.rb, line 113
def update_redis(base_key, file_contents)
  md5 = Digest::MD5.hexdigest(file_contents)
  fkey, vkey, mkey = self.class.keyset(base_key)
  return false if @redis.get(mkey) == md5

  if @dry_run
    true
  else
    @redis.set(fkey, file_contents)
    @redis.set(mkey, md5)
    ver = @redis.incr(vkey)
    [ver, md5]
  end
end