git-trac 0.0.20080206 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README +39 -24
- data/Rakefile +3 -2
- data/lib/git/trac.rb +1 -0
- data/lib/git/trac/attachment.rb +17 -11
- data/lib/git/trac/pager.rb +33 -11
- data/lib/git/trac/repository.rb +54 -3
- data/lib/git/trac/runner.rb +139 -65
- data/lib/git/trac/runner/apply.rb +14 -18
- data/lib/git/trac/runner/checkout.rb +81 -0
- data/lib/git/trac/runner/cleanup.rb +18 -9
- data/lib/git/trac/runner/fetch.rb +34 -28
- data/lib/git/trac/runner/help.rb +141 -0
- data/lib/git/trac/runner/push.rb +79 -0
- data/lib/git/trac/runner/show.rb +55 -8
- data/lib/git/trac/ticket.rb +14 -48
- data/lib/git/trac/version.rb +11 -0
- metadata +14 -12
- data/lib/git/trac/runner/download.rb +0 -44
- data/lib/git/trac/runner/upload_patch.rb +0 -62
data/README
CHANGED
@@ -1,24 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
1
|
+
= git-trac
|
2
|
+
|
3
|
+
git-trac takes the repetition out of working with trac and git-svn. Easily
|
4
|
+
download a patch, apply it at the right point in time, turn it into a commit
|
5
|
+
with useful metadata, and check it out into a branch, all in one command.
|
6
|
+
Created for (but not limited to) work on the Ruby on Rails core.
|
7
|
+
|
8
|
+
== Usage
|
9
|
+
|
10
|
+
Running `git-trac help` gives you access to usage information, including
|
11
|
+
information about how to use the help command to get more help.
|
12
|
+
|
13
|
+
== Examples
|
14
|
+
|
15
|
+
Run `git-trac help rails` for a quick start guide for the Ruby on Rails core.
|
16
|
+
|
17
|
+
== License
|
18
|
+
|
19
|
+
git-trac is available under an MIT-style license.
|
20
|
+
|
21
|
+
:include: MIT-LICENSE
|
22
|
+
|
23
|
+
== History
|
24
|
+
|
25
|
+
See the NEWS file for a version history.
|
26
|
+
|
27
|
+
== About
|
28
|
+
|
29
|
+
Author:: Tim Pope <ruby at tpope. info>
|
30
|
+
Home Page:: http://git-trac.rubyforge.org
|
31
|
+
|
32
|
+
== Feedback
|
33
|
+
|
34
|
+
Feedback welcome and appreciated. While I intend for git-trac to be
|
35
|
+
applicable to a wide variety of projects and setups, in practice it has been
|
36
|
+
tested primarily on a git-svn clone of the Rails core and the official Rails
|
37
|
+
trac while running Debian with one of a few recent versions of git. If
|
38
|
+
altering any combination of these variables does not work for you, please
|
39
|
+
report it.
|
data/Rakefile
CHANGED
@@ -13,7 +13,7 @@ require File.join(File.dirname(__FILE__), 'lib', 'git', 'trac')
|
|
13
13
|
|
14
14
|
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
|
15
15
|
PKG_NAME = 'git-trac'
|
16
|
-
PKG_VERSION =
|
16
|
+
PKG_VERSION = Git::Trac::VERSION::STRING
|
17
17
|
PKG_FILE_NAME = "#{PKG_NAME}-#{PKG_VERSION}"
|
18
18
|
# PKG_DESTINATION = ENV["PKG_DESTINATION"] || "../#{PKG_NAME}"
|
19
19
|
|
@@ -39,6 +39,7 @@ Rake::RDocTask.new { |rdoc|
|
|
39
39
|
rdoc.rdoc_dir = 'doc'
|
40
40
|
rdoc.rdoc_files.add('lib')
|
41
41
|
rdoc.rdoc_files.add('README')
|
42
|
+
rdoc.rdoc_files.add('NEWS')
|
42
43
|
rdoc.main = "README"
|
43
44
|
rdoc.title = "git-trac"
|
44
45
|
rdoc.options << '--inline-source'
|
@@ -50,7 +51,7 @@ spec = Gem::Specification.new do |s|
|
|
50
51
|
s.platform = Gem::Platform::RUBY
|
51
52
|
s.name = PKG_NAME
|
52
53
|
s.summary = 'Interact with trac from a git repository pulled from svn'
|
53
|
-
s.description = 'git-trac takes the repetition out of working with trac and git-svn.
|
54
|
+
s.description = 'git-trac takes the repetition out of working with trac and git-svn. Easily download a patch, apply it at the right point in time, turn it into a commit with useful metadata, and check it out into a branch, all in one command. Created for (but not limited to) work on the Ruby on Rails core.'
|
54
55
|
s.version = PKG_VERSION
|
55
56
|
|
56
57
|
s.author = 'Tim Pope'
|
data/lib/git/trac.rb
CHANGED
data/lib/git/trac/attachment.rb
CHANGED
@@ -39,10 +39,10 @@ module Git
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def email
|
42
|
-
if user =~
|
43
|
-
return user
|
44
|
-
elsif user =~ /<(\S*@\S*)>/
|
42
|
+
if user =~ /<(\S*@\S*)>/
|
45
43
|
return $1
|
44
|
+
elsif user =~ /\S*@\S*/
|
45
|
+
return user
|
46
46
|
else
|
47
47
|
[user, repository.url[%r{://([^/]*)},1]].compact.join("@")
|
48
48
|
end
|
@@ -52,8 +52,9 @@ module Git
|
|
52
52
|
time.utc.strftime("%Y-%m-%d_%H:%M:%S_+0000")
|
53
53
|
end
|
54
54
|
|
55
|
-
def url
|
56
|
-
"
|
55
|
+
def url(format = :raw)
|
56
|
+
query = "?format=#{format}" if format
|
57
|
+
"#{ticket.repository.url}/attachment/ticket/#{ticket.number}/#{filename}#{query}"
|
57
58
|
end
|
58
59
|
|
59
60
|
def tag_name
|
@@ -65,7 +66,7 @@ module Git
|
|
65
66
|
end
|
66
67
|
|
67
68
|
def body
|
68
|
-
@body ||= repository.agent.get_file(url)
|
69
|
+
@body ||= repository.agent.get_file(url(:raw))
|
69
70
|
end
|
70
71
|
|
71
72
|
def repository
|
@@ -78,8 +79,8 @@ module Git
|
|
78
79
|
|
79
80
|
def cleanup(options = {})
|
80
81
|
repository.each_ref("refs/remotes/#{tag_name}") do |object, ref|
|
81
|
-
repository.exec("git","update-ref","-d",ref,object)
|
82
|
-
repository.cleanup_branches(object)
|
82
|
+
repository.exec("git","update-ref","-d",ref,object) unless options[:only_branches]
|
83
|
+
repository.cleanup_branches(options, object)
|
83
84
|
return object
|
84
85
|
end
|
85
86
|
end
|
@@ -88,9 +89,13 @@ module Git
|
|
88
89
|
cleanup(options)
|
89
90
|
FileUtils.mkdir_p(ticket.trac_dir)
|
90
91
|
repository.with_index("tracindex#{$$}") do
|
91
|
-
parent = repository.exec("git","rev-list","--max-count=1","--before=#{timestamp}",options[:
|
92
|
+
parent = repository.exec("git","rev-list","--max-count=1","--before=#{timestamp}",options[:upstream] || 'refs/remotes/trunk').chomp
|
92
93
|
repository.exec("git","read-tree",parent)
|
93
|
-
applied = patch.apply(options.merge(:cached => true))
|
94
|
+
applied = patch.apply(options.merge(:cached => true))
|
95
|
+
unless applied
|
96
|
+
yield self, nil, nil
|
97
|
+
return
|
98
|
+
end
|
94
99
|
tree = repository.exec("git","write-tree").chomp
|
95
100
|
ENV["GIT_AUTHOR_NAME"] = ENV["GIT_COMMITTER_NAME"] = username
|
96
101
|
ENV["GIT_AUTHOR_EMAIL"] = ENV["GIT_COMMITTER_EMAIL"] = email
|
@@ -104,7 +109,8 @@ module Git
|
|
104
109
|
File.open(tag_path,"w") do |f|
|
105
110
|
f.puts commit
|
106
111
|
end
|
107
|
-
|
112
|
+
yield self, applied, commit
|
113
|
+
return commit
|
108
114
|
end
|
109
115
|
ensure
|
110
116
|
%w(GIT_AUTHOR_NAME GIT_COMMITTER_NAME GIT_AUTHOR_EMAIL GIT_COMMITTER_EMAIL GIT_AUTHOR_DATE GIT_COMMITTER_DATE).each {|e| ENV[e] = nil}
|
data/lib/git/trac/pager.rb
CHANGED
@@ -2,6 +2,18 @@ module Git
|
|
2
2
|
module Trac
|
3
3
|
|
4
4
|
class Repository
|
5
|
+
def pager(body, diff = false)
|
6
|
+
pager = Pager.new(ENV["GIT_PAGER"] || config("core","pager"))
|
7
|
+
if pager.command
|
8
|
+
diff &&= !%w(false no 0).include?(config("color","pager").to_s.downcase)
|
9
|
+
end
|
10
|
+
diff &&= %w(true yes 1 always auto).include?(config("color","diff").to_s.downcase)
|
11
|
+
pager.page(body, diff)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
class Pager
|
5
17
|
|
6
18
|
DIFF_COLORS = {
|
7
19
|
:reset => "\033[m",
|
@@ -14,27 +26,37 @@ module Git
|
|
14
26
|
:whitespace => "\033[41m"
|
15
27
|
}
|
16
28
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
29
|
+
attr_reader :command
|
30
|
+
|
31
|
+
def initialize(command = nil)
|
32
|
+
@command = command || ENV["PAGER"] || "less"
|
33
|
+
@command = nil if @command.empty?
|
34
|
+
end
|
35
|
+
|
36
|
+
def page(body, diff = false)
|
37
|
+
less = ENV["LESS"]
|
21
38
|
ENV["LESS"] ||= "FRSX"
|
22
39
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
40
|
+
return $stdout.puts(body) unless $stdout.tty?
|
41
|
+
|
42
|
+
if command.nil?
|
43
|
+
output_to_io($stdout, body, diff)
|
44
|
+
else
|
45
|
+
IO.popen(command, "w") do |io|
|
46
|
+
output_to_io(io, body, diff)
|
28
47
|
end
|
29
48
|
end
|
49
|
+
|
30
50
|
rescue Errno::EPIPE
|
31
51
|
# Pager was terminated
|
52
|
+
ensure
|
53
|
+
ENV["LESS"] = less
|
32
54
|
end
|
33
55
|
|
34
56
|
private
|
35
57
|
|
36
|
-
def
|
37
|
-
if
|
58
|
+
def output_to_io(io, body, diff)
|
59
|
+
if diff
|
38
60
|
state = nil
|
39
61
|
body.each_line do |line|
|
40
62
|
if state.nil? && line !~ /^(diff|Index:) /
|
data/lib/git/trac/repository.rb
CHANGED
@@ -138,6 +138,12 @@ module Git
|
|
138
138
|
options[:url] || config("svn-remote.svn",:url).to_s[%r{(http://.*)/svn},1]
|
139
139
|
end
|
140
140
|
|
141
|
+
def get_response(uri)
|
142
|
+
require 'net/http'
|
143
|
+
require 'uri'
|
144
|
+
Net::HTTP.get_response(URI.parse(uri))
|
145
|
+
end
|
146
|
+
|
141
147
|
def agent
|
142
148
|
unless defined?(@agent)
|
143
149
|
unless url
|
@@ -192,15 +198,32 @@ module Git
|
|
192
198
|
hash
|
193
199
|
end
|
194
200
|
|
195
|
-
def cleanup_branches(*revs)
|
201
|
+
def cleanup_branches(options, *revs)
|
196
202
|
return if revs.empty?
|
203
|
+
diff_hashes = revs.map {|r| diff_hash(r)}.compact if options[:rebased]
|
204
|
+
current = current_checkout
|
197
205
|
each_ref("refs/heads") do |object, ref|
|
198
|
-
if
|
199
|
-
|
206
|
+
if current != File.basename(ref)
|
207
|
+
if revs.include?(object)
|
208
|
+
exec("git","branch","-D",File.basename(ref))
|
209
|
+
elsif diff_hashes && diff_hashes.include?(dh = diff_hash(ref))
|
210
|
+
p "wooo!"
|
211
|
+
exec("git","branch","-D",File.basename(ref))
|
212
|
+
end
|
200
213
|
end
|
201
214
|
end
|
202
215
|
end
|
203
216
|
|
217
|
+
def diff_hash(head)
|
218
|
+
require 'digest/sha1'
|
219
|
+
guess = guess_upstream(head)
|
220
|
+
return unless guess
|
221
|
+
diff = exec("git","diff","#{guess}...#{head}")
|
222
|
+
diff.gsub!(/^(?:index |@@ -).*\n/,'')
|
223
|
+
diff.gsub!(/[[:space:]]/,'')
|
224
|
+
Digest::SHA1.digest(diff)
|
225
|
+
end
|
226
|
+
|
204
227
|
# See if the current commit or an ancestor was previously tagged as a
|
205
228
|
# trac ticket. Also check git config branch.branchname.tracticket
|
206
229
|
def guess_current_ticket_number
|
@@ -215,6 +238,34 @@ module Git
|
|
215
238
|
end
|
216
239
|
end
|
217
240
|
|
241
|
+
def guess_upstream(head = "HEAD")
|
242
|
+
svn = config("svn-remote.svn")
|
243
|
+
return unless (svn||{})[:url]
|
244
|
+
branch = popen3("git","log","--no-color",head) do |i,o,e|
|
245
|
+
o.each_line do |line|
|
246
|
+
next unless line.gsub!(/^\s*git-svn-id:\s*/,'')
|
247
|
+
url, uuid = line.chomp.split(" ")
|
248
|
+
url.sub!(/^#{Regexp.escape(svn[:url])}\/*/,'')
|
249
|
+
branch, revision = url.split("@")
|
250
|
+
break branch
|
251
|
+
end
|
252
|
+
end
|
253
|
+
if branch
|
254
|
+
trunk = svn[:trunk] || "trunk:refs/remotes/trunk"
|
255
|
+
branches = svn[:branches] || "branches/*:refs/remotes/*"
|
256
|
+
tags = svn[:tags] || "tags/*:refs/remotes/tags/*"
|
257
|
+
[trunk, branches, tags].each do |pair|
|
258
|
+
remote, local = pair.split(":",2)
|
259
|
+
next if local.to_s.empty?
|
260
|
+
before, after = remote.split("*",2)
|
261
|
+
if branch =~ /^#{Regexp.escape(before)}(.*)#{Regexp.escape(after.to_s)}/
|
262
|
+
return local.sub(/\*/,$1)
|
263
|
+
end
|
264
|
+
end
|
265
|
+
svn["branches"].to_s
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
218
269
|
# Fetch a ticket object by number.
|
219
270
|
def ticket(number)
|
220
271
|
Ticket.new(self, number)
|
data/lib/git/trac/runner.rb
CHANGED
@@ -10,7 +10,50 @@ module Git
|
|
10
10
|
|
11
11
|
class Runner #:nodoc:
|
12
12
|
|
13
|
-
|
13
|
+
def self.for_command(command)
|
14
|
+
klass_name = command.to_s.capitalize.gsub(/-(.)/) { $1.upcase }
|
15
|
+
if klass_name =~ /^[A-Z]\w*$/ && const_defined?(klass_name)
|
16
|
+
klass = const_get(klass_name)
|
17
|
+
if klass < Base
|
18
|
+
return klass
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.commands
|
24
|
+
Runner.constants.map {|c| Runner.const_get(c)}.select {|c| c < Runner::Base}.sort_by {|r| r.command}.uniq
|
25
|
+
end
|
26
|
+
|
27
|
+
module Fetchable #:nodoc:
|
28
|
+
|
29
|
+
def add_options(opts)
|
30
|
+
super
|
31
|
+
opts.on("--against BRANCH","apply against branch BRANCH") do |b|
|
32
|
+
options[:upstream] = b
|
33
|
+
end
|
34
|
+
opts.on("--depth NUM","search depth (see git-trac help apply)") do |n|
|
35
|
+
options[:depth] = n
|
36
|
+
end
|
37
|
+
opts.on("--root DIR","apply patches relative to DIR") do |dir|
|
38
|
+
options[:root] = dir
|
39
|
+
end
|
40
|
+
add_local_option(opts)
|
41
|
+
end
|
42
|
+
|
43
|
+
def run
|
44
|
+
options[:upstream] ||= repository.guess_upstream || "refs/remotes/trunk"
|
45
|
+
fetch_unless_local
|
46
|
+
attachment = one_attachment
|
47
|
+
fetch_or_abort(attachment)
|
48
|
+
repository.in_work_tree do
|
49
|
+
after_fetch(attachment)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def after_fetch(attachment)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
14
57
|
|
15
58
|
def initialize(argv)
|
16
59
|
@argv = argv.dup
|
@@ -18,6 +61,8 @@ module Git
|
|
18
61
|
rescue Git::Trac::Error
|
19
62
|
$stderr.puts "Error: " + $!.message
|
20
63
|
exit 1
|
64
|
+
rescue Interrupt
|
65
|
+
$stderr.puts "Interrupted!"
|
21
66
|
end
|
22
67
|
|
23
68
|
def abort(message)
|
@@ -27,43 +72,22 @@ module Git
|
|
27
72
|
def general_usage
|
28
73
|
$stderr.puts <<-EOS
|
29
74
|
Usage: git-trac <command> [options] [arguments]
|
30
|
-
|
31
|
-
Available commands:
|
32
|
-
apply Apply a patch directly to the work tree
|
33
|
-
cleanup Remove old branches for a ticket
|
34
|
-
download Download all patches for a ticket to the cwd
|
35
|
-
fetch Create brances for all patches of a ticket
|
36
|
-
show Show a summary of a ticket
|
37
|
-
upload-patch Upload the current diff against trunk to a ticket
|
75
|
+
See `git-trac help` for details.
|
38
76
|
EOS
|
39
77
|
exit 1
|
40
78
|
end
|
41
79
|
|
42
80
|
def run
|
43
81
|
|
44
|
-
command = @argv.shift
|
82
|
+
command = @argv.shift unless %w(-v --version).include?(@argv.first)
|
45
83
|
repo = nil
|
46
84
|
if command == "--repository"
|
47
85
|
repo, command = @argv.shift, @argv.shift
|
48
86
|
end
|
87
|
+
command = "help" if %w(-h --help).include?(command)
|
49
88
|
|
50
|
-
if command
|
51
|
-
|
52
|
-
@argv.unshift "--help"
|
53
|
-
end
|
54
|
-
general_usage unless command
|
55
|
-
|
56
|
-
@repository = Git::Trac::Repository.new(repo)
|
57
|
-
unless @repository.url || @argv.first == "--help"
|
58
|
-
abort "no URL. Try `git config trac.url http://trac-url`"
|
59
|
-
end
|
60
|
-
|
61
|
-
klass_name = command.capitalize.gsub(/-(.)/) { $1.upcase }
|
62
|
-
if klass_name =~ /^[A-Z]\w*$/ && self.class.const_defined?(klass_name)
|
63
|
-
klass = self.class.const_get(klass_name)
|
64
|
-
if klass < Base
|
65
|
-
return klass.new(@argv, @repository)
|
66
|
-
end
|
89
|
+
if klass = Runner.for_command(command || "help")
|
90
|
+
return klass.new(@argv, repo)
|
67
91
|
end
|
68
92
|
|
69
93
|
general_usage
|
@@ -72,13 +96,17 @@ Available commands:
|
|
72
96
|
|
73
97
|
class Base #:nodoc:
|
74
98
|
|
75
|
-
attr_reader :options
|
76
|
-
|
77
99
|
def initialize(argv, repo)
|
78
|
-
@argv, @
|
79
|
-
@options = repo.config("trac") || {}
|
100
|
+
@argv, @repository_option = argv, repo
|
80
101
|
@opts = OptionParser.new
|
81
|
-
@opts.banner = "Usage: git-trac #{command} #{banner_arguments}
|
102
|
+
@opts.banner = "Usage: git-trac #{self.class.command} #{banner_arguments}"
|
103
|
+
@opts.version = Git::Trac::VERSION::STRING
|
104
|
+
@opts.base.long["help"] = OptionParser::Switch::NoArgument.new do
|
105
|
+
help = @opts.help.chomp.chomp + "\n"
|
106
|
+
help += "\n#{description}" if description
|
107
|
+
Pager.new.page(help)
|
108
|
+
exit
|
109
|
+
end
|
82
110
|
@opts.separator("")
|
83
111
|
add_options(@opts)
|
84
112
|
begin
|
@@ -89,35 +117,63 @@ Available commands:
|
|
89
117
|
run
|
90
118
|
end
|
91
119
|
|
120
|
+
def repository
|
121
|
+
@repository ||= Git::Trac::Repository.new(@repository_option)
|
122
|
+
unless @repository.url
|
123
|
+
abort "no URL. Try `git config trac.url http://trac-url`"
|
124
|
+
end
|
125
|
+
@repository
|
126
|
+
end
|
127
|
+
|
128
|
+
def options
|
129
|
+
@options ||= repository.config("trac") || {}
|
130
|
+
end
|
131
|
+
|
92
132
|
def description
|
93
133
|
end
|
94
134
|
|
95
|
-
def
|
96
|
-
|
97
|
-
|
98
|
-
elsif number = @repository.guess_current_ticket_number
|
99
|
-
number
|
100
|
-
elsif block_given?
|
101
|
-
yield
|
102
|
-
else
|
103
|
-
abort "ticket number required"
|
135
|
+
def system(*args)
|
136
|
+
repository.in_work_tree do
|
137
|
+
Kernel.system(*args) or exit $?.exitstatus
|
104
138
|
end
|
105
139
|
end
|
106
140
|
|
107
|
-
def
|
108
|
-
if
|
109
|
-
|
110
|
-
|
111
|
-
abort "
|
141
|
+
def parse_attachment(arg)
|
142
|
+
if match_data = arg.to_s.match(/\b(\d+)\b(?:\/([^?\/]+))?/)
|
143
|
+
return Integer(match_data[1]), match_data[2]
|
144
|
+
else
|
145
|
+
abort "invalid argument '#{arg}'"
|
112
146
|
end
|
113
|
-
|
114
|
-
|
115
|
-
|
147
|
+
end
|
148
|
+
|
149
|
+
def one_attachment(abort_when_extra = true)
|
150
|
+
missing_argument if @argv.empty?
|
151
|
+
number, filename = parse_attachment(@argv.shift)
|
152
|
+
too_many_arguments if abort_when_extra && @argv.any?
|
153
|
+
return repository.ticket(number).attachment(filename)
|
154
|
+
end
|
155
|
+
|
156
|
+
def each_ticket_or_attachment(abort_when_missing = true)
|
157
|
+
missing_argument if abort_when_missing && @argv.empty?
|
158
|
+
until @argv.empty?
|
159
|
+
number, filename = parse_attachment(@argv.shift)
|
160
|
+
ticket = repository.ticket(number)
|
161
|
+
if filename
|
162
|
+
yield ticket.attachment(filename)
|
163
|
+
else
|
164
|
+
yield ticket
|
165
|
+
end
|
116
166
|
end
|
117
167
|
end
|
118
168
|
|
119
|
-
def
|
120
|
-
|
169
|
+
def each_attachment(abort_when_missing = true)
|
170
|
+
each_ticket_or_attachment(abort_when_missing) do |object|
|
171
|
+
if object.respond_to?(:attachments)
|
172
|
+
object.attachments.each {|a| yield a}
|
173
|
+
else
|
174
|
+
yield attachment
|
175
|
+
end
|
176
|
+
end
|
121
177
|
end
|
122
178
|
|
123
179
|
def abort(message)
|
@@ -125,6 +181,24 @@ Available commands:
|
|
125
181
|
exit(1)
|
126
182
|
end
|
127
183
|
|
184
|
+
def too_many_arguments
|
185
|
+
abort "too many arguments"
|
186
|
+
end
|
187
|
+
|
188
|
+
def missing_argument(label = "attachment")
|
189
|
+
abort "#{label} expected but none given"
|
190
|
+
end
|
191
|
+
|
192
|
+
def fetch_or_abort(attachment)
|
193
|
+
branch = options[:upstream] || repository.guess_upstream || "refs/remotes/trunk"
|
194
|
+
attachment.fetch(options) do |a, dir, commit|
|
195
|
+
unless dir
|
196
|
+
abort "failed to apply #{attachment.tag_name} to #{branch.sub(/^refs\/(?:remotes\/)?/,'')}"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
attachment
|
200
|
+
end
|
201
|
+
|
128
202
|
def add_options(opts)
|
129
203
|
end
|
130
204
|
|
@@ -132,8 +206,12 @@ Available commands:
|
|
132
206
|
"[options]"
|
133
207
|
end
|
134
208
|
|
209
|
+
def self.command
|
210
|
+
name[/[^:]*$/].gsub(/(.)([A-Z])/) { $1+"-"+$2 }.downcase
|
211
|
+
end
|
212
|
+
|
135
213
|
def command
|
136
|
-
self.class.
|
214
|
+
self.class.command
|
137
215
|
end
|
138
216
|
|
139
217
|
def add_local_option(opts)
|
@@ -144,17 +222,12 @@ Available commands:
|
|
144
222
|
|
145
223
|
def fetch_unless_local
|
146
224
|
unless options[:local]
|
147
|
-
if
|
148
|
-
|
149
|
-
elsif
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
154
|
-
@repository.in_work_tree do
|
155
|
-
unless system(command)
|
156
|
-
abort "#{command} failed (use --local to skip)"
|
157
|
-
end
|
225
|
+
if options[:fetch_command]
|
226
|
+
system(options[:fetch_command])
|
227
|
+
elsif repository.config("svn-remote.svn")
|
228
|
+
system("git svn fetch")
|
229
|
+
elsif repository.config("origin")
|
230
|
+
system("git fetch origin")
|
158
231
|
end
|
159
232
|
end
|
160
233
|
end
|
@@ -166,8 +239,9 @@ Available commands:
|
|
166
239
|
end
|
167
240
|
|
168
241
|
require 'git/trac/runner/apply'
|
242
|
+
require 'git/trac/runner/checkout'
|
169
243
|
require 'git/trac/runner/cleanup'
|
170
|
-
require 'git/trac/runner/download'
|
171
244
|
require 'git/trac/runner/fetch'
|
245
|
+
require 'git/trac/runner/help'
|
246
|
+
require 'git/trac/runner/push'
|
172
247
|
require 'git/trac/runner/show'
|
173
|
-
require 'git/trac/runner/upload_patch'
|