gitstats: Licensed GitStats under the Apache License, 2.0
[git-stats.git] / src / git_stats / parse.py
blob1992ebb1b9ebddf41b8087a45015f673eaa8b92e
1 #!/usr/bin/env python
3 import copy
5 from git import Repo
6 from optparse import OptionParser, Option, OptionValueError
8 def _checkFile(option, opt, value):
9 """Checks whether value is a valid file and returns it if so
10 """
12 return checkFile(value)
15 def checkFile(value, relative=False):
16 """Check whether value is a valid file and returns it if so
18 Args:
19 value: The value to check.
20 relative: Whether to treat value as a path relative to the working dir.
21 """
23 git = Repo(".").git
25 file = git.ls_files("--full-name", "--", value, with_keep_cwd=relative)
27 if not file:
28 raise OptionValueError("Unknown file '%s'" % value)
30 splitfile = file.split('\n')
32 if len(splitfile) > 1:
33 raise OptionValueError(
34 "Please specify only one file, '%s' matches more than one" % value)
36 return splitfile[0]
38 def _check_commit(option, opt, value):
39 """Checks whether value is a valid refspec and returns its hash if so
40 """
42 git = Repo(".").git
43 rev = git.rev_parse("--verify", value, with_exceptions=False)
45 if not rev:
46 raise OptionValueError("Unknown commit '%s'" % value)
48 return rev
50 def _check_bool(option, opt, value):
51 """Checks whether a value is a boolean and returns it's value
53 Understands about 'True', 'False', and 'None'.
54 """
56 if value == "True":
57 return True
59 if value == "False":
60 return False
62 if value == "None":
63 return None
65 raise OptionValueError("Not a boolean: '%s'" % value)
67 class GitOption(Option):
68 """This parser understands three new types:
69 commit: A commit must specify exactly 1 commit in the current repository.
70 file: A file must specify exactly 1 tracked file in the current repository.
71 bool: A bool must be 'True', 'False', or 'None'.
72 """
74 # Define the new types
75 TYPES = Option.TYPES + ("commit",) + ("file",) + ("bool",)
77 # Copy the type checker list so that we don't keep the default ones
78 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
80 # Add our own options
81 TYPE_CHECKER["commit"] = _check_commit
82 TYPE_CHECKER["file"] = _checkFile
83 TYPE_CHECKER["bool"] = _check_bool
85 def isUnique(options, at_least_one=False):
86 """Checks if a list of options is unique
88 Args:
89 options: The list of options to check
90 at_least_one: If set, when no optiosn are set, return False
91 """
93 unique = False
95 for option in options:
96 if option:
97 # If we already found one, it's not unique for sure
98 if unique:
99 return False
100 else:
101 unique = True
103 # If there is only one, it's unique
104 if unique:
105 return True
107 # None found, so unique only if we don't require at least one
108 return not at_least_one