#!/usr/bin/env python
# Copyright (c) 2011 The Chromium OS 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 optparse
import os
import re
import subprocess
import threading

class Result(object):
  '''A class to synchronize multiple repository request threads.

  Multiple parallel running threads collect text information (for instance,
  state of different git repositories, one per thread).

  Using this class object allows these multiple threads to synchronously
  attach collected information to a list.

  This class also provides a facility to unblock the master thread once all
  parallel running threads have finished running.

  To make matters simpler, the number of parallel threads to expect to run is
  given to this class during initialization.

  Attributes:

    thread_lock - a lock object, used as a mutex to control access to the count
                  of running threads

    finished_lock - a lock object, used as a mutex for the master thread. This
                 lock is locked as soon as the first parallel thread starts
                 and stays locked until the last parallel thread finishes.

    thread_count - an integer, number of parallel threads this object will
                 have to handle.

    fast_report - a boolean, if True - report results as they arrive, do not
                 wait for all thread results to arrive and get sorted

    started_threads - an integer, number of threads started so far.

    results - a list of strings, each representing a result of a running
                 parallel thread.
  '''

  def __init__(self, max_threads, fast_report=False):
    '''Initialize the object with the number of parallel threads to handle.'''

    self.thread_lock = threading.Lock()
    self.finished_lock = threading.Lock()
    self.finished_lock.acquire()
    self.thread_count = max_threads
    self.fast_report = fast_report
    self.started_threads = 0
    self.results = []

  def ReportThreadStatus(self):
    '''Print status line when enabled.

    If enabled, print a line showing numbers of started and still running
    threads. Make sure this line is printed in the same screen position (using
    the ANSI cursor control escape sequence).
    '''

    if self.fast_report:
        return
    print '\n%c[1AStarted threads: %3d, remaining threads: %3d' % (
        27, self.started_threads, self.thread_count),

  def ReportStartedThread(self):
    '''Increment started thread count.

    And report status, if enabled.
    '''

    self.thread_lock.acquire()
    self.started_threads = self.started_threads + 1
    self.ReportThreadStatus()
    self.thread_lock.release()

  def ReportFinishedThread(self, result):
    '''Report that a parallel thread finished running.

    Each time a finished thread is reported, decrement the running thread
    count. Once the running thread count reaches zero - unblock the master
    thread lock.

    result - a string, representing the output of the thread, could be empty.
             If not empty - ether add this string to the results attribute or
             print it, if fast reporting is enabled.
    '''

    self.thread_lock.acquire()
    if result:
        if self.fast_report:
            print result
        else:
            self.results.append(result)
    self.thread_count = self.thread_count - 1
    self.ReportThreadStatus()
    self.thread_lock.release()
    if self.thread_count == 0:
      if not self.fast_report:
        # Erase the status line.
        print '\n%c[1A%c[K%c[1A' % (27, 27, 27),
      self.finished_lock.release()

  def GetResults(self):
    '''Wait till all parallel threads finish and return results.

    This function blocks until all parallel threads finish running. Once they
    do, sort the results[] list and return it.
    '''

    self.finished_lock.acquire()
    self.results.sort()
    return self.results

def RunCommand(path, command):
  """Run a command in a given directory, return stdout."""

  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."""

  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 GetName(relative_name, color):
  """Display the directory name."""

  if color:
    return '\033[44m\033[37m%s\033[0m' % relative_name
  else:
    return relative_name


def GetBranches(full_name, color):
  """Return a list of branch descriptions."""

  command = ['git', 'branch', '-vv']

  if color:
    command.append('--color')

  branches = RunCommand(full_name, command).splitlines()

  if re.search(r"\(no branch\)", branches[0]) and len(branches) == 1:
    return []

  return branches

def GetStatus(full_name, color):
  """Return a list of files that have modifications."""

  command = ['git', 'status', '-s']

  return RunCommand(full_name, command).splitlines()


def GetHistory(full_name, color, author, days):
  """Return a list of oneline log messages.

  The messages are for the author going back a specified number of days.
  """

  command = ['git', 'log',
             '--author=' + author,
             '--after=' + '-' + str(days) + 'days',
             '--pretty=oneline',
             'm/master']

  return RunCommand(full_name, command).splitlines()


def ShowDir(full_name, color, logs, author, days, result):
  """Report active work in a single git repository."""

  result.ReportStartedThread()

  branches = GetBranches(full_name, color)
  status = GetStatus(full_name, color)

  text = []
  if logs:
    history = GetHistory(full_name, color, author, days)
  else:
    history = []

  if branches or status or history:
      # We want to use the full path for testing, but we want to use the
      # relative path for display. Add an empty string to the list to have the
      # output sections separated.
    text = [ '', GetName(os.path.relpath(full_name), color), ]

    for extra in (branches, status, history):
        if extra: text = text + extra

  result.ReportFinishedThread('\n'.join(text))


def FindRoot():
  """Returns the repo root."""

  repo_file = '.repo'
  repo_path = FindFileUpwards(repo_file, os.getcwd())

  if repo_path is None:
    raise Exception('Failed to find %s.' % repo_file)

  return os.path.dirname(repo_path)


def main():
  parser = optparse.OptionParser(usage = 'usage: %prog [options]\n')

  parser.add_option('-l', '--logs', default=False,
                    help='Show the last few days of your commits in short '
                         'form.',
                    action='store_true',
                    dest='logs')

  parser.add_option('-d', '--days', default=8,
                    help='Set the number of days of history to show.',
                    type='int',
                    dest='days')

  parser.add_option('-a', '--author', default=os.environ['USER'],
                    help='Set the author to filter for.',
                    type='string',
                    dest='author')

  parser.add_option('-f', '--fast-report', default=False,
                    help='Print results as they arrive, do not sort.',
                    action='store_true',
                    dest='fast_report')

  options, arguments = parser.parse_args()

  if arguments:
    parser.print_usage()
    return 1

  color = os.isatty(1)
  root = FindRoot()
  repos = RunCommand(root, ['repo', 'forall', '-c', 'pwd']).splitlines()

  result = Result(len(repos), options.fast_report)

  for full in repos:
    t = threading.Thread(
        target=ShowDir,
        args=(
            full, color, options.logs, options.author, options.days, result))
    t.start()

  print '\n'.join(result.GetResults())

if __name__ == '__main__':
  main()
