ZyX 06211cbe63 Unify imports
Now imports follow the following structure:

1. __future__ line: exactly one line allowed:

        from __future__ import (unicode_literals, division, absolute_import, print_function)

   (powerline.shell is the only exception due to problems with argparse).
2. Standard python library imports in a form `import X`.
3. Standard python library imports in a form `from X import Y`.
4. and 5. 2. and 3. for third-party (non-python and non-powerline imports).
6. 3. for powerline non-test imports.
7. and 8. 2. and 3. for powerline testing module imports.

Each list entry is separated by exactly one newline from another import. If
there is module docstring it goes between `# vim:` comment and `__future__`
import. So the structure containing all items is the following:

    #!/usr/bin/env python
    # vim:fileencoding=utf-8:noet

    '''Powerline super module'''

    import sys

    from argparse import ArgumentParser

    import psutil

    from colormath.color_diff import delta_e_cie2000

    from powerline.lib.unicode import u

    import tests.vim as vim_module

    from tests import TestCase

.
2014-09-01 00:25:24 +04:00

189 lines
5.1 KiB
Python

# vim:fileencoding=utf-8:noet
from __future__ import (unicode_literals, division, absolute_import, print_function)
import os
import sys
import re
from powerline.lib.vcs import get_branch_name, get_file_status
from powerline.lib.shell import readlines
_ref_pat = re.compile(br'ref:\s*refs/heads/(.+)')
def branch_name_from_config_file(directory, config_file):
try:
with open(config_file, 'rb') as f:
raw = f.read()
except EnvironmentError:
return os.path.basename(directory)
m = _ref_pat.match(raw)
if m is not None:
return m.group(1).decode('utf-8', 'replace')
return raw[:7]
def git_directory(directory):
path = os.path.join(directory, '.git')
if os.path.isfile(path):
with open(path, 'rb') as f:
raw = f.read()
if not raw.startswith(b'gitdir: '):
raise IOError('invalid gitfile format')
raw = raw[8:].decode(sys.getfilesystemencoding() or 'utf-8')
if raw[-1] == '\n':
raw = raw[:-1]
if not raw:
raise IOError('no path in gitfile')
return os.path.abspath(os.path.join(directory, raw))
else:
return path
class GitRepository(object):
__slots__ = ('directory', 'create_watcher')
def __init__(self, directory, create_watcher):
self.directory = os.path.abspath(directory)
self.create_watcher = create_watcher
def status(self, path=None):
'''Return status of repository or file.
Without file argument: returns status of the repository:
:First column: working directory status (D: dirty / space)
:Second column: index status (I: index dirty / space)
:Third column: presence of untracked files (U: untracked files / space)
:None: repository clean
With file argument: returns status of this file. Output is
equivalent to the first two columns of "git status --porcelain"
(except for merge statuses as they are not supported by libgit2).
'''
if path:
gitd = git_directory(self.directory)
# We need HEAD as without it using fugitive to commit causes the
# current file's status (and only the current file) to not be updated
# for some reason I cannot be bothered to figure out.
return get_file_status(
directory=self.directory,
dirstate_file=os.path.join(gitd, 'index'),
file_path=path,
ignore_file_name='.gitignore',
get_func=self.do_status,
create_watcher=self.create_watcher,
extra_ignore_files=tuple(os.path.join(gitd, x) for x in ('logs/HEAD', 'info/exclude')),
)
return self.do_status(self.directory, path)
def branch(self):
directory = git_directory(self.directory)
head = os.path.join(directory, 'HEAD')
return get_branch_name(
directory=directory,
config_file=head,
get_func=branch_name_from_config_file,
create_watcher=self.create_watcher,
)
try:
import pygit2 as git
class Repository(GitRepository):
@staticmethod
def ignore_event(path, name):
return False
def do_status(self, directory, path):
if path:
try:
status = git.Repository(directory).status_file(path)
except (KeyError, ValueError):
return None
if status == git.GIT_STATUS_CURRENT:
return None
else:
if status & git.GIT_STATUS_WT_NEW:
return '??'
if status & git.GIT_STATUS_IGNORED:
return '!!'
if status & git.GIT_STATUS_INDEX_NEW:
index_status = 'A'
elif status & git.GIT_STATUS_INDEX_DELETED:
index_status = 'D'
elif status & git.GIT_STATUS_INDEX_MODIFIED:
index_status = 'M'
else:
index_status = ' '
if status & git.GIT_STATUS_WT_DELETED:
wt_status = 'D'
elif status & git.GIT_STATUS_WT_MODIFIED:
wt_status = 'M'
else:
wt_status = ' '
return index_status + wt_status
else:
wt_column = ' '
index_column = ' '
untracked_column = ' '
for status in git.Repository(directory).status().values():
if status & git.GIT_STATUS_WT_NEW:
untracked_column = 'U'
continue
if status & (git.GIT_STATUS_WT_DELETED | git.GIT_STATUS_WT_MODIFIED):
wt_column = 'D'
if status & (
git.GIT_STATUS_INDEX_NEW
| git.GIT_STATUS_INDEX_MODIFIED
| git.GIT_STATUS_INDEX_DELETED
):
index_column = 'I'
r = wt_column + index_column + untracked_column
return r if r != ' ' else None
except ImportError:
class Repository(GitRepository):
@staticmethod
def ignore_event(path, name):
# Ignore changes to the index.lock file, since they happen
# frequently and dont indicate an actual change in the working tree
# status
return path.endswith('.git') and name == 'index.lock'
def _gitcmd(self, directory, *args):
return readlines(('git',) + args, directory)
def do_status(self, directory, path):
if path:
try:
return next(self._gitcmd(directory, 'status', '--porcelain', '--ignored', '--', path))[:2]
except StopIteration:
return None
else:
wt_column = ' '
index_column = ' '
untracked_column = ' '
for line in self._gitcmd(directory, 'status', '--porcelain'):
if line[0] == '?':
untracked_column = 'U'
continue
elif line[0] == '!':
continue
if line[0] != ' ':
index_column = 'I'
if line[1] != ' ':
wt_column = 'D'
r = wt_column + index_column + untracked_column
return r if r != ' ' else None