Пример #1
0
    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
    def delete(self, args):
        """
        删除分支
        :return:
        """
        if not args:
            raise exception.FlowException(u'指令格式错误,请输入h %s查看使用说明' % self.cmd)

        branch = None
        delete_remote = True
        auto_delete = False

        while args:
            c = args.pop(0)
            if c == '--np' or c == '--no-push':
                delete_remote = False
            elif c == '-y':
                auto_delete = True
            else:
                branch = igit.real_branch(c, self.cmd)

        if not branch:
            raise exception.FlowException(u'请输入分支名称')

        if auto_delete or ihelper.confirm(u'确定删除分支 %s 吗?' % branch,
                                          default='n') == 'y':
            igit.delete_branch(branch, del_remote=delete_remote)
Пример #3
0
    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'取消操作')
Пример #4
0
    def tag(self):
        """
        在生产分支上打标签
        :return:
        """
        if not self.args:
            return ihelper.execute('git tag')

        #将要在该分支上打标签
        tag_branch = igit.product_branch()

        # 当前工作空间是否干净
        if igit.current_branch() != tag_branch and not igit.workspace_is_clean(
        ):
            raise exception.FlowException(u'工作区中尚有未保存的内容')

        tag_name = None
        comment = ''

        while self.args:
            c = self.args.pop(0)
            if c == '-a':
                tag_name = self.args.pop(0)
            elif c == '-m':
                while self.args:
                    if self.args[0].startswith('-'):
                        break

                    comment += self.args.pop(0) + ' '

        if not comment:
            raise exception.FlowException(u'请输入标签注释')

        if not tag_name:
            tag_name = igit.tag_name()

        if not tag_name:
            raise exception.FlowException(u'未设置tag name')

        if ihelper.confirm(u'将在分支 %s 上打tag:%s, ok?' %
                           (tag_branch, tag_name)) != 'y':
            warn(u'取消操作')
            return

        c_branch = igit.current_branch()

        try:
            #切换分支
            if c_branch != tag_branch:
                info(u'切换到分支 %s:' % tag_branch)
                ihelper.execute('git checkout %s' % tag_branch)

            #打tag
            print igit.tag(tag_name, comment)
        except exception.FlowException, e:
            error(u'操作失败:')
            raise e
Пример #5
0
    def delete(self):
        """
        删除本地匹配模式的多个分支,并删除远程相应分支
        :return:
        """
        if not self.args:
            raise exception.FlowException(u'指令格式错误,请输入help查看使用说明')

        tag_pattern = None
        del_remote = True
        del_branches = []

        while self.args:
            c = self.args.pop(0)
            if c == '--no-remote':
                del_remote = False
            else:
                tag_pattern = c

        if not tag_pattern:
            raise exception.FlowException(u'请指定需要删除的分支匹配模式')

        for branch in igit.local_branches():
            if branch == igit.product_branch():
                continue
            if re.match(tag_pattern, branch):
                del_branches.append(branch)

        if not del_branches:
            warn(u'没有符合条件的分支')
            return

        #打印出将要删除的分支列表
        warn(u'将要删除以下分支%s:' % ('(以及其对应的远程分支)' if del_remote else ''))
        for del_branch in del_branches:
            ok(del_branch)

        print

        if (ihelper.confirm(
                u'确定删除吗%s?' %
            ('(同时删除远程分支,删除后不可恢复)' if del_remote else ''), 'n') != 'y'):
            return

        #删除分支
        for del_branch in del_branches:
            try:
                igit.delete_branch(del_branch, del_remote)
            except exception.FlowException, e:
                warn(str(e))
Пример #6
0
    def create(self, args):
        """
        创建特性/修复分支。一次只能创建一个,会推到远端,且切换到此分支
        :return:
        """
        if not args:
            raise exception.FlowException(u'指令格式错误,请输入h %s查看使用说明' % self.cmd)

        branch = None
        auto_create_from_remote = False
        push_to_remote = True

        while args:
            c = args.pop(0)
            if c == '-y':
                auto_create_from_remote = True
            elif c == '--np' or c == '--no-push':
                push_to_remote = False
            else:
                branch = c

        if not branch:
            raise exception.FlowException(u'请输入分支名称')

        # 分支简称不可与项目、迭代名称相同(防止一些指令出现歧义)
        simple_branch = igit.simple_branch(branch)
        if simple_branch == iglobal.SPRINT or simple_branch in ihelper.projects(
        ):
            raise exception.FlowException(u'分支简称不可与项目或迭代名同名')

        branch = igit.real_branch(branch, self.cmd)

        # 检查当前分支下工作区状态
        if not igit.workspace_is_clean():
            raise exception.FlowException(
                u'工作区中尚有未提交的内容,请先用git commit提交或用git stash保存到Git栈中')

        # 分支名称重复性检查
        info(u'检查本地分支...')
        if branch in igit.local_branches():
            raise exception.FlowException(u'该分支名称已经存在')

        # 本地没有但远程有
        create_from_remote = False
        info(u'检查远程分支...')
        if branch in igit.remote_branches():
            if not auto_create_from_remote and ihelper.confirm(
                    u'远程仓库已存在%s,是否基于该远程分支创建本地分支?' % branch) != 'y':
                return
            else:
                create_from_remote = True

        say(('white', u'正在创建分支'), ('sky_blue', branch), ('white', '...'))

        if create_from_remote:
            # 基于远程分支创建本地分支,会自动追踪该远程分支
            ihelper.execute('git checkout -b ' + branch + ' origin/' + branch)
        else:
            # 切换到生产分支
            p_branch = igit.product_branch()
            ihelper.execute('git checkout ' + p_branch)
            igit.pull()

            # 基于本地生产分支创建新分支
            ihelper.execute('git checkout -b ' + branch)

            # 推送到远程
            if push_to_remote:
                ihelper.execute('git push -u origin ' + branch + ':' + branch)

        if igit.workspace_is_clean():
            #处理master更新检验,防止创建分支后执行master更新检查操作
            igit.set_last_sync_master_date(branch)

            ok(u'创建成功!已进入分支:' + branch)
        else:
            raise exception.FlowException(u'创建分支失败')
Пример #7
0
    def product(self, args):
        """
        发布到生产分支
        :param list args:
        :return:
        """
        continue_p = False
        abort_p = False
        branch_alias = {}
        tick = 1

        line_branches = []
        while args:
            c = args.pop(0)

            if c == '--abort':
                abort_p = True
            elif c == '--continue':
                continue_p = True
            else:
                if c.endswith(':'):
                    c += '*'
                line_branches.append(c)

        if abort_p:
            # 清除runtime后退出
            ok(u'取消发布')
            ihelper.write_runtime('publish_branches')
            ihelper.write_runtime('publish_tags')
            return

        if continue_p:
            # 继续上次的发布
            self.publish_to_master()
            return

        if ihelper.read_runtime('publish_branches'):
            error(u'上次发布尚未完成,请执行 %s p --continue 继续,或执行 %s p --abort 结束' %
                  (self.cmd, self.cmd))
            return

        branches = self.__resolve_branches(line_branches)
        for key, val in branches.items():
            if not val:
                branches.pop(key)

        if not branches:
            warn(u'没有需要发布的分支')
            return

        # 打印列表,并为分支设置别名
        warn(u'待发布分支列表:')
        for proj, p_brs in branches.items():
            ok(proj + u':')
            for pbr in p_brs:
                alias = 'f%s' % tick
                say(('white', ' [ '), ('green', alias),
                    ('white', ' ] %s' % pbr))
                branch_alias[alias] = (proj, pbr)
                tick += 1

        print
        info(u'1. 输入 "in 分支简称列表(f1 f2...,多个分支用空格隔开)" 告知系统要发布的分支。或者')
        info(u'2. 输入 "ex 分支简称列表" 告知系统要排除的分支。或者')
        info(u'3. 输入 all 发布以上列出的所有项目分支。或者')
        info(u'4. 输入 cancel 取消发布')
        print

        retr = True
        while retr:
            retr = False

            final_branches = self.__choose_branch_dialog(branch_alias)

            if final_branches == 'cancel':
                return

            print
            warn(u'将发布以下分支到生产环境:')

            the_proj = None
            for ele in final_branches:
                if the_proj != ele[0]:
                    the_proj = ele[0]
                    ok(ele[0] + ':')
                info('  ' + ele[1])

            print
            confirm = ihelper.confirm(u'请确认')
            if confirm == 'c':
                return
            elif confirm == 'n':
                # 返回分支选择
                info(u'请重新选择待发布分支...')
                retr = True
            elif confirm == 'y':
                # 开始执行发布,发布前先持久化待发布列表
                ihelper.write_runtime('publish_branches', final_branches)
                info(u'正在发布...')
                self.publish_to_master(final_branches)
Пример #8
0
    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