/** * Find and set the current scope * * @param integer $scope Specify a scope to set for this request */ public static function setScope($scope = null) { TBGLogging::log("Setting current scope"); if ($scope !== null) { TBGLogging::log("Setting scope from function parameter"); self::$_scope = $scope; TBGSettings::forceSettingsReload(); TBGLogging::log("...done (Setting scope from function parameter)"); return true; } $row = null; try { $hostname = null; if (!self::isCLI() && !self::isInstallmode()) { TBGLogging::log("Checking if scope can be set from hostname (" . $_SERVER['HTTP_HOST'] . ")"); $hostname = $_SERVER['HTTP_HOST']; } if (!self::isUpgrademode() && !self::isInstallmode()) { $row = TBGScopesTable::getTable()->getByHostnameOrDefault($hostname); } if (!$row instanceof B2DBRow) { TBGLogging::log("It couldn't", 'main', TBGLogging::LEVEL_WARNING); if (!self::isInstallmode()) { throw new Exception("The Bug Genie isn't set up to work with this server name."); } else { return; } } TBGLogging::log("Setting scope from hostname"); self::$_scope = TBGContext::factory()->TBGScope($row->get(TBGScopesTable::ID), $row); TBGSettings::forceSettingsReload(); TBGSettings::loadSettings(); TBGLogging::log("...done (Setting scope from hostname)"); return true; } catch (Exception $e) { if (self::isCLI()) { TBGLogging::log("Couldn't set up default scope.", 'main', TBGLogging::LEVEL_FATAL); throw new Exception("Could not load default scope. Error message was: " . $e->getMessage()); } elseif (!self::isInstallmode()) { throw $e; TBGLogging::log("Couldn't find a scope for hostname {$_SERVER['HTTP_HOST']}", 'main', TBGLogging::LEVEL_FATAL); TBGLogging::log($e->getMessage(), 'main', TBGLogging::LEVEL_FATAL); throw new Exception("Could not load scope. This is usually because the scopes table doesn't have a scope for this hostname"); } else { TBGLogging::log("Couldn't find a scope for hostname {$_SERVER['HTTP_HOST']}, but we're in installmode so continuing anyway"); } } }
public static function processCommit(TBGProject $project, $commit_msg, $old_rev, $new_rev, $date = null, $changed, $author, $branch = null) { $output = ''; TBGContext::setCurrentProject($project); if ($project->isArchived()) { return; } try { TBGContext::getI18n(); } catch (Exception $e) { TBGContext::reinitializeI18n(null); } // Is VCS Integration enabled? if (TBGSettings::get('vcs_mode_' . $project->getID(), 'vcs_integration') == TBGVCSIntegration::MODE_DISABLED) { $output .= '[VCS ' . $project->getKey() . '] This project does not use VCS Integration' . "\n"; return $output; } // Parse the commit message, and obtain the issues and transitions for issues. $parsed_commit = TBGIssue::getIssuesFromTextByRegex($commit_msg); $issues = $parsed_commit["issues"]; $transitions = $parsed_commit["transitions"]; // If no issues exist, we may not be able to continue // if (count($issues) == 0) // { // $output .= '[VCS '.$project->getKey().'] This project only accepts commits which affect issues' . "\n"; // return $output; // } // Build list of affected files $file_lines = preg_split('/[\\n\\r]+/', $changed); $files = array(); foreach ($file_lines as $aline) { $action = mb_substr($aline, 0, 1); if ($action == "A" || $action == "U" || $action == "D" || $action == "M") { $theline = trim(mb_substr($aline, 1)); $files[] = array($action, $theline); } } // Find author of commit, fallback is guest /* * Some VCSes use a different format of storing the committer's name. Systems like bzr, git and hg use the format * Joe Bloggs <*****@*****.**>, instead of a classic username. Therefore a user will be found via 4 queries: * a) First we extract the email if there is one, and find a user with that email * b) If one is not found - or if no email was specified, then instead test against the real name (using the name part if there was an email) * c) the username or full name is checked against the friendly name field * d) and if we still havent found one, then we check against the username * e) and if we STILL havent found one, we use the guest user */ if (preg_match("/(?<=<)(.*)(?=>)/", $author, $matches)) { $email = $matches[0]; // a) $user = TBGUsersTable::getTable()->getByEmail($email); if (!$user instanceof TBGUser) { // Not found by email preg_match("/(?<=^)(.*)(?= <)/", $author, $matches); $author = $matches[0]; } } // b) if (!$user instanceof TBGUser) { $user = TBGUsersTable::getTable()->getByRealname($author); } // c) if (!$user instanceof TBGUser) { $user = TBGUsersTable::getTable()->getByBuddyname($author); } // d) if (!$user instanceof TBGUser) { $user = TBGUsersTable::getTable()->getByUsername($author); } // e) if (!$user instanceof TBGUser) { $user = TBGSettings::getDefaultUser(); } TBGContext::setUser($user); TBGSettings::forceSettingsReload(); TBGContext::cacheAllPermissions(); $output .= '[VCS ' . $project->getKey() . '] Commit to be logged by user ' . $user->getName() . "\n"; if ($date == null) { $date = NOW; } // Create the commit data $commit = new TBGVCSIntegrationCommit(); $commit->setAuthor($user); $commit->setDate($date); $commit->setLog($commit_msg); $commit->setPreviousRevision($old_rev); $commit->setRevision($new_rev); $commit->setProject($project); if ($branch !== null) { $data = 'branch:' . $branch; $commit->setMiscData($data); } $commit->save(); $output .= '[VCS ' . $project->getKey() . '] Commit logged with revision ' . $commit->getRevision() . "\n"; // Iterate over affected issues and update them. foreach ($issues as $issue) { $inst = new TBGVCSIntegrationIssueLink(); $inst->setIssue($issue); $inst->setCommit($commit); $inst->save(); // Process all commit-message transitions for an issue. foreach ($transitions[$issue->getFormattedIssueNo()] as $transition) { if (TBGSettings::get('vcs_workflow_' . $project->getID(), 'vcs_integration') == TBGVCSIntegration::WORKFLOW_ENABLED) { TBGContext::setUser($user); TBGSettings::forceSettingsReload(); TBGContext::cacheAllPermissions(); if ($issue->isWorkflowTransitionsAvailable()) { // Go through the list of possible transitions for an issue. Only // process transitions that are applicable to issue's workflow. foreach ($issue->getAvailableWorkflowTransitions() as $possible_transition) { if (mb_strtolower($possible_transition->getName()) == mb_strtolower($transition[0])) { $output .= '[VCS ' . $project->getKey() . '] Running transition ' . $transition[0] . ' on issue ' . $issue->getFormattedIssueNo() . "\n"; // String representation of parameters. Used for log message. $parameters_string = ""; // Iterate over the list of this transition's parameters, and // set them. foreach ($transition[1] as $parameter => $value) { $parameters_string .= "{$parameter}={$value} "; switch ($parameter) { case 'resolution': if (($resolution = TBGResolution::getResolutionByKeyish($value)) instanceof TBGResolution) { TBGContext::getRequest()->setParameter('resolution_id', $resolution->getID()); } break; case 'status': if (($status = TBGStatus::getStatusByKeyish($value)) instanceof TBGStatus) { TBGContext::getRequest()->setParameter('status_id', $status->getID()); } break; } } // Run the transition. $possible_transition->transitionIssueToOutgoingStepWithoutRequest($issue); // Log an informative message about the transition. $output .= '[VCS ' . $project->getKey() . '] Ran transition ' . $possible_transition->getName() . ' with parameters \'' . $parameters_string . '\' on issue ' . $issue->getFormattedIssueNo() . "\n"; } } } } } $issue->addSystemComment(TBGContext::getI18n()->__('This issue has been updated with the latest changes from the code repository.<source>%commit_msg</source>', array('%commit_msg' => $commit_msg)), $user->getID()); $output .= '[VCS ' . $project->getKey() . '] Updated issue ' . $issue->getFormattedIssueNo() . "\n"; } // Create file links foreach ($files as $afile) { // index 0 is action, index 1 is file $inst = new TBGVCSIntegrationFile(); $inst->setAction($afile[0]); $inst->setFile($afile[1]); $inst->setCommit($commit); $inst->save(); $output .= '[VCS ' . $project->getKey() . '] Added with action ' . $afile[0] . ' file ' . $afile[1] . "\n"; } TBGEvent::createNew('vcs_integration', 'new_commit')->trigger(array('commit' => $commit)); return $output; }