Beispiel #1
0
def _select_backup(src='db'):
    '''
    Select from available list of backups.
    '''
    def listfiles(path):
        a = [s for s in os.listdir(path)
             if os.path.isfile(os.path.join(path, s))]
        a.sort(key=lambda s: os.path.getmtime(os.path.join(path, s)))
        return a

    if not os.path.exists(src):
        print '%s directory does not exist'
        return None, None

    selected = None
    backups = listfiles(src)

    # return nothing if there are no backup files
    if len(backups) == 0:
        print 'There are no backups available'
        return None, None

    if 'last' in backups:
        f = open(os.path.join(src, 'last'), 'r')
        last = md5sum(f)
        f.close()
    else:
        last = None

    while selected is None:
        print 'Available backups (sorted by creation date):'
        position = 0
        for file in backups:
            position += 1
            name, ext = os.path.splitext(file)
            f = open(os.path.join(src, file), 'r')
            current = md5sum(f)
            f.close()
            if last == current and file != 'last':
                print ' %s %s (last)' % (position, name)
            else:
                print ' %s %s' % (position, name)
        selected = prompt('Enter backup number to import: ')
        if not selected.isdigit():
            print 'Please enter a number between 1 and %s\n' % len(backups)
            selected = None
        elif int(selected) < 0 or int(selected) > len(backups):
            print 'Please enter a number between 1 and %s\n' % len(backups)
            selected = None
    backup_name = backups[int(selected)-1]
    env.backup = (backup_name, os.path.join(src, backup_name))
    return env.backup
Beispiel #2
0
def generate():
    '''
    Generate patch for specific branch.
    '''
    repo = Repo('.')

    if repo.is_dirty:
        abort('Working tree is dirty. Working tree must be clean to perform this operation.')

    if confirm('Use master as base?'):
        for branch in repo.branches:
            if branch.name == 'master':
                master = branch
    else:
        branch, master = prompt_branch_select(repo, 'Select base branch')

    name, selected_branch = prompt_branch_select(repo)

    while exists(path(name)):
        name = prompt('Directory already exists: %s.\nWhat should I call this patch?'%path(name))

    os.mkdir(path(name))

    rawpath = join(path(name), 'raw.diff')
    local('git diff --binary %s %s > %s'%(selected_branch.commit, master.commit, rawpath))

    with open(rawpath, 'r') as raw:
        changed = raw.read()

    config = RawConfigParser()
    config.add_section('target')
    config.add_section('iteration')
    config.set('target', 'branch', master.name)
    config.set('target', 'commit', master.commit)
    config.set('iteration', 'branch', selected_branch.name)
    config.set('iteration', 'commit', selected_branch.commit)

    print("Generated %s patch directory."%name)

    diffs = Diff.list_from_string(repo, changed)

    def filter(diff):
        def match(pattern):
            if fnmatch.fnmatch(diff.b_path, pattern):
                return pattern
        matches = [match for match in map(match, patterns) if not match is None]
        if not bool(matches):
            return diff

    ignore = os.path.join(os.getcwd(), '.diffignore')
    if os.path.exists(ignore):
        patterns = open(ignore, 'r').read().split('\n')
        diffs = [diff for diff in map(filter, diffs) if not diff is None]

    binary_ext = ['.png', '.gif', '.jpg', '.jpeg', '.flv', '.swf','.zip', '.gz', '.rar', '.fla']

    # TODO: change this to use git generated binary marker
    binaries = [diff for diff in diffs if splitext(diff.b_path)[1] in binary_ext]
    text = set(diffs) - set(binaries)

    config.add_section('patch')
    config.set('patch', 'binary', int(len(binaries) > 0))
    config.set('patch', 'text', int(len(text) > 0))

    print 'Generated patch config file'

    if text:
        text_patch = join(path(name), 'text.patch')
        with open(text_patch, 'w') as pf:
            for diff in text:
                pf.write('%s\n\n'%diff.diff)
        print 'Generated %s text patch'%name
    else:
        text_patch = None

    if binaries:
        binary_list = join(path(name), 'binary.changes')
        binary_base = join(path(name), 'binaries')
        os.mkdir(binary_base)
        with open(binary_list, 'w') as pf:
            for binary in binaries:
                def mkdirs(path):
                    path = join(binary_base, path)
                    try:
                        os.makedirs(path)
                    except:
                        pass
                    return path
                def extractfile(commit, path):
                    dirs, file = os.path.split(path)
                    dirs = mkdirs('%s/%s'%(commit, dirs))
                    with settings(show('stdout'), warn_only = True):
                        if commit == 'target':
                            commit_id = master.commit
                        else:
                            commit_id = selected_branch.commit
                        get_file(commit_id, path, join(binary_base, commit, path))
                if binary.a_commit is None:
                    # new file is being created
                    extractfile('iteration', binary.b_path)
                elif binary.b_commit is None:
                    # file is being removed
                    extractfile('target', binary.a_path)
                else:
                    # file is being updated or renamed
                    extractfile('target', binary.a_path)
                    extractfile('iteration', binary.b_path)

                if binary.new_file:
                    pf.write('new %s\n'%binary.b_path)
                elif binary.deleted_file:
                    pf.write('rm %s\n'%binary.b_path)
                elif binary.renamed:
                    pf.write('mv %s %s\n'%(binary.a_path, binary.b_path))
                else:
                    pf.write('up %s\n'%binary.b_path)
                    
        print 'Generated %s'%binary_list
    else:
        binary_list = None

    with open(join(path(name), 'patch.cfg'), 'wb') as configfile:
        config.write(configfile)

    os.mkdir(join(path(name), 'db'))
    source = join(path(name), 'db', 'source.sql')
    target = join(path(name), 'db', 'target.sql')
    get_file(selected_branch.commit, join('db', 'last'), source)
    get_file(master.commit, join('db', 'last'), target)
    with open(join(path(name), 'db', 'source.sql'), 'r') as sfp:
        with open(join(path(name), 'db', 'target.sql'), 'r') as tfp:
            dbchanged = md5sum(sfp) != md5sum(tfp)
    if dbchanged and confirm('Generate database patch?'):
        dbpatch.generate(join(path(name), 'db'), source, target)
    else:
        shutil.rmtree(join(path(name), 'db'), ignore_errors=True)
        config.set('patch', 'schema', 0)
        config.set('patch', 'data', 0)

    with open(join(path(name), 'patch.cfg'), 'wb') as configfile:
        config.write(configfile)

    return name, path(name)