1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
## git ditz plugin
##
## This plugin allows issues to be associated with git commits and git
## branches. Git commits can be easily tagged with a ditz issue with the 'ditz
## commit' command, and both 'ditz show' and the ditz HTML output will then
## contain a list of associated commits for each issue.
##
## Issues can also be assigned a single git feature branch. In this case, all
## commits on that branch will listed as commits for that issue. This
## particular feature is fairly rudimentary, however---it assumes the reference
## point is the 'master' branch, and once the feature branch is merged back
## into master, the list of commits disappears.
##
## Two configuration variables are added, which, when specified, are used to
## construct HTML links for the git commit id and branch names in the generated
## HTML output.
##
## Commands added:
## ditz set-branch: set the git branch of an issue
## ditz commit: run git-commit, and insert the issue id into the commit
## message.
##
## Usage:
## 1. add a line "- git" to the .ditz-plugins file in the project root
## 2. run ditz reconfigure, and enter the URL prefixes, if any, from
## which to create commit and branch links.
## 3. use 'ditz commit' with abandon.
require 'time'
module Ditz
class Issue
field :git_branch, :ask => false
def git_commits
return @git_commits if @git_commits
filters = ["--grep=\"Ditz-issue: #{id}\""]
filters << "master..#{git_branch}" if git_branch
output = filters.map do |f|
`git log --pretty=format:\"%aD\t%an <%ae>\t%h\t%s\" #{f}`
end.join
@git_commits = output.split(/\n/).map { |l| l.split("\t") }.
map { |date, email, hash, msg| [Time.parse(date).utc, email, hash, msg] }
end
end
class Config
field :git_commit_url_prefix, :prompt => "URL prefix to link git commits to", :default => ""
field :git_branch_url_prefix, :prompt => "URL prefix to link git branches to", :default => ""
end
class ScreenView
add_to_view :issue_summary do |issue, config|
" Git branch: #{issue.git_branch || 'none'}\n"
end
add_to_view :issue_details do |issue, config|
commits = issue.git_commits[0...5]
next if commits.empty?
"Recent commits:\n" + commits.map do |date, email, hash, msg|
"- #{msg} [#{hash}] (#{email.shortened_email}, #{date.ago} ago)\n"
end.join + "\n"
end
end
class HtmlView
add_to_view :issue_summary do |issue, config|
next unless issue.git_branch
[<<EOS, { :issue => issue, :url_prefix => config.git_branch_url_prefix }]
<tr>
<td class='attrname'>Git branch:</td>
<td class='attrval'><%= url_prefix && !url_prefix.blank? ? link_to([url_prefix, issue.git_branch].join, issue.git_branch) : h(issue.git_branch) %></td>
</tr>
EOS
end
add_to_view :issue_details do |issue, config|
commits = issue.git_commits
next if commits.empty?
[<<EOS, { :commits => commits, :url_prefix => config.git_commit_url_prefix }]
<h2>Commits for this issue</h2>
<table class="log">
<% commits.each_with_index do |(time, who, hash, msg), i| %>
<tr class="<%= i % 2 == 0 ? "even-row" : "odd-row" %>">
<td class="time"><%=t time %></td>
<td class="person"><%=obscured_email who %></td>
<td class="message"><%=h msg %> [<%= url_prefix && !url_prefix.blank? ? link_to([url_prefix, hash].join, hash) : hash %>]</td>
</tr>
<tr><td></td></tr>
<% end %>
</table>
EOS
end
end
class Operator
operation :set_branch, "Set the git feature branch of an issue", :issue, :maybe_string
def set_branch project, config, issue, maybe_string
puts "Issue #{issue.name} currently " + if issue.git_branch
"assigned to git branch #{issue.git_branch.inspect}."
else
"not assigned to any git branch."
end
branch = maybe_string || ask("Git feature branch name:")
return unless branch
if branch == issue.git_branch
raise Error, "issue #{issue.name} already assigned to branch #{issue.git_branch.inspect}"
end
puts "Assigning to branch #{branch.inspect}."
issue.git_branch = branch
end
operation :commit, "Runs git-commit and auto-fills the issue name in the commit message", :issue do
opt :all, "commit all changed files", :short => "-a", :default => false
opt :verbose, "show diff between HEAD and what would be committed", \
:short => "-v", :default => false
opt :message, "Use the given <s> as the commit message.", \
:short => "-m", :type => :string
opt :edit, "Further edit the message, even if --message is given.", :short => "-e", :default => false
end
def commit project, config, opts, issue
opts[:edit] = true if opts[:message].nil?
args = {
:verbose => "--verbose",
:all => "--all",
:edit => "--edit",
}.map { |k, v| opts[k] ? v : "" }.join(" ")
comment = "# #{issue.name}: #{issue.title}"
tag = "Ditz-issue: #{issue.id}"
message = if opts[:message] && !opts[:edit]
"#{opts[:message]}\n\n#{tag}"
elsif opts[:message] && opts[:edit]
"#{opts[:message]}\n\n#{comment}\n#{tag}"
else
"#{comment}\n#{tag}"
end
message = message.gsub("\"", "\\\"")
exec "git commit #{args} --message=\"#{message}\""
end
end
end
|