gitstats: Refactoring, cleanups and documentation
[git-stats.git] / src / git_stats / parse.py
blob1a7d81b56585948be7484a2da9fc279786f337f1
1 #!/usr/bin/env python
3 import copy
5 from git import Repo
6 from optparse import OptionParser, Option, OptionValueError
8 def _check_file(option, opt, value):
9 """Checks whether value is a valid file and returns it if so
10 """
12 return check_file(value)
15 def check_file(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 '" + value + "'")
30 splitfile = file.split('\n')
32 if len(splitfile) > 1:
33 raise OptionValueError("Please specify only one file, '" + value + "' matches more than one file")
35 return splitfile[0]
37 def _check_commit(option, opt, value):
38 """Checks whether value is a valid refspec and returns its hash if so
39 """
41 git = Repo(".").git
42 rev = git.rev_parse("--verify", value, with_exceptions=False)
44 if not rev:
45 raise OptionValueError("Unknown commit '" + value + "'")
47 return rev
49 def _check_bool(option, opt, value):
50 """Checks whether a value is a boolean and returns it's value
52 Understands about 'True', 'False', and 'None'.
53 """
55 if value == "True":
56 return True
58 if value == "False":
59 return False
61 if value == "None":
62 return None
64 raise OptionValueError("Not a boolean: '" + value + "'")
66 class GitOption(Option):
67 """This parser understands three new types:
68 commit: A commit must specify exactly 1 commit in the current repository.
69 file: A file must specify exactly 1 tracked file in the current repository.
70 bool: A bool must be 'True', 'False', or 'None'.
71 """
73 # Define the new types
74 TYPES = Option.TYPES + ("commit",) + ("file",) + ("bool",)
76 # Copy the type checker list so that we don't keep the default ones
77 TYPE_CHECKER = copy.copy(Option.TYPE_CHECKER)
79 # Add our own options
80 TYPE_CHECKER["commit"] = _check_commit
81 TYPE_CHECKER["file"] = _check_file
82 TYPE_CHECKER["bool"] = _check_bool
84 def isUnique(options, atLeastOne=False):
85 """Checks if a list of options is unique
87 Args:
88 options: The list of options to check
89 atLeastOne: If set, when no optiosn are set, return False
90 """
92 unique = False
94 for option in options:
95 if option:
96 # If we already found one, it's not unique for sure
97 if unique:
98 return False
99 else:
100 unique = True
102 # If there is only one, it's unique
103 if unique:
104 return True
106 # None found, so unique only if we don't require at least one
107 return not atLeastOne