#!/usr/bin/env python
#
#===- git-clang-format - ClangFormat Git Integration ---------*- python -*--===#
#
#                     The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
#===------------------------------------------------------------------------===#

r"""                                                                             
clang-format git integration                                                     
============================                                                     
                                                                                 
This file provides a clang-format integration for git. Put it somewhere in your  
path and ensure that it is executable. Then, "git clang-format" will invoke      
clang-format on the changes in current files or a specific commit.               
                                                                                 
For further details, run:                                                        
git clang-format -h                                                              
                                                                                 
Requires Python 2.7                                                              
"""               

import argparse
import collections
import contextlib
import errno
import os
import re
import subprocess
import sys

usage = 'git clang-format [OPTIONS] [<commit>] [<commit>] [--] [<file>...]'

desc = '''
If zero or one commits are given, run clang-format on all lines that differ
between the working directory and <commit>, which defaults to HEAD.  Changes are
only applied to the working directory.

If two commits are given (requires --diff), run clang-format on all lines in the
second <commit> that differ from the first <commit>.

The following git-config settings set the default of the corresponding option:
  clangFormat.binary
  clangFormat.commit
  clangFormat.extension
  clangFormat.style
'''

# Name of the temporary index file in which save the output of clang-format.
# This file is created within the .git directory.
temp_index_basename = 'clang-format-index'


Range = collections.namedtuple('Range', 'start, count')


def main():
  config = load_git_config()

  # In order to keep '--' yet allow options after positionals, we need to
  # check for '--' ourselves.  (Setting nargs='*' throws away the '--', while
  # nargs=argparse.REMAINDER disallows options after positionals.)
  argv = sys.argv[1:]
  try:
    idx = argv.index('--')
  except ValueError:
    dash_dash = []
  else:
    dash_dash = argv[idx:]
    argv = argv[:idx]

  default_extensions = ','.join([
      # From clang/lib/Frontend/FrontendOptions.cpp, all lower case
      'c', 'h',  # C
      'm',  # ObjC
      'mm',  # ObjC++
      'cc', 'cp', 'cpp', 'c++', 'cxx', 'hpp',  # C++
      # Other languages that clang-format supports
      'proto', 'protodevel',  # Protocol Buffers
      'java',  # Java
      'js',  # JavaScript
      'ts',  # TypeScript
      ])

  p = argparse.ArgumentParser(
    usage=usage, formatter_class=argparse.RawDescriptionHelpFormatter,
    description=desc)
  p.add_argument('--binary',
                 default=config.get('clangformat.binary', 'clang-format'),
                 help='path to clang-format'),
  p.add_argument('--commit',
                 default=config.get('clangformat.commit', 'HEAD'),
                 help='default commit to use if none is specified'),
  p.add_argument('--diff', action='store_true',
                 help='print a diff instead of applying the changes')
  p.add_argument('--extensions',
                 default=config.get('clangformat.extensions',
                                    default_extensions),
                 help=('comma-separated list of file extensions to format, '
                       'excluding the period and case-insensitive')),
  p.add_argument('-f', '--force', action='store_true',
                 help='allow changes to unstaged files')
  p.add_argument('-p', '--patch', action='store_true',
                 help='select hunks interactively')
  p.add_argument('-q', '--quiet', action='count', default=0,
                 help='print less information')
  p.add_argument('--style',
                 default=config.get('clangformat.style', None),
                 help='passed to clang-format'),
  p.add_argument('-v', '--verbose', action='count', default=0,
                 help='print extra information')
  # We gather all the remaining positional arguments into 'args' since we need
  # to use some heuristics to determine whether or not <commit> was present.
  # However, to print pretty messages, we make use of metavar and help.
  p.add_argument('args', nargs='*', metavar='<commit>',
                 help='revision from which to compute the diff')
  p.add_argument('ignored', nargs='*', metavar='<file>...',
                 help='if specified, only consider differences in these files')
  opts = p.parse_args(argv)

  opts.verbose -= opts.quiet
  del opts.quiet

  commits, files = interpret_args(opts.args, dash_dash, opts.commit)
  if len(commits) > 1:
    if not opts.diff:
      die('--diff is required when two commits are given')
  else:
    if len(commits) > 2:
      die('at most two commits allowed; %d given' % len(commits))
  changed_lines = compute_diff_and_extract_lines(commits, files)
  if opts.verbose >= 1:
    ignored_files = set(changed_lines)
  filter_by_extension(changed_lines, opts.extensions.lower().split(','))
  if opts.verbose >= 1:
    ignored_files.difference_update(changed_lines)
    if ignored_files:
      print 'Ignoring changes in the following files (wrong extension):'
      for filename in ignored_files:
        print '   ', filename
    if changed_lines:
      print 'Running clang-format on the following files:'
      for filename in changed_lines:
        print '   ', filename
  if not changed_lines:
    print 'no modified files to format'
    return
  # The computed diff outputs absolute paths, so we must cd before accessing
  # those files.
  cd_to_toplevel()
  if len(commits) > 1:
    old_tree = commits[1]
    new_tree = run_clang_format_and_save_to_tree(changed_lines,
                                                 revision=commits[1],
                                                 binary=opts.binary,
                                                 style=opts.style)
  else:
    old_tree = create_tree_from_workdir(changed_lines)
    new_tree = run_clang_format_and_save_to_tree(changed_lines,
                                                 binary=opts.binary,
                                                 style=opts.style)
  if opts.verbose >= 1:
    print 'old tree:', old_tree
    print 'new tree:', new_tree
  if old_tree == new_tree:
    if opts.verbose >= 0:
      print 'clang-format did not modify any files'
  elif opts.diff:
    print_diff(old_tree, new_tree)
  else:
    changed_files = apply_changes(old_tree, new_tree, force=opts.force,
                                  patch_mode=opts.patch)
    if (opts.verbose >= 0 and not opts.patch) or opts.verbose >= 1:
      print 'changed files:'
      for filename in changed_files:
        print '   ', filename


def load_git_config(non_string_options=None):
  """Return the git configuration as a dictionary.

  All options are assumed to be strings unless in `non_string_options`, in which
  is a dictionary mapping option name (in lower case) to either "--bool" or
  "--int"."""
  if non_string_options is None:
    non_string_options = {}
  out = {}
  for entry in run('git', 'config', '--list', '--null').split('\0'):
    if entry:
      name, value = entry.split('\n', 1)
      if name in non_string_options:
        value = run('git', 'config', non_string_options[name], name)
      out[name] = value
  return out


def interpret_args(args, dash_dash, default_commit):
  """Interpret `args` as "[commits] [--] [files]" and return (commits, files).

  It is assumed that "--" and everything that follows has been removed from
  args and placed in `dash_dash`.

  If "--" is present (i.e., `dash_dash` is non-empty), the arguments to its
  left (if present) are taken as commits.  Otherwise, the arguments are checked
  from left to right if they are commits or files.  If commits are not given,
  a list with `default_commit` is used."""
  if dash_dash:
    if len(args) == 0:
      commits = [default_commit]
    else:
      commits = args
    for commit in commits:
      object_type = get_object_type(commit)
      if object_type not in ('commit', 'tag'):
        if object_type is None:
          die("'%s' is not a commit" % commit)
        else:
          die("'%s' is a %s, but a commit was expected" % (commit, object_type))
    files = dash_dash[1:]
  elif args:
    commits = []
    while args:
      if not disambiguate_revision(args[0]):
        break
      commits.append(args.pop(0))
    if not commits:
      commits = [default_commit]
    files = args
  else:
    commits = [default_commit]
    files = []
  return commits, files


def disambiguate_revision(value):
  """Returns True if `value` is a revision, False if it is a file, or dies."""
  # If `value` is ambiguous (neither a commit nor a file), the following
  # command will die with an appropriate error message.
  run('git', 'rev-parse', value, verbose=False)
  object_type = get_object_type(value)
  if object_type is None:
    return False
  if object_type in ('commit', 'tag'):
    return True
  die('`%s` is a %s, but a commit or filename was expected' %
      (value, object_type))


def get_object_type(value):
  """Returns a string description of an object's type, or None if it is not
  a valid git object."""
  cmd = ['git', 'cat-file', '-t', value]
  p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  stdout, stderr = p.communicate()
  if p.returncode != 0:
    return None
  return stdout.strip()


def compute_diff_and_extract_lines(commits, files):
  """Calls compute_diff() followed by extract_lines()."""
  diff_process = compute_diff(commits, files)
  changed_lines = extract_lines(diff_process.stdout)
  diff_process.stdout.close()
  diff_process.wait()
  if diff_process.returncode != 0:
    # Assume error was already printed to stderr.
    sys.exit(2)
  return changed_lines


def compute_diff(commits, files):
  """Return a subprocess object producing the diff from `commits`.

  The return value's `stdin` file object will produce a patch with the
  differences between the working directory and the first commit if a single
  one was specified, or the difference between both specified commits, filtered
  on `files` (if non-empty).  Zero context lines are used in the patch."""
  git_tool = 'diff-index'
  if len(commits) > 1:
    git_tool = 'diff-tree'
  cmd = ['git', git_tool, '-p', '-U0'] + commits + ['--']
  cmd.extend(files)
  p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
  p.stdin.close()
  return p


def extract_lines(patch_file):
  """Extract the changed lines in `patch_file`.

  The return value is a dictionary mapping filename to a list of (start_line,
  line_count) pairs.

  The input must have been produced with ``-U0``, meaning unidiff format with
  zero lines of context.  The return value is a dict mapping filename to a
  list of line `Range`s."""
  matches = {}
  for line in patch_file:
    match = re.search(r'^\+\+\+\ [^/]+/(.*)', line)
    if match:
      filename = match.group(1).rstrip('\r\n')
    match = re.search(r'^@@ -[0-9,]+ \+(\d+)(,(\d+))?', line)
    if match:
      start_line = int(match.group(1))
      line_count = 1
      if match.group(3):
        line_count = int(match.group(3))
      if line_count > 0:
        matches.setdefault(filename, []).append(Range(start_line, line_count))
  return matches


def filter_by_extension(dictionary, allowed_extensions):
  """Delete every key in `dictionary` that doesn't have an allowed extension.

  `allowed_extensions` must be a collection of lowercase file extensions,
  excluding the period."""
  allowed_extensions = frozenset(allowed_extensions)
  for filename in dictionary.keys():
    base_ext = filename.rsplit('.', 1)
    if len(base_ext) == 1 or base_ext[1].lower() not in allowed_extensions:
      del dictionary[filename]


def cd_to_toplevel():
  """Change to the top level of the git repository."""
  toplevel = run('git', 'rev-parse', '--show-toplevel')
  os.chdir(toplevel)


def create_tree_from_workdir(filenames):
  """Create a new git tree with the given files from the working directory.

  Returns the object ID (SHA-1) of the created tree."""
  return create_tree(filenames, '--stdin')


def run_clang_format_and_save_to_tree(changed_lines, revision=None,
                                      binary='clang-format', style=None):
  """Run clang-format on each file and save the result to a git tree.

  Returns the object ID (SHA-1) of the created tree."""
  def index_info_generator():
    for filename, line_ranges in changed_lines.iteritems():
      if revision:
        git_metadata_cmd = ['git', 'ls-tree',
                            '%s:%s' % (revision, os.path.dirname(filename)),
                            os.path.basename(filename)]
        git_metadata = subprocess.Popen(git_metadata_cmd, stdin=subprocess.PIPE,
                                        stdout=subprocess.PIPE)
        stdout = git_metadata.communicate()[0]
        mode = oct(int(stdout.split()[0], 8))
      else:
        mode = oct(os.stat(filename).st_mode)
      blob_id = clang_format_to_blob(filename, line_ranges,
                                     revision=revision,
                                     binary=binary,
                                     style=style)
      yield '%s %s\t%s' % (mode, blob_id, filename)
  return create_tree(index_info_generator(), '--index-info')


def create_tree(input_lines, mode):
  """Create a tree object from the given input.

  If mode is '--stdin', it must be a list of filenames.  If mode is
  '--index-info' is must be a list of values suitable for "git update-index
  --index-info", such as "<mode> <SP> <sha1> <TAB> <filename>".  Any other mode
  is invalid."""
  assert mode in ('--stdin', '--index-info')
  cmd = ['git', 'update-index', '--add', '-z', mode]
  with temporary_index_file():
    p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
    for line in input_lines:
      p.stdin.write('%s\0' % line)
    p.stdin.close()
    if p.wait() != 0:
      die('`%s` failed' % ' '.join(cmd))
    tree_id = run('git', 'write-tree')
    return tree_id


def clang_format_to_blob(filename, line_ranges, revision=None,
                         binary='clang-format', style=None):
  """Run clang-format on the given file and save the result to a git blob.

  Runs on the file in `revision` if not None, or on the file in the working
  directory if `revision` is None.

  Returns the object ID (SHA-1) of the created blob."""
  clang_format_cmd = [binary]
  if style:
    clang_format_cmd.extend(['-style='+style])
  clang_format_cmd.extend([
      '-lines=%s:%s' % (start_line, start_line+line_count-1)
      for start_line, line_count in line_ranges])
  if revision:
    clang_format_cmd.extend(['-assume-filename='+filename])
    git_show_cmd = ['git', 'cat-file', 'blob', '%s:%s' % (revision, filename)]
    git_show = subprocess.Popen(git_show_cmd, stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE)
    git_show.stdin.close()
    clang_format_stdin = git_show.stdout
  else:
    clang_format_cmd.extend([filename])
    git_show = None
    clang_format_stdin = subprocess.PIPE
  try:
    clang_format = subprocess.Popen(clang_format_cmd, stdin=clang_format_stdin,
                                    stdout=subprocess.PIPE)
    if clang_format_stdin == subprocess.PIPE:
      clang_format_stdin = clang_format.stdin
  except OSError as e:
    if e.errno == errno.ENOENT:
      die('cannot find executable "%s"' % binary)
    else:
      raise
  clang_format_stdin.close()
  hash_object_cmd = ['git', 'hash-object', '-w', '--path='+filename, '--stdin']
  hash_object = subprocess.Popen(hash_object_cmd, stdin=clang_format.stdout,
                                 stdout=subprocess.PIPE)
  clang_format.stdout.close()
  stdout = hash_object.communicate()[0]
  if hash_object.returncode != 0:
    die('`%s` failed' % ' '.join(hash_object_cmd))
  if clang_format.wait() != 0:
    die('`%s` failed' % ' '.join(clang_format_cmd))
  if git_show and git_show.wait() != 0:
    die('`%s` failed' % ' '.join(git_show_cmd))
  return stdout.rstrip('\r\n')


@contextlib.contextmanager
def temporary_index_file(tree=None):
  """Context manager for setting GIT_INDEX_FILE to a temporary file and deleting
  the file afterward."""
  index_path = create_temporary_index(tree)
  old_index_path = os.environ.get('GIT_INDEX_FILE')
  os.environ['GIT_INDEX_FILE'] = index_path
  try:
    yield
  finally:
    if old_index_path is None:
      del os.environ['GIT_INDEX_FILE']
    else:
      os.environ['GIT_INDEX_FILE'] = old_index_path
    os.remove(index_path)


def create_temporary_index(tree=None):
  """Create a temporary index file and return the created file's path.

  If `tree` is not None, use that as the tree to read in.  Otherwise, an
  empty index is created."""
  gitdir = run('git', 'rev-parse', '--git-dir')
  path = os.path.join(gitdir, temp_index_basename)
  if tree is None:
    tree = '--empty'
  run('git', 'read-tree', '--index-output='+path, tree)
  return path


def print_diff(old_tree, new_tree):
  """Print the diff between the two trees to stdout."""
  # We use the porcelain 'diff' and not plumbing 'diff-tree' because the output
  # is expected to be viewed by the user, and only the former does nice things
  # like color and pagination.
  #
  # We also only print modified files since `new_tree` only contains the files
  # that were modified, so unmodified files would show as deleted without the
  # filter.
  subprocess.check_call(['git', 'diff', '--diff-filter=M', old_tree, new_tree,
                         '--'])


def apply_changes(old_tree, new_tree, force=False, patch_mode=False):
  """Apply the changes in `new_tree` to the working directory.

  Bails if there are local changes in those files and not `force`.  If
  `patch_mode`, runs `git checkout --patch` to select hunks interactively."""
  changed_files = run('git', 'diff-tree', '--diff-filter=M', '-r', '-z',
                      '--name-only', old_tree,
                      new_tree).rstrip('\0').split('\0')
  if not force:
    unstaged_files = run('git', 'diff-files', '--name-status', *changed_files)
    if unstaged_files:
      print >>sys.stderr, ('The following files would be modified but '
                           'have unstaged changes:')
      print >>sys.stderr, unstaged_files
      print >>sys.stderr, 'Please commit, stage, or stash them first.'
      sys.exit(2)
  if patch_mode:
    # In patch mode, we could just as well create an index from the new tree
    # and checkout from that, but then the user will be presented with a
    # message saying "Discard ... from worktree".  Instead, we use the old
    # tree as the index and checkout from new_tree, which gives the slightly
    # better message, "Apply ... to index and worktree".  This is not quite
    # right, since it won't be applied to the user's index, but oh well.
    with temporary_index_file(old_tree):
      subprocess.check_call(['git', 'checkout', '--patch', new_tree])
    index_tree = old_tree
  else:
    with temporary_index_file(new_tree):
      run('git', 'checkout-index', '-a', '-f')
  return changed_files


def run(*args, **kwargs):
  stdin = kwargs.pop('stdin', '')
  verbose = kwargs.pop('verbose', True)
  strip = kwargs.pop('strip', True)
  for name in kwargs:
    raise TypeError("run() got an unexpected keyword argument '%s'" % name)
  p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                       stdin=subprocess.PIPE)
  stdout, stderr = p.communicate(input=stdin)
  if p.returncode == 0:
    if stderr:
      if verbose:
        print >>sys.stderr, '`%s` printed to stderr:' % ' '.join(args)
      print >>sys.stderr, stderr.rstrip()
    if strip:
      stdout = stdout.rstrip('\r\n')
    return stdout
  if verbose:
    print >>sys.stderr, '`%s` returned %s' % (' '.join(args), p.returncode)
  if stderr:
    print >>sys.stderr, stderr.rstrip()
  sys.exit(2)


def die(message):
  print >>sys.stderr, 'error:', message
  sys.exit(2)


if __name__ == '__main__':
  main()
