git-trac 0.0.20080206 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|