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;
}
}