Source

hgfilemerge / __init__.py

# -*- coding: utf-8 -*-

import os
import logging

log = logging.getLogger(__name__)
log.setLevel(logging.INFO)

class MergeGroup(object):
    def __init__(self):
        self.name = ''
        self.files = []
        self.prefix = ''
    
    def get_files(self):
        return self.files
    
    def set_files(self, possible_files, base_path='.'):
        for file_ in possible_files:
            file_path = os.path.join(base_path,
                                     os.path.join(self.prefix,
                                                  file_))
            if not os.path.exists(file_path):
                log.warning(u'File %s does not exist' % file_path)
            elif not os.path.isfile(file_path):
                log.warning(u'File %s is not a file (directory maybe?)' % file_path)
            else:
                self.files.append(file_)

    def __contains__(self, filename):
        return filename in self.files

class HgFileMerge(object):
    
    def __init__(self):
        self.base_path = '.'
        self.merge_groups = {}
    
    def configure_from_dict(self, d):
        if 'base_path' in d:
            self.base_path = d['base_path']
        if 'merge_groups' in d:
            for group in d['merge_groups']:
                m_group = MergeGroup()
                m_group.name = group['name']
                m_group.prefix = group.get('prefix', '')
                m_group.set_files(group['files'], base_path=self.base_path)
                self.merge_groups[m_group.name] = m_group
    
    def configure_from_file(self, path):
        import codecs
        
        def yml_configurer(f):
            from yaml import load
            return load(f)
        
        configurers = {
            'yml': yml_configurer,
            }
        
        configurer = (configurers.get(path[path.rfind('.'):]) or
                      configurers.get('yml'))
        
        with codecs.open(path, 'r', 'utf-8') as f:
            self.configure_from_dict(configurer(f))
    
    def get_merge_groups(self):
        """Returns merge groups names"""
        return self.merge_groups.keys()
    
    def get_merged_lines(self, group_name):
        import codecs
        
        ret_val = []
        for filename in self.merge_groups[group_name].files:
            with codecs.open(os.path.join(self.base_path, filename), 'r', 'utf-8') as f:
                ret_val += f.readlines()
        return ret_val

    def save(self, group_name=None):
        import codecs
        
        if group_name is None:
            for group_name in self.get_merge_groups():
                self.save(group_name)
        
        lines_to_save = self.get_merged_lines(group_name)
        with (codecs.open(
                os.path.join(
                    self.base_path,
                    os.path.join(self.merge_groups[group_name].prefix,
                                 self.merge_groups[group_name].name)),
                'w', 'utf-8')) as f:
            f.writelines(lines_to_save)

    def get_group_by_filename(self, filename):
        """Returns None if there's no group for that file
        """

        for group_name, group in self.merge_groups.iteritems():
            if filename in group:
                return group
        return None
    
    def filter_files(self, filenames):
        """Takes files list and returns list with files in group replaced by
        group name. Useful for css/js insertion.
        """
        ret_val = []
        groups_taken = set()
        for file_ in filenames:
            group = self.get_group_by_filename(file_)
            if group is not None:
                if group.name not in groups_taken:
                    ret_val.append(group.name)
                    groups_taken.add(group.name)
            else:
                ret_val.append(file_)
        return ret_val