6 from optparse
import OptionParser
, OptionValueError
9 from git_stats
import branch
10 from git_stats
import commit
11 from git_stats
import config
12 from git_stats
import diff
13 from git_stats
import parse
16 """Contains information about a specific commit
19 def __init__(self
, commit
):
20 """Initializes with the specified commit
27 self
.diff_matches
= ""
30 """Checks if this commit is a bugfix
32 Returns: Whether branches, reverts, msg_matches or diff_matches is set.
35 return self
.branches \
41 """Returns a string representation of this object
46 for branch
in self
.branches
:
47 result
.append("In branch: " + branch
)
49 for commit
in self
.reverts
:
50 result
.append("Reverts commit: " + commit
)
53 result
.append("Message matches: '" + self
.msg_matches
+ "'.")
56 result
.append("Diff matches: '" + self
.diff_matches
+ "'.")
58 res
= self
.commit
+ ":"
65 def aggregateType(options
):
70 result
= git
.rev_list(options
.start_from
)
71 commits
= result
.split('\n')
73 kwargs
= extractKwargs(options
)
75 result
= git
.for_each_ref("refs/heads",
77 format
="%(objectname)")
79 branches
= result
.split('\n')
80 branch_map
= branch
.getBranchMap(branches
, cut_off_prefix
=False)
81 parent_list
= branch
.getParentList(branch_map
.values())
90 for commit
in commits
:
91 stats
= determineType(commit
,
94 pretty_names
=pretty_names
,
96 parsed_diffs
=parsed_diffs
,
97 touched_files
=touched_files
,
103 def determineType(target
,
114 """Determines the type of the specified commit
117 commit: The commit to determine the type of.
118 debug: Whether to include debug information.
119 branchFilter: Type=fix if a commit belongs to any of these branches.
120 msgFilter: Type=fix if the commit log msg matches this filter.
121 diffFilter: Type=fix if the commit diff matches this filter.
122 raw_diffs: A dictionary with commits and their raw diffs.
123 parsed_diffs: A dictionary with commits and their parsed diffs.
124 touched_files: A dictionary with files and the commits that touched them.
127 branches
= branch
.belongsTo(target
,
130 pretty_names
=pretty_names
)
132 reverts
= diff
.findReverts( target
,
134 parsed_diffs
=parsed_diffs
,
135 touched_files
=touched_files
)
137 msg_matches
= msgFilter
and commit
.commitmsgMatches(target
, msgFilter
)
138 diff_matches
= diffFilter
and commit
.commitdiffMatches( target
,
142 result
= CommitInfo(target
)
144 if branchFilter
in branches
:
145 match
= set(branchFilter
).intersection(set(branches
))
146 result
.branches
= match
149 result
.reverts
= reverts
152 result
.msg_matches
= msgFilter
155 result
.diff_matches
= diffFilter
159 def extractKwargs(options
):
160 """Extracts kwargs and returns the result
162 The kwargs are extracted from the specified options and
163 from the 'config' file.
170 kwargs
["debug"] = options
.debug
or opts
.get("debug", False)
171 kwargs
["msgFilter"] = options
.message_filter
or opts
.get("msgFilter", None)
172 kwargs
["diffFilter"] = options
.diff_filter
or opts
.get("diffFilter", None)
173 kwargs
["branchFilter"] = options
.branch_filter
or opts
.get("branchFilter", None)
177 def _checkOptions(parser
, options
):
178 """Checks the specified options and uses the parser to indicate errors
181 parser: The parser to use to signal when the options are bad.
182 options: The options to check.
185 opts
= [options
.aggregate
, options
.type]
187 if not parse
.isUnique(opts
):
188 parser
.error("Please choose exactly one mode")
191 """Dispatches index related commands
194 progname
= os
.path
.basename(sys
.argv
[0]) + " bug"
196 parser
= OptionParser(option_class
=parse
.GitOption
, prog
=progname
)
201 help="show debug information")
206 help="aggregate bug information of all commits")
211 help="shows which type the specified commit is")
214 "-s", "--start-from",
217 help="the commit to start from")
220 "-m", "--message-filter",
221 help="mark the commit as a fix if it's log matches this filter")
224 "-f", "--diff-filter",
225 help="mark the commit as a fix if it's diff matches this filter")
228 "-b", "--branch-filter",
229 help="mark the commit as a fix if it belongs to this branch")
231 # Default to True for now, until there is another option
232 parser
.set_default("debug", False)
233 parser
.set_default("aggregate", False)
234 parser
.set_default("start_from", "HEAD")
236 (options
, args
) = parser
.parse_args(list(args
))
238 _checkOptions(parser
, options
)
240 if options
.aggregate
:
241 result
= aggregateType(options
)
243 kwargs
= extractKwargs(options
)
244 stats
= determineType(options
.type, **kwargs
)
245 result
= [str(stats
)]