# Copyright (c) 2005 Fredrik Kuivinen <freku045@student.liu.se>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

import sys, locale, codecs, sets

applicationName = 'Commit Tool'
shortName = 'ct'
version = 'v0.4'

executeMain = True
_settings = None

def settings():
    global _settings
    if not _settings:
        from settings import Settings
        _settings = Settings()
    return _settings

DEBUG = 0

# PyQt3 and python 2.4 isn't currently available together on
# Debian/testing we do therefore use the following quite ugly work
# around. The module 'mysubprocess' is just a copy of the 'subprocess'
# module from the Python 2.4 distribution.
ver = sys.version_info
if ver[0] < 2 or (ver[0] == 2 and ver[1] <= 3):
    import mysubprocess
    subprocess = mysubprocess
else:
    import subprocess

class File:
    def __init__(self):
        self.listViewItem = None
        self.text = None
        self.textW = None
        self.patch = None

    def getPatch(self):
        if not self.patch:
            self.patch = self.getPatchImpl()

        return self.patch

class FileSet:
    def __init__(self, addCallback, removeCallback):
        self.addCallback = addCallback
        self.removeCallback = removeCallback
        self.files = sets.Set()

    def add(self, file):
        self.files.add(file)
        self.addCallback(file)
        
    def remove(self, file):
        self.files.discard(file)
        self.removeCallback(file)

    def __iter__(self):
        return self.files.__iter__()

    def __len__(self):
        return len(self.files)

class ProgramError(Exception):
    def __init__(self, progStr, error):
        self.progStr = progStr
        self.error = error.rstrip()

    def __str__(self):
        return self.progStr + ': ' + self.error

# From http://kofoto.rosdahl.net/trac/wiki/UnicodeInPython
def getFileEncoding(f):
    if hasattr(f, "encoding") and f.encoding:
        return f.encoding
    else:
        return locale.getpreferredencoding()

def runProgram(prog, input=None, expectedexits=[0]):
    debug('runProgram prog: ' + unicode(prog) + " input: " + unicode(input))
    if type(prog) is str:
        progStr = prog
    else:
        progStr = ' '.join(prog)
    
    try:
        pop = subprocess.Popen(prog,
                               shell = type(prog) is str,
                               stderr=subprocess.STDOUT,
                               stdout=subprocess.PIPE,
                               stdin=subprocess.PIPE)
    except OSError, e:
        debug("strerror: " + e.strerror)
        raise ProgramError(progStr, e.strerror)

    if input != None:
        stdin = codecs.getwriter(getFileEncoding(pop.stdin))(pop.stdin)
        stdin.write(input)
        stdin.close()
    else:
        pop.stdin.close()

    stdout = codecs.getreader(getFileEncoding(pop.stdout))(pop.stdout)
    out = stdout.read()
    code = pop.wait()
    if code not in expectedexits:
        debug("error output: " + out)
        raise ProgramError(progStr, out)
    debug("output: " + out.replace('\0', '\n'))
    return out

def debug(str):
    if DEBUG:
        print str
