Commits

Michał Górny  committed bdedc2a

Move the VCS submodules into 'SmartLiveRebuild.vcs' namespace.

  • Participants
  • Parent commits 1ee859c

Comments (0)

Files changed (12)

File SmartLiveRebuild/core.py

 									vcses[vcs] = None
 								else:
 									try:
-										modname = 'SmartLiveRebuild.%s' % vcs
+										modname = 'SmartLiveRebuild.vcs.%s' % vcs
 										vcses[vcs] = __import__(modname, globals(), locals(), ['myvcs']).myvcs
 									except ImportError:
 										vcses[vcs] = None

File SmartLiveRebuild/cvs.py

-import hashlib, tempfile
-
-from SmartLiveRebuild.vcs import VCSSupport
-
-class CVSSupport(VCSSupport):
-	reqenv = ['ECVS_AUTH', 'ECVS_CVS_COMMAND', 'ECVS_MODULE', 'ECVS_SERVER', 'ECVS_TOP_DIR', 'ECVS_USER']
-	optenv = ['ECVS_BRANCH', 'ECVS_CLEAN', 'ECVS_LOCAL', 'ECVS_LOCALNAME', 'ECVS_PASS',
-			'ECVS_RUNAS', 'ECVS_UP_OPTS', 'ECVS_VERSION']
-
-	def __init__(self, *args):
-		VCSSupport.__init__(self, *args)
-		if self.env['ECVS_RUNAS']:
-			raise NotImplementedError('ECVS_RUNAS is not implemented (yet).')
-		elif self.env['ECVS_AUTH'] != 'pserver':
-			raise NotImplementedError('ECVS_AUTH=%s while only pserver is supported.' % self.env['ECVS_AUTH'])
-
-	def getpath(self):
-		return '%s/%s' % (self.env['ECVS_TOP_DIR'], self.env['ECVS_LOCALNAME'] or self.env['ECVS_MODULE'])
-
-	def __str__(self):
-		return '%s (%s)' % (self.env['ECVS_SERVER'], self.env['ECVS_MODULE']) or VCSSupport.__str__(self)
-
-	def getsavedrev(self):
-		return self.env['ECVS_VERSION']
-
-	def getrev(self):
-		inp = self.call(['find', self.getpath()] + '-ipath */CVS/Entries -exec cat {} +'.split()).split('\n')
-		del inp[-1] # drop the trailing newline for sorting
-		inp.sort()
-		inp.append('') # and readd it
-		hasher = hashlib.sha1()
-		hasher.update('\n'.join(inp))
-
-		return hasher.hexdigest()
-
-	def getupdatecmd(self):
-		opts = []
-		if self.env['ECVS_LOCAL']:
-			opts.append('-l')
-		if self.env['ECVS_BRANCH']:
-			opts.append('-r%s' % self.env['ECVS_BRANCH'])
-		if self.env['ECVS_CLEAN']:
-			opts.append('-C')
-
-		# XXX: server switching?
-
-		login_root = ':%s:%s:%s@%s' % (self.env['ECVS_AUTH'], self.env['ECVS_USER'],
-				self.env['ECVS_PASS'], self.env['ECVS_SERVER'])
-		login_cmd = '%s -f -d "%s" login' % (self.env['ECVS_CVS_COMMAND'], login_root)
-		up_root = ':%s:%s@%s' % (self.env['ECVS_AUTH'], self.env['ECVS_USER'],
-				self.env['ECVS_SERVER'])
-		up_cmd = '%s -f -d "%s" update %s %s' % (self.env['ECVS_CVS_COMMAND'], up_root,
-				self.env['ECVS_UP_OPTS'], ' '.join(opts))
-
-		# CVS is stupid as hell and tries to close STDOUT, which is
-		# redirected... making long story short, we need to do some
-		# random magic to make things work with our Popen()...
-		stdout_cmd = 'exec 2>&1'
-
-		cvs_passfile = tempfile.NamedTemporaryFile(delete=False)
-		env_cmd = 'export CVS_PASSFILE="%s" HOME=' % cvs_passfile.name
-		trap_cmd = 'trap \'rm -f "%s"\' EXIT' % cvs_passfile.name
-
-		cmd = '; '.join([trap_cmd, env_cmd, stdout_cmd, login_cmd, up_cmd])
-
-		return cmd
-
-myvcs = CVSSupport

File SmartLiveRebuild/git.py

-import subprocess, sys
-
-from SmartLiveRebuild.vcs import VCSSupport, NonLiveEbuild
-
-class GitSupport(VCSSupport):
-	reqenv = ['EGIT_BRANCH', 'EGIT_PROJECT', 'EGIT_STORE_DIR', 'EGIT_UPDATE_CMD']
-	optenv = ['EGIT_COMMIT', 'EGIT_DIFFSTAT_CMD', 'EGIT_HAS_SUBMODULES', 'EGIT_OPTIONS', 'EGIT_REPO_URI', 'EGIT_VERSION']
-
-	def __init__(self, *args):
-		VCSSupport.__init__(self, *args)
-		if self.env['EGIT_COMMIT'] and self.env['EGIT_COMMIT'] != self.env['EGIT_BRANCH']:
-			raise NonLiveEbuild('EGIT_COMMIT set, package is not really a live one')
-
-	def getpath(self):
-		return '%s/%s' % (self.env['EGIT_STORE_DIR'], self.env['EGIT_PROJECT'])
-
-	def __str__(self):
-		return self.env['EGIT_REPO_URI'] or VCSSupport.__str__(self)
-
-	def getsavedrev(self):
-		return self.env['EGIT_VERSION']
-
-	def getrev(self):
-		branch = self.env['EGIT_BRANCH']
-		if self.env['EGIT_HAS_SUBMODULES']:
-			branch = 'origin/%s' % branch
-		return self.call(['git', 'rev-parse', branch]).split('\n')[0]
-
-	def getupdatecmd(self):
-		if self.env['EGIT_HAS_SUBMODULES']:
-			return '%s %s' % (self.env['EGIT_UPDATE_CMD'], self.env['EGIT_OPTIONS'])
-		else:
-			return '%s %s origin %s:%s' % (self.env['EGIT_UPDATE_CMD'], self.env['EGIT_OPTIONS'], self.env['EGIT_BRANCH'], self.env['EGIT_BRANCH'])
-
-	def diffstat(self, oldrev, newrev):
-		subprocess.Popen('%s %s..%s' % (self.env['EGIT_DIFFSTAT_CMD'] or 'git diff', oldrev, newrev), stdout=sys.stderr, shell=True).wait()
-
-myvcs = GitSupport

File SmartLiveRebuild/mercurial.py

-import os.path, subprocess, sys
-import portage
-
-from SmartLiveRebuild.vcs import VCSSupport, NonLiveEbuild
-
-class HgSupport(VCSSupport):
-	reqenv = ['EHG_PROJECT', 'EHG_PULL_CMD', 'EHG_REPO_URI']
-	optenv = ['EHG_REVISION']
-
-	trustopt = ['--config', 'trusted.users=portage']
-
-	def __init__(self, *args):
-		VCSSupport.__init__(self, *args)
-		if self.env['EHG_REVISION'] and self.env['EHG_REVISION'] != 'tip':
-			raise NonLiveEbuild('EHG_REVISION set, package is not really a live one')
-
-	def getpath(self):
-		dd = portage.settings['PORTAGE_ACTUAL_DISTDIR'] or portage.settings['DISTDIR']
-		bn = os.path.basename(self.env['EHG_REPO_URI']) or os.path.basename(os.path.dirname(self.env['EHG_REPO_URI']))
-		assert (bn != '')
-
-		return '%s/hg-src/%s/%s' % (dd, self.env['EHG_PROJECT'], bn)
-
-	def __str__(self):
-		return self.env['EHG_REPO_URI'] or VCSSupport.__str__(self)
-
-	def getrev(self):
-		return self.call(['hg', 'tip', '--template', '{node}'] + self.trustopt)
-
-	def getupdatecmd(self):
-		return ' '.join([self.env['EHG_PULL_CMD']] + self.trustopt)
-
-	def diffstat(self, oldrev, newrev):
-		subprocess.Popen(['hg', 'diff', '--stat', '-r', oldrev, '-r', newrev] + self.trustopt, stdout=sys.stderr).wait()
-
-myvcs = HgSupport

File SmartLiveRebuild/subversion.py

-import re
-
-from SmartLiveRebuild.vcs import VCSSupport, NonLiveEbuild
-
-class SvnSupport(VCSSupport):
-	reqenv = ['ESVN_STORE_DIR', 'ESVN_UPDATE_CMD', 'ESVN_WC_PATH']
-	optenv = ['ESVN_REVISION', 'ESVN_OPTIONS', 'ESVN_PASSWORD', 'ESVN_REPO_URI', 'ESVN_USER', 'ESVN_WC_REVISION']
-
-	revre = re.compile('(?m)^Last Changed Rev: (\d+)$')
-
-	def __init__(self, *args):
-		VCSSupport.__init__(self, *args)
-		if self.env['ESVN_REPO_URI'] and self.env['ESVN_REPO_URI'].find('@') != -1:
-			raise NonLiveEbuild('ESVN_REPO_URI specifies revision, package is not really a live one')
-		elif self.env['ESVN_REVISION']:
-			raise NonLiveEbuild('ESVN_REVISION set, package is not really a live one')
-
-	def getpath(self):
-		return self.env['ESVN_WC_PATH']
-
-	def __str__(self):
-		return self.env['ESVN_REPO_URI'] or VCSSupport.__str__(self)
-
-	def getsavedrev(self):
-		return self.env['ESVN_WC_REVISION']
-
-	def getrev(self):
-		svninfo = self.call(['svn', '--config-dir', '%s/.subversion' % self.env['ESVN_STORE_DIR'], 'info'])
-		m = self.revre.search(svninfo)
-		return m.group(1) if m is not None else None
-
-	@staticmethod
-	def revcmp(oldrev, newrev):
-		return oldrev >= newrev
-
-	def getupdatecmd(self):
-		cmd = '%s %s --config-dir %s/.subversion' % (self.env['ESVN_UPDATE_CMD'], self.env['ESVN_OPTIONS'], self.env['ESVN_STORE_DIR'])
-		if self.env['ESVN_USER']:
-			cmd += ' --user "%s" --password "%s"' % (self.env['ESVN_USER'], self.env['ESVN_PASSWORD'])
-		return cmd
-
-myvcs = SvnSupport

File SmartLiveRebuild/vcs.py

-import os, shutil, subprocess, sys
-
-from SmartLiveRebuild.output import out
-
-class NonLiveEbuild(Exception):
-	pass
-
-class VCSSupport:
-	reqenv = []
-	optenv = []
-
-	def bashparse(self, envf, vars, f):
-		f.seek(0, 0)
-		f.truncate(0)
-		shutil.copyfileobj(envf, f)
-		f.flush()
-
-		script = 'source "%s"||exit 1;%s' % (f.name,
-			';echo -ne "\\0";'.join(['echo -n "${%s}"' % x for x in vars]))
-
-		return dict(zip(vars, self.call(['bash', '-c', script]).split('\0')))
-
-	def __init__(self, cpv, envf, tmpf, opts):
-		self.cpv = [cpv]
-		self.env = self.bashparse(envf, self.reqenv + self.optenv, tmpf)
-		self._opts = opts
-
-		missingvars = [v for v in self.reqenv if self.env[v] == '']
-		if len(missingvars) > 0:
-			raise KeyError('Environment does not declare: %s' % self.reqenv)
-
-	def getpath(self):
-		raise NotImplementedError('VCS class needs to override getpath()')
-
-	def append(self, vcs):
-		if not isinstance(vcs, self.__class__):
-			raise ValueError('Unable to append %s to %s' % (vcs.__class__, self.__class__))
-		self.cpv.append(vcs.cpv[0])
-
-	def getsavedrev(self):
-		return None
-
-	def getrev(self):
-		raise NotImplementedError('VCS class needs to override getrev() or update()')
-
-	@staticmethod
-	def revcmp(oldrev, newrev):
-		return oldrev == newrev
-
-	@staticmethod
-	def call(cmd):
-		p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
-		ret = p.communicate()[0].decode('utf8')
-		if p.wait() != 0:
-			raise SystemError('Command failed: %s' % cmd)
-		return ret
-
-	def getupdatecmd(self):
-		raise NotImplementedError('VCS class needs to override getupdatecmd()')
-
-	def diffstat(self, oldrev, newrev):
-		pass
-
-	def startupdate(self):
-		out.s2(str(self))
-		os.chdir(self.getpath())
-		self.oldrev = (not self._opts.local_rev and self.getsavedrev()) or self.getrev()
-
-		if self._opts.network:
-			cmd = self.getupdatecmd()
-			out.s3(cmd)
-			self.subprocess = subprocess.Popen(cmd, stdout=sys.stderr, shell=True)
-		else:
-			self.subprocess = None
-
-		return self.subprocess
-
-	def endupdate(self, blocking = False):
-		if self.subprocess is None:
-			ret = 0
-		elif blocking:
-			ret = self.subprocess.wait()
-		else:
-			ret = self.subprocess.poll()
-			if ret is None:
-				return None
-
-		if ret == 0:
-			os.chdir(self.getpath())
-			newrev = self.getrev()
-			if self._opts.jobs > 1:
-				out.s2(str(self))
-
-			if self.revcmp(self.oldrev, newrev):
-				out.s3('at rev %s%s%s (no changes)' % (out.green, self.oldrev, out.reset))
-				return False
-			else:
-				self.diffstat(self.oldrev, newrev)
-				out.s3('update from %s%s%s to %s%s%s' % (out.green, self.oldrev, out.reset, out.lime, newrev, out.reset))
-				return True
-		else:
-			raise Exception('update command returned non-zero result')
-
-	def abortupdate(self):
-		if self.subprocess is not None:
-			self.subprocess.terminate()
-
-	def __str__(self):
-		return ', '.join(self.cpv)

File SmartLiveRebuild/vcs/__init__.py

+import os, shutil, subprocess, sys
+
+from SmartLiveRebuild.output import out
+
+class NonLiveEbuild(Exception):
+	pass
+
+class VCSSupport:
+	reqenv = []
+	optenv = []
+
+	def bashparse(self, envf, vars, f):
+		f.seek(0, 0)
+		f.truncate(0)
+		shutil.copyfileobj(envf, f)
+		f.flush()
+
+		script = 'source "%s"||exit 1;%s' % (f.name,
+			';echo -ne "\\0";'.join(['echo -n "${%s}"' % x for x in vars]))
+
+		return dict(zip(vars, self.call(['bash', '-c', script]).split('\0')))
+
+	def __init__(self, cpv, envf, tmpf, opts):
+		self.cpv = [cpv]
+		self.env = self.bashparse(envf, self.reqenv + self.optenv, tmpf)
+		self._opts = opts
+
+		missingvars = [v for v in self.reqenv if self.env[v] == '']
+		if len(missingvars) > 0:
+			raise KeyError('Environment does not declare: %s' % self.reqenv)
+
+	def getpath(self):
+		raise NotImplementedError('VCS class needs to override getpath()')
+
+	def append(self, vcs):
+		if not isinstance(vcs, self.__class__):
+			raise ValueError('Unable to append %s to %s' % (vcs.__class__, self.__class__))
+		self.cpv.append(vcs.cpv[0])
+
+	def getsavedrev(self):
+		return None
+
+	def getrev(self):
+		raise NotImplementedError('VCS class needs to override getrev() or update()')
+
+	@staticmethod
+	def revcmp(oldrev, newrev):
+		return oldrev == newrev
+
+	@staticmethod
+	def call(cmd):
+		p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+		ret = p.communicate()[0].decode('utf8')
+		if p.wait() != 0:
+			raise SystemError('Command failed: %s' % cmd)
+		return ret
+
+	def getupdatecmd(self):
+		raise NotImplementedError('VCS class needs to override getupdatecmd()')
+
+	def diffstat(self, oldrev, newrev):
+		pass
+
+	def startupdate(self):
+		out.s2(str(self))
+		os.chdir(self.getpath())
+		self.oldrev = (not self._opts.local_rev and self.getsavedrev()) or self.getrev()
+
+		if self._opts.network:
+			cmd = self.getupdatecmd()
+			out.s3(cmd)
+			self.subprocess = subprocess.Popen(cmd, stdout=sys.stderr, shell=True)
+		else:
+			self.subprocess = None
+
+		return self.subprocess
+
+	def endupdate(self, blocking = False):
+		if self.subprocess is None:
+			ret = 0
+		elif blocking:
+			ret = self.subprocess.wait()
+		else:
+			ret = self.subprocess.poll()
+			if ret is None:
+				return None
+
+		if ret == 0:
+			os.chdir(self.getpath())
+			newrev = self.getrev()
+			if self._opts.jobs > 1:
+				out.s2(str(self))
+
+			if self.revcmp(self.oldrev, newrev):
+				out.s3('at rev %s%s%s (no changes)' % (out.green, self.oldrev, out.reset))
+				return False
+			else:
+				self.diffstat(self.oldrev, newrev)
+				out.s3('update from %s%s%s to %s%s%s' % (out.green, self.oldrev, out.reset, out.lime, newrev, out.reset))
+				return True
+		else:
+			raise Exception('update command returned non-zero result')
+
+	def abortupdate(self):
+		if self.subprocess is not None:
+			self.subprocess.terminate()
+
+	def __str__(self):
+		return ', '.join(self.cpv)

File SmartLiveRebuild/vcs/cvs.py

+import hashlib, tempfile
+
+from SmartLiveRebuild.vcs import VCSSupport
+
+class CVSSupport(VCSSupport):
+	reqenv = ['ECVS_AUTH', 'ECVS_CVS_COMMAND', 'ECVS_MODULE', 'ECVS_SERVER', 'ECVS_TOP_DIR', 'ECVS_USER']
+	optenv = ['ECVS_BRANCH', 'ECVS_CLEAN', 'ECVS_LOCAL', 'ECVS_LOCALNAME', 'ECVS_PASS',
+			'ECVS_RUNAS', 'ECVS_UP_OPTS', 'ECVS_VERSION']
+
+	def __init__(self, *args):
+		VCSSupport.__init__(self, *args)
+		if self.env['ECVS_RUNAS']:
+			raise NotImplementedError('ECVS_RUNAS is not implemented (yet).')
+		elif self.env['ECVS_AUTH'] != 'pserver':
+			raise NotImplementedError('ECVS_AUTH=%s while only pserver is supported.' % self.env['ECVS_AUTH'])
+
+	def getpath(self):
+		return '%s/%s' % (self.env['ECVS_TOP_DIR'], self.env['ECVS_LOCALNAME'] or self.env['ECVS_MODULE'])
+
+	def __str__(self):
+		return '%s (%s)' % (self.env['ECVS_SERVER'], self.env['ECVS_MODULE']) or VCSSupport.__str__(self)
+
+	def getsavedrev(self):
+		return self.env['ECVS_VERSION']
+
+	def getrev(self):
+		inp = self.call(['find', self.getpath()] + '-ipath */CVS/Entries -exec cat {} +'.split()).split('\n')
+		del inp[-1] # drop the trailing newline for sorting
+		inp.sort()
+		inp.append('') # and readd it
+		hasher = hashlib.sha1()
+		hasher.update('\n'.join(inp))
+
+		return hasher.hexdigest()
+
+	def getupdatecmd(self):
+		opts = []
+		if self.env['ECVS_LOCAL']:
+			opts.append('-l')
+		if self.env['ECVS_BRANCH']:
+			opts.append('-r%s' % self.env['ECVS_BRANCH'])
+		if self.env['ECVS_CLEAN']:
+			opts.append('-C')
+
+		# XXX: server switching?
+
+		login_root = ':%s:%s:%s@%s' % (self.env['ECVS_AUTH'], self.env['ECVS_USER'],
+				self.env['ECVS_PASS'], self.env['ECVS_SERVER'])
+		login_cmd = '%s -f -d "%s" login' % (self.env['ECVS_CVS_COMMAND'], login_root)
+		up_root = ':%s:%s@%s' % (self.env['ECVS_AUTH'], self.env['ECVS_USER'],
+				self.env['ECVS_SERVER'])
+		up_cmd = '%s -f -d "%s" update %s %s' % (self.env['ECVS_CVS_COMMAND'], up_root,
+				self.env['ECVS_UP_OPTS'], ' '.join(opts))
+
+		# CVS is stupid as hell and tries to close STDOUT, which is
+		# redirected... making long story short, we need to do some
+		# random magic to make things work with our Popen()...
+		stdout_cmd = 'exec 2>&1'
+
+		cvs_passfile = tempfile.NamedTemporaryFile(delete=False)
+		env_cmd = 'export CVS_PASSFILE="%s" HOME=' % cvs_passfile.name
+		trap_cmd = 'trap \'rm -f "%s"\' EXIT' % cvs_passfile.name
+
+		cmd = '; '.join([trap_cmd, env_cmd, stdout_cmd, login_cmd, up_cmd])
+
+		return cmd
+
+myvcs = CVSSupport

File SmartLiveRebuild/vcs/git.py

+import subprocess, sys
+
+from SmartLiveRebuild.vcs import VCSSupport, NonLiveEbuild
+
+class GitSupport(VCSSupport):
+	reqenv = ['EGIT_BRANCH', 'EGIT_PROJECT', 'EGIT_STORE_DIR', 'EGIT_UPDATE_CMD']
+	optenv = ['EGIT_COMMIT', 'EGIT_DIFFSTAT_CMD', 'EGIT_HAS_SUBMODULES', 'EGIT_OPTIONS', 'EGIT_REPO_URI', 'EGIT_VERSION']
+
+	def __init__(self, *args):
+		VCSSupport.__init__(self, *args)
+		if self.env['EGIT_COMMIT'] and self.env['EGIT_COMMIT'] != self.env['EGIT_BRANCH']:
+			raise NonLiveEbuild('EGIT_COMMIT set, package is not really a live one')
+
+	def getpath(self):
+		return '%s/%s' % (self.env['EGIT_STORE_DIR'], self.env['EGIT_PROJECT'])
+
+	def __str__(self):
+		return self.env['EGIT_REPO_URI'] or VCSSupport.__str__(self)
+
+	def getsavedrev(self):
+		return self.env['EGIT_VERSION']
+
+	def getrev(self):
+		branch = self.env['EGIT_BRANCH']
+		if self.env['EGIT_HAS_SUBMODULES']:
+			branch = 'origin/%s' % branch
+		return self.call(['git', 'rev-parse', branch]).split('\n')[0]
+
+	def getupdatecmd(self):
+		if self.env['EGIT_HAS_SUBMODULES']:
+			return '%s %s' % (self.env['EGIT_UPDATE_CMD'], self.env['EGIT_OPTIONS'])
+		else:
+			return '%s %s origin %s:%s' % (self.env['EGIT_UPDATE_CMD'], self.env['EGIT_OPTIONS'], self.env['EGIT_BRANCH'], self.env['EGIT_BRANCH'])
+
+	def diffstat(self, oldrev, newrev):
+		subprocess.Popen('%s %s..%s' % (self.env['EGIT_DIFFSTAT_CMD'] or 'git diff', oldrev, newrev), stdout=sys.stderr, shell=True).wait()
+
+myvcs = GitSupport

File SmartLiveRebuild/vcs/mercurial.py

+import os.path, subprocess, sys
+import portage
+
+from SmartLiveRebuild.vcs import VCSSupport, NonLiveEbuild
+
+class HgSupport(VCSSupport):
+	reqenv = ['EHG_PROJECT', 'EHG_PULL_CMD', 'EHG_REPO_URI']
+	optenv = ['EHG_REVISION']
+
+	trustopt = ['--config', 'trusted.users=portage']
+
+	def __init__(self, *args):
+		VCSSupport.__init__(self, *args)
+		if self.env['EHG_REVISION'] and self.env['EHG_REVISION'] != 'tip':
+			raise NonLiveEbuild('EHG_REVISION set, package is not really a live one')
+
+	def getpath(self):
+		dd = portage.settings['PORTAGE_ACTUAL_DISTDIR'] or portage.settings['DISTDIR']
+		bn = os.path.basename(self.env['EHG_REPO_URI']) or os.path.basename(os.path.dirname(self.env['EHG_REPO_URI']))
+		assert (bn != '')
+
+		return '%s/hg-src/%s/%s' % (dd, self.env['EHG_PROJECT'], bn)
+
+	def __str__(self):
+		return self.env['EHG_REPO_URI'] or VCSSupport.__str__(self)
+
+	def getrev(self):
+		return self.call(['hg', 'tip', '--template', '{node}'] + self.trustopt)
+
+	def getupdatecmd(self):
+		return ' '.join([self.env['EHG_PULL_CMD']] + self.trustopt)
+
+	def diffstat(self, oldrev, newrev):
+		subprocess.Popen(['hg', 'diff', '--stat', '-r', oldrev, '-r', newrev] + self.trustopt, stdout=sys.stderr).wait()
+
+myvcs = HgSupport

File SmartLiveRebuild/vcs/subversion.py

+import re
+
+from SmartLiveRebuild.vcs import VCSSupport, NonLiveEbuild
+
+class SvnSupport(VCSSupport):
+	reqenv = ['ESVN_STORE_DIR', 'ESVN_UPDATE_CMD', 'ESVN_WC_PATH']
+	optenv = ['ESVN_REVISION', 'ESVN_OPTIONS', 'ESVN_PASSWORD', 'ESVN_REPO_URI', 'ESVN_USER', 'ESVN_WC_REVISION']
+
+	revre = re.compile('(?m)^Last Changed Rev: (\d+)$')
+
+	def __init__(self, *args):
+		VCSSupport.__init__(self, *args)
+		if self.env['ESVN_REPO_URI'] and self.env['ESVN_REPO_URI'].find('@') != -1:
+			raise NonLiveEbuild('ESVN_REPO_URI specifies revision, package is not really a live one')
+		elif self.env['ESVN_REVISION']:
+			raise NonLiveEbuild('ESVN_REVISION set, package is not really a live one')
+
+	def getpath(self):
+		return self.env['ESVN_WC_PATH']
+
+	def __str__(self):
+		return self.env['ESVN_REPO_URI'] or VCSSupport.__str__(self)
+
+	def getsavedrev(self):
+		return self.env['ESVN_WC_REVISION']
+
+	def getrev(self):
+		svninfo = self.call(['svn', '--config-dir', '%s/.subversion' % self.env['ESVN_STORE_DIR'], 'info'])
+		m = self.revre.search(svninfo)
+		return m.group(1) if m is not None else None
+
+	@staticmethod
+	def revcmp(oldrev, newrev):
+		return oldrev >= newrev
+
+	def getupdatecmd(self):
+		cmd = '%s %s --config-dir %s/.subversion' % (self.env['ESVN_UPDATE_CMD'], self.env['ESVN_OPTIONS'], self.env['ESVN_STORE_DIR'])
+		if self.env['ESVN_USER']:
+			cmd += ' --user "%s" --password "%s"' % (self.env['ESVN_USER'], self.env['ESVN_PASSWORD'])
+		return cmd
+
+myvcs = SvnSupport
 		author_email = 'gentoo@mgorny.alt.pl',
 		url = 'http://github.com/mgorny/smart-live-rebuild',
 
-		packages = ['SmartLiveRebuild'],
+		packages = ['SmartLiveRebuild', 'SmartLiveRebuild.vcs'],
 		scripts = ['smart-live-rebuild']
 )