Esempio n. 1
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
Esempio n. 2
0
    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)
Esempio n. 3
0
    def test(self, args):
        """
        发布到测试分支,只允许单个分支发布
        :param args:
        :return:
        """
        # 当前工作空间是否干净
        if not igit.workspace_is_clean():
            raise exception.FlowException(u'工作区中尚有未保存的内容')

        if not args:
            branch = igit.current_branch()
        else:
            branch = args.pop(0)

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

        if branch != igit.current_branch():
            # 切换分支
            info(u'切换到分支%s' % branch)
            ihelper.execute('git checkout ' + branch)

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

        igit.sync_branch()

        # 切换到test分支
        test_branch = igit.test_branch()
        info(u'切换到分支%s' % test_branch)
        ihelper.execute('git checkout ' + test_branch)

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

        # 合并
        info(u'正在将%s合并到%s上...' % (branch, test_branch))
        igit.merge(branch)

        # 正常执行后,工作空间应该是干净的
        if not igit.workspace_is_clean():
            raise exception.FlowException(u'合并失败,请用git status查看工作空间详情')

        # 将test推到远程
        igit.push()

        # 切换到原来的分支
        info(u'切换回%s' % branch)
        ihelper.execute('git checkout ' + branch)

        ok(u'合并到' + test_branch + u'成功!')
Esempio n. 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()
Esempio n. 5
0
    def merge(self):
        """
        将生产分支最新代码merge到当前分支
        步骤:
            1. 拉取生产分支: git fetch origin master && git checkout master && git rebase origin/master
            2. 拉取当前分支: git fetch origin currbranch && git checkout currbranch && git rebase origin/currbranch
            3. 将master合并到当前分支: git checkout currbranch && git merge master
        :return:
        """
        prod_branch = igit.product_branch()
        curr_branch = igit.current_branch()

        if curr_branch == prod_branch:
            return

        #进入生产分支
        ihelper.execute('git checkout %s' % prod_branch)

        #拉取生产远程分支到本地
        igit.pull()

        #切回开发分支
        ihelper.execute('git checkout %s' % curr_branch)

        #拉取远程开发分支到本地
        igit.pull()

        #合并本地master到本地开发分支并推送到远程
        igit.merge(prod_branch, need_pull=False)

        igit.set_last_sync_master_date(curr_branch)

        ok('done!')
Esempio n. 6
0
    def checkout(self, args):
        """
        切换到某个特性/修复分支并拉取最新代码(如果工作空间是干净的)
        :return:
        """
        branch = None
        sync_remote = False
        while args:
            c = args.pop(0)
            if c == '-r' or c == '--remote':
                sync_remote = True
            else:
                branch = igit.real_branch(c, self.cmd)

        current_branch = igit.current_branch()

        if not branch:
            branch = current_branch

        if branch == current_branch:
            sync_remote = True

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

            out = ihelper.execute('git checkout ' + branch, return_result=True)
            # git的checkout指令输出在stderr中
            if 'Switched to branch' not in out:
                __error = True

        if __error:
            warn(u'checkout失败')
            return

        if sync_remote:
            info('fetch from remote...')
            igit.fetch(branch=branch)

        if igit.workspace_at_status(
                iglobal.GIT_BEHIND) or igit.workspace_at_status(
                    iglobal.GIT_BEHIND):
            warn(u'远程仓库已有更新,请执行 git rebase 获取最新代码')
Esempio n. 7
0
    def commit(self):
        """
        提交
        :return:
        """
        comment = ''
        push = False

        if not self.args:
            raise exception.FlowException(u'指令格式错误,请输入h ft查看使用说明')

        while self.args:
            c = self.args.pop(0)
            if c == '-p':
                push = True
            else:
                comment += ' %s' % c

        comment = comment.strip()

        if not comment:
            raise exception.FlowException(u'请填写提交说明')

        curr_branch = igit.current_branch()

        # 提交
        ihelper.execute('git add .')
        ihelper.execute('git commit -m "' +
                        igit.comment(comment,
                                     curr_branch.split('/')[0]).
                        decode('utf-8').encode(iglobal.FROM_ENCODING) + '"')

        if push:
            igit.push(curr_branch)

        ok(u'提交' + (u'并推送到远程仓库' if push else '') + u'成功!')
Esempio n. 8
0
        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
        finally:
            if c_branch != igit.current_branch():
                info(u'切换回 %s' % c_branch)
                ihelper.execute('git checkout %s' % c_branch)

        ok(u'操作成功!')

    def delete(self):
        """
        删除本地匹配模式的多个分支,并删除远程相应分支
        :return:
        """
        if not self.args:
            raise exception.FlowException(u'指令格式错误,请输入help查看使用说明')

        tag_pattern = None
        del_remote = True
Esempio n. 9
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