diff --git a/includes/VersioncontrolGitRepository.php b/includes/VersioncontrolGitRepository.php index 2ed4571..ca3c545 100644 --- a/includes/VersioncontrolGitRepository.php +++ b/includes/VersioncontrolGitRepository.php @@ -151,6 +151,44 @@ class VersioncontrolGitRepository extends VersioncontrolRepository { return $commits; } + + /** + * Change the default branch. + * + * @param $branch_name + * The name of the branch that should be checked out by default, when the + * repository is cloned. + * + * @throws Exception + * If the branch doesn't exist. + */ + public function setDefaultBranch($branch_name) { + // Ensure the branch exists. + $refs = $this->exec('show-ref --heads ' . escapeshellarg($branch_name)); + if (!count(array_filter($refs))) { + throw new Exception(t('The branch %branch_name does not exist.', array('%branch_name' => $branch_name))); + } + + // Create a symbolic ref from HEAD to the branch. + $this->exec('symbolic-ref HEAD ' . escapeshellarg('refs/heads/' . $branch_name)); + } + + /** + * Get the default branch of the repository. That is the branch HEAD points + * to. + * + * @return + * The name of the default branch or NULL if there is none. + */ + public function getDefaultBranch() { + $lines = $this->exec('name-rev --name-only HEAD'); + foreach ($lines as $line) { + if ($line) { + return $line; + } + } + } + /** * Execute a Git command using the root context and the command to be * executed. @@ -161,7 +199,7 @@ class VersioncontrolGitRepository extends VersioncontrolRepository { * Logged output from the command; an array of either strings or file * pointers. */ - protected function exec($command) { + public function exec($command) { if (!$this->envSet) { $this->setEnv(); } diff --git a/tests/VersioncontrolGitDeaultBranchTests.test b/tests/VersioncontrolGitDeaultBranchTests.test new file mode 100644 index 0000000..037bbe0 --- /dev/null +++ b/tests/VersioncontrolGitDeaultBranchTests.test @@ -0,0 +1,58 @@ + t('Git default branch tests'), + 'description' => t('Tests default branch handling in Git repositories.'), + 'group' => t('Version Control Git'), + ); + } + + /** + * Ensure that the default branch stays set after it has been changed. + */ + public function testSetAndGet() { + // If no default branch has been explicitly set, it should be master. + $repo = $this->versioncontrolCreateRepoFromTestRepo(); + $this->assertEqual($repo->getDefaultBranch(), 'master'); + + // Try to set it to fixes and ensure that worked. + $repo->setDefaultBranch('fixes'); + $this->assertEqual($repo->getDefaultBranch(), 'fixes'); + + // Assert that an exception is thrown for invalid branches. + try { + $repo->setDefaultBranch('non-existing-branch-name'); + $this->fail(t('Exception expected')); + } catch (Exception $e) { + $this->pass($e->getMessage()); + } + } + + /** + * Ensure that cloned repositories actually have the default branch checked + * out. + */ + public function testCloning() { + // Make the repo to clone from ready. + $repo = $this->versioncontrolCreateRepoFromTestRepo(); + $repo->setDefaultBranch('feature'); + + // The default branch should be the same in a clone repo. + $clone = $this->versioncontrolCreateRepoFromClone($repo->root); + $this->assertEqual($clone->getDefaultBranch(), 'feature'); + } +}