Update email adress and git respository adress.
[hgct.git] / ctcore.py
blobd613e60a4a6062167dd74affcb870c52fb44d11d
1 # Copyright (c) 2005 Fredrik Kuivinen <frekui@gmail.com>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License version 2 as
5 # published by the Free Software Foundation.
6 #
7 # This program is distributed in the hope that it will be useful,
8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 # GNU General Public License for more details.
12 # You should have received a copy of the GNU General Public License
13 # along with this program; if not, write to the Free Software
14 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 import sys, locale, codecs, sets
18 applicationName = 'Commit Tool'
19 shortName = 'ct'
20 version = 'v0.4'
22 executeMain = True
23 _settings = None
25 def settings():
26 global _settings
27 if not _settings:
28 from settings import Settings
29 _settings = Settings()
30 return _settings
32 DEBUG = 0
34 # PyQt3 and python 2.4 isn't currently available together on
35 # Debian/testing we do therefore use the following quite ugly work
36 # around. The module 'mysubprocess' is just a copy of the 'subprocess'
37 # module from the Python 2.4 distribution.
38 ver = sys.version_info
39 if ver[0] < 2 or (ver[0] == 2 and ver[1] <= 3):
40 import mysubprocess
41 subprocess = mysubprocess
42 else:
43 import subprocess
45 class File:
46 def __init__(self):
47 self.listViewItem = None
48 self.text = None
49 self.textW = None
50 self.patch = None
52 def getPatch(self):
53 if not self.patch:
54 self.patch = self.getPatchImpl()
56 return self.patch
58 class FileSet:
59 def __init__(self, addCallback, removeCallback):
60 self.addCallback = addCallback
61 self.removeCallback = removeCallback
62 self.files = sets.Set()
64 def add(self, file):
65 self.files.add(file)
66 self.addCallback(file)
68 def remove(self, file):
69 self.files.discard(file)
70 self.removeCallback(file)
72 def __iter__(self):
73 return self.files.__iter__()
75 def __len__(self):
76 return len(self.files)
78 class ProgramError(Exception):
79 def __init__(self, progStr, error):
80 self.progStr = progStr
81 self.error = error.rstrip()
83 def __str__(self):
84 return self.progStr + ': ' + self.error
86 # From http://kofoto.rosdahl.net/trac/wiki/UnicodeInPython
87 def getFileEncoding(f):
88 if hasattr(f, "encoding") and f.encoding:
89 return f.encoding
90 else:
91 return locale.getpreferredencoding()
93 def runProgram(prog, input=None, expectedexits=[0]):
94 debug('runProgram prog: ' + unicode(prog) + " input: " + unicode(input))
95 if type(prog) is str:
96 progStr = prog
97 else:
98 progStr = ' '.join(prog)
100 try:
101 pop = subprocess.Popen(prog,
102 shell = type(prog) is str,
103 stderr=subprocess.STDOUT,
104 stdout=subprocess.PIPE,
105 stdin=subprocess.PIPE)
106 except OSError, e:
107 debug("strerror: " + e.strerror)
108 raise ProgramError(progStr, e.strerror)
110 if input != None:
111 stdin = codecs.getwriter(getFileEncoding(pop.stdin))(pop.stdin)
112 stdin.write(input)
113 stdin.close()
114 else:
115 pop.stdin.close()
117 stdout = codecs.getreader(getFileEncoding(pop.stdout))(pop.stdout)
118 out = stdout.read()
119 code = pop.wait()
120 if code not in expectedexits:
121 debug("error output: " + out)
122 raise ProgramError(progStr, out)
123 debug("output: " + out.replace('\0', '\n'))
124 return out
126 def debug(str):
127 if DEBUG:
128 print str