/** * Transfers a gerrit patch to a github pull request. * * @param integer $patchId The gerrit patchset id */ public function createPullRequestFromGerritCommand($patchId) { try { $this->gitHubService->authenticate(); } catch (InvalidConfigurationException $e) { $this->outputLine('<error>It was not possible to authenticate with github.</error>'); $this->outputLine('Please run <b>./flow github:setup</b> first'); } $this->outputLine('Requesting Patch Details from gerrit.'); $package = $this->gerritService->getPatchTargetPackage($patchId); $packageKey = $package->getPackageKey(); $packagePath = $package->getPackagePath(); $this->outputLine(sprintf('Determined <b>%s</b> as the target package key for this change.', $packageKey)); $patchPathAndFileName = $this->gerritService->getPatchFromGerrit($patchId); $this->outputLine('Successfully fetched changeset from gerrit.'); $this->outputLine(sprintf('The following changes will be applied to package <b>%s</b>', $packageKey)); $this->output($this->executeGitCommand(sprintf('git apply --directory %s --check %s', $packageKey, $patchPathAndFileName), $packagePath)); $this->output($this->executeGitCommand(sprintf('git apply --directory %s --stat %s', $packageKey, $patchPathAndFileName), $packagePath)); if (!$this->output->askConfirmation("\nWould you like to apply this patch? (Y/n): ", TRUE)) { return; } $this->output($this->executeGitCommand(sprintf('git fetch upstream master'), $packagePath)); $this->output($this->executeGitCommand(sprintf('git checkout -b %s upstream/master', $patchId), $packagePath)); $this->output($this->executeGitCommand(sprintf('git am --directory %s %s', $packageKey, $patchPathAndFileName), $packagePath)); $this->outputLine(sprintf('<success>Successfully Applied patch %s</success>', $patchId)); if (!$this->output->askConfirmation("\nWould you like to push the change to your repository and create a pull request? (Y/n)", TRUE)) { return; } $remoteRepository = $this->getGitRemoteRepositoryOfDirectory($packagePath); $this->output($this->executeGitCommand(sprintf('git push origin %s', $patchId), $packagePath)); $this->createPullRequest($remoteRepository, $patchId); $this->output($this->executeGitCommand(sprintf('git checkout master'), $packagePath)); }
/** * Transfers a Gerrit patch to a Github pull request. * * @param integer $patchId The Gerrit Change-ID * @return void */ public function applyGerritChangeCommand($patchId) { $this->output->ask("Make sure your development collection is set up correctly and that the master branch is clean and synced with upstream master before continuing.\nAlso make sure <b>php-cs-fixer</b> is installed globally.\n\nPress any key to continue."); $this->outputLine(''); $this->outputLine('If anything goes wrong, go to the development collection and checkout a clean master branch.'); $this->outputLine(''); $this->outputLine('Requesting patch details from Gerrit.'); $package = $this->gerritService->getPatchTargetPackage($patchId); $packageKey = $package->getPackageKey(); $packagePath = $package->getPackagePath(); $collectionPath = dirname($packagePath); $this->outputLine(sprintf('Determined <b>%s</b> as the target package key for this change.', $packageKey)); $commitDetails = $this->gerritService->getCommitDetails($patchId); $oldParentCommitId = $commitDetails['parents'][0]['commit']; $newParentCommitId = trim($this->executeCommand(sprintf('git log --grep=%s --pretty=format:%%H', $oldParentCommitId), $collectionPath)); if (!$newParentCommitId) { $this->outputLine('<error>Unable to find old parent commit ID for change in development collection.</error>'); return; } $this->outputLine(sprintf('<success>Found old parent commit ID for change in development collection.</success>', $packageKey)); $this->outputLine(''); $cleanRepository = trim($this->executeCommand('git status --porcelain', $collectionPath)); if ($cleanRepository) { $this->outputLine(sprintf('<error>Development collection "%s" not clean.</error>', $collectionPath)); return; } $this->outputLine(''); $this->outputLine('Creating new branch for change.'); $this->output($this->executeCommand('git checkout master', $collectionPath)); $this->output($this->executeCommand('git pull', $collectionPath)); $this->output($this->executeCommand(sprintf('git branch -f gerrit-%s', $patchId), $collectionPath)); $this->output($this->executeCommand(sprintf('git checkout gerrit-%s', $patchId), $collectionPath)); $this->output($this->executeCommand(sprintf('git reset --hard %s', $newParentCommitId), $collectionPath)); $this->outputLine('<success>Successfully created new branch for change.</success>'); $this->outputLine(''); $this->outputLine('Fetching change from Gerrit.'); $patchPathAndFileName = $this->gerritService->getPatchFromGerrit($patchId); $this->outputLine('<success>Successfully fetched change from Gerrit.</success>'); $this->outputLine(sprintf('The following changes will be applied to package <b>%s</b>', $packageKey)); $this->output($this->executeCommand(sprintf('git apply --directory %s --check %s', $packageKey, $patchPathAndFileName), $collectionPath)); $this->output($this->executeCommand(sprintf('git apply --directory %s --stat %s', $packageKey, $patchPathAndFileName), $collectionPath)); $this->outputLine(''); $this->outputLine('Applying change in new branch.'); $this->output($this->executeCommand(sprintf('git am --directory %s %s', $packageKey, $patchPathAndFileName), $collectionPath)); $this->outputLine(sprintf('<success>Successfully applied patch %1$s in branch "gerrit-%1$s"</success>', $patchId)); $this->outputLine(''); $this->outputLine(sprintf('<b>Converting change to PSR-2 and updating license header</b>', $patchId)); $modifiedFiles = array_filter(explode(PHP_EOL, $this->executeCommand('git diff HEAD~1 --name-only', $collectionPath))); $this->executeCommand('git reset --soft HEAD~1', $collectionPath); foreach ($modifiedFiles as $modifiedFile) { if (pathinfo($modifiedFile, PATHINFO_EXTENSION) === 'php') { $this->output($this->executeCommand(sprintf('php-cs-fixer fix --level=psr2 %s', $modifiedFile), $collectionPath, true)); Tools::searchAndReplace('/\\/\\*{1}([\\s\\S]+?)(script belongs)([\\s\\S]+?)\\*\\//', '/* * This file is part of the ' . $packageKey . ' package. * * (c) Contributors of the Neos Project - www.neos.io * * This package is Open Source Software. For the full copyright and license * information, please view the LICENSE file which was distributed with this * source code. */', $collectionPath . DIRECTORY_SEPARATOR . $modifiedFile, true); } } $this->outputLine(''); $this->outputLine(sprintf('<b>Stashing change, resetting branch top master branch tip and applying change</b>', $patchId)); $this->executeCommand('git stash', $collectionPath); $this->executeCommand('git reset --hard master', $collectionPath); $stashApplyingOutput = trim($this->executeCommand('git stash pop', $collectionPath, true)); $commitMessage = preg_replace('/\\n\\n\\n/', "\n", preg_replace('/(Releases|Change-Id):.+/', '', $commitDetails['message'])); if (strpos($stashApplyingOutput, 'CONFLICT') !== -1) { $this->output('<error>' . $stashApplyingOutput . '</error>'); $this->outputLine(''); $this->outputLine(''); $this->outputLine('<success>Change applied with <error>conflicts</error>.</success>'); $this->outputLine(''); $this->outputLine('<b>Next steps:</b>'); $this->outputLine(''); $this->outputLine(sprintf('<b>1. Go to "%s" where the branch "gerrit-%s" is checked out with the changes applied.</b>', $collectionPath, $patchId)); $this->outputLine(''); $this->outputLine('<b>2. Fix the conflicts and create new commit with the following commit message:</b>'); $this->output($commitMessage); $this->outputLine(''); $this->outputLine('<b>3. Push the new branch to your personal fork and create a new pull request from it.</b>'); } else { $this->outputLine(''); $this->outputLine(''); $this->outputLine('<success>Change applied on master <b>without</b> conflicts.</success>'); $this->outputLine(''); $this->outputLine('<b>Next steps:</b>'); $this->outputLine(''); $this->outputLine(sprintf('<b>1. Go to "%s" where the branch "gerrit-%s" is checked out with the changes applied.</b>', $collectionPath, $patchId)); $this->outputLine(''); $this->outputLine('<b>2. Fix the conflicts and create new commit with the following commit message:</b>'); $this->outputLine(''); $this->outputLine('<b>3. Push the new branch to your personal fork and create a new pull request from it.</b>'); } }