예제 #1
1
def main():
    if len(sys.argv) < 2:
        print 'Usage: %s [version] [--install] [--local|username password]' % sys.argv[0]
        print 'Where [version] is the branch you want to checkout'
        print 'and username and password are for your eduforge account'
        print 'Eg. %s 0.7 --local' % sys.argv[0]
    else:
        version = sys.argv[1]
        branch = 'http://exe.cfdl.auckland.ac.nz/svn/exe/branches/%s' % version
        origDir = Path(sys.argv[0]).abspath().dirname()
        tmp = TempDirPath()
        os.chdir(tmp)
        os.system('svn export %s exe' % branch)
        (origDir/'../../exe/webui/firefox').copytree(tmp/'exe/exe/webui/firefox')
        os.chdir(tmp/'exe')
        tarball = Path('../exe-%s-source.tgz' % version).abspath()
        os.system('tar czf %s *' % tarball)
        os.chdir(tmp)
        if '--local' not in sys.argv:
            try:
                from paramiko import Transport
            except ImportError:
                print 'To upload you need to install paramiko python library from:'
                print 'http://www.lag.net/paramiko'
                sys.exit(2)
            from socket import socket, gethostbyname
            s = socket()
            s.connect((gethostbyname('shell.eduforge.org'), 22))
            t = Transport(s)
            t.connect()
            t.auth_password(sys.argv[-2], sys.argv[-1])
            f = t.open_sftp_client()
            f.chdir('/home/pub/exe')
            f.put(tarball.encode('utf8'), tarball.basename().encode('utf8'))
        if os.getuid() == 0:
            tarball.copyfile('/usr/portage/distfiles/' + tarball.basename())
        os.chdir(tmp/'exe/installs/gentoo')
        newEbuildFilename = Path('exe-%s.ebuild' % version).abspath()
        if not newEbuildFilename.exists():
            Path('exe-0.7.ebuild').copy(newEbuildFilename)
        if os.getuid() == 0:
            ebuildDir = Path('/usr/local/portage/dev-python/exe')
            if ebuildDir.exists():
                ebuildDir.rmtree()
            ebuildDir.makedirs()
            os.chdir(ebuildDir)
            newEbuildFilename.copy(ebuildDir)
            filesDir = ebuildDir/'files'
            filesDir.makedirs()
            Path(tmp/'exe/installs/gentoo/all-config.patch').copy(filesDir)
            if '--local' not in sys.argv:
                oldTarball = Path('/usr/portage/distfiles/')/tarball.basename()
                if oldTarball.exists():
                    oldTarball.remove()
                os.environ['GENTOO_MIRRORS']=''
                os.system('ebuild %s fetch' % newEbuildFilename.basename())
            os.system('ebuild %s manifest' % newEbuildFilename.basename())
            os.system('ebuild %s digest' % newEbuildFilename.basename())
            if '--install' in sys.argv:
                os.system('ebuild %s install' % newEbuildFilename.basename())
예제 #2
0
 def testUpgradeAppDir(self):
     """
     Tests that config files with
     'appDataDir' are upgraded to 'configDir'
     """
     # Write the old style config file
     configPath = Path(u'test.exe.conf')
     if configPath.exists():
         configPath.remove()
     oldParser = ConfigParser()
     system = oldParser.addSection('system')
     system.appDataDir = 'my old app data dir'
     oldParser.write(configPath)
     del system
     del oldParser
     # Make the config instance load it
     Config._getConfigPathOptions = lambda self: ['test.exe.conf']
     myconfig = Config()
     myconfig.loadSettings()
     # Check if it reads the old value into the new variable
     assert not hasattr(myconfig, 'appDataDir')
     self.assertEquals(myconfig.configPath, 'test.exe.conf')
     self.assertEquals(myconfig.configDir, 'my old app data dir')
     # Check if it has upgraded the file and added in some nice default values
     newParser = ConfigParser()
     newParser.read(configPath)
     self.assertEquals(newParser.system.configDir, 'my old app data dir')
예제 #3
0
파일: mki18n.py 프로젝트: jsanchez91/iteexe
def makeXulPO(applicationDirectoryPath, applicationDomain=None, verbose=0):
    """Searches through xul files and appends to messages.pot"""
    if verbose:
        print "Importing xul templates..."
    path = Path(applicationDirectoryPath)
    messages = pot2dict('exe/locale/messages.pot')
    messageCommentTemplate = '\n#: %s:%s\nmsgid "'
    seq = len(messages)
    skipPaths = (applicationDirectoryPath / 'exe/webui/firefox', )
    for fn in path.walkfiles():
        if fn.ext.lower() == '.xul':
            for skipPath in skipPaths:
                if fn.startswith(skipPath):
                    print 'IGNORING', fn
                    break
            else:
                if verbose:
                    print "template: ", fn
                reader = Sax2.Reader()
                doc = reader.fromStream(file(fn, 'rb'))
                xul2dict(doc, messages, seq, fn.relpath())
    pot = Path('exe/locale/messages.pot')
    if pot.exists():
        pot.remove()
    pot.touch()
    dict2pot(messages, 'exe/locale/messages.pot')
예제 #4
0
    def do_export(self, inputf, outputf):
        if hasattr(self, 'export_' + self.options["export"]):
            LOG.debug("Exporting to type %s, in: %s, out: %s, overwrite: %s" \
            % (self.options["export"], inputf, outputf, str(self.options["overwrite"])))
            if not outputf:
                if self.options["export"] in ('website', 'singlepage'):
                    outputf = inputf.rsplit(".elp")[0]
                else:
                    outputf = inputf + self.extensions[self.options["export"]]
            outputfp = Path(outputf)
            if outputfp.exists() and not self.options["overwrite"]:
                error = _(u'"%s" already exists.\nPlease try again \
with a different filename') % outputf
                raise Exception(error.encode(sys.stdout.encoding))
            else:
                if outputfp.exists() and self.options["overwrite"]:
                    if outputfp.isdir():
                        for filen in outputfp.walkfiles():
                            filen.remove()
                        outputfp.rmdir()
                    else:
                        outputfp.remove()
                pkg = Package.load(inputf)
                LOG.debug("Package %s loaded" % (inputf))
                if not pkg:
                    error = _(u"Invalid input package")
                    raise Exception(error.encode(sys.stdout.encoding))
                self.styles_dir = self.web_dir.joinpath('style', pkg.style)
                LOG.debug("Styles dir: %s" % (self.styles_dir))
                getattr(self, 'export_' + self.options["export"])(pkg, outputf)
                return outputf
        else:
            raise Exception(_(u"Export format not implemented")\
.encode(sys.stdout.encoding))
예제 #5
0
파일: mki18n.py 프로젝트: erral/iteexe
def makeXulPO(applicationDirectoryPath,  applicationDomain=None, verbose=0):
    """Searches through xul files and appends to messages.pot"""
    if verbose:
        print "Importing xul templates..."
    path = Path(applicationDirectoryPath)
    messages = pot2dict('exe/locale/messages.pot')
    messageCommentTemplate = '\n#: %s:%s\nmsgid "'
    seq = len(messages)
    skipPaths = (
          applicationDirectoryPath/'exe/webui/firefox',
        )
    for fn in path.walkfiles():
        if fn.ext.lower() == '.xul':
            for skipPath in skipPaths:
                if fn.startswith(skipPath):
                    print 'IGNORING', fn
                    break
            else:
                if verbose:
                    print "template: ", fn
                reader = Sax2.Reader()
                doc = reader.fromStream(file(fn, 'rb'))
                xul2dict(doc, messages, seq, fn.relpath())
    pot = Path('exe/locale/messages.pot') 
    if pot.exists(): 
        pot.remove() 
    pot.touch() 
    dict2pot(messages, 'exe/locale/messages.pot')
예제 #6
0
 def testUpgradeAppDir(self):
     """
     Tests that config files with
     'appDataDir' are upgraded to 'configDir'
     """
     # Write the old style config file
     configPath = Path(u'test.exe.conf')
     if configPath.exists():
         configPath.remove()
     oldParser = ConfigParser()
     system = oldParser.addSection('system')
     system.appDataDir = 'my old app data dir'
     oldParser.write(configPath)
     del system
     del oldParser
     # Make the config instance load it
     Config._getConfigPathOptions = lambda self: ['test.exe.conf']
     myconfig = Config()
     myconfig.loadSettings()
     # Check if it reads the old value into the new variable
     assert not hasattr(myconfig, 'appDataDir')
     self.assertEquals(myconfig.configPath, 'test.exe.conf')
     self.assertEquals(myconfig.configDir, 'my old app data dir')
     # Check if it has upgraded the file and added in some nice default values
     newParser = ConfigParser()
     newParser.read(configPath)
     self.assertEquals(newParser.system.configDir, 'my old app data dir')
예제 #7
0
파일: mki18n.py 프로젝트: erral/iteexe
def makePO(applicationDirectoryPath,  applicationDomain=None, verbose=1) :
    """Build the Portable Object Template file for the application.

    makePO builds the .pot file for the application stored inside 
    a specified directory by running xgettext for all application source 
    files.  It finds the name of all files by looking for a file called 'app.fil'. 
    If this file does not exists, makePo raises an IOError exception.
    By default the application domain (the application
    name) is the same as the directory name but it can be overridden by the 
    'applicationDomain' argument.

    makePO always creates a new file called messages.pot.  If it finds files 
    of the form app_xx.po where 'app' is the application name and 'xx' is one 
    of the ISO 639 two-letter language codes, makePO resynchronizes those 
    files with the latest extracted strings (now contained in messages.pot). 
    This process updates all line location number in the language-specific
    .po files and may also create new entries for translation (or comment out 
    some).  The .po file is not changed, instead a new file is created with 
    the .new extension appended to the name of the .po file.

    By default the function does not display what it is doing.  Set the 
    verbose argument to 1 to force it to print its commands.
    """
    if applicationDomain is None:
        applicationName = fileBaseOf(applicationDirectoryPath,withPath=0)
    else:
        applicationName = applicationDomain
    currentDir = os.getcwd()
    messages_pot = Path('exe/locale/messages.pot')
    # Use xgettext to make the base messages.pot (with header, etc.)
    if messages_pot.exists():
        messages_pot.remove()
    messages_pot.touch()
    cmd = 'xgettext -kx_ -s -j --no-wrap --output=exe/locale/messages.pot --from-code=utf8 exe/engine/package.py'
    if verbose: print cmd
    os.system(cmd)                                                
    if not os.path.exists('app.fil'):
        raise IOError(2,'No module file: app.fil')

    # Steps:                                  
    #  Use xgettext to parse all application modules
    #  The following switches are used:
    #  
    #   -s                          : sort output by string content (easier to use when we need to merge several .po files)
    #   --files-from=app.fil        : The list of files is taken from the file: app.fil
    #   --output=                   : specifies the name of the output file (using a .pot extension)
    cmd = 'xgettext -kx_ -s -j --no-wrap --output=exe/locale/messages.pot --from-code=utf8 %s'
    if verbose: print cmd
    for fn in open('app.fil'):
        print 'Extracting from', fn,
        os.system(cmd % fn[:-1])

    makeXulPO(applicationDirectoryPath, applicationDomain, verbose)

    # Merge new pot with .po files
    localeDirs = Path('exe/locale')
    for filename in localeDirs.walkfiles('*_*.po'):
        cmd = "msgmerge -U --no-wrap %s exe/locale/messages.pot" % filename
        if verbose: print cmd
        os.system(cmd)
예제 #8
0
파일: mki18n.py 프로젝트: jsanchez91/iteexe
def makePO(applicationDirectoryPath, applicationDomain=None, verbose=1):
    """Build the Portable Object Template file for the application.

    makePO builds the .pot file for the application stored inside 
    a specified directory by running xgettext for all application source 
    files.  It finds the name of all files by looking for a file called 'app.fil'. 
    If this file does not exists, makePo raises an IOError exception.
    By default the application domain (the application
    name) is the same as the directory name but it can be overridden by the 
    'applicationDomain' argument.

    makePO always creates a new file called messages.pot.  If it finds files 
    of the form app_xx.po where 'app' is the application name and 'xx' is one 
    of the ISO 639 two-letter language codes, makePO resynchronizes those 
    files with the latest extracted strings (now contained in messages.pot). 
    This process updates all line location number in the language-specific
    .po files and may also create new entries for translation (or comment out 
    some).  The .po file is not changed, instead a new file is created with 
    the .new extension appended to the name of the .po file.

    By default the function does not display what it is doing.  Set the 
    verbose argument to 1 to force it to print its commands.
    """
    if applicationDomain is None:
        applicationName = fileBaseOf(applicationDirectoryPath, withPath=0)
    else:
        applicationName = applicationDomain
    currentDir = os.getcwd()
    messages_pot = Path('exe/locale/messages.pot')
    # Use xgettext to make the base messages.pot (with header, etc.)
    if messages_pot.exists():
        messages_pot.remove()
    messages_pot.touch()
    cmd = 'xgettext -kx_ -s -j --no-wrap --output=exe/locale/messages.pot --from-code=utf8 exe/engine/package.py'
    if verbose: print cmd
    os.system(cmd)
    if not os.path.exists('app.fil'):
        raise IOError(2, 'No module file: app.fil')

    # Steps:
    #  Use xgettext to parse all application modules
    #  The following switches are used:
    #
    #   -s                          : sort output by string content (easier to use when we need to merge several .po files)
    #   --files-from=app.fil        : The list of files is taken from the file: app.fil
    #   --output=                   : specifies the name of the output file (using a .pot extension)
    cmd = 'xgettext -kx_ -L Python -s -j --no-wrap --output=exe/locale/messages.pot --from-code=utf8 %s'
    if verbose: print cmd
    for fn in open('app.fil'):
        print 'Extracting from', fn,
        os.system(cmd % fn[:-1])

    makeXulPO(applicationDirectoryPath, applicationDomain, verbose)

    # Merge new pot with .po files
    localeDirs = Path('exe/locale')
    for filename in localeDirs.walkfiles('*_*.po'):
        cmd = "msgmerge -U --no-wrap -N %s exe/locale/messages.pot" % filename
        if verbose: print cmd
        os.system(cmd)
예제 #9
0
    def do_export(self, inputf, outputf):
        if hasattr(self, 'export_' + self.options["export"]):
            LOG.debug("Exporting to type %s, in: %s, out: %s, overwrite: %s" \
            % (self.options["export"], inputf, outputf, str(self.options["overwrite"])))
            if not outputf:
                if self.options["export"] in ('website', 'singlepage'):
                    outputf = inputf.rsplit(".elp")[0]
                else:
                    outputf = inputf + self.extensions[self.options["export"]]
            outputfp = Path(outputf)
            if outputfp.exists() and not self.options["overwrite"]:
                error = _(u'"%s" already exists.\nPlease try again \
with a different filename') % outputf
                raise Exception(error.encode(sys.stdout.encoding))
            else:
                if outputfp.exists() and self.options["overwrite"]:
                    if outputfp.isdir():
                        for filen in outputfp.walkfiles():
                            filen.remove()
                        outputfp.rmdir()
                    else:
                        outputfp.remove()
                pkg = Package.load(inputf)
                LOG.debug("Package %s loaded" % (inputf))
                if not pkg:
                    error = _(u"Invalid input package")
                    raise Exception(error.encode(sys.stdout.encoding))
                self.styles_dir = self.web_dir.joinpath('style', pkg.style)
                LOG.debug("Styles dir: %s" % (self.styles_dir))
                getattr(self, 'export_' + self.options["export"])(pkg, outputf)
                return outputf
        else:
            raise Exception(_(u"Export format not implemented")\
.encode(sys.stdout.encoding))
예제 #10
0
 def exportText(self, client, filename):
     filename = Path(filename)
     log.debug(u"exportWebsite, filename=%s" % filename)
     if not filename.ext.lower() == '.txt': 
         filename += '.txt'
     if filename.exists(): 
         filename.remove()
     textExport = TextExport(filename)
     textExport.export(self.package)
     client.alert(_(u'Exported to %s') % filename)
예제 #11
0
 def exportWebZip(self, client, filename, stylesDir):
     filename = Path(filename)
     log.debug(u"exportWebsite, filename=%s" % filename)
     if not filename.ext.lower() == '.zip': 
         filename += '.zip'
     if filename.exists(): 
         filename.remove()
     websiteExport = WebsiteExport(self.config, stylesDir, filename)
     websiteExport.exportZip(self.package)
     client.alert(_(u'Exported to %s') % filename)
예제 #12
0
 def exportIMS(self, client, filename, stylesDir):
     """
     Exports this package to a ims package file
     """
     log.debug(u"exportIMS")
     if not filename.lower().endswith('.zip'): 
         filename += '.zip'
     filename = Path(filename)
     if filename.exists(): 
         filename.remove()
     imsExport = IMSExport(self.config, stylesDir, filename)
     imsExport.export(self.package)
     client.alert(_(u'Exported to %s' % filename))
예제 #13
0
 def exportScorm(self, client, filename, stylesDir, scormType):
     """
     Exports this package to a scorm package file
     """
     filename = Path(filename)
     log.debug(u"exportScorm, filename=%s" % filename)
     if not filename.ext.lower() == '.zip': 
         filename += '.zip'
     if filename.exists(): 
         filename.remove()
     scormExport = ScormExport(self.config, stylesDir, filename, scormType)
     scormExport.export(self.package)
     client.alert(_(u'Exported to %s') % filename)
예제 #14
0
def main():
    if len(sys.argv) < 2:
        print 'Usage: %s [version]' % sys.argv[0]
        print 'Where [version] is the branch you want to checkout'
        print 'Eg. %s 0.7' % sys.argv[0]
    else:
        version = sys.argv[1]
        branch = 'http://exe.cfdl.auckland.ac.nz/svn/exe/branches/%s' % version
        origDir = Path(sys.argv[0]).abspath().dirname()
        tmp = TempDirPath()
        os.chdir(tmp)
        os.system('svn export %s exe' % branch)
        (origDir/'../../exe/webui/firefox').copytree(tmp/'exe/exe/webui/firefox')
        os.chdir(tmp/'exe')
        tarball = Path('../exe-%s-source.tgz' % version).abspath()
        os.system('tar czf %s *' % tarball)
        os.chdir(tmp)
        if '--local' not in sys.argv:
            open('sftpbatch.tmp', 'w').write(
                'cd /home/pub/exe\n'
                'put %s\n' % tarball)
            os.system('sftp -b sftpbatch.tmp [email protected]')
        if os.getuid() == 0:
            tarball.copyfile('/usr/portage/distfiles/' + tarball.basename())
        os.chdir(tmp/'exe/installs/gentoo')
        newEbuildFilename = Path('exe-%s.ebuild' % version).abspath()
        if not newEbuildFilename.exists():
            Path('exe-0.7.ebuild').copy(newEbuildFilename)
        if os.getuid() == 0:
            ebuildDir = Path('/usr/local/portage/dev-python/exe')
            if ebuildDir.exists():
                ebuildDir.rmtree()
            ebuildDir.makedirs()
            os.chdir(ebuildDir)
            newEbuildFilename.copy(ebuildDir)
            filesDir = ebuildDir/'files'
            filesDir.makedirs()
            Path(tmp/'exe/installs/gentoo/all-config.patch').copy(filesDir)
            if '--local' not in sys.argv:
                oldTarball = Path('/usr/portage/distfiles/')/tarball.basename()
                if oldTarball.exists():
                    oldTarball.remove()
                os.environ['GENTOO_MIRRORS']=''
                os.system('ebuild %s fetch' % newEbuildFilename.basename())
            os.system('ebuild %s manifest' % newEbuildFilename.basename())
            os.system('ebuild %s digest' % newEbuildFilename.basename())
            if '--install' in sys.argv:
                os.system('ebuild %s install' % newEbuildFilename.basename())
예제 #15
0
 def testUpgradeAppDir(self):
     """
     Tests that config files with
     'appDataDir' are upgraded to 'configDir'
     """
     configPath = Path(u'test.exe.conf')
     if configPath.exists():
         configPath.remove()
     oldParser = ConfigParser()
     system = oldParser.addSection('system')
     system.appDataDir = 'my old app data dir'
     oldParser.write(configPath)
     del system
     del oldParser
     Config._getConfigPathOptions = lambda self: ['test.exe.conf']
     myconfig = Config()
     myconfig.loadSettings()
     assert not hasattr(myconfig, 'appDataDir')
     self.assertEquals(myconfig.configPath, 'test.exe.conf')
     self.assertEquals(myconfig.configDir, 'my old app data dir')
     newParser = ConfigParser()
     newParser.read(configPath)
     self.assertEquals(newParser.system.configDir, 'my old app data dir')
예제 #16
0
def main():
    if len(sys.argv) < 2:
        print 'Usage: %s [version] [--install] [--local|username password]' % sys.argv[0]
        print 'Where [version] is the branch you want to checkout'
        print 'and username and password are for your eduforge account'
        print 'Eg. %s 0.7 --local' % sys.argv[0]
    else:
        version = sys.argv[1]
        # Calc the svn branch name
        branch = 'http://exe.cfdl.auckland.ac.nz/svn/exe/branches/%s' % version
        # Get the original exe dir
        origDir = Path(sys.argv[0]).abspath().dirname()
        # Make the temp dir
        tmp = TempDirPath()
        os.chdir(tmp)
        # Do the export
        os.system('svn export %s exe' % branch)
        # Copy firefox accross
        (origDir/'../../exe/webui/firefox').copytree(tmp/'exe/exe/webui/firefox')
        # Now make the tarball
        os.chdir(tmp/'exe')
        tarball = Path('../exe-%s-source.tgz' % version).abspath()
        os.system('tar czf %s *' % tarball)
        os.chdir(tmp)
        # Upload it
        if '--local' not in sys.argv:
            # Connect with sftp
            try:
                from paramiko import Transport
            except ImportError:
                print 'To upload you need to install paramiko python library from:'
                print 'http://www.lag.net/paramiko'
                sys.exit(2)
            from socket import socket, gethostbyname
            s = socket()
            s.connect((gethostbyname('shell.eduforge.org'), 22))
            t = Transport(s)
            t.connect()
            t.auth_password(sys.argv[-2], sys.argv[-1])
            f = t.open_sftp_client()
            # See that the directory structure looks good
            f.chdir('/home/pub/exe')
            f.put(tarball.encode('utf8'), tarball.basename().encode('utf8'))
        # If we're root, copy the tarball to the portage cache dir to save
        # downloading it when emerging (for me anyway)
        if os.getuid() == 0:
            tarball.copyfile('/usr/portage/distfiles/' + tarball.basename())
        # Copy the ebuild file
        os.chdir(tmp/'exe/installs/gentoo')
        newEbuildFilename = Path('exe-%s.ebuild' % version).abspath()
        if not newEbuildFilename.exists():
            Path('exe-0.7.ebuild').copy(newEbuildFilename)
        # If we're root, rebuild the digests and remake the install
        if os.getuid() == 0:
            ebuildDir = Path('/usr/local/portage/dev-python/exe')
            if ebuildDir.exists():
                ebuildDir.rmtree()
            ebuildDir.makedirs()
            os.chdir(ebuildDir)
            newEbuildFilename.copy(ebuildDir)
            # Copy the patch file
            filesDir = ebuildDir/'files'
            filesDir.makedirs()
            Path(tmp/'exe/installs/gentoo/all-config.patch').copy(filesDir)
            # Remove any old source if it exists and we're supposed to download
            # it
            if '--local' not in sys.argv:
                oldTarball = Path('/usr/portage/distfiles/')/tarball.basename()
                if oldTarball.exists():
                    oldTarball.remove()
                os.environ['GENTOO_MIRRORS']=''
                os.system('ebuild %s fetch' % newEbuildFilename.basename())
            os.system('ebuild %s manifest' % newEbuildFilename.basename())
            os.system('ebuild %s digest' % newEbuildFilename.basename())
            if '--install' in sys.argv:
                os.system('ebuild %s install' % newEbuildFilename.basename())
예제 #17
0
def main():
    if len(sys.argv) < 2:
        print 'Usage: %s [version] [--install] [--local|username password]' % sys.argv[0]
        print 'Where [version] is the branch you want to checkout'
        print 'and username and password are for your eduforge account'
        print 'Eg. %s 0.7 --local' % sys.argv[0]
    else:
        version = sys.argv[1]
        # Calc the svn branch name
        branch = 'http://exe.cfdl.auckland.ac.nz/svn/exe/branches/%s' % version
        # Get the original exe dir
        origDir = Path(sys.argv[0]).abspath().dirname()
        # Make the temp dir
        tmp = TempDirPath()
        os.chdir(tmp)
        # Do the export
        os.system('svn export %s exe' % branch)
        # Copy firefox accross
        (origDir/'../../exe/webui/firefox').copytree(tmp/'exe/exe/webui/firefox')
        # Now make the tarball
        os.chdir(tmp/'exe')
        tarball = Path('../exe-%s-source.tgz' % version).abspath()
        os.system('tar czf %s *' % tarball)
        os.chdir(tmp)
        # Upload it
        if '--local' not in sys.argv:
            # Connect with sftp
            try:
                from paramiko import Transport
            except ImportError:
                print 'To upload you need to install paramiko python library from:'
                print 'http://www.lag.net/paramiko'
                sys.exit(2)
            from socket import socket, gethostbyname
            s = socket()
            s.connect((gethostbyname('shell.eduforge.org'), 22))
            t = Transport(s)
            t.connect()
            t.auth_password(sys.argv[-2], sys.argv[-1])
            f = t.open_sftp_client()
            # See that the directory structure looks good
            f.chdir('/home/pub/exe')
            f.put(tarball.encode('utf8'), tarball.basename().encode('utf8'))
        # If we're root, copy the tarball to the portage cache dir to save
        # downloading it when emerging (for me anyway)
        if os.getuid() == 0:
            tarball.copyfile('/usr/portage/distfiles/' + tarball.basename())
        # Copy the ebuild file
        os.chdir(tmp/'exe/installs/gentoo')
        newEbuildFilename = Path('exe-%s.ebuild' % version).abspath()
        if not newEbuildFilename.exists():
            Path('exe-0.7.ebuild').copy(newEbuildFilename)
        # If we're root, rebuild the digests and remake the install
        if os.getuid() == 0:
            ebuildDir = Path('/usr/local/portage/dev-python/exe')
            if ebuildDir.exists():
                ebuildDir.rmtree()
            ebuildDir.makedirs()
            os.chdir(ebuildDir)
            newEbuildFilename.copy(ebuildDir)
            # Copy the patch file
            filesDir = ebuildDir/'files'
            filesDir.makedirs()
            Path(tmp/'exe/installs/gentoo/all-config.patch').copy(filesDir)
            # Remove any old source if it exists and we're supposed to download
            # it
            if '--local' not in sys.argv:
                oldTarball = Path('/usr/portage/distfiles/')/tarball.basename()
                if oldTarball.exists():
                    oldTarball.remove()
                os.environ['GENTOO_MIRRORS']=''
                os.system('ebuild %s fetch' % newEbuildFilename.basename())
            os.system('ebuild %s manifest' % newEbuildFilename.basename())
            os.system('ebuild %s digest' % newEbuildFilename.basename())
            if '--install' in sys.argv:
                os.system('ebuild %s install' % newEbuildFilename.basename())