misaka-braid 0.4.0.1
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.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +32 -0
- data/README.txt +53 -0
- data/Rakefile +4 -0
- data/bin/braid +218 -0
- data/braid.gemspec +26 -0
- data/config/hoe.rb +68 -0
- data/config/requirements.rb +17 -0
- data/lib/braid/command.rb +74 -0
- data/lib/braid/commands/add.rb +55 -0
- data/lib/braid/commands/diff.rb +10 -0
- data/lib/braid/commands/remove.rb +27 -0
- data/lib/braid/commands/setup.rb +38 -0
- data/lib/braid/commands/update.rb +79 -0
- data/lib/braid/config.rb +148 -0
- data/lib/braid/exceptions.rb +34 -0
- data/lib/braid/operations.rb +297 -0
- data/lib/braid/version.rb +9 -0
- data/lib/braid.rb +29 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/setup.rb +1585 -0
- data/spec/braid_spec.rb +7 -0
- data/spec/config_spec.rb +117 -0
- data/spec/operations_spec.rb +52 -0
- data/spec/spec.opts +3 -0
- data/spec/spec_helper.rb +11 -0
- data/tasks/deployment.rake +27 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +32 -0
- data/tasks/website.rake +9 -0
- metadata +106 -0
@@ -0,0 +1,79 @@
|
|
1
|
+
module Braid
|
2
|
+
module Commands
|
3
|
+
class Update < Command
|
4
|
+
def run(mirror, options = {})
|
5
|
+
raise Braid::Git::LocalChangesPresent if invoke(:local_changes?)
|
6
|
+
|
7
|
+
in_work_branch do
|
8
|
+
mirror ? update_one(mirror, options) : update_all
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
def update_all
|
14
|
+
msg "Updating all mirrors."
|
15
|
+
config.mirrors.each do |mirror|
|
16
|
+
update_one(mirror)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def update_one(mirror, options = {})
|
21
|
+
params = config.get(mirror)
|
22
|
+
unless params
|
23
|
+
msg "Mirror '#{mirror}/' does not exist. Skipping."
|
24
|
+
return
|
25
|
+
end
|
26
|
+
local_branch = params["local_branch"]
|
27
|
+
|
28
|
+
if check_for_lock(params, options)
|
29
|
+
msg "Mirror '#{mirror}/' is locked to #{display_revision(params["type"], params["revision"])}. Skipping."
|
30
|
+
return
|
31
|
+
end
|
32
|
+
|
33
|
+
# unlock
|
34
|
+
if params["revision"] && options["head"]
|
35
|
+
msg "Unlocking mirror '#{mirror}/'."
|
36
|
+
options["revision"] = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
begin
|
40
|
+
fetch_remote(params["type"], local_branch)
|
41
|
+
|
42
|
+
validate_revision_option(params, options)
|
43
|
+
target = determine_target_commit(params, options)
|
44
|
+
|
45
|
+
check_merge_status(target)
|
46
|
+
rescue Braid::Commands::MirrorAlreadyUpToDate
|
47
|
+
msg "Mirror '#{mirror}/' is already up to date. Skipping."
|
48
|
+
update_revision(mirror, options["revision"])
|
49
|
+
return
|
50
|
+
end
|
51
|
+
|
52
|
+
msg "Updating #{params["type"]} mirror '#{mirror}/'."
|
53
|
+
|
54
|
+
if params["squash"]
|
55
|
+
invoke(:git_rm_r, mirror)
|
56
|
+
invoke(:git_read_tree, target, mirror)
|
57
|
+
else
|
58
|
+
invoke(:git_merge_subtree, target)
|
59
|
+
end
|
60
|
+
|
61
|
+
update_revision(mirror, options["revision"])
|
62
|
+
add_config_file
|
63
|
+
|
64
|
+
revision_message = " to " + (options["revision"] ? display_revision(params["type"], options["revision"]) : "HEAD")
|
65
|
+
commit_message = "Update mirror '#{mirror}/'#{revision_message}."
|
66
|
+
invoke(:git_commit, commit_message)
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
def check_for_lock(params, options)
|
71
|
+
params["revision"] && !options["revision"] && !options["head"]
|
72
|
+
end
|
73
|
+
|
74
|
+
def update_revision(mirror, revision)
|
75
|
+
config.update(mirror, { "revision" => revision })
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/braid/config.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'yaml/store'
|
3
|
+
|
4
|
+
module Braid
|
5
|
+
class Config
|
6
|
+
attr_accessor :db
|
7
|
+
|
8
|
+
def initialize(config_file = nil)
|
9
|
+
config_file ||= CONFIG_FILE
|
10
|
+
@db = YAML::Store.new(config_file)
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_from_options(remote, options)
|
14
|
+
mirror, params = self.class.options_to_mirror(remote, options)
|
15
|
+
|
16
|
+
raise Braid::Config::RemoteIsRequired unless params["remote"]
|
17
|
+
raise Braid::Config::MirrorTypeIsRequired unless params["type"]
|
18
|
+
raise Braid::Config::BranchIsRequired unless params["type"] == "svn" || params["branch"]
|
19
|
+
raise Braid::Config::MirrorNameIsRequired unless mirror
|
20
|
+
raise Braid::Config::UnknownMirrorType unless MIRROR_TYPES.include?(params["type"])
|
21
|
+
|
22
|
+
params.delete("rails_plugin")
|
23
|
+
params.delete("branch") if params["type"] == "svn"
|
24
|
+
add(mirror, params)
|
25
|
+
[mirror, get(mirror)]
|
26
|
+
end
|
27
|
+
|
28
|
+
def mirrors
|
29
|
+
@db.transaction(true) do
|
30
|
+
@db.roots
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def add(mirror, params)
|
35
|
+
mirror = remove_trailing_slash(mirror)
|
36
|
+
@db.transaction do
|
37
|
+
raise Braid::Config::MirrorNameAlreadyInUse if @db[mirror]
|
38
|
+
@db[mirror] = params.merge("remote" => remove_trailing_slash(params["remote"]))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def get(mirror)
|
43
|
+
mirror = remove_trailing_slash(mirror)
|
44
|
+
@db.transaction(true) do
|
45
|
+
@db[mirror]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def get!(mirror)
|
50
|
+
params = get(mirror)
|
51
|
+
raise Braid::Config::MirrorDoesNotExist unless params
|
52
|
+
params
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_by_remote(remote)
|
56
|
+
remote = remove_trailing_slash(remote)
|
57
|
+
mirror = nil
|
58
|
+
@db.transaction(true) do
|
59
|
+
mirror = @db.roots.detect { |mirror| @db[mirror]["remote"] == remote }
|
60
|
+
end
|
61
|
+
[mirror, get(mirror)]
|
62
|
+
end
|
63
|
+
|
64
|
+
def remove(mirror)
|
65
|
+
mirror = remove_trailing_slash(mirror)
|
66
|
+
@db.transaction do
|
67
|
+
@db.delete(mirror)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def update(mirror, params)
|
72
|
+
mirror = remove_trailing_slash(mirror)
|
73
|
+
@db.transaction do
|
74
|
+
raise Braid::Config::MirrorDoesNotExist unless @db[mirror]
|
75
|
+
tmp = @db[mirror].merge(params)
|
76
|
+
@db[mirror] = tmp.merge("remote" => remove_trailing_slash(tmp["remote"]))
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def replace(mirror, params)
|
81
|
+
mirror = remove_trailing_slash(mirror)
|
82
|
+
@db.transaction do
|
83
|
+
raise Braid::Config::MirrorDoesNotExist unless @db[mirror]
|
84
|
+
params["remote"] = remove_trailing_slash(params["remote"]) if params["remote"]
|
85
|
+
@db[mirror] = params
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.options_to_mirror(remote, options = {})
|
90
|
+
remote = remove_trailing_slash(remote)
|
91
|
+
branch = options["branch"] || "master"
|
92
|
+
|
93
|
+
if options["type"]
|
94
|
+
type = options["type"]
|
95
|
+
else
|
96
|
+
type = extract_type_from_path(remote)
|
97
|
+
raise Braid::Config::CannotGuessMirrorType unless type
|
98
|
+
end
|
99
|
+
|
100
|
+
mirror = options["mirror"] || extract_mirror_from_path(remote)
|
101
|
+
|
102
|
+
if options["rails_plugin"]
|
103
|
+
mirror = "vendor/plugins/#{mirror}"
|
104
|
+
end
|
105
|
+
|
106
|
+
squash = !options["full"]
|
107
|
+
|
108
|
+
[remove_trailing_slash(mirror), { "type" => type, "remote" => remote, "branch" => branch, "squash" => squash }]
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
def remove_trailing_slash(path)
|
113
|
+
self.class.send(:remove_trailing_slash, path)
|
114
|
+
end
|
115
|
+
|
116
|
+
def self.remove_trailing_slash(path)
|
117
|
+
# bluh.
|
118
|
+
path.sub(/\/$/, '')
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.extract_type_from_path(path)
|
122
|
+
return nil unless path
|
123
|
+
path = remove_trailing_slash(path)
|
124
|
+
|
125
|
+
# check for git:// and svn:// URLs
|
126
|
+
path_scheme = path.split(":").first
|
127
|
+
return path_scheme if %w[git svn].include?(path_scheme)
|
128
|
+
|
129
|
+
return "svn" if path[-6..-1] == "/trunk"
|
130
|
+
return "git" if path[-4..-1] == ".git"
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.extract_mirror_from_path(path)
|
134
|
+
return nil unless path
|
135
|
+
name = File.basename(path)
|
136
|
+
|
137
|
+
if File.extname(name) == ".git"
|
138
|
+
# strip .git
|
139
|
+
name[0..-5]
|
140
|
+
elsif name == "trunk"
|
141
|
+
# use parent
|
142
|
+
File.basename(File.dirname(path))
|
143
|
+
else
|
144
|
+
name
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Braid
|
2
|
+
class Exception < StandardError
|
3
|
+
end
|
4
|
+
|
5
|
+
module Commands
|
6
|
+
class ShellExecutionError < Braid::Exception; end
|
7
|
+
class LocalRevisionIsHigherThanRequestedRevision < Braid::Exception; end
|
8
|
+
class MirrorAlreadyUpToDate < Braid::Exception; end
|
9
|
+
class RequestedRevisionIsHigherThanRemoteRevision < Braid::Exception; end
|
10
|
+
end
|
11
|
+
|
12
|
+
class Config
|
13
|
+
class UnknownMirrorType < Braid::Exception; end
|
14
|
+
class MirrorNameAlreadyInUse < Braid::Exception; end
|
15
|
+
class MirrorDoesNotExist < Braid::Exception; end
|
16
|
+
class CannotGuessMirrorType < Braid::Exception; end
|
17
|
+
|
18
|
+
class RemoteIsRequired < Braid::Exception; end
|
19
|
+
class MirrorTypeIsRequired < Braid::Exception; end
|
20
|
+
class BranchIsRequired < Braid::Exception; end
|
21
|
+
class MirrorNameIsRequired < Braid::Exception; end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Git
|
25
|
+
class UnknownRevision < Braid::Exception; end
|
26
|
+
class GitVersionTooLow < Braid::Exception; end
|
27
|
+
class GitSvnVersionTooLow < Braid::Exception; end
|
28
|
+
class LocalChangesPresent < Braid::Exception; end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Svn
|
32
|
+
class UnknownRevision < Braid::Exception; end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,297 @@
|
|
1
|
+
module Braid
|
2
|
+
module Operations
|
3
|
+
module Git
|
4
|
+
def git_commit(message)
|
5
|
+
status, out, err = exec("git commit -m #{message.inspect} --no-verify")
|
6
|
+
|
7
|
+
if status == 0
|
8
|
+
true
|
9
|
+
elsif out.match(/nothing.* to commit/)
|
10
|
+
false
|
11
|
+
else
|
12
|
+
raise Braid::Commands::ShellExecutionError, err
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def git_fetch(remote)
|
17
|
+
# open4 messes with the pipes of index-pack
|
18
|
+
system("git fetch -n #{remote} 2>&1 > /dev/null")
|
19
|
+
raise Braid::Commands::ShellExecutionError unless $? == 0
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def git_checkout(treeish)
|
24
|
+
# TODO debug
|
25
|
+
msg "Checking out '#{treeish}'."
|
26
|
+
exec!("git checkout #{treeish}")
|
27
|
+
true
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns the base commit or nil.
|
31
|
+
def git_merge_base(target, source)
|
32
|
+
status, out, err = exec!("git merge-base #{target} #{source}")
|
33
|
+
out.strip
|
34
|
+
rescue Braid::Commands::ShellExecutionError
|
35
|
+
nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def git_rev_parse(commit)
|
39
|
+
status, out, err = exec!("git rev-parse #{commit}")
|
40
|
+
out.strip
|
41
|
+
end
|
42
|
+
|
43
|
+
# Implies tracking.
|
44
|
+
def git_remote_add(remote, path, branch)
|
45
|
+
exec!("git remote add -t #{branch} -m #{branch} #{remote} #{path}")
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def git_reset_hard(target)
|
50
|
+
exec!("git reset --hard #{target}")
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
# Implies no commit.
|
55
|
+
def git_merge_ours(commit)
|
56
|
+
exec!("git merge -s ours --no-commit #{commit}")
|
57
|
+
true
|
58
|
+
end
|
59
|
+
|
60
|
+
# Implies no commit.
|
61
|
+
def git_merge_subtree(commit)
|
62
|
+
# TODO which options are needed?
|
63
|
+
exec!("git merge -s subtree --no-commit --no-ff #{commit}")
|
64
|
+
true
|
65
|
+
end
|
66
|
+
|
67
|
+
def git_read_tree(treeish, prefix)
|
68
|
+
exec!("git read-tree --prefix=#{prefix}/ -u #{treeish}")
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def git_rm_r(path)
|
73
|
+
exec!("git rm -r #{path}")
|
74
|
+
true
|
75
|
+
end
|
76
|
+
|
77
|
+
def local_changes?
|
78
|
+
status, out, err = exec("git status")
|
79
|
+
out.split("\n").grep(/nothing to commit \(working directory clean\)/).empty?
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module Svn
|
84
|
+
# FIXME move
|
85
|
+
def svn_remote_head_revision(path)
|
86
|
+
# not using svn info because it's retarded and doesn't show the actual last changed rev for the url
|
87
|
+
# git svn has no clue on how to get the actual HEAD revision number on it's own
|
88
|
+
status, out, err = exec!("svn log -q --limit 1 #{path}")
|
89
|
+
out.split(/\n/).find { |x| x.match /^r\d+/ }.split(" | ")[0][1..-1].to_i
|
90
|
+
end
|
91
|
+
|
92
|
+
# FIXME move
|
93
|
+
def svn_git_commit_hash(remote, revision)
|
94
|
+
status, out, err = exec!("git svn log --show-commit --oneline -r #{revision} #{remote}")
|
95
|
+
part = out.split(" | ")[1]
|
96
|
+
raise Braid::Svn::UnknownRevision, "unknown revision: #{revision}" unless part
|
97
|
+
invoke(:git_rev_parse, part)
|
98
|
+
end
|
99
|
+
|
100
|
+
def git_svn_fetch(remote)
|
101
|
+
# open4 messes with the pipes of index-pack
|
102
|
+
system("git svn fetch #{remote} 2>&1 > /dev/null")
|
103
|
+
true
|
104
|
+
end
|
105
|
+
|
106
|
+
def git_svn_init(remote, path)
|
107
|
+
exec!("git svn init -R #{remote} --id=#{remote} #{path}")
|
108
|
+
true
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
module Helpers
|
113
|
+
[:invoke, :exec, :exec!].each do |method|
|
114
|
+
define_method(method) do |*args|
|
115
|
+
Braid::Operations.send(method, *args)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def extract_version(cmd)
|
120
|
+
status, out, err = exec!("#{cmd} --version")
|
121
|
+
return out.sub(/^.* version/, "").strip
|
122
|
+
end
|
123
|
+
|
124
|
+
def verify_version(cmd, required)
|
125
|
+
required_version = required.split(".")
|
126
|
+
actual_version = extract_version(cmd).split(".")
|
127
|
+
actual_version.each_with_index do |actual_piece, idx|
|
128
|
+
required_piece = required_version[idx]
|
129
|
+
|
130
|
+
return true unless required_piece
|
131
|
+
|
132
|
+
case (actual_piece <=> required_piece)
|
133
|
+
when -1
|
134
|
+
return false
|
135
|
+
when 1
|
136
|
+
return true
|
137
|
+
when 0
|
138
|
+
next
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
return actual_version.length >= required_version.length
|
143
|
+
end
|
144
|
+
|
145
|
+
def find_git_revision(commit)
|
146
|
+
invoke(:git_rev_parse, commit)
|
147
|
+
rescue Braid::Commands::ShellExecutionError
|
148
|
+
raise Braid::Git::UnknownRevision, "unknown revision: #{commit}"
|
149
|
+
end
|
150
|
+
|
151
|
+
def clean_svn_revision(revision)
|
152
|
+
if revision
|
153
|
+
revision.to_i
|
154
|
+
else
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def validate_svn_revision(old_revision, new_revision, path)
|
160
|
+
return unless new_revision = clean_svn_revision(new_revision)
|
161
|
+
old_revision = clean_svn_revision(old_revision)
|
162
|
+
|
163
|
+
# TODO add checks for unlocked mirrors
|
164
|
+
if old_revision
|
165
|
+
if new_revision < old_revision
|
166
|
+
raise Braid::Commands::LocalRevisionIsHigherThanRequestedRevision
|
167
|
+
elsif new_revision == old_revision
|
168
|
+
raise Braid::Commands::MirrorAlreadyUpToDate
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
if path && invoke(:svn_remote_head_revision, path) < new_revision
|
173
|
+
raise Braid::Commands::RequestedRevisionIsHigherThanRemoteRevision
|
174
|
+
end
|
175
|
+
|
176
|
+
true
|
177
|
+
end
|
178
|
+
|
179
|
+
# Make sure the revision is valid, then clean it.
|
180
|
+
def validate_revision_option(params, options)
|
181
|
+
if options["revision"]
|
182
|
+
case params["type"]
|
183
|
+
when "git"
|
184
|
+
options["revision"] = find_git_revision(options["revision"])
|
185
|
+
when "svn"
|
186
|
+
validate_svn_revision(params["revision"], options["revision"], params["remote"])
|
187
|
+
options["revision"] = clean_svn_revision(options["revision"])
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
true
|
192
|
+
end
|
193
|
+
|
194
|
+
def determine_target_commit(params, options)
|
195
|
+
if options["revision"]
|
196
|
+
if params["type"] == "svn"
|
197
|
+
invoke(:svn_git_commit_hash, params["local_branch"], options["revision"])
|
198
|
+
else
|
199
|
+
invoke(:git_rev_parse, options["revision"])
|
200
|
+
end
|
201
|
+
else
|
202
|
+
invoke(:git_rev_parse, params["local_branch"])
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def display_revision(type, revision)
|
207
|
+
type == "svn" ? "r#{revision}" : "'#{revision[0, 7]}'"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
module Mirror
|
212
|
+
def get_current_branch
|
213
|
+
status, out, err = exec!("git branch | grep '*'")
|
214
|
+
out[2..-1]
|
215
|
+
end
|
216
|
+
|
217
|
+
def create_work_branch
|
218
|
+
# check if branch exists
|
219
|
+
status, out, err = exec("git branch | grep '#{WORK_BRANCH}'")
|
220
|
+
if status != 0
|
221
|
+
# then create it
|
222
|
+
msg "Creating work branch '#{WORK_BRANCH}'."
|
223
|
+
exec!("git branch #{WORK_BRANCH}")
|
224
|
+
end
|
225
|
+
|
226
|
+
true
|
227
|
+
end
|
228
|
+
|
229
|
+
def get_work_head
|
230
|
+
find_git_revision(WORK_BRANCH)
|
231
|
+
end
|
232
|
+
|
233
|
+
def add_config_file
|
234
|
+
exec!("git add #{CONFIG_FILE}")
|
235
|
+
true
|
236
|
+
end
|
237
|
+
|
238
|
+
def check_merge_status(commit)
|
239
|
+
commit = find_git_revision(commit)
|
240
|
+
# tip from spearce in #git:
|
241
|
+
# `test z$(git merge-base A B) = z$(git rev-parse --verify A)`
|
242
|
+
if invoke(:git_merge_base, commit, "HEAD") == commit
|
243
|
+
raise Braid::Commands::MirrorAlreadyUpToDate
|
244
|
+
end
|
245
|
+
|
246
|
+
true
|
247
|
+
end
|
248
|
+
|
249
|
+
def fetch_remote(type, remote)
|
250
|
+
msg "Fetching data from '#{remote}'."
|
251
|
+
case type
|
252
|
+
when "git"
|
253
|
+
invoke(:git_fetch, remote)
|
254
|
+
when "svn"
|
255
|
+
invoke(:git_svn_fetch, remote)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def find_remote(remote)
|
260
|
+
# TODO clean up and maybe return more information
|
261
|
+
!!File.readlines(".git/config").find { |line| line =~ /^\[(svn-)?remote "#{remote}"\]/ }
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
extend Git
|
266
|
+
extend Svn
|
267
|
+
|
268
|
+
def self.invoke(*args)
|
269
|
+
send(*args)
|
270
|
+
end
|
271
|
+
|
272
|
+
def self.exec(cmd)
|
273
|
+
#puts cmd
|
274
|
+
out = ""
|
275
|
+
err = ""
|
276
|
+
cmd.strip!
|
277
|
+
|
278
|
+
ENV['LANG'] = 'C' unless ENV['LANG'] == 'C'
|
279
|
+
status = Open4::popen4(cmd) do |pid, stdin, stdout, stderr|
|
280
|
+
out = stdout.read.strip
|
281
|
+
err = stderr.read.strip
|
282
|
+
end
|
283
|
+
[status.exitstatus, out, err]
|
284
|
+
end
|
285
|
+
|
286
|
+
def self.exec!(cmd)
|
287
|
+
status, out, err = exec(cmd)
|
288
|
+
raise Braid::Commands::ShellExecutionError, err unless status == 0
|
289
|
+
return status, out, err
|
290
|
+
end
|
291
|
+
|
292
|
+
private
|
293
|
+
def self.msg(str)
|
294
|
+
Braid::Command.msg(str)
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
data/lib/braid.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
$:.unshift dir = File.dirname(__FILE__)
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rubygems'
|
5
|
+
rescue LoadError
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'open4'
|
9
|
+
require 'yaml'
|
10
|
+
require 'yaml/store'
|
11
|
+
|
12
|
+
module Braid
|
13
|
+
MIRROR_TYPES = %w[git svn]
|
14
|
+
WORK_BRANCH = "braid/track"
|
15
|
+
CONFIG_FILE = ".braids"
|
16
|
+
REQUIRED_GIT_VERSION = "1.5.4.5"
|
17
|
+
REQUIRED_GIT_SVN_VERSION = "1.5.4.5"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'braid/version'
|
21
|
+
require 'braid/exceptions'
|
22
|
+
|
23
|
+
require 'braid/config'
|
24
|
+
require 'braid/operations'
|
25
|
+
|
26
|
+
require 'braid/command'
|
27
|
+
Dir["#{dir}/braid/commands/*"].each do |file|
|
28
|
+
require file
|
29
|
+
end
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! :rubygems
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! :rubygems, :newgem
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|