gitstats: Moved the commit information into a seperate class
[git-stats.git] / src / git_stats / bug.py
blob91c6d11de82f659dede95bcedf0e93923093409e
1 #!/usr/bin/env python
3 import os
4 import sys
6 from optparse import OptionParser, OptionValueError
7 from git import Repo
9 from git_stats import branch
10 from git_stats import commit
11 from git_stats import config
12 from git_stats import parse
14 class CommitInfo:
15 """Contains information about a specific commit
16 """
18 def __init__(self, commit):
19 """Initializes with the specified commit
20 """
22 self.commit = commit
23 self.branches = []
24 self.reverts = []
25 self.msg_matches = ""
26 self.diff_matches = ""
28 def isBugfix():
29 """Checks if this commit is a bugfix
31 Returns: Whether branches, reverts, msg_matches or diff_matches is set.
32 """
34 return self.branches \
35 or self.reverts \
36 or self.msg_matches \
37 or self.diff_matches
39 def __str__(self):
40 """Returns a string representation of this object
41 """
43 result = []
45 for branch in self.branches:
46 result.append("In branch: " + branch)
48 for commit in self.reverts:
49 result.append("Reverts commit: " + commit)
51 if self.msg_matches:
52 result.append("Message matches: '" + self.msg_matches + "'.")
54 if self.diff_matches:
55 result.append("Diff matches: '" + self.diff_matches + "'.")
57 res = self.commit + ":"
59 for line in result:
60 res += "\n" + line
62 return res
64 def aggregateType(debug):
65 """
66 """
68 result = []
70 # TODO, implement
72 return result
74 def determineType(target,
75 debug=False,
76 branchFilter=None,
77 msgFilter=None,
78 diffFilter=None):
79 """Determines the type of the specified commit
81 Args:
82 commit: The commit to determine the type of.
83 debug: Whether to include debug information.
84 branchFilter: Type=fix if a commit belongs to any of these branches.
85 msgFilter: Type=fix if the commit log msg matches this filter.
86 diffFilter: Type=fix if the commit diff matches this filter.
87 """
89 branches = branch.belongsTo(target)
90 reverts = commit.findReverts(target)
91 msg_matches = msgFilter and commit.commitmsgMatches(target, msgFilter)
92 diff_matches = diffFilter and commit.commitdiffMatches(target, diffFilter)
94 result = CommitInfo(target)
96 if branchFilter in branches:
97 match = set(branchFilter).intersect(set(branches))
98 result.branches = match
100 if reverts:
101 result.reverts = reverts
103 if msg_matches:
104 result.msg_matches = msgFilter
106 if diff_matches:
107 result.diff_matches = diffFilter
109 return result
111 def _checkOptions(parser, options):
112 """Checks the specified options and uses the parser to indicate errors
114 Args:
115 parser: The parser to use to signal when the options are bad.
116 options: The options to check.
119 opts = [options.aggregate, options.type]
121 if not parse.isUnique(opts):
122 parser.error("Please choose exactly one mode")
124 def dispatch(*args):
125 """Dispatches index related commands
128 progname = os.path.basename(sys.argv[0]) + " bug"
130 parser = OptionParser(option_class=parse.GitOption, prog=progname)
132 parser.add_option(
133 "-d", "--debug",
134 action="store_true",
135 help="show debug information")
137 parser.add_option(
138 "-a", "--aggregate",
139 action="store_true",
140 help="aggregate bug information of all commits")
142 parser.add_option(
143 "-t", "--type",
144 type="commit",
145 help="shows which type the specified commit is")
147 parser.add_option(
148 "-m", "--message-filter",
149 help="mark the commit as a fix if it's log matches this filter")
151 parser.add_option(
152 "-f", "--diff-filter",
153 help="mark the commit as a fix if it's diff matches this filter")
155 parser.add_option(
156 "-b", "--branch-filter",
157 help="mark the commit as a fix if it belongs to this branch")
159 # Default to True for now, until there is another option
160 parser.set_default("debug", False)
161 parser.set_default("aggregate", False)
163 (options, args) = parser.parse_args(list(args))
165 _checkOptions(parser, options)
167 if options.aggregate:
168 result = aggregateType(options.debug)
169 elif options.type:
170 opts = config.read()
171 stats = determineType(
172 options.type,
173 debug=options.debug or opts.get("debug", False),
174 msgFilter=options.message_filter or opts.get("msgFilter", None),
175 diffFilter=options.diff_filter or opts.get("diffFilter", None),
176 branchFilter=options.branch_filter or opts.get("branchFilter", None))
178 result = [str(stats)]
180 for line in result:
181 print(line)