blob: 6ee7f774fb1912df4a206f51bca09f21fdccf5c1 [file] [log] [blame]
Anton Staaf60f4fd72011-02-01 13:20:54 -08001#!/usr/bin/env python
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -07002# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
Anton Staaf60f4fd72011-02-01 13:20:54 -08003# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Display active git branches and code changes in a ChromiumOS workspace."""
7
Anton Staaf9a7288c2011-02-09 13:03:31 -08008import optparse
Anton Staaf60f4fd72011-02-01 13:20:54 -08009import os
10import re
11import subprocess
12
13def RunCommand(path, command):
14 """Run a command in a given directory, return stdout."""
15
16 return subprocess.Popen(command,
17 cwd=path,
18 stdout=subprocess.PIPE).communicate()[0].rstrip()
19
20#
21# Taken with slight modification from gclient_utils.py in the depot_tools
22# project.
23#
24def FindFileUpwards(filename, path):
25 """Search upwards from the a directory to find a file."""
26
27 path = os.path.realpath(path)
28 while True:
29 file_path = os.path.join(path, filename)
30 if os.path.exists(file_path):
31 return file_path
32 (new_path, _) = os.path.split(path)
33 if new_path == path:
34 return None
35 path = new_path
36
37
38def ShowName(relative_name, color):
39 """Display the directory name."""
40
41 if color:
42 print('\033[44m\033[37m%s\033[0m' % relative_name)
43 else:
44 print relative_name
45
46
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070047def GetBranches(full_name, color):
Anton Staaf1037c442011-02-08 14:39:53 -080048 """Return a list of branch descriptions."""
Anton Staaf60f4fd72011-02-01 13:20:54 -080049
Anton Staaf60f4fd72011-02-01 13:20:54 -080050 command = ['git', 'branch', '-vv']
51
52 if color:
53 command.append('--color')
54
Anton Staaf1037c442011-02-08 14:39:53 -080055 branches = RunCommand(full_name, command).splitlines()
Anton Staaf60f4fd72011-02-01 13:20:54 -080056
Anton Staaf1037c442011-02-08 14:39:53 -080057 if re.search(r"\(no branch\)", branches[0]):
58 return []
Anton Staaf60f4fd72011-02-01 13:20:54 -080059
Anton Staaf1037c442011-02-08 14:39:53 -080060 return branches
Anton Staaf60f4fd72011-02-01 13:20:54 -080061
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070062def GetStatus(full_name, color):
Anton Staaf1037c442011-02-08 14:39:53 -080063 """Return a list of files that have modifications."""
Anton Staaf60f4fd72011-02-01 13:20:54 -080064
Anton Staaf1037c442011-02-08 14:39:53 -080065 command = ['git', 'status', '-s']
66
67 return RunCommand(full_name, command).splitlines()
68
69
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070070def GetHistory(full_name, color, author, days):
Anton Staaf9a7288c2011-02-09 13:03:31 -080071 """Return a list of oneline log messages.
72
73 The messages are for the author going back a specified number of days.
74 """
75
76 command = ['git', 'log',
77 '--author=' + author,
78 '--after=' + '-' + str(days) + 'days',
79 '--pretty=oneline',
80 'm/master']
81
82 return RunCommand(full_name, command).splitlines()
83
84
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070085def ShowDir(full_name, color, logs, author, days):
Anton Staaf1037c442011-02-08 14:39:53 -080086 """Display active work in a single git repository."""
87
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070088 branches = GetBranches(full_name, color)
89 status = GetStatus(full_name, color)
Anton Staaf1037c442011-02-08 14:39:53 -080090
Anton Staaf9a7288c2011-02-09 13:03:31 -080091 if logs:
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070092 history = GetHistory(full_name, color, author, days)
Anton Staaf9a7288c2011-02-09 13:03:31 -080093 else:
94 history = []
95
96 if branches or status or history:
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -070097 # We want to use the full path for testing, but we want to use the
98 # relative path for display.
99 ShowName(os.path.relpath(full_name), color)
Anton Staaf1037c442011-02-08 14:39:53 -0800100
101 if branches: print '\n'.join(branches)
102 if status: print '\n'.join(status)
Anton Staaf9a7288c2011-02-09 13:03:31 -0800103 if history: print '\n'.join(history)
Anton Staaf1037c442011-02-08 14:39:53 -0800104
Anton Staaf9a7288c2011-02-09 13:03:31 -0800105 if branches or status or history:
Anton Staaf60f4fd72011-02-01 13:20:54 -0800106 print ""
107
108
109def FindRoot():
110 """Returns the repo root."""
111
112 repo_file = '.repo'
113 repo_path = FindFileUpwards(repo_file, os.getcwd())
114
115 if repo_path is None:
116 raise Exception('Failed to find %s.' % repo_file)
117
118 return os.path.dirname(repo_path)
119
120
121def main():
Anton Staaf9a7288c2011-02-09 13:03:31 -0800122 parser = optparse.OptionParser(usage = 'usage: %prog [options]\n')
123
124 parser.add_option('-l', '--logs', default=False,
125 help='Show the last few days of your commits in short '
126 'form.',
127 action='store_true',
128 dest='logs')
129
130 parser.add_option('-d', '--days', default=8,
131 help='Set the number of days of history to show.',
132 type='int',
133 dest='days')
134
135 parser.add_option('-a', '--author', default=os.environ['USER'],
136 help='Set the author to filter for.',
137 type='string',
138 dest='author')
139
140 options, arguments = parser.parse_args()
141
142 if arguments:
143 parser.print_usage()
144 return 1
Anton Staaf60f4fd72011-02-01 13:20:54 -0800145
146 color = os.isatty(1)
Anton Staaf60f4fd72011-02-01 13:20:54 -0800147 root = FindRoot()
148 repos = RunCommand(root, ['repo', 'forall', '-c', 'pwd']).splitlines()
149
Vadim Bendebury2ed43ee2011-04-08 13:49:22 -0700150 for full in repos:
151 ShowDir(full, color, options.logs, options.author, options.days)
Anton Staaf60f4fd72011-02-01 13:20:54 -0800152
153
154if __name__ == '__main__':
155 main()