dreamcat4-braid 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2007-2008 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.textile ADDED
@@ -0,0 +1,120 @@
1
+ h1. 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 at "http://github.com/evilchelu/braid/wikis/home":http://github.com/evilchelu/braid/wikis/home
6
+
7
+ h2. Requirements
8
+
9
+ * git 1.6+ (and git-svn if you want to mirror svn repositories)
10
+ * main >= 2.8.0
11
+ * open4 >= 0.9.6
12
+
13
+ h2. Installing using rubygems - official releases
14
+
15
+ gem install braid
16
+
17
+ h2. Installing using rubygems - development releases
18
+
19
+ gem sources -a http://gems.github.com
20
+ gem install evilchelu-braid
21
+
22
+ h2. Installing from source
23
+
24
+ git clone git://github.com/evilchelu/braid.git
25
+ cd braid
26
+ gem build braid.gemspec
27
+ sudo gem install braid-x.y.z.gem
28
+
29
+ h2. Quick usage - ruby project
30
+
31
+ Let's assume we're writing something like gitnub that needs grit in lib/grit. Initialize the repo (nothing braid related here):
32
+
33
+ git init gritty
34
+ cd gritty
35
+ touch README
36
+ git add README
37
+ git commit -m "initial commit"
38
+
39
+ Now let's vendor grit:
40
+
41
+ braid add git://github.com/mojombo/grit.git lib/grit
42
+
43
+ And you're done! Braid vendored grit into lib/grit. Feel free to inspect the changes with git log or git show.
44
+
45
+ If further down the line, you want to bring new changes from grit in your repository, just update the mirror:
46
+
47
+ braid update lib/grit
48
+
49
+ h2. Quick usage - rails project
50
+
51
+ Let's assume you want to start a new rails app called shiny. Initialize the repo (nothing braid related here):
52
+
53
+ git init shiny
54
+ cd shiny
55
+ touch README
56
+ git add README
57
+ git commit -m "initial commit"
58
+
59
+ Vendor rails (this might take a while because the rails repo is huge!):
60
+
61
+ braid add git://github.com/rails/rails.git vendor/rails
62
+
63
+ Create your new rails app (nothing braid related here):
64
+
65
+ ruby vendor/rails/railties/bin/rails .
66
+ git add .
67
+ git commit -m "rails ."
68
+
69
+ Add any plugins you might need:
70
+
71
+ braid add git://github.com/thoughtbot/shoulda.git -p
72
+ braid add git://github.com/thoughtbot/factory_girl.git -p
73
+ braid add git://github.com/mbleigh/subdomain-fu.git -p
74
+
75
+ And you're done! Braid vendored rails and your plugins. Feel free to inspect the changes with git log or git show.
76
+
77
+ If further down the line, you want to bring new changes from rails in your repository, just update the mirror:
78
+
79
+ braid update vendor/rails
80
+
81
+ Or, if you want all mirrors updated:
82
+
83
+ braid update
84
+
85
+ h2. More usage
86
+
87
+ Use the built in help system to find out about all commands and options:
88
+
89
+ braid help
90
+ braid help add # or braid add --help
91
+
92
+ You may also want to read "Usage and examples":http://github.com/evilchelu/braid/wikis/usage-and-examples.
93
+
94
+ h2. Troubleshooting
95
+
96
+ Check "Troubleshooting":http://github.com/evilchelu/braid/wikis/troubleshooting if you're having issues.
97
+
98
+ h2. Contributing
99
+
100
+ 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.
101
+
102
+ Bugs and feature requests: "*braid project on lighthouse*":http://evilchelu.lighthouseapp.com/projects/10600-braid
103
+
104
+ Discussions and community support: "*braid-gem google group*":http://groups.google.com/group/braid-gem
105
+
106
+ h2. Authors
107
+
108
+ * Cristi Balan (evilchelu)
109
+ * Norbert Crombach (norbert)
110
+
111
+ h2. Contributors (alphabetically)
112
+
113
+ * Alan Harper
114
+ * Christoph Sturm
115
+ * Dennis Muhlestein
116
+ * Ferdinand Svehla
117
+ * Michael Klishin
118
+ * Roman Heinrich
119
+ * Tyler Rick
120
+
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ task :default => :test
5
+
6
+ def test_task(name, pattern)
7
+ Rake::TestTask.new(name) do |t|
8
+ ENV['TESTOPTS'] = '--runner=s'
9
+
10
+ t.libs << 'lib'
11
+ t.pattern = pattern
12
+ t.verbose = true
13
+ end
14
+ end
15
+
16
+ test_task(:test, "test/*_test.rb")
17
+ namespace(:test) { test_task(:integration, "test/integration/*_test.rb") }
data/bin/braid ADDED
@@ -0,0 +1,249 @@
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 help commandname' 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_rails_gem, :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, "rails_gem" => rails_gem, "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(:setup) {
111
+ description <<-TXT
112
+ Set up git or git-svn remote for a mirror.
113
+ All commands that need a remote run setup internally.
114
+
115
+ Defaults to setting up remotes for all mirrors if none is specified.
116
+ TXT
117
+
118
+ examples <<-TXT
119
+ . braid setup local/dir
120
+ TXT
121
+
122
+ mixin :optional_path, :option_verbose
123
+
124
+ run {
125
+ Braid.verbose = verbose
126
+ Braid::Command.run(:setup, path)
127
+ }
128
+ }
129
+
130
+ mode(:diff) {
131
+ description <<-TXT
132
+ Show diff of local changes to mirror.
133
+ TXT
134
+
135
+ examples <<-TXT
136
+ . braid diff local/dir
137
+ TXT
138
+
139
+ mixin :argument_path, :option_verbose
140
+
141
+ run {
142
+ Braid::Command.run(:diff, path)
143
+ }
144
+ }
145
+
146
+ mode(:version) {
147
+ description 'Show braid version.'
148
+
149
+ run {
150
+ puts "braid #{Braid::VERSION}"
151
+ }
152
+ }
153
+
154
+ mixin(:argument_path) {
155
+ argument(:path) {
156
+ attr
157
+ }
158
+ }
159
+
160
+ mixin(:optional_path) {
161
+ argument(:path) {
162
+ optional
163
+ attr
164
+ }
165
+ }
166
+
167
+ mixin(:argument_url) {
168
+ argument(:url) {
169
+ attr
170
+ }
171
+ }
172
+
173
+ mixin(:option_type) {
174
+ option(:type, :t) {
175
+ optional
176
+ argument :required
177
+ desc 'mirror type'
178
+ attr
179
+ }
180
+ }
181
+
182
+ mixin(:option_branch) {
183
+ option(:branch, :b) {
184
+ optional
185
+ argument :required
186
+ desc 'remote branch name'
187
+ attr
188
+ }
189
+ }
190
+
191
+ mixin(:option_rails_plugin) {
192
+ option(:rails_plugin, :p) {
193
+ optional
194
+ desc 'added mirror is a Rails plugin'
195
+ attr
196
+ }
197
+ }
198
+
199
+ mixin(:option_rails_gem) {
200
+ option(:rails_gem, :p) {
201
+ optional
202
+ desc 'added mirror is a Rails gem'
203
+ attr
204
+ }
205
+ }
206
+
207
+ mixin(:option_revision) {
208
+ option(:revision, :r) {
209
+ optional
210
+ argument :required
211
+ desc 'revision to track'
212
+ attr
213
+ }
214
+ }
215
+
216
+ mixin(:option_head) {
217
+ option(:head) {
218
+ optional
219
+ desc 'mirror head'
220
+ attr
221
+ }
222
+ }
223
+
224
+ mixin(:option_full) {
225
+ option(:full) {
226
+ optional
227
+ desc 'include mirror history' # FIXME
228
+ attr
229
+ }
230
+ }
231
+
232
+ mixin(:option_verbose) {
233
+ option(:verbose, :v) {
234
+ optional
235
+ desc 'log shell commands'
236
+ attr
237
+ }
238
+ }
239
+
240
+ mixin(:option_keep_remote) {
241
+ option(:keep) {
242
+ optional
243
+ desc 'do not remove the remote'
244
+ attr
245
+ }
246
+ }
247
+
248
+ run { help! }
249
+ }
data/braid.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{braid}
3
+ s.version = "0.5.1"
4
+
5
+ s.specification_version = 2 if s.respond_to? :specification_version=
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Cristi Balan", "Norbert Crombach"]
9
+ s.date = %q{2008-10-29}
10
+ s.default_executable = %q{braid}
11
+ s.description = %q{A simple tool for tracking vendor branches in git.}
12
+ s.email = %q{evil@che.lu}
13
+ s.executables = ["braid"]
14
+ s.files = ["bin/braid", "braid.gemspec", "lib/braid/command.rb", "lib/braid/commands/add.rb", "lib/braid/commands/diff.rb", "lib/braid/commands/remove.rb", "lib/braid/commands/setup.rb", "lib/braid/commands/update.rb", "lib/braid/config.rb", "lib/braid/mirror.rb", "lib/braid/operations.rb", "lib/braid.rb", "LICENSE", "Rakefile", "README.textile", "test/braid_test.rb", "test/config_test.rb", "test/fixtures/shiny/README", "test/fixtures/skit1/layouts/layout.liquid", "test/fixtures/skit1/preview.png", "test/fixtures/skit1.1/layouts/layout.liquid", "test/fixtures/skit1.2/layouts/layout.liquid", "test/integration/adding_test.rb", "test/integration/updating_test.rb", "test/integration_helper.rb", "test/mirror_test.rb", "test/operations_test.rb", "test/test_helper.rb"]
15
+ s.has_rdoc = false
16
+ s.homepage = %q{http://evil.che.lu/projects/braid}
17
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "braid", "--main"]
18
+ s.require_paths = ["lib"]
19
+ s.rubyforge_project = %q{braid}
20
+ s.rubygems_version = %q{1.1.0}
21
+ s.summary = %q{A simple tool for tracking vendor branches in git.}
22
+
23
+ s.add_dependency(%q<main>, [">= 2.8.0"])
24
+ s.add_dependency(%q<open4>, [">= 0.9.6"])
25
+ end
@@ -0,0 +1,131 @@
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
+ private
42
+ def setup_remote(mirror)
43
+ Command.run(:setup, mirror.path)
44
+ end
45
+
46
+ def use_local_cache?
47
+ Braid.use_local_cache
48
+ end
49
+
50
+ def self.verify_git_version!
51
+ git.require_version!(REQUIRED_GIT_VERSION)
52
+ end
53
+
54
+ def bail_on_local_changes!
55
+ git.ensure_clean!
56
+ end
57
+
58
+ def with_reset_on_error
59
+ work_head = git.head
60
+
61
+ begin
62
+ yield
63
+ rescue => error
64
+ msg "Resetting to '#{work_head[0, 7]}'."
65
+ git.reset_hard(work_head)
66
+ raise error
67
+ end
68
+ end
69
+
70
+ def load_and_migrate_config
71
+ config = Config.new
72
+ unless config.valid?
73
+ msg "Configuration is outdated. Migrating."
74
+ bail_on_local_changes!
75
+ config.migrate!
76
+ git.commit("Upgrade .braids", "-- .braids")
77
+ end
78
+ config
79
+ end
80
+
81
+ def add_config_file
82
+ git.add(CONFIG_FILE)
83
+ end
84
+
85
+ def display_revision(mirror, revision = nil)
86
+ revision ||= mirror.revision
87
+ mirror.type == "svn" ? "r#{revision}" : "'#{revision[0, 7]}'"
88
+ end
89
+
90
+ def validate_new_revision(mirror, new_revision)
91
+ unless new_revision
92
+ unless mirror.type == "svn"
93
+ return git.rev_parse(mirror.remote)
94
+ else
95
+ return svn.head_revision(mirror.url)
96
+ end
97
+ end
98
+
99
+ unless mirror.type == "svn"
100
+ new_revision = git.rev_parse(new_revision)
101
+ else
102
+ new_revision = svn.clean_revision(new_revision)
103
+ end
104
+ old_revision = mirror.revision
105
+
106
+ if new_revision == old_revision
107
+ raise InvalidRevision, "mirror is already at requested revision"
108
+ end
109
+
110
+ if mirror.type == "svn"
111
+ if old_revision && new_revision < old_revision
112
+ raise InvalidRevision, "local revision is higher than request revision"
113
+ end
114
+
115
+ if svn.head_revision(mirror.url) < new_revision
116
+ raise InvalidRevision, "requested revision is higher than remote revision"
117
+ end
118
+ end
119
+
120
+ new_revision
121
+ end
122
+
123
+ def determine_target_revision(mirror, new_revision)
124
+ unless mirror.type == "svn"
125
+ git.rev_parse(new_revision)
126
+ else
127
+ git_svn.commit_hash(mirror.remote, new_revision)
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,48 @@
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
+
19
+ if mirror.type == "git-clone"
20
+ gitclone.add_gitignore(mirror.path)
21
+ mirror.rspec_git.update
22
+ else
23
+ mirror.fetch
24
+
25
+ new_revision = validate_new_revision(mirror, options["revision"])
26
+ target_revision = determine_target_revision(mirror, new_revision)
27
+
28
+ unless mirror.squashed?
29
+ git.merge_ours(target_revision)
30
+ end
31
+ git.read_tree_prefix(target_revision, mirror.path)
32
+
33
+ mirror.revision = new_revision
34
+ mirror.lock = new_revision if options["revision"]
35
+ end
36
+ config.update(mirror)
37
+ add_config_file
38
+
39
+ commit_message = "Added mirror '#{mirror.path}' at #{display_revision(mirror)}"
40
+
41
+ git.commit(commit_message)
42
+ msg commit_message
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,20 @@
1
+ module Braid
2
+ module Commands
3
+ class Diff < Command
4
+ def run(path)
5
+ mirror = config.get!(path)
6
+ if mirror.type == "git-clone"
7
+ unless system("cd #{mirror.path} && git diff")
8
+ msg "Error diffing \"#{path}\" in \"#{mirror.path}\""
9
+ exit 1
10
+ end
11
+ else
12
+ setup_remote(mirror)
13
+
14
+ diff = mirror.diff
15
+ puts diff unless diff.empty?
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,40 @@
1
+ module Braid
2
+ module Commands
3
+ class Remove < Command
4
+ def run(path, options = {})
5
+ mirror = config.get!(path)
6
+
7
+ bail_on_local_changes!
8
+
9
+ with_reset_on_error do
10
+ msg "Removing mirror from '#{mirror.path}'."
11
+
12
+ if mirror.type == "git-clone"
13
+ gitclone.remove_gitignore(mirror.path)
14
+ FileUtils.rm_rf(mirror.path)
15
+ config.remove(mirror)
16
+ add_config_file
17
+ else
18
+ git.rm_r(mirror.path)
19
+
20
+ config.remove(mirror)
21
+ add_config_file
22
+
23
+ if options[:keep]
24
+ msg "Not removing remote '#{mirror.remote}'" if verbose?
25
+ elsif git.remote_url(mirror.remote)
26
+ msg "Removed remote '#{mirror.path}'" if verbose?
27
+ git.remote_rm mirror.remote
28
+ else
29
+ msg "Remote '#{mirror.remote}' not found, nothing to cleanup" if verbose?
30
+ end
31
+ end
32
+
33
+ commit_message = "Removed mirror '#{mirror.path}'"
34
+ git.commit(commit_message)
35
+ msg commit_message
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end