realityforge-braid 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ *.gem
2
+ *.rbc
3
+ *.sw?
4
+ .DS_Store
5
+ .bundle
6
+ .idea
7
+ Gemfile.lock
8
+ coverage
9
+ nbproject
10
+ pkg
11
+ pkg/*
12
+ rdoc
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007-2010 Cristi Balan, Norbert Crombach
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # Braid
2
+
3
+ Braid is a simple tool to help track git and svn vendor branches in a git repository.
4
+
5
+ The project homepage is [here](http://github.com/evilchelu/braid/wikis/home).
6
+
7
+ ## Requirements
8
+
9
+ * git 1.6+ (and git-svn if you want to mirror svn repositories)
10
+ * main >= 4.2.0
11
+ * open4 >= 1.0.1 (unless using jruby)
12
+
13
+ ## Installing using rubygems - official releases
14
+
15
+ gem install braid
16
+
17
+ ## Installing from source
18
+
19
+ git clone git://github.com/evilchelu/braid.git
20
+ cd braid
21
+ bundle install
22
+ rake install # possibly requiring sudo
23
+
24
+ ## Quick usage - ruby project
25
+
26
+ Let's assume we're writing something like gitnub that needs grit in lib/grit. Initialize the repo (nothing braid related here):
27
+
28
+ git init gritty
29
+ cd gritty
30
+ touch README
31
+ git add README
32
+ git commit -m "initial commit"
33
+
34
+ Now let's vendor grit:
35
+
36
+ braid add git://github.com/mojombo/grit.git lib/grit
37
+
38
+ And you're done! Braid vendored grit into lib/grit. Feel free to inspect the changes with git log or git show.
39
+
40
+ If further down the line, you want to bring new changes from grit in your repository, just update the mirror:
41
+
42
+ braid update lib/grit
43
+
44
+ ## Quick usage - rails project
45
+
46
+ Let's assume you want to start a new rails app called shiny. Initialize the repo (nothing braid related here):
47
+
48
+ git init shiny
49
+ cd shiny
50
+ touch README
51
+ git add README
52
+ git commit -m "initial commit"
53
+
54
+ Vendor rails (this might take a while because the rails repo is huge!):
55
+
56
+ braid add git://github.com/rails/rails.git vendor/rails
57
+
58
+ Create your new rails app (nothing braid related here):
59
+
60
+ ruby vendor/rails/railties/bin/rails .
61
+ git add .
62
+ git commit -m "rails ."
63
+
64
+ Add any plugins you might need:
65
+
66
+ braid add git://github.com/thoughtbot/shoulda.git -p
67
+ braid add git://github.com/thoughtbot/factory_girl.git -p
68
+ braid add git://github.com/mbleigh/subdomain-fu.git -p
69
+
70
+ And you're done! Braid vendored rails and your plugins. Feel free to inspect the changes with git log or git show.
71
+
72
+ If further down the line, you want to bring new changes from rails in your repository, just update the mirror:
73
+
74
+ braid update vendor/rails
75
+
76
+ Or, if you want all mirrors updated:
77
+
78
+ braid update
79
+
80
+ ## More usage
81
+
82
+ Use the built in help system to find out about all commands and options:
83
+
84
+ braid help
85
+ braid help add # or braid add --help
86
+
87
+ You may also want to read [Usage and examples](http://github.com/evilchelu/braid/wikis/usage-and-examples).
88
+
89
+ ## Troubleshooting
90
+
91
+ Check [Troubleshooting](http://github.com/evilchelu/braid/wikis/troubleshooting) if you're having issues.
92
+
93
+ ## Contributing
94
+
95
+ We appreciate any patches, error reports and usage ideas you may have. Please submit a lighthouse ticket or start a thread on the mailing list.
96
+
97
+ Bugs and feature requests: [braid project on lighthouse](http://evilchelu.lighthouseapp.com/projects/10600-braid)
98
+
99
+ Discussions and community support: [braid-gem google group](http://groups.google.com/group/braid-gem)
100
+
101
+ ## Authors
102
+
103
+ * Cristi Balan (evilchelu)
104
+ * Norbert Crombach (norbert)
105
+
106
+ ## Contributors (alphabetically)
107
+
108
+ * Alan Harper
109
+ * Christoph Sturm
110
+ * Dennis Muhlestein
111
+ * Ferdinand Svehla
112
+ * Michael Klishin
113
+ * Roman Heinrich
114
+ * Travis Tilley
115
+ * Tyler Rick
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rake'
5
+ require 'rake/testtask'
6
+
7
+ task :default => :test
8
+
9
+ def test_task(name, pattern)
10
+ Rake::TestTask.new(name) do |t|
11
+ ENV['TESTOPTS'] = '--runner=s'
12
+
13
+ t.libs << 'lib'
14
+ t.pattern = pattern
15
+ t.verbose = true
16
+ end
17
+ end
18
+
19
+ test_task(:test, "test/*_test.rb")
20
+ namespace(:test) { test_task(:integration, "test/integration/*_test.rb") }
data/bin/braid ADDED
@@ -0,0 +1,263 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../lib"))
4
+ require 'braid'
5
+
6
+ require 'rubygems'
7
+ require 'main'
8
+
9
+ Home = File.expand_path(ENV['HOME'] || '~')
10
+
11
+ # mostly blantantly stolen from ara's punch script
12
+ # main kicks ass!
13
+ Main {
14
+ description <<-TXT
15
+ braid is a simple tool to help track git or svn repositories inside a git repository.
16
+
17
+ Run 'braid commandname help' for more details.
18
+
19
+ All operations will be executed in the braid/track branch.
20
+ You can then merge back or cherry-pick changes.
21
+ TXT
22
+
23
+ mode(:add) {
24
+ description <<-TXT
25
+ Add a new mirror to be tracked.
26
+
27
+ * adds metadata about the mirror to .braids
28
+ * adds the git or git svn remotes to .git/config
29
+ * fetches and merges remote code into given directory
30
+
31
+ --type defaults:
32
+
33
+ * svn://path # => svn
34
+ * git://path # => git
35
+ * http://path/trunk # => svn
36
+ * http://path.git # => git
37
+
38
+ Name defaults:
39
+
40
+ * remote/path # => path
41
+ * remote/path/trunk # => path
42
+ * remote/path.git # => path
43
+ TXT
44
+
45
+ examples <<-TXT
46
+ . braid add svn://remote/path
47
+ . braid add svn://remote/path local/dir
48
+ . braid add git://remote/path local/dir
49
+ . braid add http://remote/path.git local/dir
50
+ . braid add http://remote/path --type git local/dir
51
+ . braid add svn://remote/path --branch notmaster
52
+ TXT
53
+
54
+ mixin :argument_url, :option_type, :optional_path, :option_branch, :option_rails_plugin, :option_revision, :option_full, :option_verbose
55
+
56
+ run {
57
+ Braid.verbose = verbose
58
+ Braid::Command.run(:add, url, {"type" => type, "path" => path, "branch" => branch, "rails_plugin" => rails_plugin, "revision" => revision, "full" => full})
59
+ }
60
+ }
61
+
62
+ mode(:update) {
63
+ description <<-TXT
64
+ Update a braid mirror.
65
+
66
+ * get new changes from remote
67
+ * always creates a merge commit
68
+ * updates metadata in .braids when revisions are changed
69
+
70
+ Defaults to updating all unlocked mirrors if none is specified.
71
+ TXT
72
+
73
+ examples <<-TXT
74
+ . braid update
75
+ . braid update local/dir
76
+ TXT
77
+
78
+ mixin :optional_path, :option_revision, :option_head, :option_verbose
79
+
80
+ run {
81
+ Braid.verbose = verbose
82
+ Braid::Command.run(:update, path, {"revision" => revision, "head" => head})
83
+ }
84
+ }
85
+
86
+ mode(:remove) {
87
+ description <<-TXT
88
+ Remove a mirror.
89
+
90
+ * removes metadata from .braids
91
+ * removes the local directory and commits the removal
92
+ * removes the git remote by default, --keep can be used to supress that
93
+ TXT
94
+
95
+ examples <<-TXT
96
+ . braid remove local/dir
97
+ TXT
98
+
99
+ mixin :argument_path, :option_verbose, :option_keep_remote
100
+
101
+ run {
102
+ options = {
103
+ :keep => keep
104
+ }
105
+ Braid.verbose = verbose
106
+ Braid::Command.run(:remove, path, options)
107
+ }
108
+ }
109
+
110
+ mode(:diff) {
111
+ description <<-TXT
112
+ Show diff of local changes to mirror.
113
+ TXT
114
+
115
+ mixin :argument_path, :option_verbose
116
+
117
+ run {
118
+ Braid::Command.run(:diff, path)
119
+ }
120
+ }
121
+
122
+ mode(:push) {
123
+ description <<-TXT
124
+ Push local mirror changes to remote.
125
+ TXT
126
+
127
+ mixin :argument_path, :option_verbose
128
+
129
+ run {
130
+ Braid.verbose = verbose
131
+ Braid::Command.run(:push, path)
132
+ }
133
+ }
134
+
135
+ mode(:setup) {
136
+ description <<-TXT
137
+ Set up git and git-svn remotes.
138
+ TXT
139
+
140
+ mixin :optional_path, :option_verbose, :option_force
141
+
142
+ run {
143
+ Braid.verbose = verbose
144
+ Braid.force = force
145
+ Braid::Command.run(:setup, path)
146
+ }
147
+ }
148
+
149
+ mode(:version) {
150
+ description 'Show braid version.'
151
+
152
+ run {
153
+ puts "braid #{Braid::VERSION}"
154
+ }
155
+ }
156
+
157
+ mode(:list) {
158
+ description 'Show all tracked mirrors (and if updates are available).'
159
+
160
+ mixin :option_verbose
161
+
162
+ run {
163
+ Braid.verbose = verbose
164
+ Braid::Command.run(:list)
165
+ }
166
+ }
167
+
168
+ mixin(:argument_path) {
169
+ argument(:path) {
170
+ attr
171
+ }
172
+ }
173
+
174
+ mixin(:optional_path) {
175
+ argument(:path) {
176
+ optional
177
+ attr
178
+ }
179
+ }
180
+
181
+ mixin(:argument_url) {
182
+ argument(:url) {
183
+ attr
184
+ }
185
+ }
186
+
187
+ mixin(:option_type) {
188
+ option(:type, :t) {
189
+ optional
190
+ argument :required
191
+ desc 'mirror type'
192
+ attr
193
+ }
194
+ }
195
+
196
+ mixin(:option_branch) {
197
+ option(:branch, :b) {
198
+ optional
199
+ argument :required
200
+ desc 'remote branch name'
201
+ attr
202
+ }
203
+ }
204
+
205
+ mixin(:option_rails_plugin) {
206
+ option(:rails_plugin, :p) {
207
+ optional
208
+ desc 'added mirror is a Rails plugin'
209
+ attr
210
+ }
211
+ }
212
+
213
+ mixin(:option_revision) {
214
+ option(:revision, :r) {
215
+ optional
216
+ argument :required
217
+ desc 'revision to track'
218
+ attr
219
+ }
220
+ }
221
+
222
+ mixin(:option_head) {
223
+ option(:head) {
224
+ optional
225
+ desc 'mirror head'
226
+ attr
227
+ }
228
+ }
229
+
230
+ mixin(:option_full) {
231
+ option(:full) {
232
+ optional
233
+ desc 'include mirror history' # FIXME
234
+ attr
235
+ }
236
+ }
237
+
238
+ mixin(:option_verbose) {
239
+ option(:verbose, :v) {
240
+ optional
241
+ desc 'log shell commands'
242
+ attr
243
+ }
244
+ }
245
+
246
+ mixin(:option_force) {
247
+ option(:force, :f) {
248
+ optional
249
+ desc 'force'
250
+ attr
251
+ }
252
+ }
253
+
254
+ mixin(:option_keep_remote) {
255
+ option(:keep) {
256
+ optional
257
+ desc 'do not remove the remote'
258
+ attr
259
+ }
260
+ }
261
+
262
+ run { help! }
263
+ }
data/braid.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require 'braid/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = %q{realityforge-braid}
7
+ s.version = Braid::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+
10
+ s.authors = ["Cristi Balan", "Norbert Crombach"]
11
+ s.email = %q{evil@che.lu}
12
+
13
+ s.homepage = %q{http://evil.che.lu/projects/braid}
14
+ s.summary = %q{A simple tool for tracking vendor branches in git.}
15
+ s.description = %q{A simple tool for tracking vendor branches in git.}
16
+
17
+ s.rubyforge_project = %q{braid}
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
22
+ s.default_executable = %q{braid}
23
+ s.require_paths = ["lib"]
24
+
25
+ s.has_rdoc = false
26
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "braid", "--main"]
27
+
28
+ s.add_dependency(%q<main>, [">= 4.7.3"])
29
+ s.add_dependency(%q<open4>, [">= 1.0.1"]) unless defined?(JRUBY_VERSION)
30
+
31
+ s.add_development_dependency(%q<test-spec>, [">= 0.10.0"])
32
+ s.add_development_dependency(%q<mocha>, [">= 0.9.11"])
33
+ end
@@ -0,0 +1,136 @@
1
+ module Braid
2
+ class Command
3
+ class InvalidRevision < BraidError
4
+ end
5
+
6
+ extend Operations::VersionControl
7
+ include Operations::VersionControl
8
+
9
+ def self.run(command, *args)
10
+ verify_git_version!
11
+
12
+ klass = Commands.const_get(command.to_s.capitalize)
13
+ klass.new.run(*args)
14
+
15
+ rescue BraidError => error
16
+ case error
17
+ when Operations::ShellExecutionError
18
+ msg "Shell error: #{error.message}"
19
+ else
20
+ msg "Error: #{error.message}"
21
+ end
22
+ exit(1)
23
+ end
24
+
25
+ def self.msg(str)
26
+ puts "Braid: #{str}"
27
+ end
28
+
29
+ def msg(str)
30
+ self.class.msg(str)
31
+ end
32
+
33
+ def config
34
+ @config ||= load_and_migrate_config
35
+ end
36
+
37
+ def verbose?
38
+ Braid.verbose
39
+ end
40
+
41
+ def force?
42
+ Braid.force
43
+ end
44
+
45
+ private
46
+
47
+ def setup_remote(mirror)
48
+ Command.run(:setup, mirror.path)
49
+ end
50
+
51
+ def use_local_cache?
52
+ Braid.use_local_cache
53
+ end
54
+
55
+ def self.verify_git_version!
56
+ git.require_version!(REQUIRED_GIT_VERSION)
57
+ end
58
+
59
+ def bail_on_local_changes!
60
+ git.ensure_clean!
61
+ end
62
+
63
+ def with_reset_on_error
64
+ work_head = git.head
65
+
66
+ begin
67
+ yield
68
+ rescue => error
69
+ msg "Resetting to '#{work_head[0, 7]}'."
70
+ git.reset_hard(work_head)
71
+ raise error
72
+ end
73
+ end
74
+
75
+ def load_and_migrate_config
76
+ config = Config.new
77
+ unless config.valid?
78
+ msg "Configuration is outdated. Migrating."
79
+ bail_on_local_changes!
80
+ config.migrate!
81
+ git.commit("Upgrade .braids", "-- .braids")
82
+ end
83
+ config
84
+ end
85
+
86
+ def add_config_file
87
+ git.add(CONFIG_FILE)
88
+ end
89
+
90
+ def display_revision(mirror, revision = nil)
91
+ revision ||= mirror.revision
92
+ mirror.type == "svn" ? "r#{revision}" : "'#{revision[0, 7]}'"
93
+ end
94
+
95
+ def validate_new_revision(mirror, new_revision)
96
+ unless new_revision
97
+ unless mirror.type == "svn"
98
+ return git.rev_parse(mirror.remote)
99
+ else
100
+ return svn.head_revision(mirror.url)
101
+ end
102
+ end
103
+
104
+ unless mirror.type == "svn"
105
+ new_revision = git.rev_parse(new_revision)
106
+ else
107
+ new_revision = svn.clean_revision(new_revision)
108
+ end
109
+ old_revision = mirror.revision
110
+
111
+ if new_revision == old_revision
112
+ raise InvalidRevision, "mirror is already at requested revision"
113
+ end
114
+
115
+ if mirror.type == "svn"
116
+ if old_revision && new_revision < old_revision
117
+ raise InvalidRevision, "local revision is higher than request revision"
118
+ end
119
+
120
+ if svn.head_revision(mirror.url) < new_revision
121
+ raise InvalidRevision, "requested revision is higher than remote revision"
122
+ end
123
+ end
124
+
125
+ new_revision
126
+ end
127
+
128
+ def determine_target_revision(mirror, new_revision)
129
+ unless mirror.type == "svn"
130
+ git.rev_parse(new_revision)
131
+ else
132
+ git_svn.commit_hash(mirror.remote, new_revision)
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,40 @@
1
+ module Braid
2
+ module Commands
3
+ class Add < Command
4
+ def run(url, options = {})
5
+ bail_on_local_changes!
6
+
7
+ with_reset_on_error do
8
+ mirror = config.add_from_options(url, options)
9
+
10
+ branch_message = (mirror.type == "svn" || mirror.branch == "master") ? "" : " branch '#{mirror.branch}'"
11
+ revision_message = options["revision"] ? " at #{display_revision(mirror, options["revision"])}" : ""
12
+ msg "Adding #{mirror.type} mirror of '#{mirror.url}'#{branch_message}#{revision_message}."
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
+ mirror.fetch
19
+
20
+ new_revision = validate_new_revision(mirror, options["revision"])
21
+ target_revision = determine_target_revision(mirror, new_revision)
22
+
23
+ unless mirror.squashed?
24
+ git.merge_ours(target_revision)
25
+ end
26
+ git.read_tree_prefix(target_revision, mirror.path)
27
+
28
+ mirror.revision = new_revision
29
+ mirror.lock = new_revision if options["revision"]
30
+ config.update(mirror)
31
+ add_config_file
32
+
33
+ git.commit("Add mirror '#{mirror.path}' at #{display_revision(mirror)}")
34
+ msg "Added mirror at #{display_revision(mirror)}."
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ module Braid
2
+ module Commands
3
+ class Diff < Command
4
+ def run(path)
5
+ mirror = config.get!(path)
6
+ setup_remote(mirror)
7
+
8
+ diff = mirror.diff
9
+ puts diff unless diff.empty?
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ module Braid
2
+ module Commands
3
+ class List < Command
4
+ def run(path = nil, options = {})
5
+ with_reset_on_error do
6
+ path ? list_one(path, options) : list_all(options)
7
+ end
8
+ end
9
+
10
+ protected
11
+ def list_all(options = {})
12
+ options.reject! { |k, v| %w(revision head).include?(k) }
13
+ print "\n"
14
+ msg "Listing all mirrors.\n=======================================================\n"
15
+ config.mirrors.each_with_index do |path, i|
16
+ mirror = config.get!(path)
17
+ print " #{i + 1}) #{path.to_s}"
18
+ print " [LOCKED]" if mirror.locked?
19
+ setup_remote(mirror)
20
+ msg "Fetching new commits for '#{mirror.path}'." if verbose?
21
+ mirror.fetch
22
+ new_revision = validate_new_revision(mirror, options["revision"])
23
+ target_revision = determine_target_revision(mirror, new_revision)
24
+ print " !!! UPDATE AVAILABLE !!!" if new_revision.to_s != mirror.base_revision.to_s
25
+ print "\n"
26
+ end
27
+ print "\n"
28
+ end
29
+
30
+ end
31
+ end
32
+ end