Skip to content
This repository has been archived by the owner on Nov 11, 2017. It is now read-only.

Commit

Permalink
Initial commit: syncronize a single file
Browse files Browse the repository at this point in the history
  • Loading branch information
jferris committed Sep 10, 2010
0 parents commit cd49bc9
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
@@ -0,0 +1,5 @@
tmp
.swo
*~
*.swp

5 changes: 5 additions & 0 deletions bin/trout
@@ -0,0 +1,5 @@
#!/usr/bin/env ruby

require 'trout'
Trout::CLI.run(ARGV)

15 changes: 15 additions & 0 deletions features/support/env.rb
@@ -0,0 +1,15 @@
require 'rubygems'
require 'aruba'
require 'fileutils'

Before do
FileUtils.rm_rf("tmp")
FileUtils.mkdir("tmp")
end

PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
BIN_PATH = File.join(PROJECT_ROOT, 'bin').freeze
LIB_PATH = File.join(PROJECT_ROOT, 'lib').freeze

ENV['PATH'] = [BIN_PATH, ENV['PATH']].join(':')
ENV['RUBYLIB'] = LIB_PATH
54 changes: 54 additions & 0 deletions features/sync_gemfile.feature
@@ -0,0 +1,54 @@
Feature: sync a Gemfile between two repositories

@puts @announce
Scenario: sync a Gemfile
Given a directory named "upstream_repo"
And a directory named "child_repo"
And a file named "upstream_repo/Gemfile" with:
"""
source "http://rubygems.org"
gem "rails"
gem "mysql"
"""
When I cd to "upstream_repo"
And I run "git init"
And I run "git add Gemfile"
And I run "git commit -m 'Added gemfile'"
And I cd to "../child_repo"
And I run "trout checkout Gemfile ../upstream_repo"
And I run "cat Gemfile"
Then the output should contain:
"""
source "http://rubygems.org"
gem "rails"
gem "mysql"
"""
When I cd to "../upstream_repo"
And I write to "Gemfile" with:
"""
source "http://rubygems.org"
gem "rails"
gem "postgresql"
"""
When I run "git add Gemfile"
And I run "git commit -m 'Changed to postgres'"
And I cd to "../child_repo"
When I append to "Gemfile" with:
"""
gem "redcloth"
"""
When I run "trout update Gemfile"
And I run "cat Gemfile"
Then the output should contain:
"""
source "http://rubygems.org"
gem "rails"
<<<<<<< Gemfile
gem "mysql"
gem "redcloth"
=======
gem "postgresql"
>>>>>>> .trout/upstream
"""

2 changes: 2 additions & 0 deletions lib/trout.rb
@@ -0,0 +1,2 @@
require 'trout/cli'

36 changes: 36 additions & 0 deletions lib/trout/cli.rb
@@ -0,0 +1,36 @@
require 'trout/managed_file'

module Trout
class CLI
def self.run(arguments)
new(arguments).run
end

attr_reader :arguments, :git_url, :filename, :file, :command

def initialize(arguments)
self.arguments = arguments
self.file = ManagedFile.new(filename)
end

def run
case command
when 'checkout'
self.git_url = arguments[2]
file.copy_from(git_url)
when 'update'
file.update
end
end

private

def arguments=(arguments)
@arguments = arguments
self.command = arguments[0]
self.filename = arguments[1]
end

attr_writer :git_url, :filename, :file, :command
end
end
124 changes: 124 additions & 0 deletions lib/trout/managed_file.rb
@@ -0,0 +1,124 @@
require 'fileutils'
require 'trout/version_list'

module Trout
class ManagedFile
attr_reader :filename, :checked_out_url

def initialize(filename)
@filename = filename
end

def copy_from(git_url)
checkout(git_url)
copy_to_destination
write_url_and_version
ensure
cleanup
end

def update
checkout(previous_git_url)
merge_to_destination
ensure
cleanup
end

private

def checkout(git_url)
run_or_fail("git clone #{git_url} #{working('git')}")
@checked_out_url = git_url
end

def copy_to_destination
FileUtils.cp(working('git', filename), filename)
end

def merge_to_destination
upstream = working('upstream')
at_last_update = working('at_last_update')
merge = working('merge')

FileUtils.cp(working('git', filename), upstream)

checkout_last_version
FileUtils.cp(working('git', filename), at_last_update)

enforce_newline(upstream)
enforce_newline(at_last_update)
enforce_newline(filename)

run("diff3 -mX #{filename} #{at_last_update} #{upstream} > #{merge}")
FileUtils.mv(merge, filename)
ensure
FileUtils.rm_rf(upstream)
FileUtils.rm_rf(at_last_update)
end

def cleanup
FileUtils.rm_rf(working('git'))
@checked_out_url = nil
end

def prepare_working_directory
FileUtils.mkdir(working_root)
end

def working_root
'.trout'
end

def write_url_and_version
version_list.update(filename,
'git_url' => checked_out_url,
'version' => checked_out_version)
end

def checked_out_version
git_command("rev-parse HEAD")
end

def checkout_last_version
git_command("checkout #{previous_git_version}")
end

def git_command(command)
run_or_fail("git --git-dir=#{working('git/.git')} --work-tree=#{working('git')} #{command}").strip
end

def previous_git_url
version_list.git_url_for(filename)
end

def previous_git_version
version_list.version_for(filename)
end

def version_list
@version_list ||= VersionList.new(working('versions'))
end

def working(*paths)
File.join(working_root, *paths)
end

def enforce_newline(path)
if IO.read(path)[-1].chr != "\n"
File.open(path, "a") { |file| file.puts }
end
end

def run(command)
`#{command} 2>&1`
end

def run_or_fail(command)
output = run(command)
unless $? == 0
raise "Command failed with status #{$?}:\n#{command}\n#{output}"
end
output
end
end
end
44 changes: 44 additions & 0 deletions lib/trout/version_list.rb
@@ -0,0 +1,44 @@
require 'yaml'

module Trout
class VersionList
attr_reader :path, :entries

def initialize(path)
@path = path
end

def git_url_for(filename)
read
entries[filename]['git_url']
end

def version_for(filename)
read
entries[filename]['version']
end

def update(filename, info)
read
entries[filename] ||= {}
entries[filename].update(info)
write
end

private

def read
if File.exist?(path)
@entries = YAML.load(IO.read(path))
else
@entries = {}
end
end

def write
File.open(path, 'w') do |file|
file.write(YAML.dump(entries))
end
end
end
end

0 comments on commit cd49bc9

Please sign in to comment.