public
Rubygem
Description: Simple tool to help track git and svn vendor branches in a git repository
Homepage: http://github.com/evilchelu/braid/wikis/home
Clone URL: git://github.com/evilchelu/braid.git
Migrate config on load
norbert (author)
Tue Jul 15 06:22:13 -0700 2008
commit  3110de747a4b5dab499726c5a625568557247092
tree    56f5ff810c846b831e5b5790b0caa806ba3ff890
parent  c3baa80dfb6a29245f253c30b20fa23ad9465929
...
31
32
33
34
 
35
36
37
...
55
56
57
 
 
 
 
 
 
 
 
 
 
 
58
59
60
...
31
32
33
 
34
35
36
37
...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
0
@@ -31,7 +31,7 @@ module Braid
0
     end
0
 
0
     def config
0
-      @config ||= Config.new
0
+      @config ||= load_and_migrate_config
0
     end
0
 
0
     private
0
@@ -55,6 +55,17 @@ module Braid
0
         end
0
       end
0
 
0
+      def load_and_migrate_config
0
+        config = Config.new
0
+        unless config.valid?
0
+          msg "Configuration is outdated. Migrating."
0
+          bail_on_local_changes!
0
+          config.migrate!
0
+          git.commit("Upgrade .braids", "-- .braids")
0
+        end
0
+        config
0
+      end
0
+
0
       def add_config_file
0
         git.add(CONFIG_FILE)
0
       end
...
31
32
33
34
35
36
37
38
39
40
41
42
43
...
52
53
54
 
 
 
 
 
 
 
55
56
57
...
61
62
63
64
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
67
68
69
 
 
 
 
70
71
 
72
73
74
...
31
32
33
 
 
 
 
 
 
 
34
35
36
...
45
46
47
48
49
50
51
52
53
54
55
56
57
...
61
62
63
 
 
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
 
98
99
100
101
0
@@ -31,13 +31,6 @@ module Braid
0
       end
0
     end
0
 
0
-    def add(mirror)
0
-      @db.transaction do
0
-        raise PathAlreadyInUse, mirror.path if @db[mirror.path]
0
-        @db[mirror.path] = clean_attributes(mirror.attributes)
0
-      end
0
-    end
0
-
0
     def get(path)
0
       @db.transaction(true) do
0
         if attributes = @db[path.to_s.sub(/\/$/, '')]
0
@@ -52,6 +45,13 @@ module Braid
0
       mirror
0
     end
0
 
0
+    def add(mirror)
0
+      @db.transaction do
0
+        raise PathAlreadyInUse, mirror.path if @db[mirror.path]
0
+        write_mirror(mirror)
0
+      end
0
+    end
0
+
0
     def remove(mirror)
0
       @db.transaction do
0
         @db.delete(mirror.path)
0
@@ -61,14 +61,41 @@ module Braid
0
     def update(mirror)
0
       @db.transaction do
0
         raise MirrorDoesNotExist, mirror.path unless @db[mirror.path]
0
-        @db.delete(mirror)
0
-        @db[mirror.path] = clean_attributes(mirror.attributes)
0
+        @db.delete(mirror.path)
0
+        write_mirror(mirror)
0
+      end
0
+    end
0
+
0
+    def valid?
0
+      @db.transaction(true) do
0
+        !@db.roots.any? do |path|
0
+          @db[path]["url"].nil?
0
+        end
0
+      end
0
+    end
0
+
0
+    def migrate!
0
+      @db.transaction do
0
+        @db.roots.each do |path|
0
+          attributes = @db[path]
0
+          if attributes["local_branch"]
0
+            attributes["url"] = attributes.delete("remote")
0
+            attributes["remote"] = attributes.delete("local_branch")
0
+            attributes["squashed"] = attributes.delete("squash")
0
+            attributes["lock"] = attributes["revision"] # so far this has always been true
0
+          end
0
+          @db[path] = clean_attributes(attributes)
0
+        end
0
       end
0
     end
0
 
0
     private
0
+      def write_mirror(mirror)
0
+        @db[mirror.path] = clean_attributes(mirror.attributes)
0
+      end
0
+
0
       def clean_attributes(hash)
0
-        (hash = hash.dup).each { |k,v| hash.delete(k) if v.nil? }
0
+        hash.reject { |k,v| v.nil? }
0
       end
0
   end
0
 end
...
13
14
15
16
 
17
18
19
...
40
41
42
43
 
44
45
46
...
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
...
73
74
75
 
 
 
 
 
 
 
 
76
77
78
...
84
85
86
87
88
89
90
91
92
 
93
94
 
95
96
97
...
116
117
118
119
120
 
 
 
 
 
 
121
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
124
125
...
13
14
15
 
16
17
18
19
...
40
41
42
 
43
44
45
46
...
55
56
57
 
 
 
 
 
 
 
 
 
58
59
60
...
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
83
84
85
 
 
 
 
86
 
87
88
 
89
90
91
92
...
111
112
113
 
 
114
115
116
117
118
119
120
 
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
0
@@ -13,7 +13,7 @@ module Braid
0
         "cannot guess type: #{super}"
0
       end
0
     end
0
-    class PathIsRequired < BraidError
0
+    class PathRequired < BraidError
0
       def message
0
         "path is required"
0
       end
0
@@ -40,7 +40,7 @@ module Braid
0
       end
0
 
0
       unless path = options["path"] || extract_path_from_url(url)
0
-        raise PathIsRequired
0
+        raise PathRequired
0
       end
0
 
0
       if options["rails_plugin"]
0
@@ -55,15 +55,6 @@ module Braid
0
       self.new(path, attributes)
0
     end
0
 
0
-    def locked?
0
-      # the question mark just looks nicer
0
-      !!lock
0
-    end
0
-
0
-    def squashed?
0
-      !!squashed
0
-    end
0
-
0
     def ==(comparison)
0
       path == comparison.path && attributes == comparison.attributes
0
     end
0
@@ -73,6 +64,14 @@ module Braid
0
       attributes["type"]
0
     end
0
 
0
+    def locked?
0
+      !!lock
0
+    end
0
+
0
+    def squashed?
0
+      !!squashed
0
+    end
0
+
0
     def merged?(commit)
0
       # tip from spearce in #git:
0
       # `test z$(git merge-base A B) = z$(git rev-parse --verify A)`
0
@@ -84,14 +83,10 @@ module Braid
0
       end
0
     end
0
 
0
-    def local_changes?
0
-      !diff.empty?
0
-    end
0
-
0
     def diff
0
-      remote_hash = git.rev_parse(base_revision)
0
+      remote_hash = git.rev_parse("#{base_revision}:")
0
       local_hash = git.tree_hash(path)
0
-      git.diff_tree(remote_hash, local_hash, path)
0
+      remote_hash != local_hash ? git.diff_tree(remote_hash, local_hash, path) : ""
0
     end
0
 
0
     def fetch
0
@@ -116,10 +111,36 @@ module Braid
0
       end
0
 
0
       def base_revision
0
-        revision && unless type == "svn"
0
-          git.rev_parse(revision)
0
+        if revision
0
+          unless type == "svn"
0
+            git.rev_parse(revision)
0
+          else
0
+            git_svn.commit_hash(remote, revision)
0
+          end
0
         else
0
-          git_svn.commit_hash(remote, revision)
0
+          inferred_revision
0
+        end
0
+      end
0
+
0
+      def inferred_revision
0
+        time = list_revisions("-E --grep='^(Add|Update) mirror'", "-1", "HEAD", "-- #{path}").first[0]
0
+        revs = list_revisions("--reverse", remote)
0
+        hash = nil
0
+        revs.each_with_index do |rev, idx|
0
+          if !revs[idx + 1] || revs[idx + 1][0] > time
0
+            hash = revs[idx][1]
0
+            break
0
+          end
0
+        end
0
+        hash
0
+      end
0
+
0
+      def list_revisions(*args)
0
+        out = git.rev_list("--timestamp", *args)
0
+        out.split("\n").map do |line|
0
+          parts = line.split(' ', 2)
0
+          parts[0] = parts[0].to_i
0
+          parts
0
         end
0
       end
0
 
...
110
111
112
113
114
 
 
115
116
117
...
219
220
221
222
 
223
224
225
 
226
227
228
...
242
243
244
245
 
246
247
248
...
110
111
112
 
 
113
114
115
116
117
...
219
220
221
 
222
223
 
 
224
225
226
227
...
241
242
243
 
244
245
246
247
0
@@ -110,8 +110,8 @@ module Braid
0
     end
0
 
0
     class Git < Proxy
0
-      def commit(message)
0
-        status, out, err = exec("git commit -m #{message.inspect} --no-verify")
0
+      def commit(message, *args)
0
+        status, out, err = exec("git commit -m #{message.inspect} --no-verify #{args.join(' ')}")
0
 
0
         if status == 0
0
           true
0
@@ -219,10 +219,9 @@ module Braid
0
         out[2..-1]
0
       end
0
 
0
-      def apply(diff)
0
+      def apply(diff, *args)
0
         err = nil
0
-        # always uses index
0
-        status = Open4.popen4("git apply --index -") do |pid, stdin, stdout, stderr|
0
+        status = Open4.popen4("git apply --index --whitespace=nowarn #{args.join(' ')} -") do |pid, stdin, stdout, stderr|
0
           stdin.puts(diff)
0
           stdin.close
0
 
0
@@ -242,7 +241,7 @@ module Braid
0
       def self.command; "git-svn"; end
0
 
0
       def commit_hash(remote, revision)
0
-        status, out, err = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
0
+        out = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
0
         part = out.to_s.split(" | ")[1]
0
         raise UnknownRevision, "r#{revision}" unless part
0
         Git.instance.rev_parse(part) # FIXME ugly ugly ugly
...
52
53
54
55
 
56
57
58
...
52
53
54
 
55
56
57
58
0
@@ -52,7 +52,7 @@ describe "Braid::Config, with one mirror" do
0
   it "should update the mirror with new params" do
0
     @mirror.branch = "other"
0
     @config.update(@mirror)
0
-    @config.get("path").attributes.should == { "url" => "url", "branch" => "other" }
0
+    @config.get("path").attributes.should == { "branch" => "other" }
0
   end
0
 
0
   it "should raise when trying to update nonexistent mirror" do
...
43
44
45
46
47
48
 
 
 
 
 
 
 
49
50
51
52
53
 
 
 
 
54
55
56
57
58
 
 
 
 
 
59
60
61
62
63
64
 
 
65
66
 
 
67
68
69
70
71
 
 
72
73
74
 
 
 
 
 
 
 
 
 
 
 
...
43
44
45
 
 
 
46
47
48
49
50
51
52
53
54
 
 
 
55
56
57
58
59
60
 
 
 
61
62
63
64
65
66
67
68
69
 
 
70
71
72
 
73
74
75
76
77
 
 
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
0
@@ -43,32 +43,51 @@ end
0
 
0
 describe "Braid::Mirror#diff" do
0
   before(:each) do
0
-    @mirror = new_from_options("git://path")
0
-    git.stubs(:rev_parse)
0
-    git.stubs(:tree_hash)
0
+    @mirror = build_mirror("revision" => 'a' * 40)
0
+    @mirror.stubs(:base_revision).returns(@mirror.revision) # bypass rev_parse
0
+  end
0
+
0
+  def set_hashes(remote_hash, local_hash)
0
+    git.expects(:rev_parse).with("#{@mirror.revision}:").returns(remote_hash)
0
+    git.expects(:tree_hash).with(@mirror.path).returns(local_hash)
0
   end
0
 
0
-  it "should return true when the diff is not empty" do
0
-    git.expects(:diff_tree).returns("diff --git a/path b/path\n")
0
-    @mirror.local_changes?.should == true
0
+  it "should return an empty string when the hashes match" do
0
+    set_hashes('b' * 40, 'b' * 40)
0
+    git.expects(:diff_tree).never
0
+    @mirror.diff.should == ""
0
   end
0
 
0
-  it "should return false when the diff is empty" do
0
-    git.expects(:diff_tree).returns("")
0
-    @mirror.local_changes?.should == false
0
+  it "should generate a diff when the hashes do not match" do
0
+    set_hashes('b' * 40, 'c' * 40)
0
+    diff = "diff --git a/path b/path\n"
0
+    git.expects(:diff_tree).with('b' * 40, 'c' * 40, @mirror.path).returns(diff)
0
+    @mirror.diff.should == diff
0
   end
0
 end
0
 
0
 describe "Braid::Mirror#base_revision" do
0
-  it "should be nil when no revision is set" do
0
-    @mirror = Braid::Mirror.new("path")
0
+  it "should be inferred when no revision is set" do
0
+    @mirror = build_mirror
0
     @mirror.revision.should.be.nil
0
-    @mirror.send(:base_revision).should.be.nil
0
+    @mirror.expects(:inferred_revision).returns('b' * 40)
0
+    @mirror.send(:base_revision).should == 'b' * 40
0
   end
0
 
0
   it "should be the parsed hash for git mirrors" do
0
-    @mirror = Braid::Mirror.new("path", "revision" => ('a' * 7))
0
-    git.expects(:rev_parse).returns('a' * 40)
0
+    @mirror = build_mirror("revision" => 'a' * 7)
0
+    git.expects(:rev_parse).with('a' * 7).returns('a' * 40)
0
     @mirror.send(:base_revision).should == 'a' * 40
0
   end
0
 end
0
+
0
+describe "Braid::Mirror#inferred_revision" do
0
+  it "should return the last commit before the most recent update" do
0
+    @mirror = new_from_options("git://path")
0
+    @mirror.expects(:list_revisions).times(2).returns(
0
+      [[4, 'a' * 40], [2, 'b' * 40]],
0
+      [[1, 'c' * 40], [3, 'd' * 40], [5, 'e' * 40]]
0
+    )
0
+    @mirror.send(:inferred_revision).should == 'd' * 40
0
+  end
0
+end
...
8
9
10
11
12
 
 
13
14
15
...
8
9
10
 
 
11
12
13
14
15
0
@@ -8,8 +8,8 @@ def new_from_options(url, options = {})
0
   @mirror = Braid::Mirror.new_from_options(url, options)
0
 end
0
 
0
-def build_mirror
0
-  Braid::Mirror.new("path", "url" => "url")
0
+def build_mirror(options = {})
0
+  Braid::Mirror.new("path", options)
0
 end
0
 
0
 include Braid::Operations::VersionControl

Comments