# -*- coding: utf-8 -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
import ulib.base.i_need_py23

__all__ = ('is_cvsdir', 'CVSDir')

from os import path

from ulib.base.uio import _s
from ulib.base.base import updated
from ulib.base.paths import relpath
from ulib.base.procs import spawn, spawnall, spawn_redirect
from ulib.base.tmpfiles import mktempfile
from base import *

def cvscmd(*args, **kw):
    if isquiet(kw): return ('cvs', '-q') + args
    else: return ('cvs',) + args

def is_cvsdir(p):
    return path.isdir(path.join(p, 'CVS'))

class CVSDir(VcsDir):
    def __init__(self, p, rootdir=None):
        VcsDir.__init__(self, p, rootdir)

    __str__ = VcsDir.get_path
    __repr__ = VcsDir.get_path

    def get_vcs_name(self):
        return "cvs"

    def _is_vcsdir(self, p):
        return is_cvsdir(p)

    def _new_vcsdir(self, p, rootdir=False):
        vcsdir = CVSDir(p)
        if rootdir: vcsdir.rootdir = vcsdir
        return vcsdir

    def add(self, *files, **kw):
        basedir = self.get_path()
        cmds = []
        for file in files:
            cmds.append(cvscmd('add', relpath(file, basedir), **kw))
        return spawnall(*cmds, **kw)

    def remove(self, *files, **kw):
        basedir = self.get_path()
        cmds = []
        for file in files:
            file = relpath(file, basedir)
            cmds.append(('rm', file))
            cmds.append(cvscmd('remove', file, **kw))
        return spawnall(*cmds, **kw)

    def copy(self, fromf, tof, **kw):
        basedir = self.get_path()
        fromf = relpath(fromf, basedir)
        tof = relpath(tof, basedir)
        return spawnall(('cp', fromf, tof),
                        cvscmd('add', tof, **kw),
                        **kw)

    def move(self, fromf, tof, **kw):
        basedir = self.get_path()
        fromf = relpath(fromf, basedir)
        tof = relpath(tof, basedir)
        return spawnall(('mv', fromf, tof),
                        cvscmd('remove', fromf, **kw),
                        cvscmd('add', tof, **kw),
                        **kw)

    def mkdir(self, dir, **kw):
        basedir = self.get_path()
        dir = relpath(dir, basedir)
        return spawnall(('mkdir', '-p', dir),
                        cvscmd('add', dir, **kw),
                        **kw)

    def commit(self, message=None, *files, **kw):
        basedir = self.get_path()
        folded = self.autofold(**kw)
        try:
            if message is None: cmd = cvscmd('ci', **kw)
            else: cmd = cvscmd('ci', '-m', message, **kw)
            cmd = list(cmd)

            if not files: files = ['.']
            for file in files:
                cmd.append(relpath(file, basedir))
            return spawn(*cmd, **kw)
        finally:
            if folded: self.autounfold(**kw)

    def status(self, **kw):
        folded = self.autofold(**kw)
        try:
            return spawn(*cvscmd('update', **kw), **kw)
        finally:
            if folded: self.autounfold(**kw)

    def update(self, **kw):
        folded = self.autofold(**kw)
        try:
            return spawn(*cvscmd('update', **kw), **kw)
        finally:
            if folded: self.autounfold(**kw)

    def tag(self, name, message=None, **kw):
        if self._tag_rootdir and not self.is_rootdir():
            return self.get_rootdir().tag(name, message, **kw)
        folded = self.autofold(**kw)
        try:
            return spawn(*cvscmd('tag', name, relpath(self.get_path()), **kw), **kw)
        finally:
            if folded: self.autounfold(**kw)

    def diff_to(self, outfile=None, compare_with=None, **kw):
        folded = self.autofold(**kw)
        try:
            cmd = cvscmd('diff', '-u')
            if compare_with is not None: cmd += ('-r', _s(compare_with))
            if outfile is None: outfile = mktempfile()
            status, _, _ = spawn_redirect(*cmd, **updated(kw, stdout=outfile))
            return status, outfile
        finally:
            if folded: self.autounfold(**kw)
