Index: host/willis |
diff --git a/host/willis b/host/willis |
new file mode 100755 |
index 0000000000000000000000000000000000000000..e031651e78b9cbc8bc4c6866e63e6d0a2f4ffb90 |
--- /dev/null |
+++ b/host/willis |
@@ -0,0 +1,108 @@ |
+#!/usr/bin/env python |
+# Copyright (c) 2011 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+"""Display active git branches and code changes in a ChromiumOS workspace.""" |
+ |
+import os |
+import re |
+import subprocess |
+import sys |
+ |
+def RunCommand(path, command): |
+ """Run a command in a given directory, return stdout""" |
Kenneth Waters
2011/02/01 00:56:04
Period after stdout. And a blank line after the d
robotboy
2011/02/01 20:44:55
Done.
|
+ return subprocess.Popen(command, |
+ cwd=path, |
+ stdout=subprocess.PIPE).communicate()[0].rstrip() |
+ |
+# |
+# Taken with slight modification from gclient_utils.py in the depot_tools |
+# project. |
+# |
+def FindFileUpwards(filename, path): |
+ """Search upwards from the a directory to find a file.""" |
Kenneth Waters
2011/02/01 00:56:04
Blank line after the docstring.
robotboy
2011/02/01 20:44:55
Done.
|
+ path = os.path.realpath(path) |
+ while True: |
+ file_path = os.path.join(path, filename) |
+ if os.path.exists(file_path): |
+ return file_path |
+ (new_path, _) = os.path.split(path) |
+ if new_path == path: |
+ return None |
+ path = new_path |
+ |
+ |
+def ShowName(relative_name, color): |
+ """Display the directory name.""" |
+ |
+ if color: |
+ sys.stdout.write('%s[44m%s[37m%s%s[0m\n' % |
Kenneth Waters
2011/02/01 00:56:04
'\033[44m\033[37m%s\033[0m\n'
Kenneth Waters
2011/02/01 00:56:04
Why not print?
robotboy
2011/02/01 20:44:55
Done.
robotboy
2011/02/01 20:44:55
Cut and paste-itis. Fixed, thanks.
|
+ (chr(27), chr(27), relative_name, chr(27))) |
+ else: |
+ sys.stdout.write('%s\n' % relative_name) |
+ |
+ |
+def ShowDir(full_name, relative_name, color): |
+ """Display active work in a single git repo.""" |
+ |
+ lines_printed = 0 |
+ command = ['git', 'branch', '-vv'] |
+ |
+ if color: |
+ command.append('--color') |
+ |
+ branch = RunCommand(full_name, command) |
+ lines = branch.splitlines() |
+ |
+ if (len(lines) > 1 or |
+ (len(lines) == 1 and not re.search("\(no branch\)", lines[0]))) : |
Kenneth Waters
2011/02/01 00:56:04
"\(no branch\)" is almost certainly wrong. Did yo
robotboy
2011/02/01 20:44:55
Yes, thanks, done.
|
+ if lines_printed == 0: |
+ ShowName(relative_name, color) |
+ lines_printed += 1 |
+ print branch |
+ |
+ status = RunCommand(full_name, ['git', 'status', '-s']) |
+ |
+ if len(status.splitlines()) > 0: |
Kenneth Waters
2011/02/01 00:56:04
if status.splitlines():
robotboy
2011/02/01 20:44:55
Done.
|
+ if lines_printed == 0: |
+ ShowName(relative_name, color) |
+ if lines_printed == 1: |
+ print '---------------' |
+ lines_printed += 1 |
+ print status |
+ |
+ if lines_printed > 0: |
+ print "" |
+ |
+ |
+def FindRoot(): |
+ """Returns the repo root.""" |
Kenneth Waters
2011/02/01 00:56:04
Add blank line after docstring.
robotboy
2011/02/01 20:44:55
Done.
|
+ repo_file = '.repo' |
+ repo_path = FindFileUpwards(repo_file, os.getcwd()) |
+ |
+ if not repo_path: |
Kenneth Waters
2011/02/01 00:56:04
if repo_path is None:
not "" -> True
robotboy
2011/02/01 20:44:55
Done.
|
+ raise Exception('Failed to find %s.' % repo_file) |
+ |
+ return os.path.dirname(repo_path) |
+ |
+ |
+def main(): |
+ """Take no arguments.""" |
+ |
+ color = os.isatty(1) |
+ base = os.path.basename(os.getcwd()) |
+ root = FindRoot() |
+ repos = RunCommand(root, ['repo', 'forall', '-c', 'pwd']).splitlines() |
+ |
+ # We want to use the full path for testing, but we want to use the relative |
+ # path for display. |
+ fulldirs = map(lambda(p): os.path.normpath(os.path.join(root, p)), repos) |
Kenneth Waters
2011/02/01 00:56:04
fulldirs = [os.path.normpath(os.path.join(root, p)
robotboy
2011/02/01 20:44:55
Done.
|
+ reldirs = map(lambda(p): re.sub('^' + base, '.', p), repos) |
Kenneth Waters
2011/02/01 00:56:04
reldirs = [re.sub('^' + re.escape(base), '.', p) f
robotboy
2011/02/01 20:44:55
Done.
|
+ |
+ for full_path, relative_path in zip(fulldirs, reldirs): |
+ ShowDir(full_path, relative_path, color) |
+ |
+ |
+if __name__ == '__main__': |
+ main() |