gitstats: Teach 'stats.py author -f' to sort output by commit count
[git-stats.git] / src / git_stats / index.py
blob7945c5e281dc0b817447543d5a888374b5a2a87c
1 #!/usr/bin/env python
3 import os
4 import sys
6 from optparse import OptionParser
7 from git import Repo
9 from git_stats import commit
11 def stagedChanges(ignore_added_files=False):
12 """Returns the paths to all files that have changes staged.
13 When calling this function the current directory should be the root
14 of the git directory that should be acted on.
16 Params:
17 ignore_added_files: When True files that added newly are ignored.
19 Returns:
20 A list of paths that were changed.
21 """
23 git = Repo(".").git
24 result = git.diff_index("--cached", "--name-status", "HEAD")
26 log = result.split('\n')
28 changed = []
30 for line in log:
31 # Skip the last empty line
32 if len(line.lstrip()) == 0:
33 continue
35 splitline = line.split('\t')
37 # Skip files that were freshly added
38 if splitline[0] == 'A' and ignore_added_files:
39 continue
41 changed.append(splitline[1])
43 return changed
45 def touched(show_all):
46 """Returns which commits touched the same files as the staged changes.
48 Args:
49 show_all: When true, all files, even new ones, are searched.
51 Returns: If there were no staged changes, None is returned.
52 Otherwise the list of matching commits is returned.
53 """
55 staged = stagedChanges(not show_all)
57 # There were no starged changes, return 'None' explicitly
58 if not staged:
59 return None
61 # Find all commits that touched the same files and return them
62 touched = commit.commitsThatTouched(staged)
63 return touched
65 def dispatch(*args):
66 """Dispatches index related commands
67 """
69 progname = os.path.basename(sys.argv[0]) + " index"
71 parser = OptionParser(prog=progname)
73 parser.add_option(
74 "-a", "--all",
75 action="store_true",
76 help="search even new files, which usually have no matching commits")
78 parser.add_option(
79 "-t", "--touched",
80 action="store_true",
81 help="shows all commits that touch the same paths as the staged changes")
83 # Default to True for now, until there is another option
84 parser.set_default("touched", True)
85 parser.set_default("all", False)
87 (options, args) = parser.parse_args(list(args))
89 result = touched(options.all)
91 if not result:
92 msg = "No changes staged"
93 if options.all:
94 msg += " or no matching commits"
95 else:
96 msg += ", no matching commits, or only new files added"
98 print(msg)
99 return
101 commit.prettyPrint(result)