braid 0.6.2 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,29 +6,30 @@ module Braid
6
6
  end
7
7
 
8
8
  protected
9
- def setup_all
10
- msg "Setting up all mirrors."
11
- config.mirrors.each do |path|
12
- setup_one(path)
13
- end
9
+
10
+ def setup_all
11
+ msg "Setting up all mirrors."
12
+ config.mirrors.each do |path|
13
+ setup_one(path)
14
14
  end
15
+ end
15
16
 
16
- def setup_one(path)
17
- mirror = config.get!(path)
17
+ def setup_one(path)
18
+ mirror = config.get!(path)
18
19
 
19
- if git.remote_url(mirror.remote)
20
- msg "Setup: Mirror '#{mirror.path}' already has a remote. Reusing it." if verbose?
21
- return
22
- end
20
+ if git.remote_url(mirror.remote)
21
+ msg "Setup: Mirror '#{mirror.path}' already has a remote. Reusing it." if verbose?
22
+ return
23
+ end
23
24
 
24
- msg "Setup: Creating remote for '#{mirror.path}'."
25
- unless mirror.type == "svn"
26
- url = use_local_cache? ? git_cache.path(mirror.url) : mirror.url
27
- git.remote_add(mirror.remote, url, mirror.branch)
28
- else
29
- git_svn.init(mirror.remote, mirror.url)
30
- end
25
+ msg "Setup: Creating remote for '#{mirror.path}'."
26
+ unless mirror.type == "svn"
27
+ url = use_local_cache? ? git_cache.path(mirror.url) : mirror.url
28
+ git.remote_add(mirror.remote, url, mirror.branch)
29
+ else
30
+ git_svn.init(mirror.remote, mirror.url)
31
31
  end
32
+ end
32
33
  end
33
34
  end
34
35
  end
@@ -10,92 +10,93 @@ module Braid
10
10
  end
11
11
 
12
12
  protected
13
- def update_all(options = {})
14
- options.reject! { |k,v| %w(revision head).include?(k) }
15
- msg "Updating all mirrors."
16
- config.mirrors.each do |path|
17
- update_one(path, options)
18
- end
13
+
14
+ def update_all(options = {})
15
+ options.reject! { |k, v| %w(revision head).include?(k) }
16
+ msg "Updating all mirrors."
17
+ config.mirrors.each do |path|
18
+ update_one(path, options)
19
19
  end
20
+ end
20
21
 
21
- def update_one(path, options = {})
22
- mirror = config.get!(path)
22
+ def update_one(path, options = {})
23
+ mirror = config.get!(path)
23
24
 
24
- revision_message = options["revision"] ? " to #{display_revision(mirror, options["revision"])}" : ""
25
- msg "Updating mirror '#{mirror.path}'#{revision_message}."
25
+ revision_message = options["revision"] ? " to #{display_revision(mirror, options["revision"])}" : ""
26
+ msg "Updating mirror '#{mirror.path}'#{revision_message}."
26
27
 
27
- # check options for lock modification
28
- if mirror.locked?
29
- if options["head"]
30
- msg "Unlocking mirror '#{mirror.path}'." if verbose?
31
- mirror.lock = nil
32
- elsif !options["revision"]
33
- msg "Mirror '#{mirror.path}' is locked to #{display_revision(mirror, mirror.lock)}. Use --head to force."
34
- return
35
- end
28
+ # check options for lock modification
29
+ if mirror.locked?
30
+ if options["head"]
31
+ msg "Unlocking mirror '#{mirror.path}'." if verbose?
32
+ mirror.lock = nil
33
+ elsif !options["revision"]
34
+ msg "Mirror '#{mirror.path}' is locked to #{display_revision(mirror, mirror.lock)}. Use --head to force."
35
+ return
36
36
  end
37
+ end
37
38
 
38
- setup_remote(mirror)
39
- msg "Fetching new commits for '#{mirror.path}'." if verbose?
40
- mirror.fetch
39
+ setup_remote(mirror)
40
+ msg "Fetching new commits for '#{mirror.path}'." if verbose?
41
+ mirror.fetch
41
42
 
42
- new_revision = validate_new_revision(mirror, options["revision"])
43
- target_revision = determine_target_revision(mirror, new_revision)
43
+ new_revision = validate_new_revision(mirror, options["revision"])
44
+ target_revision = determine_target_revision(mirror, new_revision)
44
45
 
45
- if mirror.merged?(target_revision)
46
- msg "Mirror '#{mirror.path}' is already up to date."
47
- return
48
- end
46
+ if mirror.merged?(target_revision)
47
+ msg "Mirror '#{mirror.path}' is already up to date."
48
+ return
49
+ end
49
50
 
50
- if mirror.squashed?
51
- diff = mirror.diff
52
- base_revision = mirror.base_revision
53
- end
51
+ if mirror.squashed?
52
+ diff = mirror.diff
53
+ base_revision = mirror.base_revision
54
+ end
55
+
56
+ mirror.revision = new_revision
57
+ mirror.lock = new_revision if options["revision"]
54
58
 
55
- mirror.revision = new_revision
56
- mirror.lock = new_revision if options["revision"]
57
-
58
- msg "Merging in mirror '#{mirror.path}'." if verbose?
59
- begin
60
- if mirror.squashed?
61
- local_hash = git.rev_parse("HEAD")
62
- if !diff.empty?
63
- base_hash = generate_tree_hash(mirror, base_revision)
64
- else
65
- base_hash = local_hash
66
- end
67
- remote_hash = generate_tree_hash(mirror, target_revision)
68
- ENV["GITHEAD_#{local_hash}"] = "HEAD"
69
- ENV["GITHEAD_#{remote_hash}"] = target_revision
70
- git.merge_recursive(base_hash, local_hash, remote_hash)
59
+ msg "Merging in mirror '#{mirror.path}'." if verbose?
60
+ begin
61
+ if mirror.squashed?
62
+ local_hash = git.rev_parse("HEAD")
63
+ if !diff.empty?
64
+ base_hash = generate_tree_hash(mirror, base_revision)
71
65
  else
72
- git.merge_subtree(target_revision)
66
+ base_hash = local_hash
73
67
  end
74
- rescue Operations::MergeError => error
75
- msg "Caught merge error. Breaking."
68
+ remote_hash = generate_tree_hash(mirror, target_revision)
69
+ ENV["GITHEAD_#{local_hash}"] = "HEAD"
70
+ ENV["GITHEAD_#{remote_hash}"] = target_revision
71
+ git.merge_recursive(base_hash, local_hash, remote_hash)
72
+ else
73
+ git.merge_subtree(target_revision)
76
74
  end
75
+ rescue Operations::MergeError => error
76
+ msg "Caught merge error. Breaking."
77
+ end
77
78
 
78
- config.update(mirror)
79
- add_config_file
79
+ config.update(mirror)
80
+ add_config_file
80
81
 
81
- commit_message = "Update mirror '#{mirror.path}' to #{display_revision(mirror)}"
82
- if error
83
- File.open(".git/MERGE_MSG", 'w') { |f| f.puts(commit_message) }
84
- return
85
- end
86
-
87
- git.commit(commit_message)
88
- msg "Updated mirror to #{display_revision(mirror)}."
82
+ commit_message = "Update mirror '#{mirror.path}' to #{display_revision(mirror)}"
83
+ if error
84
+ File.open(".git/MERGE_MSG", 'w') { |f| f.puts(commit_message) }
85
+ return
89
86
  end
90
87
 
91
- def generate_tree_hash(mirror, revision)
92
- git.rm_r(mirror.path)
93
- git.read_tree_prefix(revision, mirror.path)
94
- success = git.commit("Temporary commit for mirror '#{mirror.path}'")
95
- hash = git.rev_parse("HEAD")
96
- git.reset_hard("HEAD^") if success
97
- hash
98
- end
88
+ git.commit(commit_message)
89
+ msg "Updated mirror to #{display_revision(mirror)}."
90
+ end
91
+
92
+ def generate_tree_hash(mirror, revision)
93
+ git.rm_r(mirror.path)
94
+ git.read_tree_prefix(revision, mirror.path)
95
+ success = git.commit("Temporary commit for mirror '#{mirror.path}'")
96
+ hash = git.rev_parse("HEAD")
97
+ git.reset_hard("HEAD^") if success
98
+ hash
99
+ end
99
100
  end
100
101
  end
101
102
  end
data/lib/braid/config.rb CHANGED
@@ -79,10 +79,10 @@ module Braid
79
79
  @db.roots.each do |path|
80
80
  attributes = @db[path]
81
81
  if attributes["local_branch"]
82
- attributes["url"] = attributes.delete("remote")
83
- attributes["remote"] = attributes.delete("local_branch")
82
+ attributes["url"] = attributes.delete("remote")
83
+ attributes["remote"] = attributes.delete("local_branch")
84
84
  attributes["squashed"] = attributes.delete("squash")
85
- attributes["lock"] = attributes["revision"] # so far this has always been true
85
+ attributes["lock"] = attributes["revision"] # so far this has always been true
86
86
  end
87
87
  @db[path] = clean_attributes(attributes)
88
88
  end
@@ -90,12 +90,12 @@ module Braid
90
90
  end
91
91
 
92
92
  private
93
- def write_mirror(mirror)
94
- @db[mirror.path] = clean_attributes(mirror.attributes)
95
- end
93
+ def write_mirror(mirror)
94
+ @db[mirror.path] = clean_attributes(mirror.attributes)
95
+ end
96
96
 
97
- def clean_attributes(hash)
98
- hash.reject { |k,v| v.nil? }
99
- end
97
+ def clean_attributes(hash)
98
+ hash.reject { |k, v| v.nil? }
99
+ end
100
100
  end
101
101
  end
data/lib/braid/mirror.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Braid
2
2
  class Mirror
3
- TYPES = %w(git svn)
3
+ TYPES = %w(git svn)
4
4
  ATTRIBUTES = %w(url remote type branch squashed revision lock)
5
5
 
6
6
  class UnknownType < BraidError
@@ -24,12 +24,12 @@ module Braid
24
24
  attr_reader :path, :attributes
25
25
 
26
26
  def initialize(path, attributes = {})
27
- @path = path.sub(/\/$/, '')
27
+ @path = path.sub(/\/$/, '')
28
28
  @attributes = attributes
29
29
  end
30
30
 
31
31
  def self.new_from_options(url, options = {})
32
- url = url.sub(/\/$/, '')
32
+ url = url.sub(/\/$/, '')
33
33
 
34
34
  branch = options["branch"] || "master"
35
35
 
@@ -47,11 +47,11 @@ module Braid
47
47
  path = "vendor/plugins/#{path}"
48
48
  end
49
49
 
50
- remote = "braid/#{path}".gsub("_", '-') # stupid git svn changes all _ to ., weird
50
+ remote = "braid/#{path}".gsub("_", '-') # stupid git svn changes all _ to ., weird
51
51
  squashed = !options["full"]
52
52
  branch = nil if type == "svn"
53
53
 
54
- attributes = { "url" => url, "remote" => remote, "type" => type, "branch" => branch, "squashed" => squashed }
54
+ attributes = {"url" => url, "remote" => remote, "type" => type, "branch" => branch, "squashed" => squashed}
55
55
  self.new(path, attributes)
56
56
  end
57
57
 
@@ -85,7 +85,7 @@ module Braid
85
85
 
86
86
  def diff
87
87
  remote_hash = git.rev_parse("#{base_revision}:")
88
- local_hash = git.tree_hash(path)
88
+ local_hash = git.tree_hash(path)
89
89
  remote_hash != local_hash ? git.diff_tree(remote_hash, local_hash) : ""
90
90
  end
91
91
 
@@ -119,59 +119,60 @@ module Braid
119
119
  end
120
120
 
121
121
  private
122
- def method_missing(name, *args)
123
- if ATTRIBUTES.find { |attribute| name.to_s =~ /^(#{attribute})(=)?$/ }
124
- unless $2
125
- attributes[$1]
126
- else
127
- attributes[$1] = args[0]
128
- end
122
+
123
+ def method_missing(name, *args)
124
+ if ATTRIBUTES.find { |attribute| name.to_s =~ /^(#{attribute})(=)?$/ }
125
+ unless $2
126
+ attributes[$1]
129
127
  else
130
- raise NameError, "unknown attribute `#{name}'"
128
+ attributes[$1] = args[0]
131
129
  end
130
+ else
131
+ raise NameError, "unknown attribute `#{name}'"
132
132
  end
133
+ end
133
134
 
134
- def inferred_revision
135
- local_commits = git.rev_list("HEAD", "-- #{path}").split("\n")
136
- remote_hashes = git.rev_list("--pretty=format:\"%T\"", remote).split("commit ").map do |chunk|
137
- chunk.split("\n", 2).map { |value| value.strip }
138
- end
139
- hash = nil
140
- local_commits.each do |local_commit|
141
- local_tree = git.tree_hash(path, local_commit)
142
- if match = remote_hashes.find { |_, remote_tree| local_tree == remote_tree }
143
- hash = match[0]
144
- break
145
- end
135
+ def inferred_revision
136
+ local_commits = git.rev_list("HEAD", "-- #{path}").split("\n")
137
+ remote_hashes = git.rev_list("--pretty=format:\"%T\"", remote).split("commit ").map do |chunk|
138
+ chunk.split("\n", 2).map { |value| value.strip }
139
+ end
140
+ hash = nil
141
+ local_commits.each do |local_commit|
142
+ local_tree = git.tree_hash(path, local_commit)
143
+ if match = remote_hashes.find { |_, remote_tree| local_tree == remote_tree }
144
+ hash = match[0]
145
+ break
146
146
  end
147
- hash
148
147
  end
148
+ hash
149
+ end
149
150
 
150
- def self.extract_type_from_url(url)
151
- return nil unless url
152
- url.sub!(/\/$/, '')
151
+ def self.extract_type_from_url(url)
152
+ return nil unless url
153
+ url.sub!(/\/$/, '')
153
154
 
154
- # check for git:// and svn:// URLs
155
- url_scheme = url.split(":").first
156
- return url_scheme if TYPES.include?(url_scheme)
155
+ # check for git:// and svn:// URLs
156
+ url_scheme = url.split(":").first
157
+ return url_scheme if TYPES.include?(url_scheme)
157
158
 
158
- return "svn" if url[-6..-1] == "/trunk"
159
- return "git" if url[-4..-1] == ".git"
160
- end
159
+ return "svn" if url[-6..-1] == "/trunk"
160
+ return "git" if url[-4..-1] == ".git"
161
+ end
161
162
 
162
- def self.extract_path_from_url(url)
163
- return nil unless url
164
- name = File.basename(url)
163
+ def self.extract_path_from_url(url)
164
+ return nil unless url
165
+ name = File.basename(url)
165
166
 
166
- if File.extname(name) == ".git"
167
- # strip .git
168
- name[0..-5]
169
- elsif name == "trunk"
170
- # use parent
171
- File.basename(File.dirname(url))
172
- else
173
- name
174
- end
167
+ if File.extname(name) == ".git"
168
+ # strip .git
169
+ name[0..-5]
170
+ elsif name == "trunk"
171
+ # use parent
172
+ File.basename(File.dirname(url))
173
+ else
174
+ name
175
175
  end
176
+ end
176
177
  end
177
178
  end
@@ -1,6 +1,6 @@
1
1
  require 'singleton'
2
2
  require 'rubygems'
3
- require 'open4'
3
+ require defined?(JRUBY_VERSION) ? 'open3' : 'open4'
4
4
  require 'tempfile'
5
5
 
6
6
  module Braid
@@ -16,8 +16,8 @@ module Braid
16
16
  end
17
17
  class VersionTooLow < BraidError
18
18
  def initialize(command, version, required)
19
- @command = command
20
- @version = version.to_s.split("\n").first
19
+ @command = command
20
+ @version = version.to_s.split("\n").first
21
21
  @required = required
22
22
  end
23
23
 
@@ -45,8 +45,11 @@ module Braid
45
45
  class Proxy
46
46
  include Singleton
47
47
 
48
- def self.command; name.split('::').last.downcase; end # hax!
48
+ def self.command;
49
+ name.split('::').last.downcase;
50
+ end
49
51
 
52
+ # hax!
50
53
  def version
51
54
  status, out, err = exec!("#{self.class.command} --version")
52
55
  out.sub(/^.* version/, "").strip
@@ -54,7 +57,7 @@ module Braid
54
57
 
55
58
  def require_version(required)
56
59
  required = required.split(".")
57
- actual = version.split(".")
60
+ actual = version.split(".")
58
61
 
59
62
  actual.each_with_index do |actual_piece, idx|
60
63
  required_piece = required[idx]
@@ -79,62 +82,72 @@ module Braid
79
82
  end
80
83
 
81
84
  private
82
- def command(name)
83
- # stub
84
- name
85
- end
86
85
 
87
- def invoke(arg, *args)
88
- exec!("#{command(arg)} #{args.join(' ')}".strip)[1].strip # return stdout
89
- end
86
+ def command(name)
87
+ # stub
88
+ name
89
+ end
90
90
 
91
- def method_missing(name, *args)
92
- invoke(name, *args)
93
- end
91
+ def invoke(arg, *args)
92
+ exec!("#{command(arg)} #{args.join(' ')}".strip)[1].strip # return stdout
93
+ end
94
+
95
+ def method_missing(name, *args)
96
+ invoke(name, *args)
97
+ end
98
+
99
+ def exec(cmd)
100
+ cmd.strip!
94
101
 
95
- def exec(cmd)
96
- cmd.strip!
102
+ previous_lang = ENV['LANG']
103
+ ENV['LANG'] = 'C'
97
104
 
98
- previous_lang = ENV['LANG']
99
- ENV['LANG'] = 'C'
105
+ out, err = nil
106
+ log(cmd)
100
107
 
101
- out, err = nil
102
- log(cmd)
108
+ if defined?(JRUBY_VERSION)
109
+ Open3.popen3(cmd) do |stdin, stdout, stderr|
110
+ out = stdout.read
111
+ err = stderr.read
112
+ end
113
+ status = $?.exitstatus
114
+ else
103
115
  status = Open4.popen4(cmd) do |pid, stdin, stdout, stderr|
104
116
  out = stdout.read
105
117
  err = stderr.read
106
118
  end.exitstatus
107
- [status, out, err]
108
-
109
- ensure
110
- ENV['LANG'] = previous_lang
111
119
  end
112
120
 
113
- def exec!(cmd)
114
- status, out, err = exec(cmd)
115
- raise ShellExecutionError, err unless status == 0
116
- [status, out, err]
117
- end
121
+ [status, out, err]
122
+ ensure
123
+ ENV['LANG'] = previous_lang
124
+ end
118
125
 
119
- def sh(cmd, message = nil)
120
- message ||= "could not fetch" if cmd =~ /fetch/
121
- log(cmd)
122
- `#{cmd}`
123
- raise ShellExecutionError, message unless $?.exitstatus == 0
124
- true
125
- end
126
+ def exec!(cmd)
127
+ status, out, err = exec(cmd)
128
+ raise ShellExecutionError, err unless status == 0
129
+ [status, out, err]
130
+ end
126
131
 
127
- def msg(str)
128
- puts "Braid: #{str}"
129
- end
132
+ def sh(cmd, message = nil)
133
+ message ||= "could not fetch" if cmd =~ /fetch/
134
+ log(cmd)
135
+ `#{cmd}`
136
+ raise ShellExecutionError, message unless $?.exitstatus == 0
137
+ true
138
+ end
130
139
 
131
- def log(cmd)
132
- msg "Executing `#{cmd}`" if verbose?
133
- end
140
+ def msg(str)
141
+ puts "Braid: #{str}"
142
+ end
134
143
 
135
- def verbose?
136
- Braid.verbose
137
- end
144
+ def log(cmd)
145
+ msg "Executing `#{cmd}`" if verbose?
146
+ end
147
+
148
+ def verbose?
149
+ Braid.verbose
150
+ end
138
151
  end
139
152
 
140
153
  class Git < Proxy
@@ -275,12 +288,22 @@ module Braid
275
288
 
276
289
  def apply(diff, *args)
277
290
  err = nil
278
- status = Open4.popen4("git apply --index --whitespace=nowarn #{args.join(' ')} -") do |pid, stdin, stdout, stderr|
279
- stdin.puts(diff)
280
- stdin.close
281
291
 
282
- err = stderr.read
283
- end.exitstatus
292
+ if defined?(JRUBY_VERSION)
293
+ Open3.popen3("git apply --index --whitespace=nowarn #{args.join(' ')} -") do |stdin, stdout, stderr|
294
+ stdin.puts(diff)
295
+ stdin.close
296
+ err = stderr.read
297
+ end
298
+ status = $?.exitstatus
299
+ else
300
+ status = Open4.popen4("git apply --index --whitespace=nowarn #{args.join(' ')} -") do |pid, stdin, stdout, stderr|
301
+ stdin.puts(diff)
302
+ stdin.close
303
+ err = stderr.read
304
+ end.exitstatus
305
+ end
306
+
284
307
  raise ShellExecutionError, err unless status == 0
285
308
  true
286
309
  end
@@ -291,17 +314,21 @@ module Braid
291
314
  end
292
315
 
293
316
  private
294
- def command(name)
295
- "#{self.class.command} #{name.to_s.gsub('_', '-')}"
296
- end
317
+
318
+ def command(name)
319
+ "#{self.class.command} #{name.to_s.gsub('_', '-')}"
320
+ end
297
321
  end
298
322
 
299
323
  class GitSvn < Proxy
300
- def self.command; "git svn"; end
324
+ def self.command;
325
+ "git svn";
326
+ end
301
327
 
302
328
  def commit_hash(remote, revision)
303
- out = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
304
- part = out.to_s.split(" | ")[1]
329
+ out = invoke(:log, "--show-commit --oneline", "-r #{revision}", remote)
330
+ part = out.to_s.split("|")[1]
331
+ part.strip!
305
332
  raise UnknownRevision, "r#{revision}" unless part
306
333
  git.rev_parse(part)
307
334
  end
@@ -316,13 +343,14 @@ module Braid
316
343
  end
317
344
 
318
345
  private
319
- def command(name)
320
- "#{self.class.command} #{name}"
321
- end
322
346
 
323
- def git
324
- Git.instance
325
- end
347
+ def command(name)
348
+ "#{self.class.command} #{name}"
349
+ end
350
+
351
+ def git
352
+ Git.instance
353
+ end
326
354
  end
327
355
 
328
356
  class Svn < Proxy
@@ -364,13 +392,14 @@ module Braid
364
392
  end
365
393
 
366
394
  private
367
- def local_cache_dir
368
- Braid.local_cache_dir
369
- end
370
395
 
371
- def git
372
- Git.instance
373
- end
396
+ def local_cache_dir
397
+ Braid.local_cache_dir
398
+ end
399
+
400
+ def git
401
+ Git.instance
402
+ end
374
403
  end
375
404
 
376
405
  module VersionControl