Skip to content

Commit

Permalink
Migrate config on load
Browse files Browse the repository at this point in the history
  • Loading branch information
norbert committed Aug 19, 2008
1 parent c3baa80 commit 3110de7
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 54 deletions.
13 changes: 12 additions & 1 deletion lib/braid/command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def msg(str)
end

def config
@config ||= Config.new
@config ||= load_and_migrate_config
end

private
Expand All @@ -55,6 +55,17 @@ def with_reset_on_error
end
end

def load_and_migrate_config
config = Config.new
unless config.valid?
msg "Configuration is outdated. Migrating."
bail_on_local_changes!
config.migrate!
git.commit("Upgrade .braids", "-- .braids")
end
config
end

def add_config_file
git.add(CONFIG_FILE)
end
Expand Down
47 changes: 37 additions & 10 deletions lib/braid/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,6 @@ def mirrors
end
end

def add(mirror)
@db.transaction do
raise PathAlreadyInUse, mirror.path if @db[mirror.path]
@db[mirror.path] = clean_attributes(mirror.attributes)
end
end

def get(path)
@db.transaction(true) do
if attributes = @db[path.to_s.sub(/\/$/, '')]
Expand All @@ -52,6 +45,13 @@ def get!(path)
mirror
end

def add(mirror)
@db.transaction do
raise PathAlreadyInUse, mirror.path if @db[mirror.path]
write_mirror(mirror)
end
end

def remove(mirror)
@db.transaction do
@db.delete(mirror.path)
Expand All @@ -61,14 +61,41 @@ def remove(mirror)
def update(mirror)
@db.transaction do
raise MirrorDoesNotExist, mirror.path unless @db[mirror.path]
@db.delete(mirror)
@db[mirror.path] = clean_attributes(mirror.attributes)
@db.delete(mirror.path)
write_mirror(mirror)
end
end

def valid?
@db.transaction(true) do
!@db.roots.any? do |path|
@db[path]["url"].nil?
end
end
end

def migrate!
@db.transaction do
@db.roots.each do |path|
attributes = @db[path]
if attributes["local_branch"]
attributes["url"] = attributes.delete("remote")
attributes["remote"] = attributes.delete("local_branch")
attributes["squashed"] = attributes.delete("squash")
attributes["lock"] = attributes["revision"] # so far this has always been true
end
@db[path] = clean_attributes(attributes)
end
end
end

private
def write_mirror(mirror)
@db[mirror.path] = clean_attributes(mirror.attributes)
end

def clean_attributes(hash)
(hash = hash.dup).each { |k,v| hash.delete(k) if v.nil? }
hash.reject { |k,v| v.nil? }
end
end
end
61 changes: 41 additions & 20 deletions lib/braid/mirror.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ def message
"cannot guess type: #{super}"
end
end
class PathIsRequired < BraidError
class PathRequired < BraidError
def message
"path is required"
end
Expand All @@ -40,7 +40,7 @@ def self.new_from_options(url, options = {})
end

unless path = options["path"] || extract_path_from_url(url)
raise PathIsRequired
raise PathRequired
end

if options["rails_plugin"]
Expand All @@ -55,15 +55,6 @@ def self.new_from_options(url, options = {})
self.new(path, attributes)
end

def locked?
# the question mark just looks nicer
!!lock
end

def squashed?
!!squashed
end

def ==(comparison)
path == comparison.path && attributes == comparison.attributes
end
Expand All @@ -73,6 +64,14 @@ def type
attributes["type"]
end

def locked?
!!lock
end

def squashed?
!!squashed
end

def merged?(commit)
# tip from spearce in #git:
# `test z$(git merge-base A B) = z$(git rev-parse --verify A)`
Expand All @@ -84,14 +83,10 @@ def merged?(commit)
end
end

def local_changes?
!diff.empty?
end

def diff
remote_hash = git.rev_parse(base_revision)
remote_hash = git.rev_parse("#{base_revision}:")
local_hash = git.tree_hash(path)
git.diff_tree(remote_hash, local_hash, path)
remote_hash != local_hash ? git.diff_tree(remote_hash, local_hash, path) : ""
end

def fetch
Expand All @@ -116,10 +111,36 @@ def method_missing(name, *args)
end

def base_revision
revision && unless type == "svn"
git.rev_parse(revision)
if revision
unless type == "svn"
git.rev_parse(revision)
else
git_svn.commit_hash(remote, revision)
end
else
git_svn.commit_hash(remote, revision)
inferred_revision
end
end

def inferred_revision
time = list_revisions("-E --grep='^(Add|Update) mirror'", "-1", "HEAD", "-- #{path}").first[0]
revs = list_revisions("--reverse", remote)
hash = nil
revs.each_with_index do |rev, idx|
if !revs[idx + 1] || revs[idx + 1][0] > time
hash = revs[idx][1]
break
end
end
hash
end

def list_revisions(*args)
out = git.rev_list("--timestamp", *args)
out.split("\n").map do |line|
parts = line.split(' ', 2)
parts[0] = parts[0].to_i
parts
end
end

Expand Down
11 changes: 5 additions & 6 deletions lib/braid/operations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ def exec!(cmd)
end

class Git < Proxy
def commit(message)
status, out, err = exec("git commit -m #{message.inspect} --no-verify")
def commit(message, *args)
status, out, err = exec("git commit -m #{message.inspect} --no-verify #{args.join(' ')}")

if status == 0
true
Expand Down Expand Up @@ -219,10 +219,9 @@ def branch
out[2..-1]
end

def apply(diff)
def apply(diff, *args)
err = nil
# always uses index
status = Open4.popen4("git apply --index -") do |pid, stdin, stdout, stderr|
status = Open4.popen4("git apply --index --whitespace=nowarn #{args.join(' ')} -") do |pid, stdin, stdout, stderr|
stdin.puts(diff)
stdin.close

Expand All @@ -242,7 +241,7 @@ class GitSvn < Proxy
def self.command; "git-svn"; end

def commit_hash(remote, revision)
status, out, err = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
out = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
part = out.to_s.split(" | ")[1]
raise UnknownRevision, "r#{revision}" unless part
Git.instance.rev_parse(part) # FIXME ugly ugly ugly
Expand Down
2 changes: 1 addition & 1 deletion test/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
it "should update the mirror with new params" do
@mirror.branch = "other"
@config.update(@mirror)
@config.get("path").attributes.should == { "url" => "url", "branch" => "other" }
@config.get("path").attributes.should == { "branch" => "other" }
end

it "should raise when trying to update nonexistent mirror" do
Expand Down
47 changes: 33 additions & 14 deletions test/mirror_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,32 +43,51 @@

describe "Braid::Mirror#diff" do
before(:each) do
@mirror = new_from_options("git://path")
git.stubs(:rev_parse)
git.stubs(:tree_hash)
@mirror = build_mirror("revision" => 'a' * 40)
@mirror.stubs(:base_revision).returns(@mirror.revision) # bypass rev_parse
end

def set_hashes(remote_hash, local_hash)
git.expects(:rev_parse).with("#{@mirror.revision}:").returns(remote_hash)
git.expects(:tree_hash).with(@mirror.path).returns(local_hash)
end

it "should return true when the diff is not empty" do
git.expects(:diff_tree).returns("diff --git a/path b/path\n")
@mirror.local_changes?.should == true
it "should return an empty string when the hashes match" do
set_hashes('b' * 40, 'b' * 40)
git.expects(:diff_tree).never
@mirror.diff.should == ""
end

it "should return false when the diff is empty" do
git.expects(:diff_tree).returns("")
@mirror.local_changes?.should == false
it "should generate a diff when the hashes do not match" do
set_hashes('b' * 40, 'c' * 40)
diff = "diff --git a/path b/path\n"
git.expects(:diff_tree).with('b' * 40, 'c' * 40, @mirror.path).returns(diff)
@mirror.diff.should == diff
end
end

describe "Braid::Mirror#base_revision" do
it "should be nil when no revision is set" do
@mirror = Braid::Mirror.new("path")
it "should be inferred when no revision is set" do
@mirror = build_mirror
@mirror.revision.should.be.nil
@mirror.send(:base_revision).should.be.nil
@mirror.expects(:inferred_revision).returns('b' * 40)
@mirror.send(:base_revision).should == 'b' * 40
end

it "should be the parsed hash for git mirrors" do
@mirror = Braid::Mirror.new("path", "revision" => ('a' * 7))
git.expects(:rev_parse).returns('a' * 40)
@mirror = build_mirror("revision" => 'a' * 7)
git.expects(:rev_parse).with('a' * 7).returns('a' * 40)
@mirror.send(:base_revision).should == 'a' * 40
end
end

describe "Braid::Mirror#inferred_revision" do
it "should return the last commit before the most recent update" do
@mirror = new_from_options("git://path")
@mirror.expects(:list_revisions).times(2).returns(
[[4, 'a' * 40], [2, 'b' * 40]],
[[1, 'c' * 40], [3, 'd' * 40], [5, 'e' * 40]]
)
@mirror.send(:inferred_revision).should == 'd' * 40
end
end
4 changes: 2 additions & 2 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ def new_from_options(url, options = {})
@mirror = Braid::Mirror.new_from_options(url, options)
end

def build_mirror
Braid::Mirror.new("path", "url" => "url")
def build_mirror(options = {})
Braid::Mirror.new("path", options)
end

include Braid::Operations::VersionControl

0 comments on commit 3110de7

Please sign in to comment.