evilchelu-braid 0.3.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,53 @@
1
+ module Braid
2
+ class Command
3
+ include Operations::Mirror
4
+ include Operations::Helpers
5
+
6
+ def self.run(command, *args)
7
+ klass = Braid::Commands.const_get(command.to_s.capitalize)
8
+ klass.new.run(*args)
9
+ rescue => e
10
+ # FIXME
11
+ end
12
+
13
+ def self.msg(str)
14
+ puts str
15
+ end
16
+
17
+ def config
18
+ @config ||= Braid::Config.new
19
+ end
20
+
21
+ private
22
+ def msg(str)
23
+ self.class.msg(str)
24
+ end
25
+
26
+ def in_work_branch
27
+ # make sure there is a git repository
28
+ begin
29
+ old_branch = get_current_branch
30
+ rescue => e
31
+ msg "Error occured: #{e.message}"
32
+ raise e
33
+ end
34
+
35
+ create_work_branch
36
+ work_head = get_work_head
37
+
38
+ begin
39
+ invoke(:git_checkout, WORK_BRANCH)
40
+ yield
41
+ rescue => e
42
+ msg "Error occured: #{e.message}"
43
+ if get_current_branch == WORK_BRANCH
44
+ msg "Resetting '#{WORK_BRANCH}' to '#{work_head}'."
45
+ invoke(:git_reset_hard, work_head)
46
+ end
47
+ raise e
48
+ ensure
49
+ invoke(:git_checkout, old_branch)
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,53 @@
1
+ module Braid
2
+ module Commands
3
+ class Add < Command
4
+ def run(remote, options = {})
5
+ in_work_branch do
6
+ mirror, params = config.add_from_options(remote, options)
7
+ local_branch = get_local_branch_name(mirror, params)
8
+
9
+ config.update(mirror, { "local_branch" => local_branch })
10
+ params["local_branch"] = local_branch # TODO check
11
+
12
+ msg "Adding #{params["type"]} mirror of '#{params["remote"]}'" + (params["type"] == "git" ? ", branch '#{params["branch"]}'" : "") + "."
13
+
14
+ # these commands are explained in the subtree merge guide
15
+ # http://www.kernel.org/pub/software/scm/git/docs/howto/using-merge-subtree.html
16
+
17
+ setup_remote(mirror)
18
+ fetch_remote(params["type"], local_branch)
19
+
20
+ validate_revision_option(params, options)
21
+ target = determine_target_commit(params, options)
22
+
23
+ msg "Merging code into '#{mirror}/'."
24
+
25
+ unless params["squash"]
26
+ invoke(:git_merge_ours, target)
27
+ end
28
+ invoke(:git_read_tree, target, mirror)
29
+
30
+ config.update(mirror, { "revision" => options["revision"] })
31
+ add_config_file
32
+
33
+ revision_message = options["revision"] ? " at #{display_revision(params["type"], options["revision"])}" : ""
34
+ commit_message = "Add mirror '#{mirror}/'#{revision_message}."
35
+ invoke(:git_commit, commit_message)
36
+ end
37
+ end
38
+
39
+ protected
40
+ def setup_remote(mirror)
41
+ Braid::Command.run(:setup, mirror)
42
+ end
43
+
44
+ private
45
+ def get_local_branch_name(mirror, params)
46
+ res = "braid/#{params["type"]}/#{mirror}"
47
+ res << "/#{params["branch"]}" if params["type"] == "git"
48
+ res.gsub!("_", '-') # stupid git svn changes all _ to ., weird
49
+ res
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,10 @@
1
+ module Braid
2
+ module Commands
3
+ class Diff < Command
4
+ def run(mirror)
5
+ # easiest call, liek, evar.
6
+ system("git diff #{WORK_BRANCH} HEAD #{mirror}")
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ module Braid
2
+ module Commands
3
+ class Remove < Command
4
+ def run(mirror)
5
+ in_work_branch do
6
+ params = config.get(mirror)
7
+ unless params
8
+ msg "Mirror '#{mirror}/' does not exist."
9
+ return
10
+ end
11
+
12
+ msg "Removing #{params["type"]} mirror from '#{mirror}/'."
13
+
14
+ invoke(:git_rm_r, mirror)
15
+
16
+ config.remove(mirror)
17
+ add_config_file
18
+
19
+ commit_message = "Remove mirror '#{mirror}/'."
20
+ invoke(:git_commit, commit_message)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ module Braid
2
+ module Commands
3
+ class Setup < Command
4
+ def run(mirror)
5
+ in_work_branch do
6
+ mirror ? setup_one(mirror) : setup_all
7
+ end
8
+ end
9
+
10
+ protected
11
+ def setup_all
12
+ msg "Setting up all mirrors."
13
+ config.mirrors.each do |mirror|
14
+ setup_one(mirror)
15
+ end
16
+ end
17
+
18
+ def setup_one(mirror)
19
+ params = config.get(mirror)
20
+ unless params
21
+ msg "Mirror '#{mirror}/' does not exist. Skipping."
22
+ return
23
+ end
24
+
25
+ if find_remote(params["local_branch"])
26
+ msg "Mirror '#{mirror}/' already has a remote. Skipping."
27
+ return
28
+ end
29
+
30
+ msg "Setting up remote for '#{mirror}/'."
31
+ case params["type"]
32
+ when "git"
33
+ invoke(:git_remote_add, params["local_branch"], params["remote"], params["branch"])
34
+ when "svn"
35
+ invoke(:git_svn_init, params["local_branch"], params["remote"])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,77 @@
1
+ module Braid
2
+ module Commands
3
+ class Update < Command
4
+ def run(mirror, options = {})
5
+ in_work_branch do
6
+ mirror ? update_one(mirror, options) : update_all
7
+ end
8
+ end
9
+
10
+ protected
11
+ def update_all
12
+ msg "Updating all mirrors."
13
+ config.mirrors.each do |mirror|
14
+ update_one(mirror)
15
+ end
16
+ end
17
+
18
+ def update_one(mirror, options = {})
19
+ params = config.get(mirror)
20
+ unless params
21
+ msg "Mirror '#{mirror}/' does not exist. Skipping."
22
+ return
23
+ end
24
+ local_branch = params["local_branch"]
25
+
26
+ if check_for_lock(params, options)
27
+ msg "Mirror '#{mirror}/' is locked to #{display_revision(params["type"], params["revision"])}. Skipping."
28
+ return
29
+ end
30
+
31
+ # unlock
32
+ if params["revision"] && options["head"]
33
+ msg "Unlocking mirror '#{mirror}/'."
34
+ options["revision"] = nil
35
+ end
36
+
37
+ begin
38
+ fetch_remote(params["type"], local_branch)
39
+
40
+ validate_revision_option(params, options)
41
+ target = determine_target_commit(params, options)
42
+
43
+ check_merge_status(target)
44
+ rescue Braid::Commands::MirrorAlreadyUpToDate
45
+ msg "Mirror '#{mirror}/' is already up to date. Skipping."
46
+ update_revision(mirror, options["revision"])
47
+ return
48
+ end
49
+
50
+ msg "Updating #{params["type"]} mirror '#{mirror}/'."
51
+
52
+ if params["squash"]
53
+ invoke(:git_rm_r, mirror)
54
+ invoke(:git_read_tree, target, mirror)
55
+ else
56
+ invoke(:git_merge_subtree, target)
57
+ end
58
+
59
+ update_revision(mirror, options["revision"])
60
+ add_config_file
61
+
62
+ revision_message = " to " + (options["revision"] ? display_revision(params["type"], options["revision"]) : "HEAD")
63
+ commit_message = "Update mirror '#{mirror}/'#{revision_message}."
64
+ invoke(:git_commit, commit_message)
65
+ end
66
+
67
+ private
68
+ def check_for_lock(params, options)
69
+ params["revision"] && !options["revision"] && !options["head"]
70
+ end
71
+
72
+ def update_revision(mirror, revision)
73
+ config.update(mirror, { "revision" => revision })
74
+ end
75
+ end
76
+ end
77
+ end
@@ -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,31 @@
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
+ end
27
+
28
+ class Svn
29
+ class UnknownRevision < Braid::Exception; end
30
+ end
31
+ end