Source

gorilla / lib / gorilla / guts / repo.py

Full commit
import os, shutil, subprocess, urllib

class MercurialRepo(object):
    def __init__(self, path, sources):
        self.path = path
        self.sources = sources['hg']
        self.command = ['hg', '-R', self.path]
    
    def clone(self):
        command = ['hg', 'clone', self.sources[0], self.path, '--noupdate']
        
        rc = subprocess.call(command, shell=False, stdout=subprocess.PIPE)
        return rc == 0
    
    def pull(self):
        command = self.command + ['pull', self.sources[0]]
        
        rc = subprocess.call(command, shell=False, stdout=subprocess.PIPE)
        return rc == 0
    
    def update(self, version):
        version = 'tip' if version == 'latest' else version
        command = self.command + ['update', version]
        
        rc = subprocess.call(command, shell=False, stdout=subprocess.PIPE)
        return rc == 0
    
    
    @property
    def tags(self):
        command = self.command + ['tags', '--quiet']
        proc = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE)
        
        output = proc.communicate()[0]
        return [t.strip() for t in output.splitlines() if t.strip() != 'tip']
    
    
    @property
    def current_tags(self):
        command = self.command + ['parents', '--template', '{tags}']
        proc = subprocess.Popen(command, shell=False, stdout=subprocess.PIPE)
        
        output = proc.communicate()[0]
        tags = output.split(' ') + ['latest']
        return [t.strip() for t in tags if t.strip() != 'tip']
    

class StaticRepo(object):
    def __init__(self, path, sources):
        self.path = path
        self.sources = sources['static']
    
    def clone(self):
        if not os.path.isdir(self.path):
            os.mkdir(self.path)
    
    def pull(self):
        pass
    
    def update(self, version):
        path = os.path.join(self.path, version)
        temp_path = os.path.join(self.path, 'tmp')
        
        if version != 'latest' and os.path.exists(path):
            return
        
        url = self.sources[version]
        archive_filename = url.split('/')[-1]
        archive_path = os.path.join(self.path, archive_filename)
        
        with open(archive_path, 'w') as archive_file:
            archive_file.write(urllib.urlopen(url).read())
        
        _, _, archive_ext = archive_filename.rpartition('.')
        if archive_ext in ('tar', 'gz', 'tgz'):
            import tarfile
            
            mode = 'r'
            if archive_ext in ('gz', 'tgz'):
                mode += ':gz'
            
            f = tarfile.open(archive_path, mode=mode)
            
            names = f.getnames()
            dir_names = list(set(n.partition('/')[0] for n in names))
            
            if '' in dir_names:
                print 'wtf? no, we are not allowing tars with absolute paths'
                f.close()
                return
            
            if len(dir_names) > 1:
                print 'oh god how did this tarbomb get here i am not good with tar'
                f.close()
                return
            
            f.extractall(path=temp_path)
            f.close()
            
            source = os.path.join(temp_path, dir_names[0])
        
        if os.path.exists(path):
            shutil.rmtree(path)
        
        shutil.copytree(source, path)
    
    
    @property
    def tags(self):
        return self.sources.keys()
    
    
    @property
    def current_tags(self):
        return None