diff --git a/bin/Source/GitSource.py b/bin/Source/GitSource.py index 956dbc85b..23a380f08 100644 --- a/bin/Source/GitSource.py +++ b/bin/Source/GitSource.py @@ -1,273 +1,284 @@ -# -# copyright (c) 2009 Ralf Habacker -# copyright (c) 2009 Patrick Spendrin -# -# git support - -from Source.VersionSystemSourceBase import * -import tempfile - -## \todo requires installed git package -> add suport for installing packages - -class GitSource ( VersionSystemSourceBase ): - """git support""" - def __init__(self, subinfo=None): - utils.trace( 'GitSource __init__', 2 ) - if subinfo: - self.subinfo = subinfo - VersionSystemSourceBase.__init__( self ) - - # detect git installation - gitInstallDir = os.path.join( self.rootdir, 'dev-utils', 'git' ) - if os.path.exists( gitInstallDir ): - self.gitPath = os.path.join(gitInstallDir, 'bin', 'git') - utils.debug( 'using git from %s' % gitInstallDir, 1 ) - else: - self.gitPath = 'git' - - def __getCurrentBranch( self ): - branch = None - if os.path.exists( self.checkoutDir() ): - tmpFile = tempfile.TemporaryFile() - self.__git("branch -a", stdout=tmpFile ) - # TODO: check return value for success - tmpFile.seek( 0 ) - for line in tmpFile: - line = str(line,"UTF-8") - if line.startswith("*"): - branch = line[2:].rstrip() - break - return branch - - def __isLocalBranch( self, branch ): - if os.path.exists( self.checkoutDir() ): - tmpFile = tempfile.TemporaryFile() - self.__git("branch", stdout=tmpFile ) - # TODO: check return value for success - tmpFile.seek( 0 ) - for line in tmpFile: - if str(line[2:].rstrip(), "UTF-8") == branch: - return True - return False - - def __isTag( self, _tag ): - if os.path.exists( self.checkoutDir() ): - tmpFile = tempfile.TemporaryFile() - self.__git("tag", stdout=tmpFile ) - # TODO: check return value for success - tmpFile.seek( 0 ) - for line in tmpFile: - if str(line.rstrip(), "UTF-8") == _tag: - return True - return False - - def __getCurrentRevision( self ): - """return the revision returned by git show""" - - # run the command - branch = self.__getCurrentBranch() - if not self.__isTag( branch ): - # open a temporary file - do not use generic tmpfile because this doesn't give a good file object with python - with tempfile.TemporaryFile() as tmpFile: - self.__git("show", "--abbrev-commit", stdout=tmpFile ) - tmpFile.seek( os.SEEK_SET ) - # read the temporary file and grab the first line - # print the revision - everything else should be quiet now - line = tmpFile.readline() - return str(line, "UTF-8").replace("commit ", "").strip() - else: - # in case this is a tag, print out the tag version - return branch - - def __fetchSingleBranch( self, repopath = None ): - utils.trace( 'GitSource __fetchSingleBranch', 2 ) - # get the path where the repositories should be stored to - if repopath == None: - repopath = self.repositoryUrl() - - # in case you need to move from a read only Url to a writeable one, here it gets replaced - repopath = repopath.replace( "[git]", "" ) - repoString = utils.replaceVCSUrl( repopath ) - [ repoUrl, repoBranch, repoTag ] = utils.splitVCSUrl( repoString ) - if not repoBranch and not repoTag: - repoBranch = "master" - - ret = True - # only run if wanted (e.g. no --offline is given on the commandline) - if ( not self.noFetch ): - self.setProxy() - safePath = os.environ[ "PATH" ] - # add the git path to the PATH variable so that git can be called without path - os.environ[ "PATH" ] = os.path.join( self.rootdir, "git", "bin" ) + ";" + safePath - checkoutDir = self.checkoutDir() - # if we only have the checkoutdir but no .git within, - # clean this up first - if os.path.exists(checkoutDir) \ - and not os.path.exists(checkoutDir + "\.git"): - os.rmdir(checkoutDir) - if os.path.exists(checkoutDir): - if not repoTag: - ret = self.__git("pull", "origin", repoBranch or "master" ) - if self.subinfo.options.fetch.checkoutSubmodules: - self.__git("submodule update --init --recursive") - else: - # it doesn't exist so clone the repo - os.makedirs( checkoutDir ) - # first try to replace with a repo url from etc/portage/emergehosts.conf - recursive = '--recursive' if self.subinfo.options.fetch.checkoutSubmodules else '' - ret = self.__git('clone', recursive, repoUrl, '.') - - # if a branch is given, we should check first if the branch is already downloaded - # locally, otherwise we can track the remote branch - if ret and repoBranch and not repoTag: - track = "" - if not self.__isLocalBranch( repoBranch ): - track = "--track origin/" - ret = self.__git('checkout', "%s%s" % (track, repoBranch )) - - # we can have tags or revisions in repoTag - if ret and repoTag: - if self.__isTag( repoTag ): - if not self.__isLocalBranch( "_" + repoTag ): - ret = self.__git('checkout', '-b', '_%s' % repoTag, repoTag) - else: - ret = self.__git('checkout', '_%s' % repoTag) - else: - ret = self.__git('checkout', repoTag) - - else: - utils.debug( "skipping git fetch (--offline)" ) - return ret - - def __git(self, command, *args, **kwargs): - """executes a git command in a shell. - Default for cwd is self.checkoutDir()""" - if command in ('clone', 'checkout', 'fetch', 'pull', 'submodule') and os.getenv("EMERGE_LOG_DIR"): - # if stdout/stderr is redirected, git clone qt hangs forever. - # It does not with option -q (suppressing progress info) - command += ' -q' - parts = [self.gitPath, command] - parts.extend(args) - if not kwargs.get('cwd'): - kwargs['cwd'] = self.checkoutDir() - return utils.system(' '.join(parts), **kwargs) - - def __fetchMultipleBranch(self, repopath=None): - utils.trace( 'GitSource __fetchMultipleBranch', 2 ) - # get the path where the repositories should be stored to - if repopath == None: - repopath = self.repositoryUrl() - - # in case you need to move from a read only Url to a writeable one, here it gets replaced - repopath = repopath.replace("[git]", "") - repoString = utils.replaceVCSUrl( repopath ) - [repoUrl, repoBranch, repoTag ] = utils.splitVCSUrl( repoString ) - - ret = True - # only run if wanted (e.g. no --offline is given on the commandline) - if ( not self.noFetch ): - self.setProxy() - safePath = os.environ["PATH"] - # add the git path to the PATH variable so that git can be called without path - os.environ["PATH"] = os.path.join( self.rootdir, "git", "bin" ) + ";" + safePath - rootCheckoutDir = os.path.join(self.checkoutDir(), '.git') - if not os.path.exists( rootCheckoutDir ): - # it doesn't exist so clone the repo - os.makedirs( rootCheckoutDir ) - ret = self.__git('clone', '--mirror', repoUrl, '.', cwd=rootCheckoutDir) - else: - ret = self.__git('fetch', cwd=rootCheckoutDir) - if not ret: - utils.die( "could not fetch remote data" ) - - if repoBranch == "": - repoBranch = "master" - if ret: - branchDir = os.path.join(self.checkoutDir(), repoBranch) - if not os.path.exists(branchDir): - os.makedirs(branchDir) - ret = self.__git('clone', '--local --shared -b', repoBranch, rootCheckoutDir, branchDir, cwd=branchDir) - else: - ret = self.__git('pull') - if not ret: - utils.die( "could not pull into branch %s" % repoBranch ) - - if ret: - #ret = self.__git('checkout', '-f') - ret = self.__git("checkout", "-f", repoTag or repoBranch, cwd=branchDir) - else: - utils.debug( "skipping git fetch (--offline)" ) - return ret - - - def fetch(self, repopath=None): - utils.trace( 'GitSource fetch', 2 ) - if utils.envAsBool("EMERGE_GIT_MULTIBRANCH"): - return self.__fetchMultipleBranch(repopath) - else: - return self.__fetchSingleBranch(repopath) - - def applyPatch(self, fileName, patchdepth, unusedSrcDir=None): - """apply single patch o git repository""" - utils.trace( 'GitSource ', 2 ) - if fileName: - patchfile = os.path.join ( self.packageDir(), fileName ) - if utils.envAsBool("EMERGE_GIT_MULTIBRANCH"): - repopath = self.repositoryUrl() - # in case you need to move from a read only Url to a writeable one, here it gets replaced - repopath = repopath.replace("[git]", "") - repoString = utils.replaceVCSUrl( repopath ) - repoBranch = utils.splitVCSUrl( repoString )[1] or "master" - sourceDir = os.path.join(self.checkoutDir(), repoBranch) - else: - sourceDir = self.sourceDir() - #FIXME this reverts previously applied patches ! - #self.__git('checkout', '-f',cwd=sourceDir) - sourceDir = self.checkoutDir() - return self.__git('apply', '--whitespace=fix', - '-p %d' % patchdepth, patchfile, cwd=sourceDir) - return True - - def createPatch( self ): - """create patch file from git source into the related package dir. - The patch file is named autocreated.patch""" - utils.trace( 'GitSource createPatch', 2 ) - patchFileName = os.path.join( self.packageDir(), "%s-%s.patch" % \ - ( self.package, str( datetime.date.today() ).replace('-', '') ) ) - with open(patchFileName,'w') as patchFile: - return self.__git('diff', stdout=patchFile) - - def sourceVersion( self ): - """print the revision returned by git show""" - utils.trace( 'GitSource sourceVersion', 2 ) - - print(self.__getCurrentRevision()) - return True - - def checkoutDir(self, index=0 ): - utils.trace( 'GitSource checkoutDir', 2 ) - return VersionSystemSourceBase.checkoutDir( self, index ) - - def sourceDir(self, index=0 ): - utils.trace( 'GitSource sourceDir', 2 ) - repopath = self.repositoryUrl() - # in case you need to move from a read only Url to a writeable one, here it gets replaced - repopath = repopath.replace("[git]", "") - repoString = utils.replaceVCSUrl( repopath ) - _, repoBranch, _ = utils.splitVCSUrl( repoString ) - if repoBranch == "": - repoBranch = "master" - if utils.envAsBool("EMERGE_GIT_MULTIBRANCH"): - sourcedir = os.path.join(self.checkoutDir(index), repoBranch) - else: - sourcedir = self.checkoutDir(index) - - if self.subinfo.hasTargetSourcePath(): - sourcedir = os.path.join(sourcedir, self.subinfo.targetSourcePath()) - - utils.debug("using sourcedir: %s" % sourcedir, 2) - return sourcedir - - def currentRevision(self): - """return the name or number of the current revision""" - return self.__getCurrentRevision() +# +# copyright (c) 2009 Ralf Habacker +# copyright (c) 2009 Patrick Spendrin +# +# git support + +from Source.VersionSystemSourceBase import * +import tempfile + +## \todo requires installed git package -> add suport for installing packages + +class GitSource ( VersionSystemSourceBase ): + """git support""" + def __init__(self, subinfo=None): + utils.trace( 'GitSource __init__', 2 ) + if subinfo: + self.subinfo = subinfo + VersionSystemSourceBase.__init__( self ) + + # detect git installation + gitInstallDir = os.path.join( self.rootdir, 'dev-utils', 'git' ) + if os.path.exists( gitInstallDir ): + self.gitPath = os.path.join(gitInstallDir, 'bin', 'git') + utils.debug( 'using git from %s' % gitInstallDir, 1 ) + else: + self.gitPath = 'git' + + def __getCurrentBranch( self ): + branch = None + if os.path.exists( self.checkoutDir() ): + tmpFile = tempfile.TemporaryFile() + self.__git("branch -a", stdout=tmpFile ) + # TODO: check return value for success + tmpFile.seek( 0 ) + for line in tmpFile: + line = str(line,"UTF-8") + if line.startswith("*"): + branch = line[2:].rstrip() + break + return branch + + def __isLocalBranch( self, branch ): + if os.path.exists( self.checkoutDir() ): + tmpFile = tempfile.TemporaryFile() + self.__git("branch", stdout=tmpFile ) + # TODO: check return value for success + tmpFile.seek( 0 ) + for line in tmpFile: + if str(line[2:].rstrip(), "UTF-8") == branch: + return True + return False + + def __isTag( self, _tag ): + if os.path.exists( self.checkoutDir() ): + tmpFile = tempfile.TemporaryFile() + self.__git("tag", stdout=tmpFile ) + # TODO: check return value for success + tmpFile.seek( 0 ) + for line in tmpFile: + if str(line.rstrip(), "UTF-8") == _tag: + return True + return False + + def __getCurrentRevision( self ): + """return the revision returned by git show""" + + # run the command + branch = self.__getCurrentBranch() + if not self.__isTag( branch ): + # open a temporary file - do not use generic tmpfile because this doesn't give a good file object with python + with tempfile.TemporaryFile() as tmpFile: + self.__git("show", "--abbrev-commit", stdout=tmpFile ) + tmpFile.seek( os.SEEK_SET ) + # read the temporary file and grab the first line + # print the revision - everything else should be quiet now + line = tmpFile.readline() + return str(line, "UTF-8").replace("commit ", "").strip() + else: + # in case this is a tag, print out the tag version + return branch + + def __fetchSingleBranch( self, repopath = None ): + utils.trace( 'GitSource __fetchSingleBranch', 2 ) + # get the path where the repositories should be stored to + if repopath == None: + repopath = self.repositoryUrl() + + # in case you need to move from a read only Url to a writeable one, here it gets replaced + repopath = repopath.replace( "[git]", "" ) + repoString = utils.replaceVCSUrl( repopath ) + [ repoUrl, repoBranch, repoTag ] = utils.splitVCSUrl( repoString ) + if not repoBranch and not repoTag: + repoBranch = "master" + + ret = True + # only run if wanted (e.g. no --offline is given on the commandline) + if ( not self.noFetch ): + self.setProxy() + safePath = os.environ[ "PATH" ] + # add the git path to the PATH variable so that git can be called without path + os.environ[ "PATH" ] = os.path.join( self.rootdir, "git", "bin" ) + ";" + safePath + checkoutDir = self.checkoutDir() + # if we only have the checkoutdir but no .git within, + # clean this up first + if os.path.exists(checkoutDir) \ + and not os.path.exists(checkoutDir + "\.git"): + os.rmdir(checkoutDir) + if os.path.exists(checkoutDir): + if not repoTag: + ret = self.__git("pull", "origin", repoBranch or "master" ) + if self.subinfo.options.fetch.checkoutSubmodules: + self.__git("submodule update --init --recursive") + else: + # it doesn't exist so clone the repo + os.makedirs( checkoutDir ) + # first try to replace with a repo url from etc/portage/emergehosts.conf + recursive = '--recursive' if self.subinfo.options.fetch.checkoutSubmodules else '' + ret = self.__git('clone', recursive, repoUrl, '.') + + # if a branch is given, we should check first if the branch is already downloaded + # locally, otherwise we can track the remote branch + if ret and repoBranch and not repoTag: + track = "" + if not self.__isLocalBranch( repoBranch ): + track = "--track origin/" + ret = self.__git('checkout', "%s%s" % (track, repoBranch )) + + # we can have tags or revisions in repoTag + if ret and repoTag: + if self.__isTag( repoTag ): + if not self.__isLocalBranch( "_" + repoTag ): + ret = self.__git('checkout', '-b', '_%s' % repoTag, repoTag) + else: + ret = self.__git('checkout', '_%s' % repoTag) + else: + ret = self.__git('checkout', repoTag) + + else: + utils.debug( "skipping git fetch (--offline)" ) + return ret + + def __git(self, command, *args, **kwargs): + """executes a git command in a shell. + Default for cwd is self.checkoutDir()""" + if command in ('clone', 'checkout', 'fetch', 'pull', 'submodule') and os.getenv("EMERGE_LOG_DIR"): + # if stdout/stderr is redirected, git clone qt hangs forever. + # It does not with option -q (suppressing progress info) + command += ' -q' + parts = [self.gitPath, command] + parts.extend(args) + if not kwargs.get('cwd'): + kwargs['cwd'] = self.checkoutDir() + return utils.system(' '.join(parts), **kwargs) + + def __fetchMultipleBranch(self, repopath=None): + utils.trace( 'GitSource __fetchMultipleBranch', 2 ) + # get the path where the repositories should be stored to + if repopath == None: + repopath = self.repositoryUrl() + + # in case you need to move from a read only Url to a writeable one, here it gets replaced + repopath = repopath.replace("[git]", "") + repoString = utils.replaceVCSUrl( repopath ) + [repoUrl, repoBranch, repoTag ] = utils.splitVCSUrl( repoString ) + + ret = True + # only run if wanted (e.g. no --offline is given on the commandline) + if ( not self.noFetch ): + self.setProxy() + safePath = os.environ["PATH"] + # add the git path to the PATH variable so that git can be called without path + os.environ["PATH"] = os.path.join( self.rootdir, "git", "bin" ) + ";" + safePath + rootCheckoutDir = os.path.join(self.checkoutDir(), '.git') + if not os.path.exists( rootCheckoutDir ): + # it doesn't exist so clone the repo + os.makedirs( rootCheckoutDir ) + ret = self.__git('clone', '--mirror', repoUrl, '.', cwd=rootCheckoutDir) + else: + ret = self.__git('fetch', cwd=rootCheckoutDir) + if not ret: + utils.die( "could not fetch remote data" ) + + if repoBranch == "": + repoBranch = "master" + if ret: + branchDir = os.path.join(self.checkoutDir(), repoBranch) + if not os.path.exists(branchDir): + os.makedirs(branchDir) + ret = self.__git('clone', '--local --shared -b', repoBranch, rootCheckoutDir, branchDir, cwd=branchDir) + else: + ret = self.__git('pull') + if not ret: + utils.die( "could not pull into branch %s" % repoBranch ) + + if ret: + #ret = self.__git('checkout', '-f') + ret = self.__git("checkout", "-f", repoTag or repoBranch, cwd=branchDir) + else: + utils.debug( "skipping git fetch (--offline)" ) + return ret + + + def fetch(self, repopath=None): + utils.trace( 'GitSource fetch', 2 ) + if utils.envAsBool("EMERGE_GIT_MULTIBRANCH"): + return self.__fetchMultipleBranch(repopath) + else: + return self.__fetchSingleBranch(repopath) + + def applyPatch(self, fileName, patchdepth, unusedSrcDir=None): + """apply single patch o git repository""" + utils.trace( 'GitSource ', 2 ) + if fileName: + patchfile = os.path.join ( self.packageDir(), fileName ) + if utils.envAsBool("EMERGE_GIT_MULTIBRANCH"): + repopath = self.repositoryUrl() + # in case you need to move from a read only Url to a writeable one, here it gets replaced + repopath = repopath.replace("[git]", "") + repoString = utils.replaceVCSUrl( repopath ) + repoBranch = utils.splitVCSUrl( repoString )[1] or "master" + sourceDir = os.path.join(self.checkoutDir(), repoBranch) + else: + sourceDir = self.sourceDir() + #FIXME this reverts previously applied patches ! + #self.__git('checkout', '-f',cwd=sourceDir) + sourceDir = self.checkoutDir() + return self.__git('apply', '--whitespace=fix', + '-p %d' % patchdepth, patchfile, cwd=sourceDir) + return True + + def createPatch( self ): + """create patch file from git source into the related package dir. + The patch file is named autocreated.patch""" + utils.trace( 'GitSource createPatch', 2 ) + patchFileName = os.path.join( self.packageDir(), "%s-%s.patch" % \ + ( self.package, str( datetime.date.today() ).replace('-', '') ) ) + with open(patchFileName,'w') as patchFile: + return self.__git('diff', stdout=patchFile) + + def sourceVersion( self ): + """print the revision returned by git show""" + utils.trace( 'GitSource sourceVersion', 2 ) + + print(self.__getCurrentRevision()) + return True + + def checkoutDir(self, index=0 ): + utils.trace( 'GitSource checkoutDir', 2 ) + return VersionSystemSourceBase.checkoutDir( self, index ) + + def sourceDir(self, index=0 ): + utils.trace( 'GitSource sourceDir', 2 ) + repopath = self.repositoryUrl() + # in case you need to move from a read only Url to a writeable one, here it gets replaced + repopath = repopath.replace("[git]", "") + repoString = utils.replaceVCSUrl( repopath ) + _, repoBranch, _ = utils.splitVCSUrl( repoString ) + if repoBranch == "": + repoBranch = "master" + if utils.envAsBool("EMERGE_GIT_MULTIBRANCH"): + sourcedir = os.path.join(self.checkoutDir(index), repoBranch) + else: + sourcedir = self.checkoutDir(index) + + if self.subinfo.hasTargetSourcePath(): + sourcedir = os.path.join(sourcedir, self.subinfo.targetSourcePath()) + + utils.debug("using sourcedir: %s" % sourcedir, 2) + return sourcedir + + def getUrls( self ): + """print the url where to clone from and the branch/tag/hash""" + # in case you need to move from a read only Url to a writeable one, here it gets replaced + repopath = self.repositoryUrl().replace( "[git]", "" ) + repoString = utils.replaceVCSUrl( repopath ) + [ repoUrl, repoBranch, repoTag ] = utils.splitVCSUrl( repoString ) + if not repoBranch and not repoTag: + repoBranch = "master" + print('|'.join([repoUrl, repoBranch, repoTag])) + return True + + def currentRevision(self): + """return the name or number of the current revision""" + return self.__getCurrentRevision() diff --git a/bin/Source/SvnSource.py b/bin/Source/SvnSource.py index 52da9e1c8..2684caec1 100644 --- a/bin/Source/SvnSource.py +++ b/bin/Source/SvnSource.py @@ -1,238 +1,241 @@ -# -# copyright (c) 2009 Ralf Habacker -# -# subversion support -## \todo needs dev-utils/subversion package, add some kind of tool requirement tracking for SourceBase derived classes - -from Source.VersionSystemSourceBase import * - -class SvnSource (VersionSystemSourceBase): - """subversion support""" - def __init__(self, subinfo=None): - utils.trace( "SvnSource.__init__", 2 ) - if subinfo: - self.subinfo = subinfo - VersionSystemSourceBase.__init__( self ) - self.options = None - ## \todo add internal dependency for subversion package - self.svnInstallDir = os.path.join(self.rootdir, 'dev-utils', 'svn', 'bin') - - def checkoutDir( self, index=0 ): - utils.trace( "SvnSource.checkoutDir", 2 ) - if self.subinfo.hasSvnTarget(): - u = self.getUrl(index) - (url, dummy) = self.splitUrl(u) - - if url.find("://") == -1: - if os.getenv("KDESVNDIR") == None: - sourcedir = os.path.join( self.downloadDir(), "svn-src", "kde", url ) - else: - sourcedir = os.path.join( os.getenv("KDESVNDIR"), url ) - else: - sourcedir = os.path.join( self.downloadDir(), "svn-src" ) - sourcedir = os.path.join( sourcedir, self.package ) - _, path = self.__splitPath(url) - if path and utils.envAsBool("EMERGE_SVN_STDLAYOUT"): - sourcedir = os.path.join( sourcedir, path ) - else: - utils.die("svnTarget property not set for this target") - - if self.subinfo.targetSourceSuffix() != None: - sourcedir = "%s-%s" % (sourcedir, self.subinfo.targetSourceSuffix()) - - return sourcedir - - def applyPatch(self, fileName, patchdepth, unusedSrcDir=None): - """apply a patch to a svn repository checkout""" - utils.trace( "SvnSource.applyPatch", 2 ) - if fileName: - patchfile = os.path.join (self.packageDir(), fileName) - # @todo check if this could be merged into SourceBase.applyPatch - if self.noCopy: - srcdir = self.sourceDir() - else: - srcdir = self.buildDir() - return utils.applyPatch(srcdir, patchfile, patchdepth) - return True - - def setProxy(self): - """set proxy for fetching sources from subversion repository""" - (host, port, username, password) = self.proxySettings() - if host == None: - return - - proxyOptions = " --config-option servers:global:http-proxy-host=%s" % host - proxyOptions += " --config-option servers:global:http-proxy-port=%s" % port - if username != None: - proxyOptions += " --config-option servers:global:http-proxy-username=%s" % username - proxyOptions += " --config-option servers:global:http-proxy-password=%s" % password - - self.options = proxyOptions - - def fetch( self, repopath = None ): - """ checkout or update an existing repository path """ - utils.trace( "SvnSource.fetch", 2 ) - if self.noFetch: - utils.debug( "skipping svn fetch (--offline)" ) - return True - - if not os.path.exists(self.svnInstallDir): - utils.die("required subversion package not installed in %s" % self.svnInstallDir) - - for i in range(0, self.repositoryUrlCount()): - if repopath: - url = repopath - else: - url = self.repositoryUrl(i) - sourcedir = self.checkoutDir(i) - if self.repositoryUrlOptions(i) == 'norecursive': - self.__tryCheckoutFromRoot(url, sourcedir, False) - else: - self.__tryCheckoutFromRoot(url, sourcedir, True) - i += 1 - return True - - def __getCurrentRevision( self ): - """ return the revision returned by svn info """ - - revision = None - # first, change the output to always be english - if "LANG" in os.environ: - oldLanguage = os.environ["LANG"] - else: - oldLanguage = "" - os.environ["LANG"] = "C" - - # handle multiple urls in targets - # we need to find the main url which is marked with #main - # if not marked use the second last one, which is used currently - sourcedir = None - n = self.repositoryUrlCount() - if n > 1: - for i in range(0, n): - if self.repositoryUrlOptions(i) == 'main': - sourcedir = self.checkoutDir(i) - break - # if not found use the second last one - if sourcedir == None: - sourcedir = self.checkoutDir(n-2) - else: - sourcedir = self.checkoutDir() - - # set up the command - cmd = "%s/svn info %s" % ( self.svnInstallDir, sourcedir ) - - # open a temporary file - do not use generic tmpfile because this doesn't give a good file object with python - tempFileName = os.path.join( self.checkoutDir().replace('/', '\\'), ".emergesvninfo.tmp" ) - with open( tempFileName, "wb+" ) as tempfile: - - # run the command - with utils.LockFile(utils.LockFileName("SVN")): - utils.system( cmd, stdout=tempfile ) - - tempfile.seek(os.SEEK_SET) - # read the temporary file and find the line with the revision - for line in tempfile: - if line.startswith("Revision: "): - revision = line.replace("Revision: ", "").strip() - break - - os.environ["LANG"] = oldLanguage - os.remove( tempFileName ) - return revision - - def __splitPath(self, path): - """ split a path into a base part and a relative repository url. - The delimiters are currently 'trunk', 'branches' and 'tags'. - """ - pos = path.find('trunk') - if pos == -1: - pos = path.find('branches') - if pos == -1: - pos = path.find('tags') - if pos == -1: - ret = [path, None] - else: - ret = [path[:pos-1], path[pos:]] - return ret - - def __tryCheckoutFromRoot ( self, url, sourcedir, recursive=True ): - """This method checkout source with svn informations from - the svn root repository directory. It detects the svn root - by searching the predefined root subdirectories 'trunk', 'branches' - and 'tags' which will probably fit for most servers - """ - (urlBase, urlPath) = self.__splitPath(url) - if urlPath == None: - return self.__checkout(url, sourcedir, recursive) - - (srcBase, srcPath) = self.__splitPath(sourcedir) - if srcPath == None: - return self.__checkout(url, sourcedir, recursive) - - urlRepo = urlBase - srcDir = srcBase - urlParts = urlPath.split('/') - pathSep = '/' - srcParts = srcPath.split(pathSep) - - # url and source parts not match - if len(urlParts) != len(srcParts): - return self.__checkout(url, sourcedir, recursive) - - for i in range(0, len(urlParts)-1): - urlPart = urlParts[i] - srcPart = srcParts[i] - if ( urlPart == "" ): - continue - - urlRepo += '/' + urlPart - srcDir += pathSep + srcPart - - if os.path.exists(srcDir): - continue - self.__checkout( urlRepo, srcDir, False ) - - self.__checkout( url, sourcedir, recursive ) - - def __checkout( self, url, sourcedir, recursive=True ): - """internal method for subversion checkout and update""" - option = "" - if not recursive: - option = "--depth=files" - - if utils.verbose() < 2 and not utils.envAsBool("KDESVNVERBOSE"): - option += " --quiet" - - self.setProxy() - - if self.options != None: - option += self.options - - if self.subinfo.options.fetch.ignoreExternals: - option += " --ignore-externals " - - url = utils.replaceVCSUrl( url ) - - if os.path.exists( sourcedir ): - cmd = "%s/svn update %s %s" % ( self.svnInstallDir, option, sourcedir ) - else: - cmd = "%s/svn checkout %s %s %s" % (self.svnInstallDir, option, url, sourcedir ) - - with utils.LockFile(utils.LockFileName("SVN")): - return utils.system( cmd ) - - def createPatch( self ): - """create patch file from svn source into the related package dir. The patch file is named autocreated.patch""" - cmd = "%s/svn diff %s > %s" % ( self.svnInstallDir, self.checkoutDir(), os.path.join( self.packageDir(), "%s-%s.patch" % \ - ( self.package, str( datetime.date.today() ).replace('-', '') ) ) ) - with utils.LockFile(utils.LockFileName("SVN")): - return utils.system( cmd ) - - def sourceVersion( self ): - """ print the revision returned by svn info """ - return True - - def currentRevision(self): - """return the name or number of the current revision""" - return self.__getCurrentRevision() +# +# copyright (c) 2009 Ralf Habacker +# +# subversion support +## \todo needs dev-utils/subversion package, add some kind of tool requirement tracking for SourceBase derived classes + +from Source.VersionSystemSourceBase import * + +class SvnSource (VersionSystemSourceBase): + """subversion support""" + def __init__(self, subinfo=None): + utils.trace( "SvnSource.__init__", 2 ) + if subinfo: + self.subinfo = subinfo + VersionSystemSourceBase.__init__( self ) + self.options = None + ## \todo add internal dependency for subversion package + self.svnInstallDir = os.path.join(self.rootdir, 'dev-utils', 'svn', 'bin') + + def checkoutDir( self, index=0 ): + utils.trace( "SvnSource.checkoutDir", 2 ) + if self.subinfo.hasSvnTarget(): + u = self.getUrl(index) + (url, dummy) = self.splitUrl(u) + + if url.find("://") == -1: + if os.getenv("KDESVNDIR") == None: + sourcedir = os.path.join( self.downloadDir(), "svn-src", "kde", url ) + else: + sourcedir = os.path.join( os.getenv("KDESVNDIR"), url ) + else: + sourcedir = os.path.join( self.downloadDir(), "svn-src" ) + sourcedir = os.path.join( sourcedir, self.package ) + _, path = self.__splitPath(url) + if path and utils.envAsBool("EMERGE_SVN_STDLAYOUT"): + sourcedir = os.path.join( sourcedir, path ) + else: + utils.die("svnTarget property not set for this target") + + if self.subinfo.targetSourceSuffix() != None: + sourcedir = "%s-%s" % (sourcedir, self.subinfo.targetSourceSuffix()) + + return sourcedir + + def applyPatch(self, fileName, patchdepth, unusedSrcDir=None): + """apply a patch to a svn repository checkout""" + utils.trace( "SvnSource.applyPatch", 2 ) + if fileName: + patchfile = os.path.join (self.packageDir(), fileName) + # @todo check if this could be merged into SourceBase.applyPatch + if self.noCopy: + srcdir = self.sourceDir() + else: + srcdir = self.buildDir() + return utils.applyPatch(srcdir, patchfile, patchdepth) + return True + + def setProxy(self): + """set proxy for fetching sources from subversion repository""" + (host, port, username, password) = self.proxySettings() + if host == None: + return + + proxyOptions = " --config-option servers:global:http-proxy-host=%s" % host + proxyOptions += " --config-option servers:global:http-proxy-port=%s" % port + if username != None: + proxyOptions += " --config-option servers:global:http-proxy-username=%s" % username + proxyOptions += " --config-option servers:global:http-proxy-password=%s" % password + + self.options = proxyOptions + + def fetch( self, repopath = None ): + """ checkout or update an existing repository path """ + utils.trace( "SvnSource.fetch", 2 ) + if self.noFetch: + utils.debug( "skipping svn fetch (--offline)" ) + return True + + if not os.path.exists(self.svnInstallDir): + utils.die("required subversion package not installed in %s" % self.svnInstallDir) + + for i in range(self.repositoryUrlCount()): + if repopath: + url = repopath + else: + url = self.repositoryUrl(i) + self.__tryCheckoutFromRoot(url, self.checkoutDir(i), self.repositoryUrlOptions(i) != 'norecursive') + return True + + def __getCurrentRevision( self ): + """ return the revision returned by svn info """ + + revision = None + # first, change the output to always be english + if "LANG" in os.environ: + oldLanguage = os.environ["LANG"] + else: + oldLanguage = "" + os.environ["LANG"] = "C" + + # handle multiple urls in targets + # we need to find the main url which is marked with #main + # if not marked use the second last one, which is used currently + sourcedir = None + n = self.repositoryUrlCount() + if n > 1: + for i in range(0, n): + if self.repositoryUrlOptions(i) == 'main': + sourcedir = self.checkoutDir(i) + break + # if not found use the second last one + if sourcedir == None: + sourcedir = self.checkoutDir(n-2) + else: + sourcedir = self.checkoutDir() + + # set up the command + cmd = "%s/svn info %s" % ( self.svnInstallDir, sourcedir ) + + # open a temporary file - do not use generic tmpfile because this doesn't give a good file object with python + tempFileName = os.path.join( self.checkoutDir().replace('/', '\\'), ".emergesvninfo.tmp" ) + with open( tempFileName, "wb+" ) as tempfile: + + # run the command + with utils.LockFile(utils.LockFileName("SVN")): + utils.system( cmd, stdout=tempfile ) + + tempfile.seek(os.SEEK_SET) + # read the temporary file and find the line with the revision + for line in tempfile: + if line.startswith("Revision: "): + revision = line.replace("Revision: ", "").strip() + break + + os.environ["LANG"] = oldLanguage + os.remove( tempFileName ) + return revision + + def __splitPath(self, path): + """ split a path into a base part and a relative repository url. + The delimiters are currently 'trunk', 'branches' and 'tags'. + """ + pos = path.find('trunk') + if pos == -1: + pos = path.find('branches') + if pos == -1: + pos = path.find('tags') + if pos == -1: + ret = [path, None] + else: + ret = [path[:pos-1], path[pos:]] + return ret + + def __tryCheckoutFromRoot ( self, url, sourcedir, recursive=True ): + """This method checkout source with svn informations from + the svn root repository directory. It detects the svn root + by searching the predefined root subdirectories 'trunk', 'branches' + and 'tags' which will probably fit for most servers + """ + (urlBase, urlPath) = self.__splitPath(url) + if urlPath == None: + return self.__checkout(url, sourcedir, recursive) + + (srcBase, srcPath) = self.__splitPath(sourcedir) + if srcPath == None: + return self.__checkout(url, sourcedir, recursive) + + urlRepo = urlBase + srcDir = srcBase + urlParts = urlPath.split('/') + pathSep = '/' + srcParts = srcPath.split(pathSep) + + # url and source parts not match + if len(urlParts) != len(srcParts): + return self.__checkout(url, sourcedir, recursive) + + for i in range(0, len(urlParts)-1): + urlPart = urlParts[i] + srcPart = srcParts[i] + if ( urlPart == "" ): + continue + + urlRepo += '/' + urlPart + srcDir += pathSep + srcPart + + if os.path.exists(srcDir): + continue + self.__checkout( urlRepo, srcDir, False ) + + self.__checkout( url, sourcedir, recursive ) + + def __checkout( self, url, sourcedir, recursive=True ): + """internal method for subversion checkout and update""" + option = "" + if not recursive: + option = "--depth=files" + + if utils.verbose() < 2 and not utils.envAsBool("KDESVNVERBOSE"): + option += " --quiet" + + self.setProxy() + + if self.options != None: + option += self.options + + if self.subinfo.options.fetch.ignoreExternals: + option += " --ignore-externals " + + url = utils.replaceVCSUrl( url ) + + if os.path.exists( sourcedir ): + cmd = "%s/svn update %s %s" % ( self.svnInstallDir, option, sourcedir ) + else: + cmd = "%s/svn checkout %s %s %s" % (self.svnInstallDir, option, url, sourcedir ) + + with utils.LockFile(utils.LockFileName("SVN")): + return utils.system( cmd ) + + def createPatch( self ): + """create patch file from svn source into the related package dir. The patch file is named autocreated.patch""" + cmd = "%s/svn diff %s > %s" % ( self.svnInstallDir, self.checkoutDir(), os.path.join( self.packageDir(), "%s-%s.patch" % \ + ( self.package, str( datetime.date.today() ).replace('-', '') ) ) ) + with utils.LockFile(utils.LockFileName("SVN")): + return utils.system( cmd ) + + def sourceVersion( self ): + """ print the revision returned by svn info """ + return True + + def getUrls( self ): + """print the url where to check out from""" + for i in range(self.repositoryUrlCount()): + url = self.repositoryUrl(i) + if self.repositoryUrlOptions(i) == 'norecursive': url = '--depth=files ' + url + print(url) + return True + + def currentRevision(self): + """return the name or number of the current revision""" + return self.__getCurrentRevision()