예제 #1
0
파일: transform.py 프로젝트: alexQi/iflow
    def f2f(self, args):
        """
        修复分支转修复分支,默认转到下个迭代
        :param list args:
        :return:
        """
        if '-n' not in args and '-s' not in args:
            args.append('-n')

        b_info = self.__branch_and_sprint(args)
        if not b_info['branch']:
            raise exception.FlowException(u'未指定分支名称')

        old_branch = igit.real_branch(
            b_info['branch'],
            iconfig.read_config('system', 'branch')['feature_prefix'])
        new_branch = igit.real_branch(
            '%s/%s' % (b_info['sprint'], b_info['branch'].split('/')[-1]),
            iconfig.read_config('system', 'branch')['feature_prefix'])

        if not old_branch or not new_branch:
            raise exception.FlowException(u'分支名称不合法')

        if old_branch not in igit.local_branches():
            raise exception.FlowException(u'分支不存在:%s' % old_branch)

        if ihelper.confirm(u'确定将特性分支%s转为特性分支%s吗?' %
                           (old_branch, new_branch)) == 'y':
            git.Git('rename', [old_branch, new_branch]).execute()
            ok()
        else:
            ok(u'取消操作')
예제 #2
0
파일: transform.py 프로젝트: alexQi/iflow
    def f2h(self, args):
        """
        本迭代的特性分支转修复分支
        :return:
        """
        branch = None
        while args:
            branch = args.pop(0)

        if not branch:
            raise exception.FlowException(u'未指定分支名称')

        old_branch = igit.real_branch(
            branch,
            iconfig.read_config('system', 'branch')['feature_prefix'])
        new_branch = igit.real_branch(
            branch.split('/')[-1],
            iconfig.read_config('system', 'branch')['hotfix_prefix'])

        if not old_branch or not new_branch:
            raise exception.FlowException(u'分支名称不合法')

        if old_branch not in igit.local_branches():
            raise exception.FlowException(u'分支不存在:%s' % old_branch)

        if ihelper.confirm(u'确定将特性分支%s转为修复分支%s吗?' %
                           (old_branch, new_branch)) == 'y':
            git.Git('rename', [old_branch, new_branch]).execute()
            ok()
        else:
            ok(u'取消操作')
예제 #3
0
파일: develop.py 프로젝트: alexQi/iflow
    def __resolve_branches(self, line_branches):
        """
        分支解析
        vmember,member-center
        vmember:/weigao,membercenter:order
        order-manager
        :param list line_branches:
        :return:dict
        """
        if not line_branches:
            # 所有项目
            line_branches = map(lambda x: str(x) + ':*', ihelper.projects())

        line_branches = map(lambda x: x.replace(':', ':'), line_branches)

        branches = {}
        only_this_sprint = True if self.cmd == iconfig.read_config(
            'system', 'branch')['feature_prefix'] else False
        for br in line_branches:
            if ':' not in br:
                # 判断是项目名还是分支名
                if br in ihelper.projects():
                    br += ':*'
                else:
                    br = iglobal.PROJECT + ':' + br

            br = br.split(':')
            proj = br[0]
            branch = br[1]

            if branch == '*':
                # 同步该项目下的本地和远程分支
                igit.sync(proj,
                          self.cmd,
                          only_this_sprint=self.cmd == iconfig.read_config(
                              'system', 'branch')['feature_prefix'])
                # 获取该项目下的所有相关分支
                branch = igit.project_branches(self.cmd, proj,
                                               only_this_sprint)
            else:
                branch = [igit.real_branch(branch, self.cmd)]

            if not branches.has_key(proj):
                branches[proj] = []

            branches[proj] += branch

        # 去重
        for key, val in branches.items():
            branches[key] = list(set(val))

        return branches
예제 #4
0
def headline():
    """
    页眉
    """
    print
    project = iglobal.PROJECT
    curr_proj_info = iconfig.read_config('project', project)
    branch = igit.current_branch() if project != 'global' else None
    real_path = os.getcwd() if (project == 'global'
                                or not project
                                or not curr_proj_info
                                or not curr_proj_info.has_key('dir')) \
        else curr_proj_info['dir']

    if real_path.count('/') > 2:
        path_arr = real_path.split('/')
        real_path = '/'.join(
            [path_arr[0], path_arr[1], '...', path_arr[len(path_arr) - 1]])

    iprint.green(
        iglobal.SPRINT), iprint.sky_blue('/'), iprint.yellow(project + '(' +
                                                             real_path + ')')
    if branch:
        status = igit.workspace_status(text=True)
        iprint.sky_blue('[ ' + branch +
                        ('(' + status + ')' if status else '') + ' ]')
    print
    sys.stdout.flush()
예제 #5
0
def required_check():
    """
    必须进行的检查
    """
    iprint.info(u'正在进行工作环境检查...')

    #git版本检测
    git_version = igit.git_version()
    if int(git_version[0]) < 2:
        raise exception.FlowException(u'git版本过低,请安装2.0.0以上版本')

    # 检查project.json有没有配置以及路径是否正确
    proj_cfg = iconfig.read_config('project', use_cache=False)
    if not proj_cfg:
        raise exception.FlowException(
            u'请配置项目信息(config/project.json文件,具体格式参见readme.md文件)')

    for proj_name, info in proj_cfg.items():
        if proj_name == 'global':
            raise exception.FlowException(u'项目名称不能叫global,请使用别的名称')

        if not info['dir'] or not os.path.exists(
                info['dir']) or not os.path.isdir(info['dir']):
            raise exception.FlowException(u'项目' + proj_name + u'的目录配置不正确')

        # 检测目录是否有效的git仓库
        if not igit.dir_is_repository(info['dir']):
            raise exception.FlowException(u'目录' + info['dir'] + u'不是有效的git仓库')

    # sprint版本号检测
    return isprint.check_sprint()
예제 #6
0
파일: command.py 프로젝트: alexQi/iflow
    def real_cmd(cmd, raise_err=True, valid=True, top_cmd=None):
        """
        valid=True时,如果不指定top_cmd,则认为cmd是一级指令,否则认为是top_cmd的二级指令
        :param str top_cmd:
        :param cmd:
        :param raise_err:
        :param valid:
        :return:
        """
        config = iconfig.read_config('system')
        alias = config['alias']
        cmd = alias[cmd] if alias.has_key(cmd) else cmd

        if valid:
            error = False
            if top_cmd:
                top_cmd = alias[top_cmd] if top_cmd in alias else top_cmd
                cls = config['cmd_cls'][top_cmd] if top_cmd in config['cmd_cls'] else None

                if not cls:
                    error = True
                else:
                    if cmd not in dir(eval('%s.%s' % (cls.lower(), cls))):
                        error = True
            elif not config['cmd_cls'].has_key(cmd):
                error = True

            if error:
                if raise_err:
                    raise exception.FlowException(u'无效指令')
                else:
                    return None

        return cmd
예제 #7
0
파일: igit.py 프로젝트: alexQi/iflow
def match(text, match_text, startswitch=False):
    """
    git文本匹配
    :param bool startswitch:
    :param str text:
    :param str match_text:
    :return:bool
    """
    match_dict = iconfig.read_config('system', 'git_match_text')

    if not match_dict or match_text not in match_dict:
        return False

    txts = match_dict[match_text]

    if type(txts) != list:
        txts = [txts]

    for txt in txts:
        if startswitch and text.startswith(txt):
            return True
        elif txt in text:
            return True

    return False
예제 #8
0
파일: igit.py 프로젝트: alexQi/iflow
def test_branch():
    """
    获取项目的测试分支
    :return:
    """
    project = iglobal.PROJECT

    if project != 'global':
        proj_cfg = iconfig.read_config('project', project)
        if proj_cfg.has_key('branch') and dict(proj_cfg['branch']).has_key('test'):
            return proj_cfg['branch']['test']

    config = iconfig.read_config('system', 'branch')
    if config.has_key('test'):
        return config['test']
    else:
        return 'sp-dev'
예제 #9
0
파일: icommand.py 프로젝트: alexQi/iflow
def top_cmd_list():
    """
    获取所有的一级指令列表
    返回:字典:指令->别名列表
    :return:
    """
    cmds = iconfig.read_config('system', 'cmd_cls').keys()
    alias = iconfig.read_config('system', 'alias')
    lst = {}
    for cmd in cmds:
        if cmd not in lst:
            lst[cmd] = []
        for al, c in alias.items():
            if cmd == c:
                lst[cmd].append(al)

    return lst
예제 #10
0
파일: isprint.py 프로젝트: alexQi/iflow
def check_sprint_format(sprint, loose=False):
    """
    迭代号格式检验
    :param Bool loose:
    """
    return re.compile(
        iconfig.read_config('system')
        ['sprint_format' if not loose else "sprint_format_loose"]).match(
            sprint)
예제 #11
0
def read_runtime(key=None):
    """
    读取运行时信息
    :param key:
    """
    info = iconfig.read_config(iglobal.BASE_DIR + '/runtime', use_cache=False)

    if key:
        return info[key] if info.has_key(key) else None
    else:
        return info
예제 #12
0
    def match_transform(self, text, line_words):
        if text.startswith('-'):
            return self.match_parameter(None, command.Transform.parameters,
                                        text)
        else:
            branch_cfg = iconfig.read_config('system', 'branch')

            prefix = branch_cfg['feature_prefix'] if line_words[0].startswith(
                'f') else branch_cfg['hotfix_prefix']
            if prefix == branch_cfg['feature_prefix']:
                prefix += '/' + iglobal.SPRINT
            return self.match_branch(prefix, text)
예제 #13
0
    def match_develop(self, text, line_words):
        if len(line_words) == 1:
            return self.top_cmd(text)
        elif len(line_words) == 2:
            # 二级指令
            matches = None
            if not line_words[1].startswith('-'):
                matches = self.sub_cmd(command.Develop.sub_cmd_list, text)

            if not matches:
                # 没有匹配上二级指令
                line_words.insert(1, 'checkout')
                return self.match_develop(text, line_words)

            return matches
        else:
            if line_words[1].startswith('-'):
                line_words.insert(1, 'checkout')

            # 分支或其他
            top_cmd = icommand.real_cmd(line_words[0], raise_err=False)
            sub_cmd = icommand.real_cmd(line_words[1],
                                        raise_err=False,
                                        top_cmd=top_cmd)

            if not sub_cmd:
                return None

            if top_cmd == iconfig.read_config('system',
                                              'branch')['feature_prefix']:
                branch_prefix = top_cmd + '/' + iglobal.SPRINT + '/'
            else:
                branch_prefix = top_cmd

            if text.startswith('-'):
                return self.match_parameter(sub_cmd,
                                            command.Develop.parameters, text)

            if sub_cmd == 'create':
                # 创建分支时,提示远程存在而本地不存在的分支
                return self.match_remoteonly_branch(branch_prefix, text)
            elif sub_cmd == 'product':
                # 此时可能是项目或分支名
                return self.match_project_branch(branch_prefix, text)
            elif sub_cmd == 'checkout':
                iglobal.SILENCE = True
                include_remote = '-r' in line_words or '--remote' in line_words
                match = self.match_branch(branch_prefix, text, include_remote)
                iglobal.SILENCE = False
                return match
            else:
                # 提示分支名
                return self.match_branch(branch_prefix, text)
예제 #14
0
파일: command.py 프로젝트: alexQi/iflow
    def exec_hook(flag, position, proj=None, branch=None):
        """
        执行钩子指令
        :param flag:  标识,如product
        :param position: 位置,如post(主指令后),pre(主指令前)
        :param proj:  所在的项目
        :param branch: 所在的分支
        :return: None
        """
        hook_cfg = iconfig.read_config('system', "hook")

        if not hook_cfg or not hook_cfg.has_key(flag) or not isinstance(hook_cfg[flag], dict):
            return None

        hook_cfg = hook_cfg[flag]

        if not hook_cfg.has_key(position) or not isinstance(hook_cfg[position], list) or not hook_cfg[position]:
            return None

        orig_dir = os.getcwd()
        orig_branch = igit.current_branch()

        for cfg in hook_cfg[position]:
            if not cfg or not isinstance(cfg, dict) or not cfg.has_key('cmd'):
                continue

            # 项目限制
            if proj and cfg.has_key("proj") \
                    and isinstance(cfg["proj"], list) \
                    and cfg["proj"] \
                    and proj not in cfg["proj"]:
                continue

            # 分支限制
            if branch and cfg.has_key("branch") \
                    and isinstance(cfg["branch"], list) \
                    and cfg["branch"] \
                    and branch not in cfg["branch"]:
                continue

            if not cfg.has_key("title") or not cfg["title"]:
                cfg["title"] = u"自定义脚本:%s" % cfg["cmd"]

            # 执行钩子
            iprint.say(('green', u'执行'), ('yellow', cfg["title"]), ('green', '...'))
            ihelper.execute(cfg["cmd"])
            iprint.say(('yellow', cfg["title"]), ('green', u'执行完成!'))

        if os.getcwd() != orig_dir:
            os.chdir(orig_dir)

        if igit.current_branch() != orig_branch:
            os.system('git checkout %s' % orig_branch)
예제 #15
0
파일: igit.py 프로젝트: alexQi/iflow
def real_branch( branch, prefix):
    """
    获取完整的分支名
    :param str prefix:
    :param str branch:
    :return: str
    """
    if not branch:
        raise exception.FlowException(u'参数错误')

    if branch.find(':') != -1:
        branch = branch.split(':')[1]

    original_branch = branch
    branch = filter(lambda x:x != '', branch.split('/'))
    config = iconfig.read_config('system', 'branch')

    if len(branch) > 2 and branch[0] != config['feature_prefix']:
        raise exception.FlowException(u'分支格式不合法')

    if len(branch) == 3:
        branch[1] = isprint.get_sprint(branch[1])
        if not branch[1]:
            raise exception.FlowException(u'分支格式不合法')
        return '/'.join(branch)

    if len(branch) == 2:
        if branch[0] == 'hotfix':
            return '/'.join(branch)
        elif isprint.check_sprint_format(branch[0], True):
            # 迭代号开始的,此时prefix只能是feature
            if prefix != config['feature_prefix']:
                raise exception.FlowException(u'分支格式不合法')

            branch[0] = isprint.get_sprint(branch[0])
            branch.insert(0, config[prefix + '_prefix'])
        else:
            # 看是否以feature或hotfix开头
            if branch[0] != config['feature_prefix'] and branch[0] != config['hotfix_prefix']:
                raise exception.FlowException(u'分支格式不合法')

        return '/'.join(branch)

    if original_branch.find('/') == 0:
        return config[prefix + '_prefix'] + original_branch
    else:
        return config[prefix + '_prefix'] + ('/' + iglobal.SPRINT if prefix == 'feature' else '') + '/' + branch[0]
예제 #16
0
    def match_git(self, text, line_words):
        top_cmd = icommand.real_cmd(line_words[0], raise_err=False)

        if top_cmd in ['delete', 'commit'] and text.startswith('-'):
            return self.match_parameter(top_cmd, command.Git.parameters, text)
        elif top_cmd in ['delete', 'rename']:
            return self.match_branch(None, text)
        elif top_cmd == 'git':
            if not text:
                return None
            elif len(line_words) > 2:
                return self.match_branch(None, text)
            else:
                return [ele + ' ' for ele in iconfig.read_config('system', 'git_common_cmds') if ele.startswith(text)] \
                or [ele + ' ' for ele in igit.sub_cmd_list() if ele.startswith(text)]

        return None
예제 #17
0
def write_runtime(key, val=None):
    """
    写入运行时信息
    :param val:
    :param key:
    """
    if not key and not val:
        return True

    info = iconfig.read_config(iglobal.BASE_DIR + '/runtime')

    if val:
        info[key] = val
    else:
        info.has_key(key) and info.pop(key)

    iconfig.write_config(iglobal.BASE_DIR + '/runtime', info)

    return True
예제 #18
0
    def match(self, text):
        """
        一级指令 二级指令 参数1 参数2 ...
        :type text: str
        :return:
        """
        line = re.compile('\s+').sub(' ', readline.get_line_buffer())
        line_words = line.split(' ')

        if len(line_words) == 1:
            return self.top_cmd(text)
        else:
            cls = iconfig.read_config('system', 'cmd_cls')
            cmd = icommand.real_cmd(line_words[0], raise_err=False)

            if not cmd:
                return None

            return eval('self.match_%s' % str(cls[cmd]).lower())(text,
                                                                 line_words)
예제 #19
0
def init():
    """
    初始化
    """
    # 检查必要目录
    check_dir()

    # 进入项目目录
    proj = read_runtime('project')
    iglobal.PROJECT = proj or 'global'

    if proj:
        pinfo = iconfig.read_config('project', proj)
        if pinfo.has_key('dir'):
            os.chdir(pinfo['dir'])

    iglobal.SPRINT = read_runtime('sprint') or 'none'

    # 设置Git参数
    execute('git config --global push.default simple')
예제 #20
0
파일: extra.py 프로젝트: alexQi/iflow
    def cd(args):
        """
        进入项目目录
        :param args:
        """
        if not args:
            raise exception.FlowException(u'指令格式不正确,请键入help查看该指令使用方式')

        proj_name = args[0]
        proj = iconfig.read_config('project', proj_name)

        if not proj or not proj.has_key('dir'):
            raise exception.FlowException(u'未配置项目' + proj_name + u'信息,请进入config/project.json中正确配置')

        if not os.path.isdir(proj['dir']):
            raise exception.FlowException(u'该项目git根目录配置不正确,请进入config/project.json中正确配置')

        iglobal.PROJECT = proj_name
        ihelper.write_runtime('project', proj_name)
        os.chdir(proj['dir'])
예제 #21
0
    def sub_cmd(self, sub_list, word=None):
        """
        二级指令
        :type sub_list: list
        :type word: str
        :return:
        """
        if not word:
            return list(sub_list)

        alias = iconfig.read_config('system', 'alias')
        matches = []
        for sub in sub_list:
            if sub.startswith(word):
                matches.append(sub)
            else:
                for al, c in alias.items():
                    if c == sub and str(al).startswith(word):
                        matches.append(al)

        matches = map(lambda x: x + ' ', matches)
        matches.sort()

        return matches
예제 #22
0
    sys.exit(0)

reload(sys)
sys.setdefaultencoding('utf-8')

if __name__ == '__main__':
    iglobal.BASE_DIR = os.getcwd().replace('\\', '/')

    # 初始化
    try:
        ihelper.init()
    except Exception, e:
        print e.message.decode('utf-8').encode(iglobal.FROM_ENCODING)
        raw_input()

    cfg = iconfig.read_config('system')

    # 操作系统命令行编码
    if 'console_encoding' in cfg:
        iglobal.FROM_ENCODING = cfg['console_encoding']

    blue(u'=========================***=========================', True)
    blue(cfg['name'], True)
    blue(u'作者:' + cfg['author'], True)
    blue(cfg['desc'], True)
    blue(cfg['more_info'], True)
    blue(u'=========================***=========================', True)

    # tab键自动补全
    icompleter.tab()
예제 #23
0
파일: extra.py 프로젝트: alexQi/iflow
 def alias(args=None):
     cfg = iconfig.read_config('system', 'alias')
     arr = []
     for key, val in cfg.items():
         if key != val:
             print "%3s%12s"%(key, val)
예제 #24
0
def projects():
    """
    项目名称列表
    :return:
    """
    return dict(iconfig.read_config('project')).keys()
예제 #25
0
파일: extra.py 프로젝트: alexQi/iflow
    def sql(args=None):
        """
        获取项目下面的所有sql
        :param args:
        :return:
        """
        dirs = []
        old_proj = iglobal.PROJECT
        for proj, info in iconfig.read_config('project').items():
            if 'ignore_sql_file' in info and info['ignore_sql_file']:
                continue

            # 需要先将项目切换到相应的分支
            sql_branch = info['branch']['sql_branch'] \
                if info.has_key('branch') and 'sql_branch' in info['branch'] \
                else iconfig.read_config('system', 'branch')['sql_branch']

            # 进入项目
            if iglobal.PROJECT != proj:
                iprint.info(u'进入项目%s' % proj)
                Extra.cd([proj])

            curr_branch = igit.current_branch()
            if curr_branch != sql_branch:
                if not igit.workspace_is_clean():
                    raise exception.FlowException(u'项目的工作空间有尚未保存的修改,请先执行git commit提交或git clean -fd丢弃。处理后请再次执行sql指令')
                # 切换分支
                ihelper.system('git checkout %s' % sql_branch)

            # 拉取
            igit.pull()

            base_dir = info['dir']

            if 'sql_dir' in info:
                rel_dir = info['sql_dir']
            else:
                rel_dir = iconfig.read_config('system', 'sql_dir')

            dirs.append((proj, ihelper.real_path(str(base_dir).rstrip('/') + '/' + rel_dir)))

        if iglobal.PROJECT != old_proj:
            Extra.cd([old_proj])

        sql_file_suffixes = [ele.lstrip('.') for ele in str(iconfig.read_config('system', 'sql_file_suffix')).split('|')]

        if not dirs:
            return

        files = []
        for proj, sql_path in dirs:
            if not sql_path or not os.path.exists(sql_path):
                continue

            # 获取文件夹下所有的sql文件
            for f in os.listdir(sql_path):
                f = sql_path + f
                if not os.path.isfile(f):
                    continue

                if f.split('.')[-1] in sql_file_suffixes:
                    files.append(f)

        if not files:
            iprint.info(u'本次迭代没有sql需要执行')
            return

        # 排序
        def __isort(x, y):
            """
            :type x: str
            :type y: str
            :return:
            """
            sp_date = isprint.get_date_from_sprint(iglobal.SPRINT).split('-')
            year = sp_date[0]
            month = sp_date[1]

            x = os.path.basename(x)
            y = os.path.basename(y)

            if month == '12' and x.startswith('01'):
                x = str(int(year) + 1) + x
            else:
                x = year + x

            if month == '12' and y.startswith('01'):
                y = str(int(year) + 1) + y
            else:
                y = year + y

            if x < y:
                return -1

            return 1 if x > y else 0

        files.sort(__isort)

        print
        iprint.warn(u'以下sql需要发布:')
        for f in files:
            iprint.info('  ' + os.path.basename(f))
        print

        out_file = iglobal.BASE_DIR + '/runtime/' + iglobal.SPRINT + '.sql'
        if ihelper.confirm(u'是否导出sql?') == 'y':
            out_handler = open(out_file, 'w')
            out_handler.write('set names utf8;\n')
            for f_name in files:
                f_handler = open(f_name, 'r')
                out_handler.write('\n\n-- ----------------------------------- %s -----------------------------------\n' % os.path.basename(f_name))
                out_handler.write(f_handler.read())
                f_handler.close()
            out_handler.close()
            print
            iprint.ok(u'已写入到%s中' % out_file)
        else:
            return