1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
4 include '../inc/common.php';
8 MTrackACL::requireAllRights('Browser', 'read');
10 $pi = mtrack_get_pathinfo(true);
11 $crumbs = MTrackSCM::makeBreadcrumbs($pi);
12 if (!strlen($pi) || $pi == '/') {
15 if (count($crumbs) > 2) {
16 $repo = MTrackSCM::factory($pi);
21 if (!isset($_GET['_'])) {
27 function one_line_cl($changelog)
29 list($one) = explode("\n", $changelog);
30 return rtrim($one, " \r\n");
33 function get_browse_data($repo, $pi, $object, $ident)
38 $data->dirs = array();
39 $data->files = array();
40 $data->jumps = array();
45 $branches = $repo->getBranches();
46 $tags = $repo->getTags();
47 if (count($branches) + count($tags)) {
48 $jumps = array("" => "- Select Branch / Tag - ");
49 if (is_array($branches)) {
50 foreach ($branches as $name => $notcare) {
51 $jumps["branch:$name"] = "Branch: $name";
54 if (is_array($tags)) {
55 foreach ($tags as $name => $notcare) {
56 $jumps["tag:$name"] = "Tag: $name";
59 $data->jumps = $jumps;
66 $ents = $repo->readdir($pi, $object, $ident);
67 } catch (Exception $e) {
68 // Typically a freshly created repo
70 $data->err = $e->getMessage();
72 foreach ($ents as $file) {
73 $basename = basename($file->name);
75 $dirs[$basename] = $file;
77 $files[$basename] = $file;
81 uksort($files, 'strnatcmp');
82 uksort($dirs, 'strnatcmp');
84 $data->files = array();
85 $data->dirs = array();
87 $urlbase = $ABSWEB . 'browse.php';
88 $pathbase = '/' . $repo->getBrowseRootName();
89 $urlbase .= $pathbase;
91 foreach ($dirs as $basename => $file) {
92 $ent = $file->getChangeEvent();
93 $url = $urlbase . '/' . $file->name;
96 $d->basename = $basename;
98 $d->ctime = $ent->ctime;
99 $d->changeby = $ent->changeby;
100 $d->changelog = one_line_cl($ent->changelog);
104 foreach ($files as $basename => $file) {
105 $ent = $file->getChangeEvent();
106 $url = $ABSWEB . 'file.php' . $pathbase .
107 '/' . $file->name . '?rev=' . $ent->rev;
110 $d->basename = $basename;
112 $d->ctime = $ent->ctime;
113 $d->changeby = $ent->changeby;
114 $d->changelog = one_line_cl($ent->changelog);
122 if (isset($_GET['jump']) && strlen($_GET['jump'])) {
123 list($object, $ident) = explode(':', $_GET['jump'], 2);
129 if ($USE_AJAX && !$AJAX) {
130 mtrack_head("Browse $pi");
132 // Since big dirs can take a while to gather the browse data,
133 // We want to show *something* to the user while we wait for
134 // the data to come in
137 $url = $_SERVER['REQUEST_URI'] . '?' . http_build_query($g);
140 <p>Loading browse data, please wait</p>
143 \$(document).ready(function () {
144 \$('#browsediv').load('$url');
151 mtrack_head("Browse $pi");
154 $bdata = mtrack_cache('get_browse_data',
155 array($repo, $pi, $object, $ident));
157 if (isset($bdata->err) && strlen($pi) > 1) {
158 throw new Exception($bdata->err);
161 /* Render a bread-crumb enabled location indicator */
162 echo "<div class='browselocation'>Location: ";
164 foreach ($crumbs as $path) {
165 if (!strlen($path)) {
168 $location .= '/' . urlencode($path);
170 $path = htmlentities($path, ENT_QUOTES, 'utf-8');
171 echo "<a href='{$ABSWEB}browse.php$location'>$path</a> / ";
174 if (count($bdata->jumps)) {
176 echo mtrack_select_box("jump", $bdata->jumps,
177 isset($_GET['jump']) ? $_GET['jump'] : null);
178 echo "<button type='submit'>Choose</button></form>\n";
183 $me = mtrack_canon_username(MTrackAuth::whoami());
184 if (MTrackACL::hasAllRights('Browser', 'create')) {
185 /* some users may have rights to create repos that belong to projects.
186 * Determine that list of projects here, because we need it for both
187 * the fork and new repo cases */
188 $owners = array("user:$me" => $me);
190 foreach (MTrackDB::q(
191 'select projid, shortname, name from projects order by ordinal')
194 if (MTrackACL::hasAllRights("project:$row[0]", 'modify')) {
195 $owners["project:$row[1]"] = $row[1];
198 if (count($owners) > 1) {
199 $owners = mtrack_select_box('repo:parent', $owners, null, true);
206 MTrackACL::requireAllRights("repo:$repo->repoid", 'read');
208 $description = MTrackWiki::format_to_html($repo->description);
209 $url = $repo->getCheckoutCommand();
211 echo "<div class='repodesc'>$description</div>";
213 echo "<div class='checkout'>\n";
214 echo "Use the following command to obtain a working copy:<br>";
215 echo "<pre>\$ $url</pre>";
220 if ($repo->canFork() && MTrackACL::hasAllRights('Browser', 'fork')
221 && MTrackConfig::get('repos', 'allow_user_repo_creation')) {
222 $forkname = "$me/$repo->shortname";
223 if ($forkname == $repo->getBrowseRootName()) {
224 /* if this is mine already, make a "more unique" name for my new fork */
225 $forkname = $repo->shortname . '2';
227 $forkname = $repo->shortname;
229 $forkname = htmlentities($forkname, ENT_QUOTES, 'utf-8');
231 <div id='forkdialog' style='display:none'
232 title='Really create a fork?'>
233 <form id='forkform' action='${ABSWEB}admin/forkrepo.php' method='post'>
234 <input type='hidden' name='source' value='$repo->repoid'>
236 A fork is your own copy of a repo that is stored and maintained
240 If all you want to do is obtain a working copy so that you can
241 collaborate on this repo, you should not create a fork.
244 You may want to fork if you want the server to keep your work backed up,
245 or to collaborate with others on work that you want to share
246 with this repo later on.
249 Choose a name for your fork:
250 $owners <input type='text' name='name' value='$forkname'>
254 <button id='forkbtn' type='button'>Fork</button>
256 \$(document).ready(function() {
257 \$('#forkdialog').dialog({
265 $(this).dialog('close');
268 $('#forkform').submit();
272 \$('#forkbtn').click(function () {
273 \$('#forkdialog').dialog('open');
283 MTrackACL::hasAllRights("repo:$repo->repoid", "delete")) {
285 <div id='deletedialog' style='display:none'
286 title='Really delete this repo?'>
287 <form id='deleteform' action='${ABSWEB}admin/deleterepo.php'
289 <input type='hidden' name='repoid' value='$repo->repoid'>
290 <p>Are you sure you want to delete this repo?</p>
291 <p><b>You cannot undo this action; any data will be permanently
295 <button id='deletebtn' type='button'>Delete</button>
297 \$(document).ready(function() {
298 \$('#deletedialog').dialog({
305 $(this).dialog('close');
307 'Delete': function() {
308 $('#deleteform').submit();
312 \$('#deletebtn').click(function () {
313 \$('#deletedialog').dialog('open');
321 if (MTrackACL::hasAllRights("repo:$repo->repoid", "modify")) {
323 <a class='button' href='{$ABSWEB}admin/repo.php/$repo->repoid'>Edit</a>
327 MTrackWatch::renderWatchUI('repo', $repo->repoid);
329 echo "<br>\n<a href='{$ABSWEB}log.php/{$repo->getBrowseRootName()}/$pi'>Show History</a><br>\n";
332 if (!$repo && MTrackACL::hasAllRights('Browser', 'fork')
333 && MTrackConfig::get('repos', 'allow_user_repo_creation')) {
334 $repotypes = array();
335 foreach (MTrackRepo::getAvailableSCMs() as $t => $r) {
336 $d = $r->getSCMMetaData();
337 $repotypes[$t] = $d['name'];
339 $repotypes = mtrack_select_box("repo:type", $repotypes, null, true);
341 <div id='newdialog' style='display:none'
342 title='Create a new repo?'>
343 <form id='newrepoform' action='${ABSWEB}admin/repo.php/new' method='post'>
345 Choose a name for your repo:
346 $owners <input type='text' name='repo:name' value='myrepo'>
349 Choose a repository type: $repotypes
353 <em>You may use <a href='{$ABSWEB}help.php/WikiFormatting' target='_blank'>WikiFormatting</a></em><br>
354 <textarea name='repo:description' class='wiki shortwiki' rows='5' cols='78'></textarea>
357 <button id='newrepobtn' type='button'>New</button>
359 \$(document).ready(function() {
360 \$('#newdialog').dialog({
367 'Cancel': function() {
368 $(this).dialog('close');
370 'Create': function() {
371 $('#newrepoform').submit();
375 \$('#newrepobtn').click(function () {
376 \$('#newdialog').dialog('open');
388 <table class='listing' id='dirlist'>
394 <th class='name' width='1%'>Name</th>
395 <th class='desc'>Description</th>
399 <th class='name' width='1%'>Name</th>
400 <th class='rev' width='1%'>Revision</th>
401 <th class='age' width='1%'>Age</th>
402 <th class='change'>Last Change</th>
412 if (count($crumbs) > 1) {
413 $class = $even++ % 2 ? 'even' : 'odd';
414 $url = $ABSWEB . 'browse.php' . dirname(mtrack_get_pathinfo(true));
415 if (isset($_GET['jump'])) {
416 $url .= '?jump=' . urlencode($_GET['jump']);
418 $url = htmlentities($url, ENT_QUOTES, 'utf-8');
420 echo "<tr class='$class'>\n";
421 echo "<td class='name'><a class='parent' href='$url'>.. [up]</a></td>";
423 echo "<td class='rev'></td>\n";
424 echo "<td class='age'></td>\n";
425 echo "<td class='change'></td>\n";
427 echo "<td class='desc'></td>\n";
432 foreach ($bdata->dirs as $d) {
433 $class = $even++ % 2 ? 'even' : 'odd';
435 if (isset($_GET['jump'])) {
436 $url .= '?jump=' . urlencode($_GET['jump']);
438 $url = htmlentities($url, ENT_QUOTES, 'utf-8');
439 echo "<tr class='$class'>\n";
440 echo "<td class='name'><a class='dir' href='$url'>$d->basename</a></td>";
441 echo "<td class='rev'>" . mtrack_changeset($d->rev, $repo) . "</td>\n";
442 echo "<td class='age'>" . mtrack_date($d->ctime) . "</td>\n";
443 echo "<td class='change'>" .
444 mtrack_username($d->changeby, array('size' => 16)) . ": " .
445 MTrackWiki::format_to_oneliner($d->changelog) . "</td>\n";
449 foreach ($bdata->files as $d) {
450 $class = $even++ % 2 ? 'even' : 'odd';
452 if (isset($_GET['jump'])) {
453 $url .= '&jump=' . urlencode($_GET['jump']);
455 $url = htmlentities($url, ENT_QUOTES, 'utf-8');
456 echo "<tr class='$class'>\n";
457 echo "<td class='name'><a class='file' href='$url'>$d->basename</a></td>";
458 echo "<td class='rev'>" . mtrack_changeset($d->rev, $repo) . "</td>\n";
459 echo "<td class='age'>" . mtrack_date($d->ctime) . "</td>\n";
460 echo "<td class='change'>" .
461 mtrack_username($d->changeby, array('size' => 16)) . ": " .
462 MTrackWiki::format_to_oneliner($d->changelog) . "</td>\n";
467 $mine = 'user:' . mtrack_canon_username(MTrackAuth::whoami());
469 if (count($crumbs) == 2 && $crumbs[1] != 'default') {
470 /* looking for a particular subset */
471 $where = "parent like('%:' || ?)";
472 $params[] = $crumbs[1];
473 } else if (count($crumbs) == 2 && $crumbs[1] == 'default') {
474 /* looking at system items */
475 $where = "parent = ''";
477 /* looking for top level items */
480 /* have my own repos bubble up */
483 select repoid, parent, shortname, description
487 case when parent = ? then 0 else 1 end,
491 $q = MTrackDB::get()->prepare($sql);
492 $q->execute($params);
494 foreach ($q->fetchAll(PDO::FETCH_OBJ) as $rep) {
495 if (!MTrackACL::hasAnyRights("repo:$rep->repoid", 'read')) {
499 $class = $even++ % 2 ? 'even' : 'odd';
500 $url = $ABSWEB . 'browse.php/';
501 $label = MTrackRepo::makeDisplayName($rep);
504 echo "<tr class='$class'>\n";
505 echo "<td class='name'><a class='dir' href='$url'>$label</a></td>\n";
506 $desc = MTrackWiki::format_to_html($rep->description);
507 echo "<td class='desc'>$desc</td>\n";
512 echo "</tbody></table>\n";