0%

git操作脚本

php实现了git命令的运行
安装 git 后,在git bash里运行

getBranch();
if ($branchName == GitCommand::MERGE_BRANCH) {
    exit('the two branch is same.');
}
if (!$branchName) {
    exit('can not get branch name');
}
$needToCommit = $gitCommand->needCommit();
$mergeBranch = GitCommand::MERGE_BRANCH;
if ($needToCommit) {
    echo 'Please commit before merge.' . PHP_EOL;
    exit;
}

//拉master
$command = GitCommand::ORIGIN_PULL . $mergeBranch;
exec($command, $pullOutput);
$haveConflict = GitCommand::haveConflict($pullOutput);
if ($haveConflict) {
    echo 'may have conflict, please solve it.' . PHP_EOL;
    exit;
}

GitCommand::checkout($mergeBranch);

//origin pull
$command = GitCommand::ORIGIN_PULL . $mergeBranch;
exec($command, $pullOutput);
$haveConflict = GitCommand::haveConflict($pullOutput);
if ($haveConflict) {
    echo 'may have conflict, please solve it.' . PHP_EOL;
    exit;
}

//merge
$command = GitCommand::MERGE . $branchName;
exec($command, $mergeOutput);
$haveConflict = GitCommand::haveConflict($mergeOutput);
if ($haveConflict) {
    echo 'may have conflict, please solve it.' . PHP_EOL;
    exit;
}

//tag
$lastTag = GitCommand::getTag();
if (!$lastTag) {
    exit('can not get the last tag.');
}

if (!$description) {
    $description = 'default description';
}
$addRes = $gitCommand->addTag($lastTag, $description);
if (!$addRes) {
    exit('add tag fail.');
}

$pushRes = GitCommand::pushToOrigin($mergeBranch, true);
if (!$pushRes) {
    exit('push to origin ' . $mergeBranch . ' fail.');
}

//回到原分支
GitCommand::checkout($branchName);

$response = 'success merge&push to origin ' . $mergeBranch;
$outputObj = new Output();
$outputObj->customEcho($response);

class GitCommand
{
    const PROJECT_ROOT = '/e/project';
    const MERGE_BRANCH = 'master';
    const BRANCH = "git branch ";
    const PULL = "git pull ";
    const ORIGIN_PULL = "git pull origin ";
    const PUSH = "git push ";
    const ORIGIN_PUSH = "git push origin ";
    const ORIGIN_PUSH_TAG = "git push origin BRANCH --tag";
    const CHECKOUT = "git checkout ";
    const STATUS = 'git status';
    const MERGE = 'git merge ';
    const FETCH_TAG = 'git fetch --tag';
    const TAG_TAIL = 'git tag | tail -1';
    const CONFIG_NAME = 'git config --global user.name';
    const ADD_TAG = 'git tag -a TAG -m "DESCRIPTION"';

    private $branch = null;
    private $needCommit = null;

    public function __construct()
    {
        exec(GitCommand::STATUS, $output);
        $branchName = '';
        $needToCommit = false;
        if ($output) {
            //匹配所在分支
            //"On branch watson-git"
            $branchNameRegex = '/^On branch ((\w|-){1,})$/';

            //有文件改了
            //有新文件
            //未commit
            $change = 'Changes to be committed:';
            $new = 'Changes not staged for commit:';

            foreach ($output as $item) {
                if (!$branchName) {
                    preg_match($branchNameRegex, $item, $match);
                    $branchName = $match[1];
                }
                if ((false !== strpos($item, $change)) || (false !== strpos($item, $new))) {
                    $needToCommit = true;
                    break;
                }
            }
        }
        $this->branch = $branchName;
        $this->needCommit = $needToCommit;
    }

    public static function checkout($branch)
    {
        $command = GitCommand::CHECKOUT . $branch;
        exec($command, $temp);
    }

    public static function toProjectDir()
    {
        exec('pwd', $dir);
        if (GitCommand::PROJECT_ROOT != $dir[0]) {
            exec('cd ' . GitCommand::PROJECT_ROOT, $cdLog);
        }
    }

    public function getBranch()
    {
        if (null === $this->branch) {
            exit('error, git status can not be resolved.');
        }
        return $this->branch;
    }

    public function needCommit()
    {
        if (null === $this->needCommit) {
            exit('error, git status can not be resolved.');
        }
        return $this->needCommit;
    }

    public static function haveConflict($output)
    {
        $res = false;
        if ($output) {
            $conflict = 'conflict';
            foreach ($output as $item) {
                if (strpos($item, $conflict) > 0 || strpos($item, $conflict) === 0) {
                    $res = true;
                }
            }
        }
        return $res;
    }

    public function addTag($lastTag, $tagDescription = '')
    {
        $name = $this->getAuthor();
        if (!$name) {
            return false;
        }
        //解析tag
        if (!$lastTag) {
            return false;
        }
        $tagArr = explode('-', $lastTag);
        $project = $tagArr[0];
        $versionStr = $tagArr[1];
        $time = date('YmdHi');
        $versionArr = explode('.', $versionStr);
        $versionNum = implode('', $versionArr);
        $versionNum++;
        $versionArr = str_split($versionNum);
        $versionStr = implode('.', $versionArr);
        if (!$project || !$versionStr || !$time || !$name) {
            return false;
        }
        $newTagArr = array($project, $versionStr, $time, $name);
        $newTag = implode('-', $newTagArr);
        $command = str_replace('TAG', $newTag, self::ADD_TAG);
        $command = str_replace('DESCRIPTION', $tagDescription, $command);
        exec($command, $addOutput);
        return true;
    }

    private function getAuthor()
    {
        $name = '';
        exec(self::CONFIG_NAME, $output);
        if ($output) {
            $fullName = $output[0];
            $arr = explode('.', $fullName);
            $name = $arr[0];
        }
        return $name;
    }

    public static function getTag()
    {
        exec(self::FETCH_TAG, $output);
        exec(self::TAG_TAIL, $output);
        $lastTag = '';
        if ($output) {
            $lastTag = array_pop($output);
        }
        return $lastTag;
    }

    public static function pushToOrigin($branch, $withTag = false)
    {
        if ($withTag) {
            $command = str_replace('BRANCH', $branch, GitCommand::ORIGIN_PUSH_TAG);
        } else {
            $command = GitCommand::ORIGIN_PUSH . $branch;
        }
        exec($command, $pushOutput);
        if ($pushOutput) {
            foreach ($pushOutput as $item) {
                $pos = strpos($item, 'hint');
                if ($pos > 0 || 0 === $pos) {
                    return false;
                }
            }
        }
        return true;
    }

}

class Output
{
    public function customEcho($str)
    {
        $middle = '****** ' . $str . ' ******';
        $len = strlen($middle);
        $this->printStar($len);
        echo $middle . PHP_EOL;
        $this->printStar($len);
    }

    private function printStar($len)
    {
        for ($i = 0; $i < $len; $i++) {
            echo "*";
        }
        echo PHP_EOL;
    }
}