function start($text, $request, $echo = true, $wordwrap = true, $esc = true, $autolink = true, $nl2br = false) { $this->project = $request->project; $this->request = $request; $this->scm = IDF_Scm::get($request->project); if ($esc) { $text = Pluf_esc($text); } if ($autolink) { $text = preg_replace('#([a-z]+://[^\\s\\(\\)]+)#i', '<a href="\\1">\\1</a>', $text); } if ($request->rights['hasIssuesAccess']) { $text = preg_replace_callback('#((?:issue|bug|ticket)(s)?\\s+|\\s+\\#)(\\d+)(\\#ic\\d+)?(?(2)((?:[, \\w]+(?:\\s+\\#)?)?\\d+(?:\\#ic\\d+)?){0,})#im', array($this, 'callbackIssues'), $text); } if ($request->rights['hasReviewAccess']) { $text = preg_replace_callback('#(reviews?\\s+)(\\d+(?:(?:\\s+and|\\s+or|,)\\s+\\d+)*)\\b#i', array($this, 'callbackReviews'), $text); } if ($request->rights['hasSourceAccess']) { $text = preg_replace_callback('#(commits?\\s+)([0-9a-f]{1,40}(?:(?:\\s+and|\\s+or|,)\\s+[0-9a-f]{1,40})*)\\b#i', array($this, 'callbackCommits'), $text); $text = preg_replace_callback('#(src:)([^\\s\\(\\)\\\\]+(?:(\\\\)\\s+[^\\s\\(\\)\\\\]+){0,})+#im', array($this, 'callbackSource'), $text); } if ($wordwrap) { $text = Pluf_Text::wrapHtml($text, 69, "\n"); } if ($nl2br) { $text = nl2br($text); } if ($echo) { echo $text; } else { return $text; } }
/** * Returns an array of model classes for which the current user * has rights and which should be used according to his filter * * @param object $request * @param string $model_filter * @return array */ private static function determineModelClasses($request, $model_filter = 'all') { $classes = array(); if (true === IDF_Precondition::accessSource($request) && ($model_filter == 'all' || $model_filter == 'commits')) { $classes[] = '\'IDF_Commit\''; // FIXME: this looks like a hack... IDF_Scm::syncTimeline($request->project); } if (true === IDF_Precondition::accessIssues($request) && ($model_filter == 'all' || $model_filter == 'issues')) { $classes[] = '\'IDF_Issue\''; $classes[] = '\'IDF_IssueComment\''; } if (true === IDF_Precondition::accessDownloads($request) && ($model_filter == 'all' || $model_filter == 'downloads')) { $classes[] = '\'IDF_Upload\''; } if (true === IDF_Precondition::accessWiki($request) && ($model_filter == 'all' || $model_filter == 'documents')) { $classes[] = '\'IDF_WikiPage\''; $classes[] = '\'IDF_WikiRevision\''; } if (true === IDF_Precondition::accessReview($request) && ($model_filter == 'all' || $model_filter == 'reviews')) { $classes[] = '\'IDF_Review_Comment\''; $classes[] = '\'IDF_Review_Patch\''; } if (count($classes) == 0) { $classes[] = '\'IDF_Dummy\''; } return $classes; }
/** * Entry point for the post-update signal. * * It tries to find the name of the project, when found it runs an * update of the timeline. */ public static function postUpdate($signal, &$params) { // Chop the ".git" and get what is left $pname = basename($params['git_dir'], '.git'); try { $project = IDF_Project::getOr404($pname); } catch (Pluf_HTTP_Error404 $e) { Pluf_Log::event(array('IDF_Plugin_SyncGit::postUpdate', 'Project not found.', array($pname, $params))); return false; // Project not found } // Now we have the project and can update the timeline Pluf_Log::debug(array('IDF_Plugin_SyncGit::postUpdate', 'Project found', $pname, $project->id)); IDF_Scm::syncTimeline($project, true); Pluf_Log::event(array('IDF_Plugin_SyncGit::postUpdate', 'sync', array($pname, $project->id))); }
function callbackEmbeddedDoc($m) { $scm = IDF_Scm::get($this->request->project); $view_source = new IDF_Views_Source(); $match = array('dummy', $this->request->project->shortname); $match[] = isset($m[2]) ? $m[2] : $scm->getMainBranch(); $match[] = $m[1]; $res = $view_source->getFile($this->request, $match); if ($res->status_code != 200) { return $m[0]; } $info = pathinfo($m[1]); $fileinfo = array($res->headers['Content-Type'], $m[1], isset($info['extension']) ? $info['extension'] : 'bin'); if (!IDF_Views_Source::isText($fileinfo)) { return $m[0]; } return $res->content; }
/** * Validates the revision given in the URL path and acts accordingly * * @param $request * @return true | Pluf_HTTP_Response_Redirect * @throws Exception */ public static function revisionValid($request) { list($url_info, $url_matches) = $request->view; list(, $project, $commit) = $url_matches; $scm = IDF_Scm::get($request->project); $res = $scm->validateRevision($commit); switch ($res) { case IDF_Scm::REVISION_VALID: return true; case IDF_Scm::REVISION_INVALID: $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::invalidRevision', array($request->project->shortname, $commit)); return new Pluf_HTTP_Response_Redirect($url); case IDF_Scm::REVISION_AMBIGUOUS: $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::disambiguateRevision', array($request->project->shortname, $commit, $url_info['model'] . '::' . $url_info['method'])); return new Pluf_HTTP_Response_Redirect($url); default: throw new Exception('unknown validation result: ' . $res); } }
/** * Create a commit from a simple class commit info of a changelog. * * @param stdClass Commit info * @param IDF_Project Current project * @return IDF_Commit */ public static function getOrAdd($change, $project) { $sql = new Pluf_SQL('project=%s AND scm_id=%s', array($project->id, $change->commit)); $r = Pluf::factory('IDF_Commit')->getList(array('filter' => $sql->gen())); if ($r->count() > 0) { return $r[0]; } if (!isset($change->full_message)) { $change->full_message = ''; } $scm = IDF_Scm::get($project); $commit = new IDF_Commit(); $commit->project = $project; $commit->scm_id = $change->commit; $commit->summary = self::toUTF8($change->title); $commit->fullmessage = self::toUTF8($change->full_message); $commit->author = $scm->findAuthor($change->author); $commit->origauthor = $change->author; $commit->creation_dtime = $change->date; $commit->create(); $commit->notify($project->getConf()); return $commit; }
function start($text, $request, $echo = true, $wordwrap = true, $esc = true, $autolink = true, $nl2br = false) { $this->project = $request->project; $this->request = $request; $this->scm = IDF_Scm::get($request->project); if ($esc) { $text = Pluf_esc($text); } if ($autolink) { $text = preg_replace('#([a-z]+://[^\\s\\(\\)]+)#i', '<a href="\\1">\\1</a>', $text); } if ($request->rights['hasIssuesAccess']) { $text = preg_replace_callback('#((?:issue|bug|ticket)(s)?\\s+|\\s+\\#)(\\d+)(\\#ic\\d+)?(?(2)((?:[, \\w]+(?:\\s+\\#)?)?\\d+(?:\\#ic\\d+)?){0,})#im', array($this, 'callbackIssues'), $text); } if ($request->rights['hasReviewAccess']) { $text = preg_replace_callback('#(reviews?\\s+)(\\d+(?:(?:\\s+and|\\s+or|,)\\s+\\d+)*)\\b#i', array($this, 'callbackReviews'), $text); } if ($request->rights['hasSourceAccess']) { $verbs = array('added', 'fixed', 'reverted', 'changed', 'removed'); $nouns = array('commit', 'commits', 'revision', 'revisions', 'rev', 'revs'); $prefix = implode(' in|', $verbs) . ' in' . '|' . implode('|', $nouns); $text = preg_replace_callback('#((?:' . $prefix . ')(?:\\s+r?))([0-9a-f]{1,40}((?:\\s+and|\\s+or|,)\\s+r?[0-9a-f]{1,40})*)\\b#i', array($this, 'callbackCommits'), $text); $text = preg_replace_callback('=(src:)([^\\s@#,\\(\\)\\\\]+(?:(\\\\)[\\s@#][^\\s@#,\\(\\)\\\\]+){0,})+(?:\\@([^\\s#,]+))(?:#(\\d+))?=im', array($this, 'callbackSource'), $text); } if ($wordwrap) { $text = Pluf_Text::wrapHtml($text, 69, "\n"); } if ($nl2br) { $text = nl2br($text); } if ($echo) { echo $text; } else { return $text; } }
/** * Update the timeline after a push * */ public function processSyncTimeline($project_name) { try { $project = IDF_Project::getOr404($project_name); } catch (Pluf_HTTP_Error404 $e) { Pluf_Log::event(array('IDF_Plugin_SyncMonotone::processSyncTimeline', 'Project not found.', array($project_name, $params))); return false; // Project not found } Pluf_Log::debug(array('IDF_Plugin_SyncMonotone::processSyncTimeline', 'Project found', $project_name, $project->id)); IDF_Scm::syncTimeline($project, true); Pluf_Log::event(array('IDF_Plugin_SyncMonotone::processSyncTimeline', 'sync', array($project_name, $project->id))); }
public function download($request, $match) { $commit = trim($match[2]); $scm = IDF_Scm::get($request->project); if (!$scm->isValidRevision($commit)) { // Redirect to the first branch $url = Pluf_HTTP_URL_urlForView('IDF_Views_Source::treeBase', array($request->project->shortname, $scm->getMainBranch())); return new Pluf_HTTP_Response_Redirect($url); } $base = $request->project->shortname . '-' . $commit; $cmd = $scm->getArchiveCommand($commit, $base . '/'); $rep = new Pluf_HTTP_Response_CommandPassThru($cmd, 'application/x-zip'); $rep->headers['Content-Transfer-Encoding'] = 'binary'; $rep->headers['Content-Disposition'] = 'attachment; filename="' . $base . '.zip"'; return $rep; }
/** * Sync the changes in the repository with the timeline. * */ public static function syncTimeline($project, $force = false) { $cache = Pluf_Cache::factory(); $key = 'IDF_Scm:' . $project->shortname . ':lastsync'; if ($force or null === ($res = $cache->get($key))) { $scm = IDF_Scm::get($project); if ($scm->isAvailable()) { foreach ($scm->getChangeLog($scm->getMainBranch(), 25) as $change) { IDF_Commit::getOrAdd($change, $project); } $cache->set($key, true, (int) (Pluf::f('cache_timeout', 300) / 2)); } } }
/** * Update the timeline in post commit. * */ public function processSyncTimeline($params) { $pname = basename($params['rel_dir']); try { $project = IDF_Project::getOr404($pname); } catch (Pluf_HTTP_Error404 $e) { Pluf_Log::event(array('IDF_Plugin_SyncMercurial::processSyncTimeline', 'Project not found.', array($pname, $params))); return false; // Project not found } // Now we have the project and can update the timeline Pluf_Log::debug(array('IDF_Plugin_SyncMercurial::processSyncTimeline', 'Project found', $pname, $project->id)); IDF_Scm::syncTimeline($project, true); Pluf_Log::event(array('IDF_Plugin_SyncMercurial::processSyncTimeline', 'sync', array($pname, $project->id))); }
public function timelineFeed($request, $match) { $prj = $request->project; // Need to check the rights $rights = array(); if (true === IDF_Precondition::accessSource($request)) { $rights[] = '\'IDF_Commit\''; IDF_Scm::syncTimeline($request->project); } if (true === IDF_Precondition::accessIssues($request)) { $rights[] = '\'IDF_Issue\''; $rights[] = '\'IDF_IssueComment\''; } if (true === IDF_Precondition::accessDownloads($request)) { $rights[] = '\'IDF_Upload\''; } if (true === IDF_Precondition::accessWiki($request)) { $rights[] = '\'IDF_WikiPage\''; $rights[] = '\'IDF_WikiRevision\''; } if (true === IDF_Precondition::accessReview($request)) { $rights[] = '\'IDF_Review_Comment\''; $rights[] = '\'IDF_Review_Patch\''; } if (count($rights) == 0) { $rights[] = '\'IDF_Dummy\''; } $sqls = sprintf('model_class IN (%s)', implode(', ', $rights)); $sql = new Pluf_SQL('project=%s AND ' . $sqls, array($prj->id)); $params = array('filter' => $sql->gen(), 'order' => 'creation_dtime DESC', 'nb' => 20); $items = Pluf::factory('IDF_Timeline')->getList($params); $set = new Pluf_Model_Set($items, array('public_dtime' => 'public_dtime')); $out = array(); foreach ($set as $item) { if ($item->id) { $out[] = $item->feedFragment($request); } } if ($items->count() > 0) { $date = Pluf_Date::gmDateToGmString($items[0]->creation_dtime); } else { $date = gmdate('c'); } $out = Pluf_Template::markSafe(implode("\n", $out)); $tmpl = new Pluf_Template('idf/index.atom'); $title = __('Updates'); $feedurl = Pluf::f('url_base') . Pluf::f('idf_base') . $request->query; $viewurl = Pluf_HTTP_URL_urlForView('IDF_Views_Project::timeline', array($prj->shortname)); $context = new Pluf_Template_Context_Request($request, array('body' => $out, 'date' => $date, 'title' => $title, 'feedurl' => $feedurl, 'viewurl' => $viewurl)); return new Pluf_HTTP_Response('<?xml version="1.0" encoding="utf-8"?>' . "\n" . $tmpl->render($context), 'application/atom+xml; charset=utf-8'); }
/** * Create a commit from a simple class commit info of a changelog. * * @param stdClass Commit info * @param IDF_Project Current project * @return IDF_Commit */ public static function getOrAdd($change, $project) { $sql = new Pluf_SQL('project=%s AND scm_id=%s', array($project->id, $change->commit)); $r = Pluf::factory('IDF_Commit')->getList(array('filter' => $sql->gen())); if ($r->count() > 0) { $r[0]->extra = new IDF_Gconf(); $r[0]->extra->serialize = true; $r[0]->extra->setModel($r[0]); $r[0]->extra->initCache(); return $r[0]; } if (!isset($change->full_message)) { $change->full_message = ''; } $scm = IDF_Scm::get($project); $commit = new IDF_Commit(); $commit->project = $project; $commit->scm_id = $change->commit; $commit->summary = self::toUTF8($change->title); $commit->fullmessage = self::toUTF8($change->full_message); $commit->author = $scm->findAuthor($change->author); $commit->origauthor = self::toUTF8($change->author); $commit->creation_dtime = $change->date; $commit->create(); $extra = $scm->getExtraProperties($change); $commit->extra = new IDF_Gconf(); $commit->extra->serialize = true; // As we can store arrays $commit->extra->setModel($commit); foreach ($extra as $key => $val) { $commit->extra->setVal($key, $val); } $commit->notify($project->getConf()); return $commit; }
/** * Get the repository size. * * @param bool Force to skip the cache (false) * @return int Size in byte or -1 if not available */ public function getRepositorySize($force = false) { $last_eval = $this->getConf()->getVal('repository_size_check_date', 0); if (Pluf::f('idf_no_size_check', false) or !$force and $last_eval > time() - 172800) { return $this->getConf()->getVal('repository_size', -1); } $this->getConf()->setVal('repository_size_check_date', time()); $scm = IDF_Scm::get($this); $this->getConf()->setVal('repository_size', $scm->getRepositorySize()); return $this->getConf()->getVal('repository_size', -1); }
/** * @see IDF_Scm::getAnonymousAccessUrl() */ public static function getAnonymousAccessUrl($project, $commit = null) { $scm = IDF_Scm::get($project); $branch = $scm->getMainBranch(); if (!empty($commit)) { $revs = $scm->_resolveSelector($commit); if (count($revs) > 0) { $certs = $scm->_getCerts($revs[0]); // for the very seldom case that a revision // has no branch certificate if (!array_key_exists('branch', $certs)) { $branch = '*'; } else { $branch = $certs['branch'][0]; } } } $remote_url = Pluf::f('mtn_remote_url', ''); if (empty($remote_url)) { return ''; } return sprintf($remote_url, $project->shortname) . '?' . $branch; }
public function view($request, $match) { $prj = $request->project; $review = Pluf_Shortcuts_GetObjectOr404('IDF_Review', $match[2]); $prj->inOr404($review); $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', array($prj->shortname, $review->id)); $title = Pluf_Template::markSafe(sprintf(__('Review <a href="%s">%d</a>: %s'), $url, $review->id, $review->summary)); $patches = $review->get_patches_list(); $patch = $patches[0]; $diff = new IDF_Diff(file_get_contents(Pluf::f('upload_issue_path') . '/' . $patch->patch)); $diff->parse(); // The form to submit comments is based on the files in the // diff if ($request->method == 'POST' and !$request->user->isAnonymous()) { $form = new IDF_Form_ReviewFileComment($request->POST, array('files' => $diff->files, 'user' => $request->user, 'patch' => $patch, 'project' => $prj)); if ($form->isValid()) { $review_comment = $form->save(); $review = $patch->get_review(); $urlr = Pluf_HTTP_URL_urlForView('IDF_Views_Review::view', array($prj->shortname, $review->id)); $request->user->setMessage(sprintf(__('Your <a href="%s">code review %d</a> has been published.'), $urlr, $review->id)); $url = Pluf_HTTP_URL_urlForView('IDF_Views_Review::index', array($prj->shortname)); $review_comment->notify($request->conf); return new Pluf_HTTP_Response_Redirect($url); } } else { $form = new IDF_Form_ReviewFileComment(null, array('files' => $diff->files, 'user' => $request->user, 'project' => $prj, 'patch' => $patch)); } $scm = IDF_Scm::get($request->project); $files = array(); $reviewers = array(); foreach ($diff->files as $filename => $def) { $fileinfo = $scm->getPathInfo($filename, $patch->get_commit()->scm_id); $sql = new Pluf_SQL('cfile=%s', array($filename)); $cts = $patch->getFileComments(array('filter' => $sql->gen(), 'order' => 'creation_dtime ASC')); foreach ($cts as $ct) { $reviewers[] = $ct->get_comment()->get_submitter(); } if (count($def['chunks'])) { $orig_file = $fileinfo ? $scm->getFile($fileinfo) : ''; $files[$filename] = array($diff->fileCompare($orig_file, $def, $filename), $form->f->{md5($filename)}, $cts); } else { $files[$filename] = array('', $form->f->{md5($filename)}, $cts); } } $reviewers = Pluf_Model_RemoveDuplicates($reviewers); return Pluf_Shortcuts_RenderToResponse('idf/review/view.html', array_merge(array('page_title' => $title, 'review' => $review, 'files' => $files, 'diff' => $diff, 'patch' => $patch, 'comments' => $patch->get_comments_list(array('sort' => 'id ASC')), 'form' => $form, 'reviewers' => $reviewers), IDF_Views_Issue::autoCompleteArrays($prj)), $request); }
public function download($request, $match) { $commit = trim($match[2]); $scm = IDF_Scm::get($request->project); $base = $request->project->shortname . '-' . $commit; $rep = $scm->getArchiveStream($commit, $base . '/'); $rep->headers['Content-Transfer-Encoding'] = 'binary'; $rep->headers['Content-Disposition'] = 'attachment; filename="' . $base . '.zip"'; return $rep; }