Пример #1
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!')
Пример #2
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
Пример #3
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))
Пример #4
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'创建分支失败')
Пример #5
0
    def publish_to_master(self, branches=None):
        """
        发布分支到生产环境
        :param branches: 待发布分支列表:[(proj_name, branch)]
        """
        curr_p_branch = None
        tag_list = []

        if not branches:
            #接着上次的继续发布
            branches = ihelper.read_runtime('publish_branches')
            tag_list = ihelper.read_runtime('publish_tags') or []

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

        orig_branches = list(branches)

        try:
            curr_proj = None
            for index, item in enumerate(branches):
                curr_p_branch = item
                proj, branch = tuple(item)

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

                if not igit.workspace_is_clean():
                    raise exception.FlowException(
                        u'项目%s工作空间有未提交的更改,请先提交(或丢弃)后执行 %s p --continue 继续' %
                        (proj, self.cmd))

                # 首次进入项目执行fetch获取本地和远程分支差异
                if curr_proj != proj:
                    info('fetch...')
                    igit.fetch(useCache=False)

                # 切换到将要合并的分支(如果不存在本地分支则会自动创建)
                ihelper.execute('git checkout %s' % branch)

                # 同步当前本地和远程分支(此处可能会出现冲突)
                igit.sync_branch()

                # 切换到master分支
                ihelper.execute('git checkout %s' % igit.product_branch())

                is_last_branch = index >= len(
                    branches) - 1 or proj != branches[index + 1][0]

                # 合并
                info(u'合并%s...' % branch)
                igit.merge(branch,
                           need_pull=proj != curr_proj,
                           need_push=is_last_branch)
                info(u'合并完成:%s' % branch)

                # 完成
                orig_branches.remove(curr_p_branch)

                if proj != curr_proj:
                    curr_proj = proj

                # 本项目发布完成后的一些操作
                if is_last_branch:
                    self.__post_publish(proj, tag_list)

            ok(u'发布完成!tag:')

            # 打印tag信息
            for (proj_name, tag_name) in tag_list:
                info(' %s  %s' % (proj_name, tag_name))

            # 清空tag list
            tag_list = []
        except Exception, e:
            error(e.message)
            warn(u'处理完成后执行 %s p --continue 继续。或执行 %s p --abort 结束' %
                 (self.cmd, self.cmd))