aureooms/sak

View on GitHub
sak/git.py

Summary

Maintainability
C
1 day
Test Coverage
"""
    git module

    some git snippets freely derived from https://github.com/badele/gitcheck
"""


import os
import subprocess
import re
import functools
import lib.sys
from shlex import quote


def info(*args):

    def callback(d):
        lo = helper.locals(d)
        fr = {}
        to = {}

        branch = helper.branch(d)

        for remote in helper.remotes(d):
            if helper.hasbranch(d, remote, branch):
                fr[remote] = helper.pulls(d, remote, branch)
                to[remote] = helper.pushs(d, remote, branch)

        helper.pretty(d, lo, fr, to)

    return helper.wrap(args, callback)


def do(action, *args):

    def callback(d):
        print('%s \'%s\'' % (action, d))
        getattr(helper, action)(d)

    return helper.wrap(args, callback)


def update(*args):
    return do('update', *args)


def up(*args):
    return do('up', *args)


def pull(*args):
    return do('pull', *args)


def status(*args):
    return do('status', *args)


def diff(*args):
    return do('diff', *args)


def commit(*cmplxargs):

    args, dirs = helper.parsecmplx(*cmplxargs)

    def callback(d):
        print('%s \'%s\'' % ("commit", d))
        helper.commit(d, *args)

    return helper.wrap(dirs, callback)


def add(*cmplxargs):

    args, dirs = helper.parsecmplx(*cmplxargs)

    def callback(d):
        print('%s \'%s\'' % ("add", d))
        helper.add(d, *args)

    return helper.wrap(dirs, callback)


def push(*args):
    return do('push', *args)


def ls(*args):

    def callback(d):
        print(quote(d))

    return helper.wrap(args, callback)


def count(*args):

    n = [0]

    def callback(d):
        n[0] += 1

    helper.wrap(args, callback)

    print(n[0])


class helper(object):

    class exception(Exception):

        def __init__(self, what):
            Exception.__init__(self, what)

        def what(self):
            return self.args[0]

        def __repr__(self):
            return self.what()

    def check(args):
        for d in args:
            if not os.path.isdir(d):
                raise helper.exception(
                    '[Errno 2] No such file or directory: \'%s\'' % d)

    def wrap(args, callback):

        try:
            helper.check(args)
            helper.recursive(args, callback)

        except helper.exception as e:
            print(e)

    def parsecmplx(*cmplxargs):

        try:
            i = list(cmplxargs).index("--")
        except Exception as e:
            i = len(cmplxargs)

        return cmplxargs[:i], cmplxargs[i + 1:]

    def recursive(args, callback):
        if len(args) == 0:
            args = ['.']

        for d in args:

            try:

                l = [x for x in os.listdir(
                    d) if os.path.isdir(os.path.join(d, x))]
                if len(l) == 0:
                    continue
                if '.git' in l:
                    callback(d)
                else:
                    helper.recursive([os.path.join(d, x) for x in l], callback)

            except Exception as e:

                print("skipping", d, "because", e)

    BRANCH = re.compile(r'^\* (.*)')

    def branch(d):
        out, _, _ = lib.sys.call(['git', 'branch'], cwd=d)
        m = helper.BRANCH.match(out.decode())
        return None if m is None else m.group(1)

    def remotes(d):
        out, _, _ = lib.sys.call(['git', 'remote'], cwd=d)
        return out.decode().split('\n')[:-1]

    def update(d):
        subprocess.call(['git', 'remote', 'update'], cwd=d)

    def up(d):
        subprocess.call(['git', 'up'], cwd=d)

    def commit(d, *args):
        subprocess.call(['git', 'commit'] + list(args), cwd=d)

    def add(d, *args):
        subprocess.call(['git', 'add'] + list(args), cwd=d)

    def push(d):
        subprocess.call(['git', 'push'], cwd=d)

    def pull(d):
        subprocess.call(['git', 'pull'], cwd=d)

    def status(d):
        subprocess.call(['git', 'status'], cwd=d)

    def diff(d):
        subprocess.call(['git', 'diff'], cwd=d)

    def ls(d):
        pass

    def pulls(d, remote, branch):
        return helper.commits(d, 'HEAD', '%s/%s' % (remote, branch))

    def pushs(d, remote, branch):
        return helper.commits(d, '%s/%s' % (remote, branch), 'HEAD')

    def commits(d, a, b):
        out, _, _ = lib.sys.call(
            ['git', 'log', '%s..%s' % (a, b),  '--oneline'], cwd=d)
        return out.decode().split('\n')[:-1]

    def locals(d):
        out, _, _ = lib.sys.call(['git', 'status', '--porcelain', '-u'], cwd=d)
        return [c for c in out.decode().split('\n')[:-1]]

    def hasbranch(d, remote, branch):
        out, _, _ = lib.sys.call(['git', 'branch', '-r'], cwd=d)
        return out.decode().find('%s/%s' % (remote, branch)) != -1

    def pretty(d, lo, fr, to):
        r = [] if len(lo) == 0 else ['local[%d]' % len(lo)]
        for key in fr:
            if len(fr[key]) > 0 or len(to[key]) > 0:
                r.append('%s[pull:%d, push:%d]' %
                         (key, len(fr[key]), len(to[key])))

        if len(r) > 0:
            print(' '.join([d] + r))