Gem cycling using md5 hashes

I have a directory containing gems, and I often change them. To save myself the task of manually re-installing each one whenever anything changes, I wrote a simple script which keeps track of the files and runs rake tasks whenever any is modified.

The script is almost self-explanatory, but here’s the gist:

- first time you run it, it writes a YAML file with a big hash of a relevant files and their hashes
- after that, it performs the same md5 hashes and if the hash has changed it runs rake gem:uninstall rake gem:repackage rake gem:install in the directory where the change was noticed, then rewrites the hash.

It’s pretty scrappy, and needs to be placed and run from the base dir of the gems. And it doesn’t check manifests, yet.

require 'pathname'
require 'find'
require 'digest/md5'
require 'yaml'
 
 = []
@new = {}
 = []
 
 = ENV['PWD']
 
def get_new_file_list
  Dir.chdir 
  Find.find('./') do |f| 
     << f 
  end
  .delete_if {|e| e.split('/').size == 2 } # ie in root dir
  .delete_if {|e| e.include?('pkg') } # ignore build dirs
end
 
def recurse_files
  @new = {}
  .each do |f|
    if !FileTest.directory?(f) && File.exists?(f)
      @new[f] = Digest::MD5.hexdigest(File.read(f))
    end
  end
end
 
def write_new
  Dir.chdir 
  File.open("md5.yaml", "w+") do |file|
    file.write @new.to_yaml
  end
end
 
def differences
  newclone = @new.clone
  oldclone = @old.clone
  newclone.delete_if {|key, value| @old[key] == value }
  oldclone.delete_if {|key, value| @new[key] == value }
  diff = newclone.merge(oldclone)
  diff.keys.each do |k|
     << k.split('/')[1]
  end
  .uniq!
end
 
def cycle_gem gem_dir
  puts "updating #{gem_dir}..."
  dir =  + '/' +  gem_dir
  Dir.chdir(dir)
  system('rake gem:uninstall')
  system('rake gem:repackage')
  system('rake gem:install')
end
 
get_new_file_list
recurse_files
 
if File::exists?('md5.yaml')
  @old = YAML.load_file('md5.yaml')
  differences
else
  write_new
end
 
if .size > 0
  .each do |g| cycle_gem g end
  get_new_file_list
  recurse_files
  write_new
  puts "updated #{.join(' ')}"
else
  puts "nothing to update"
end

Tags: , scripts

Leave a Reply