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/lib/git/trac/runner/show.rb
CHANGED
@@ -4,8 +4,12 @@ module Git
|
|
4
4
|
|
5
5
|
class Show < Base #:nodoc:
|
6
6
|
|
7
|
+
def self.summary
|
8
|
+
"Show an attachment or a list of attachments"
|
9
|
+
end
|
10
|
+
|
7
11
|
def banner_arguments
|
8
|
-
"[ticket
|
12
|
+
"[<ticket> | <attachment> | branches | rebased | today]"
|
9
13
|
end
|
10
14
|
|
11
15
|
def description
|
@@ -13,6 +17,11 @@ module Git
|
|
13
17
|
Show the given ticket attachment. The patch will be highlighted in a manner
|
14
18
|
If the filename is omitted, show a list of attachments for the ticket.
|
15
19
|
|
20
|
+
If the literal word "branches" is given, a list of all remote heads is output,
|
21
|
+
followed by the branches that refer to them. A literal "rebased" also shows
|
22
|
+
branches that appear to be rebased attachments. These rebased branches will be
|
23
|
+
shown in brackets.
|
24
|
+
|
16
25
|
Attachments can be downloaded by redirecting to a file. The following example
|
17
26
|
shows how one might download all patches for a given ticket:
|
18
27
|
|
@@ -23,21 +32,59 @@ shows how one might download all patches for a given ticket:
|
|
23
32
|
end
|
24
33
|
|
25
34
|
def run
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
35
|
+
if [[], %w(branches), %w(rebased)].include?(@argv)
|
36
|
+
puts branches(@argv == %w(rebased))
|
37
|
+
return
|
38
|
+
elsif %w(today) == @argv
|
39
|
+
Pager.new.page(today)
|
40
|
+
return
|
41
|
+
end
|
42
|
+
each_ticket_or_attachment do |ticket|
|
43
|
+
if ticket.respond_to?(:body)
|
44
|
+
repository.pager(ticket.body, %w(.diff .patch).include?(ticket.extension))
|
31
45
|
else
|
32
46
|
body = ticket.attachments.map do |attachment|
|
33
|
-
"#{number}/#{attachment.filename}\n"
|
47
|
+
"#{attachment.ticket.number}/#{attachment.filename}\n"
|
34
48
|
end.join
|
35
49
|
exit(1) if body.empty?
|
36
|
-
|
50
|
+
repository.pager(body)
|
37
51
|
end
|
38
52
|
end
|
39
53
|
end
|
40
54
|
|
55
|
+
def branches(rebased = false)
|
56
|
+
output = ""
|
57
|
+
current_checkout = repository.current_checkout
|
58
|
+
branches = []
|
59
|
+
repository.each_ref("refs/heads") do |object, ref|
|
60
|
+
branches << [ref.sub(/^refs\/heads\//,''), object]
|
61
|
+
branches.last << (rebased ? repository.diff_hash(object) : nil)
|
62
|
+
end
|
63
|
+
repository.each_ref("refs/remotes/trac") do |object, ref|
|
64
|
+
current = (object == current_checkout)
|
65
|
+
line = ref.sub(/^refs\/remotes\//,'')
|
66
|
+
diff_hash = rebased && repository.diff_hash(object)
|
67
|
+
branches.each do |(branch,branch_object,branch_hash)|
|
68
|
+
if object == branch_object
|
69
|
+
line << " <#{branch}>"
|
70
|
+
elsif diff_hash == branch_hash
|
71
|
+
line << " [#{branch}]"
|
72
|
+
current ||= (branch == current_checkout)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
output << (current ? "* " : " ") + line + "\n"
|
76
|
+
end
|
77
|
+
output
|
78
|
+
end
|
79
|
+
|
80
|
+
def today(days_back = 2)
|
81
|
+
require 'hpricot'
|
82
|
+
response = repository.get_response("#{repository.url}/timeline?ticket_details=on&max=#{50*days_back}&daysback=#{days_back}&format=rss")
|
83
|
+
response.error! unless response.kind_of?(Net::HTTPSuccess)
|
84
|
+
h = Hpricot(response.body)
|
85
|
+
(h/:title).map {|y| y.inner_text.match(/^(.*) attached to ticket #(\d+)$/) && "#$2/#$1\n"}.compact.join
|
86
|
+
end
|
87
|
+
|
41
88
|
end
|
42
89
|
|
43
90
|
end
|
data/lib/git/trac/ticket.rb
CHANGED
@@ -24,14 +24,8 @@ module Git
|
|
24
24
|
"#{@repository.url}/attachment/ticket/#{@number}"
|
25
25
|
end
|
26
26
|
|
27
|
-
def get_response(uri)
|
28
|
-
require 'net/http'
|
29
|
-
require 'uri'
|
30
|
-
Net::HTTP.get_response(URI.parse(uri))
|
31
|
-
end
|
32
|
-
|
33
27
|
def csv
|
34
|
-
response = get_response(url(:tab))
|
28
|
+
response = repository.get_response(url(:tab))
|
35
29
|
no_such_ticket if response.kind_of?(Net::HTTPInternalServerError)
|
36
30
|
response.error! unless response.kind_of?(Net::HTTPSuccess)
|
37
31
|
body = response.body
|
@@ -53,7 +47,7 @@ module Git
|
|
53
47
|
attr_reader :number
|
54
48
|
|
55
49
|
def attachments
|
56
|
-
response = get_response(attachment_url)
|
50
|
+
response = repository.get_response(attachment_url)
|
57
51
|
if html = response.body[/<dl class="attachments">.*?<\/dl>/m]
|
58
52
|
return Attachment.from_html(self,html)
|
59
53
|
elsif response.kind_of?(Net::HTTPSuccess)
|
@@ -77,26 +71,6 @@ module Git
|
|
77
71
|
"#{repository.git_dir}/refs/remotes/trac/#{number}"
|
78
72
|
end
|
79
73
|
|
80
|
-
class Form
|
81
|
-
def initialize(mech_form)
|
82
|
-
@mech_form = mech_form
|
83
|
-
end
|
84
|
-
|
85
|
-
def submit(*args)
|
86
|
-
@mech_form.submit
|
87
|
-
end
|
88
|
-
|
89
|
-
def method_missing(method,*args,&block)
|
90
|
-
if method.to_s[-1] == "=" && @mech_form.fields.name(method.to_s[0..-2]).any?
|
91
|
-
@mech_form.fields.name(method.to_s[0..-2]).send(:value=,*args,&block)
|
92
|
-
elsif @mech_form.fields.name(method.to_s).any?
|
93
|
-
@mech_form.fields.name(method.to_s).send(:value,*args,&block)
|
94
|
-
else
|
95
|
-
super(method,*args,&block)
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
74
|
def form
|
101
75
|
repository.agent.get(url).forms.last
|
102
76
|
end
|
@@ -124,8 +98,9 @@ module Git
|
|
124
98
|
|
125
99
|
def upload_patch(options = {})
|
126
100
|
filename = options[:filename] || "#{File.basename(repository.current_checkout)}.patch"
|
127
|
-
|
128
|
-
|
101
|
+
upstream = options[:upstream] || "refs/remotes/trunk"
|
102
|
+
upstream += "...HEAD" unless upstream.include?(".")
|
103
|
+
diff = repository.exec("git","diff",upstream)
|
129
104
|
return false if diff.empty?
|
130
105
|
# Don't upload the exact same patch that was pulled down
|
131
106
|
return false if repository.generated_commits[repository.rev_parse("HEAD")] == number
|
@@ -143,29 +118,20 @@ module Git
|
|
143
118
|
def cleanup(options = {})
|
144
119
|
revs = []
|
145
120
|
repository.each_ref("refs/remotes/trac/#{number}") do |object, ref|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
121
|
+
revs << object
|
122
|
+
repository.exec("git","update-ref","-d",ref,object) unless options[:only_branches]
|
123
|
+
end
|
124
|
+
begin
|
125
|
+
Dir.unlink("#{repository.git_dir}/refs/remotes/trac/#{number}")
|
126
|
+
rescue Errno::ENOENT, Errno::ENOTEMPTY
|
150
127
|
end
|
151
|
-
repository.cleanup_branches(*revs)
|
152
128
|
revs.any?
|
153
129
|
end
|
154
130
|
|
155
|
-
def fetch(options = {})
|
131
|
+
def fetch(options = {}, &block)
|
156
132
|
cleanup(options)
|
157
|
-
|
158
|
-
|
159
|
-
attachment.filename =~ /#{options[:filter] || "\\.(diff|patch)$"}/
|
160
|
-
end.map do |attachment|
|
161
|
-
commit, applied = attachment.fetch(options)
|
162
|
-
yield attachment, applied if block_given?
|
163
|
-
seen[attachment.name] = commit if commit
|
164
|
-
end
|
165
|
-
seen.each do |k,v|
|
166
|
-
if !File.exists?(path = "#{repository.git_dir}/refs/heads/#{k}")
|
167
|
-
File.open(path, "w") {|f| f.puts v}
|
168
|
-
end
|
133
|
+
attachments.each do |attachment|
|
134
|
+
attachment.fetch(options,&block)
|
169
135
|
end
|
170
136
|
end
|
171
137
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: git-trac
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Pope
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-02-
|
12
|
+
date: 2008-02-11 00:00:00 -06:00
|
13
13
|
default_executable: git-trac
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: 0.6.8
|
23
23
|
version:
|
24
|
-
description: git-trac takes the repetition out of working with trac and git-svn.
|
24
|
+
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.
|
25
25
|
email: ruby@tpope.info
|
26
26
|
executables:
|
27
27
|
- git-trac
|
@@ -36,19 +36,21 @@ files:
|
|
36
36
|
- bin/git-trac
|
37
37
|
- lib/git/trac.rb
|
38
38
|
- lib/git/trac/attachment.rb
|
39
|
-
- lib/git/trac/repository.rb
|
40
|
-
- lib/git/trac/runner.rb
|
41
|
-
- lib/git/trac/ticket.rb
|
42
39
|
- lib/git/trac/pager.rb
|
43
40
|
- lib/git/trac/patch.rb
|
44
|
-
- lib/git/trac/
|
45
|
-
- lib/git/trac/runner
|
46
|
-
- lib/git/trac/runner/fetch.rb
|
47
|
-
- lib/git/trac/runner/cleanup.rb
|
48
|
-
- lib/git/trac/runner/upload_patch.rb
|
41
|
+
- lib/git/trac/repository.rb
|
42
|
+
- lib/git/trac/runner.rb
|
49
43
|
- lib/git/trac/runner/apply.rb
|
50
|
-
-
|
44
|
+
- lib/git/trac/runner/cleanup.rb
|
45
|
+
- lib/git/trac/runner/fetch.rb
|
46
|
+
- lib/git/trac/runner/help.rb
|
47
|
+
- lib/git/trac/runner/push.rb
|
48
|
+
- lib/git/trac/runner/show.rb
|
49
|
+
- lib/git/trac/runner/checkout.rb
|
50
|
+
- lib/git/trac/ticket.rb
|
51
|
+
- lib/git/trac/version.rb
|
51
52
|
- test/attachment_test.rb
|
53
|
+
- test/execution_test.rb
|
52
54
|
has_rdoc: true
|
53
55
|
homepage: http://git-trac.rubyforge.org
|
54
56
|
post_install_message:
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Git
|
2
|
-
module Trac
|
3
|
-
class Runner
|
4
|
-
|
5
|
-
class Download < Base #:nodoc:
|
6
|
-
|
7
|
-
def description
|
8
|
-
<<-EOF
|
9
|
-
Download all attachments that look like patches to the current working
|
10
|
-
directory.
|
11
|
-
|
12
|
-
This command is a candidate for removal. Individual patches can be downloaded
|
13
|
-
by redirecting git-trac show to a file.
|
14
|
-
EOF
|
15
|
-
end
|
16
|
-
|
17
|
-
def banner_arguments
|
18
|
-
"[options] [ticket[/filename]] ..."
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_options(opts)
|
22
|
-
require_ticket_number
|
23
|
-
opts.separator("Options:")
|
24
|
-
opts.on("--root DIR","prefix patch paths with DIR") do |dir|
|
25
|
-
options[:root] = dir
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def run
|
30
|
-
each_ticket_argument do |number, filename|
|
31
|
-
@repository.ticket(number).attachments.each do |attach|
|
32
|
-
next if filename && attach.filename != filename
|
33
|
-
File.open(attach.filename, "w") do |f|
|
34
|
-
f.puts attach.patch.with_root(options[:root])
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
module Git
|
2
|
-
module Trac
|
3
|
-
class Runner
|
4
|
-
|
5
|
-
class UploadPatch < Base #:nodoc:
|
6
|
-
|
7
|
-
def banner_arguments
|
8
|
-
"[options] [ticket]"
|
9
|
-
end
|
10
|
-
|
11
|
-
def description
|
12
|
-
<<-EOF
|
13
|
-
Do a `git diff` against trunk (or another branch) and upload the result as an
|
14
|
-
attachment to a ticket. The potential patch will be shown in a pager and you
|
15
|
-
will be given the opportunity to cancel.
|
16
|
-
EOF
|
17
|
-
end
|
18
|
-
|
19
|
-
def add_options(opts)
|
20
|
-
require_ticket_number
|
21
|
-
opts.on("--branch BRANCH", "git diff BRANCH (default trunk...HEAD)") do |b|
|
22
|
-
options[:branch] = b
|
23
|
-
end
|
24
|
-
opts.on("--description TEXT", "use TEXT as description") do |text|
|
25
|
-
options[:description] = text
|
26
|
-
end
|
27
|
-
opts.on("--[no-]force", "do not prompt before uploading") do |force|
|
28
|
-
options[:force] = force
|
29
|
-
end
|
30
|
-
add_local_option(opts)
|
31
|
-
end
|
32
|
-
|
33
|
-
def run
|
34
|
-
number = get_ticket_number
|
35
|
-
fetch_unless_local
|
36
|
-
ticket = @repository.ticket(number)
|
37
|
-
if $stdin.tty? && !options[:force]
|
38
|
-
block = lambda do
|
39
|
-
@repository.in_work_tree do
|
40
|
-
system("git","diff", options[:branch] || "trunk...HEAD")
|
41
|
-
end
|
42
|
-
description = "##{number} (#{ticket.csv["summary"]}"
|
43
|
-
cols = ENV["COLUMNS"].to_i
|
44
|
-
cols = 80 if cols.zero?
|
45
|
-
description.sub!(/^(.{#{cols-22}}).{4,}/,"\\1...")
|
46
|
-
print "#{description}) Proceed? [yN] "
|
47
|
-
$stdin.gets[0,1] == "y"
|
48
|
-
end
|
49
|
-
else
|
50
|
-
block = lambda { true }
|
51
|
-
end
|
52
|
-
if uri = ticket.upload_patch(options,&block)
|
53
|
-
puts uri
|
54
|
-
else
|
55
|
-
exit 1
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|