evilchelu-braid 0.3.5

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.
@@ -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