buildr 1.4.15 → 1.4.16

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,296 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # Licensed to the Apache Software Foundation (ASF) under one or more
3
- # contributor license agreements. See the NOTICE file distributed with this
4
- # work for additional information regarding copyright ownership. The ASF
5
- # licenses this file to you under the Apache License, Version 2.0 (the
6
- # "License"); you may not use this file except in compliance with the License.
7
- # You may obtain a copy of the License at
8
- #
9
- # http://www.apache.org/licenses/LICENSE-2.0
10
- #
11
- # Unless required by applicable law or agreed to in writing, software
12
- # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
- # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
- # License for the specific language governing permissions and limitations under
15
- # the License.
16
-
17
- require 'optparse'
18
- require 'ostruct'
19
- require 'fileutils'
20
-
21
- module GitFlow
22
- extend self
23
-
24
- attr_accessor :should_run, :trace, :program
25
-
26
- self.program = 'gitflow'
27
- self.should_run = true # should we run at exit?
28
-
29
- HELP = <<-HELP
30
-
31
- GitFlow is a tool to create custom git commands implemented in ruby.
32
- It is generic enougth to be used on any git based project besides Apache Buildr.
33
-
34
- OVERVIEW:
35
-
36
- gitflow is intended to help developers with their daily git workflow,
37
- performing repetitive git commands for them. It is implemented in
38
- ruby so you can do anything, from invoking rake tasks to telling
39
- people on twitter you are having trouble with their code :P.
40
-
41
- To get help for a specific command use:
42
- gitflow.rb help command
43
- gitflow.rb command --help
44
-
45
- For convenience you can create an alias to be execute using git.
46
- The following example registers buildr-git.rb, which provides apache
47
- svn and git synchronization commands:
48
-
49
- git config alias.apache '!'"ruby $PWD/doc/scripts/buildr-git.rb"
50
-
51
- After that you can use
52
- git apache command --help
53
-
54
- EXTENDING YOUR WORKFLOW:
55
-
56
- You can create your own gitflow commands, to adapt your development
57
- workflow.
58
-
59
- Simply create a ruby script somewhere say ~/.buildr/gitflow.rb
60
- And alias it in your local repo:
61
-
62
- git config alias.flow '!'"ruby ~/.buildr/gitflow.rb"
63
- git config alias.work '!'"ruby ~/.buildr/gitflow.rb my-flow sub-work"
64
-
65
- A sample command would look like this.. (you may want to look at buildr-git.rb)
66
-
67
- #!/usr/bin/env ruby
68
- require /path/to/gitflow.rb
69
-
70
- class MyCommand < GitFlow/'my-flow'
71
-
72
- @help = "Summary to be displayed when listing commands"
73
- @documentation = "Very long help that will be paged if necessary. (for --help)"
74
-
75
- # takes an openstruct to place default values and option values.
76
- # returns an array of arguments given to optparse.on
77
- def options(opts)
78
- opts.something = 'default'
79
- [
80
- ['--name NAME', lambda { |n| opts.name = n }],
81
- ['--yes', lambda { |n| opts.yes = true }]
82
- ]
83
- end
84
-
85
- # takes the opts openstruct after options have been parsed and
86
- # an argv array with non-option arguments.
87
- def execute(opts, argv)
88
- # you can run another command using
89
- run('other-command', '--using-this', 'arg')
90
- some = git('config', '--get', 'some.property').chomp rescue nil
91
- page { puts "This will be paged on terminal if needed" }
92
- end
93
-
94
- class SubCommand < MyCommand/'sub-work'
95
- ... # implement a subcommand
96
- end
97
-
98
- end
99
-
100
- You would then get help for your command with
101
-
102
- git flow my-flow --help
103
- git work --help
104
-
105
- Using gitflow you can customize per-project git interface.
106
-
107
- HELP
108
-
109
- # Pager from http://nex-3.com/posts/73-git-style-automatic-paging-in-ruby
110
- def pager
111
- return if RUBY_PLATFORM =~ /win32/
112
- return unless STDOUT.tty?
113
-
114
- read, write = IO.pipe
115
-
116
- unless Kernel.fork # Child process
117
- STDOUT.reopen(write)
118
- STDERR.reopen(write) if STDERR.tty?
119
- read.close
120
- write.close
121
- return
122
- end
123
-
124
- # Parent process, become pager
125
- STDIN.reopen(read)
126
- read.close
127
- write.close
128
-
129
- ENV['LESS'] = 'FSRX' # Don't page if the input is short enough
130
-
131
- Kernel.select [STDIN] # Wait until we have input before we start the pager
132
- pager = ENV['PAGER'] || 'less'
133
- exec pager rescue exec '/bin/sh', '-c', pager
134
- end
135
-
136
- # Return a class to be extended in order to register a GitFlow command
137
- # if command name is nil, it will be registered as the top level command.
138
- # Classes implementing commands also provide this method, allowing for
139
- # sub-command creation.
140
- def /(command_name)
141
- command_name = command_name.to_s unless command_name.nil?
142
- cls = Class.new { include GitFlow::Mixin }
143
- (class << cls; self; end).module_eval do
144
- attr_accessor :help, :documentation, :command
145
- define_method(:/) do |subcommand|
146
- raise "Subcommand cannot be nil" unless subcommand
147
- GitFlow/([command_name, subcommand].compact.join(' '))
148
- end
149
- define_method(:inherited) do |subclass|
150
- subclass.command = command_name
151
- GitFlow.commands[command_name] = subclass
152
- end
153
- end
154
- cls
155
- end
156
-
157
- def commands
158
- @commands ||= Hash.new
159
- end
160
-
161
- def optparse
162
- optparse = opt = OptionParser.new
163
- opt.separator ' '
164
- opt.separator 'OPTIONS'
165
- opt.separator ' '
166
- opt.on('-h', '--help', 'Display this help') do
167
- GitFlow.pager; puts opt; throw :exit
168
- end
169
- opt.on('--trace', 'Display traces') { GitFlow.trace = true }
170
- optparse
171
- end
172
-
173
- def command(argv)
174
- cmds = []
175
- argv.each_with_index do |arg, i|
176
- arg = argv[0..i].join(' ')
177
- cmds << commands[arg] if commands.key?(arg)
178
- end
179
- cmds.last || commands[nil]
180
- end
181
-
182
- def run(*argv)
183
- catch :exit do
184
- command = self.command(argv).new
185
- argv = argv[command.class.command.split.length..-1] if command.class.command
186
- parser = optparse
187
- parser.banner = "Usage: #{GitFlow.program} #{command.class.command} [options]"
188
- options = OpenStruct.new
189
- if command.respond_to?(:options)
190
- command.options(options).each { |args| parser.on(*args) }
191
- end
192
- if command.class.documentation && command.class.documentation != ''
193
- parser.separator ' '
194
- parser.separator command.class.documentation.split(/\n/)
195
- end
196
- parser.parse!(argv)
197
- command.execute(options, argv)
198
- end
199
- end
200
-
201
- module Mixin
202
- include FileUtils
203
-
204
- # Override this method in your command class if it
205
- # needs to parse command line options.
206
- #
207
- # This method takes an openstruct object as argument
208
- # allowing you to store default values on it, and
209
- # set option values.
210
- #
211
- # The return value must be an array of arguments
212
- # given to optparse.on
213
- def options(opt)
214
- []
215
- end
216
-
217
- # Override this method in your command class to implement
218
- # the command.
219
- # First argument is the openstruct object after
220
- # it has been populated by the option parser.
221
- # Second argument is the array of non-option arguments.
222
- def execute(opt, argv)
223
- fail "#{self.class.command} not implemented"
224
- end
225
-
226
- # Run the command line given on argv
227
- def run(*argv, &block)
228
- GitFlow.run(*argv, &block)
229
- end
230
-
231
- # Yield paging the blocks output if necessary.
232
- def page
233
- GitFlow.pager
234
- yield
235
- end
236
-
237
- def trace(*str)
238
- STDERR.puts(*str) if GitFlow.trace
239
- end
240
-
241
- def git(*args)
242
- cmd = 'git ' + args.map { |arg| arg[' '] ? %Q{"#{arg}"} : arg }.join(' ')
243
- trace cmd
244
- `#{cmd}`.tap {
245
- fail "GIT command `#{cmd}` failed with status #{$?.exitstatus}" unless $?.exitstatus == 0
246
- }
247
- end
248
-
249
- def sh(*args)
250
- `#{args.join(' ')}`.tap {
251
- fail "Shell command `#{args.join(' ')}` failed with status #{$?.exitstatus}" unless $?.exitstatus == 0
252
- }
253
- end
254
-
255
- def expand_path(path, dir=Dir.pwd)
256
- File.expand_path(path, dir)
257
- end
258
- end
259
-
260
- class NoSuchCommand < GitFlow/nil
261
- @documentation = HELP
262
-
263
- def execute(opts, argv)
264
- page do
265
- puts "Command not found: #{argv.join(' ').inspect}"
266
- puts "Try `#{GitFlow.program} help` to obtain a list of commands."
267
- end
268
- end
269
- end
270
-
271
- class HelpCommand < GitFlow/:help
272
- @help = "Display help for a command or show command list"
273
- @documentation = "Displays help for the command given as argument"
274
-
275
- def execute(opts, argv)
276
- if argv.empty?
277
- opt = GitFlow.optparse
278
- opt.banner = "Usage: #{GitFlow.program} command [options]"
279
- opt.separator ' '
280
- opt.separator 'COMMANDS'
281
- opt.separator ' '
282
- commands = GitFlow.commands.map { |name, cls| [nil, name, cls.help] }.
283
- sort_by { |a| a[1] || '' }
284
- commands.each { |a| opt.separator("%-2s%-25s%s" % a) if a[1] }
285
- opt.separator ' '
286
- opt.separator 'You can also obtain help for any command giving it --help.'
287
- page { puts opt }
288
- else
289
- run(*(argv + ['--help']))
290
- end
291
- end
292
- end
293
-
294
- end
295
-
296
- at_exit { GitFlow.run(*ARGV) if GitFlow.should_run }