Class: GitDis

Inherits:
Object
  • Object
show all
Defined in:
lib/gitdis.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(repo_dir, redis_options = {}) ⇒ GitDis



53
54
55
56
57
# File 'lib/gitdis.rb', line 53

def initialize(repo_dir, redis_options = {})
  @repo_dir = File.expand_path(repo_dir)
  raise "#{@repo_dir} does not exist!" unless Dir.exist? @repo_dir
  @redis = Redis.new(redis_options)
end

Instance Attribute Details

#redisObject

Returns the value of attribute redis.



51
52
53
# File 'lib/gitdis.rb', line 51

def redis
  @redis
end

#repo_dirObject

Returns the value of attribute repo_dir.



51
52
53
# File 'lib/gitdis.rb', line 51

def repo_dir
  @repo_dir
end

Class Method Details

.dump(keys, redis_options) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
# 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) ⇒ Object

return Process::Status, stream through STDOUT and STDERR



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 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) ⇒ Object

raise on nonzero exit code



27
28
29
30
31
# 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) ⇒ Object

file contents, version, md5



34
35
36
# File 'lib/gitdis.rb', line 34

def self.keyset(base_key)
  [base_key, [base_key, 'version'].join(':'), [base_key, 'md5'].join(':')]
end

Instance Method Details

#git_pull(git_branch) ⇒ Object



59
60
61
62
63
64
65
66
67
68
# File 'lib/gitdis.rb', line 59

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) ⇒ Object

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

false      # no update needed
[ver, md5] # updated


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/gitdis.rb', line 92

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
    puts "concatenating #{files.length} files"
    result = ''
    sep = "\n"
    files.each { |fname|
      s = File.read(fname)
      if s and !s.empty?
        # scan for carriage returns (Microsoft text format)
        sep = "\r\n" if sep == "\n" and s.include?("\r")
        s << sep if s.last != "\n"
        result << s
      # debugging
      elsif s
        puts "#{fname} is empty"
      else
        puts "File.read(#{fname}) returned false/nil"
      end
    }
    self.update_redis(base_key, result.chomp(sep))
  end
end

#update_redis(base_key, file_contents) ⇒ Object

quick false if calculated md5 == redis md5 otherwise update contents and md5; increment version



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/gitdis.rb', line 72

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
    puts "DRY RUN: would have updated #{base_key} with md5 #{md5}"
    true
  else
    @redis.set(fkey, file_contents)
    @redis.set(mkey, md5)
    ver = @redis.incr(vkey)
    [ver, md5]
  end
end