php8
[web.mtrack] / admin / repo.php
1 <?php # vim:ts=2:sw=2:et:
2 /* For licensing and copyright terms, see the file named LICENSE */
3 include '../../inc/common.php';
4
5 $rid = mtrack_get_pathinfo();
6
7 if ($_SERVER['REQUEST_METHOD'] == 'POST') {
8   if ($rid == 'new') {
9     MTrackACL::requireAnyRights('Browser', array('create', 'fork'));
10     $P = new MTrackRepo;
11   } else {
12     MTrackACL::requireAnyRights("repo:$rid", 'modify');
13     $P = MTrackRepo::loadById($rid);
14   }
15   $links = $P->getLinks();
16   $plinks = array();
17
18   foreach ($_POST as $name => $value) {
19     if (preg_match("/^link:(\d+|new):project$/", $name, $M)) {
20       $lid = $M[1];
21       $plinks[$lid] = array(
22         (int)$_POST["link:$lid:project"],
23         trim($_POST["link:$lid:regex"]));
24     }
25   }
26   if (isset($plinks['new'])) {
27     $n = $plinks['new'];
28     unset($plinks['new']);
29     if (strlen($n[1])) {
30       $P->addLink($n[0], $n[1]);
31     }
32   }
33   foreach ($plinks as $lid => $n) {
34     if (isset($links[$lid])) {
35       if ($n != $links[$lid] || !strlen($n[1])) {
36         $P->removeLink($lid);
37         if (strlen($n[1])) {
38           $P->addLink($n[0], $n[1]);
39         }
40       }
41     } else if (strlen($n[1])) {
42       $P->addLink($n[0], $n[1]);
43     }
44   }
45
46   $restricted = !MTrackACL::hasAnyRights('Browser', 'create');
47   if ($rid == 'new') {
48     if (isset($_POST['repo:name'])) {
49       $P->shortname = $_POST["repo:name"];
50     }
51     if (isset($_POST['repo:type'])) {
52       $P->scmtype = $_POST["repo:type"];
53     }
54     if (isset($_POST['repo:path'])) {
55       if ($restricted) throw new Exception("cannot set the repo path");
56       $P->repopath = $_POST["repo:path"];
57     }
58     if (isset($_POST['repo:parent']) && strlen($_POST['repo:parent'])) {
59       $P->parent = $_POST["repo:parent"];
60     }
61   } else {
62     $editable = !strlen($P->parent);
63
64     if (isset($_POST['repo:name']) && $_POST['repo:name'] != $P->shortname) {
65       if (!$editable) throw new Exception("cannot change the repo name");
66       $P->shortname = $_POST["repo:name"];
67     }
68     if (isset($_POST['repo:type']) && $_POST['repo:type'] != $P->scmtype) {
69       if (!$editable) throw new Exception("cannot change the repo type");
70       $P->scmtype = $_POST["repo:type"];
71     }
72     if (isset($_POST['repo:path']) && $_POST['repo:path'] != $P->repopath) {
73       if (!$editable) throw new Exception("cannot change the repo path");
74       $P->repopath = $_POST["repo:path"];
75     }
76     if (isset($_POST['repo:parent']) && $_POST['repo:parent'] != $P->parent) {
77       if (!$editable) throw new Exception("cannot change the repo parent");
78       $P->parent = $_POST["repo:parent"];
79     }
80   }
81   if (isset($_POST["repo:description"])) {
82     $P->description = $_POST["repo:description"];
83   }
84
85   $CS = MTrackChangeset::begin("repo:$rid", "Edit repo $P->shortname");
86   $P->save($CS);
87   $CS->setObject("repo:$P->repoid");
88
89   if (isset($_POST['perms'])) {
90     $perms = json_decode($_POST['perms']);
91     MTrackACL::setACL("repo:$P->repoid", 0, $perms);
92   }
93
94   $CS->commit();
95   header("Location: ${ABSWEB}browse.php/" . $P->getBrowseRootName());
96   exit;
97 }
98
99 mtrack_head("Administration - Repositories");
100 if (!strlen($rid)) {
101   MTrackACL::requireAnyRights('Browser', 'modify');
102 ?>
103 <h1>Repositories</h1>
104
105 <p>
106 Repositories are version controlled folders that remember your files and
107 folders at various points in time.  Mtrack has support for multiple different
108 Software Configuration Management systems (also known as Version Control
109 Systems; SCM and VCS are the common acronyms).
110 </p>
111 <p>
112 Listed below are the repositories that mtrack is configured to use.
113 The <em>wiki</em> repository is treated specially by mtrack; it stores the
114 wiki pages.  Click on the repository name to edit it, or click on the "Add"
115 button to tell mtrack to use another repository.
116 </p>
117 <ul>
118 <?php
119   foreach (MTrackDB::q(
120       'select repoid, shortname, parent from repos order by parent, shortname')
121       as $row) {
122     $rid = $row[0];
123     if (MTrackACL::hasAnyRights("repo:$rid", 'modify')) {
124       $name = MTrackSCM::makeDisplayName($row);
125       $name = htmlentities($name, ENT_QUOTES, 'utf-8');
126       echo "<li><a href='{$ABSWEB}admin/repo.php/$rid'>$name</a></li>\n";
127     }
128   }
129   echo "</ul>";
130   if (MTrackACL::hasAnyRights('Browser', 'create')) {
131     echo "<a href='{$ABSWEB}admin/repo.php/new'>Add new repo</a><br>\n";
132   }
133   mtrack_foot();
134   exit;
135 }
136
137 $repotypes = array();
138 foreach (MTrackRepo::getAvailableSCMs() as $t => $r) {
139   $d = $r->getSCMMetaData();
140   $repotypes[$t] = $d['name'];
141 }
142
143 echo "<form method='post'>";
144
145 if ($rid == 'new') {
146   MTrackACL::requireAnyRights('Browser', 'create');
147 ?>
148 <h2>Add new or existing Repository</h2>
149 <p>
150   Use the form below to tell mtrack where to find an existing
151   repository and add it to its list.  Leave the "Path" field
152   blank to create a new repository.
153 </p>
154 <table>
155 <?php
156   echo "<tr><th>Name</th>" .
157     "<td><input type='text' name='repo:name' value=''></td>" .
158     "</tr>";
159   echo "<tr><th>Type</th>" .
160     "<td>" .
161     mtrack_select_box("repo:type", $repotypes, null, true) .
162     "</td></tr>\n";
163   echo "<tr><th>Path</th>" .
164     "<td><input type='text' name='repo:path' size='50' value=''></td>" .
165     "</tr>\n";
166   echo "<tr><td colspan='2'>Description<br><em>You may use <a href='{$ABSWEB}help.php/WikiFormatting' target='_blank'>WikiFormatting</a></em><br>\n";
167   echo "<textarea name='repo:description' class='wiki shortwiki' rows='5' cols='78'>";
168   echo "</textarea></td></tr>\n";
169   echo "</table>";
170 } else {
171   $P = MTrackRepo::loadById($rid);
172   MTrackACL::requireAnyRights("repo:$P->repoid", 'modify');
173
174   $name = htmlentities($P->shortname, ENT_QUOTES, 'utf-8');
175   $type = htmlentities($P->scmtype, ENT_QUOTES, 'utf-8');
176   $path = htmlentities($P->repopath, ENT_QUOTES, 'utf-8');
177   $desc = htmlentities($P->description, ENT_QUOTES, 'utf-8');
178
179   echo "<h2>Repository: $name</h2>\n";
180   echo "<table>\n";
181
182   if (!$P->parent) {
183     /* not created/managed by us; some fields are editable */
184     $name = "<input type='text' name='repo:name' value='$name'>";
185     $type = mtrack_select_box("repo:type", $repotypes, $type);
186     $path = "<input type='text' name='repo:path' size='50' value='$path'>";
187   } else {
188     $name = htmlentities($P->getBrowseRootName(), ENT_QUOTES, 'utf-8');
189   }
190
191   echo "<tr><th>Name</th><td>$name</td></tr>";
192   echo "<tr><th>Type</th><td>$type</td></tr>\n";
193   echo "<tr><th>Path</th><td>$path</td></tr>\n";
194   echo "<tr><td colspan='2'>Description<br><em>You may use <a href='{$ABSWEB}help.php/WikiFormatting' target='_blank'>WikiFormatting</a></em><br>\n";
195   echo "<textarea name='repo:description' class='wiki shortwiki' rows='5' cols='78'>$desc";
196   echo "</textarea></td></tr>\n";
197
198   echo "<tr><td colspan='2'>\n";
199
200   $action_map = array(
201     'Web' => array(
202       'read'   => 'Browse via web UI',
203       'modify' => 'Administer via web UI',
204       'delete' => 'Delete repo via web UI',
205     ),
206     'SSH' => array(
207       'checkout' => 'Check-out repo via SSH',
208       'commit' => 'Commit changes to repo via SSH',
209     ),
210   );
211
212   MTrackACL::renderACLForm('perms', "repo:$P->repoid", $action_map);
213
214   echo "</tr>\n";
215   echo "</table>";
216 }
217
218 $projects = array();
219 foreach (MTrackDB::q('select projid, name, shortname from projects
220     order by name')->fetchAll() as $row) {
221   if ($row[1] != $row[2]) {
222     $projects[$row[0]] = $row[1] . " ($row[2])";
223   } else {
224     $projects[$row[0]] = $row[1];
225   }
226 }
227
228 if (count($projects)) {
229
230   echo <<<HTML
231 <h3>Linked Projects</h3>
232 <p>
233 Project links help associate code changes made in a repository with a project,
234 and this in turn helps mtrack decide who to notify about the change.
235 </p>
236 <p>
237 When assessing a change, mtrack will try each regex listed below and then take
238 the project that corresponds with the longest match--not the longest pattern;
239 the longest actual match.
240 </p>
241 <p>
242 The regex should just be the bare regex string--you must not enclose it in
243 regex delimiters.
244 </p>
245 <p>
246 You can remove a link by setting the regex to the empty string.
247 </p>
248 HTML;
249
250   echo "<table>";
251   echo "<tr><th>Regex</th><th>Project</th></tr>\n";
252
253   if ($rid != 'new') {
254     foreach ($P->getLinks() as $lid => $n) {
255       list($pid, $regex) = $n;
256
257       $regex = htmlentities($regex, ENT_QUOTES, 'utf-8');
258       echo "<tr><td>" .
259         "<input type='text' name='link:$lid:regex' value='$regex'></td>".
260         "<td>" . mtrack_select_box("link:$lid:project", $projects, $pid) .
261         "</td></tr>\n";
262     }
263   }
264
265   if ($rid == 'new') {
266     $newre = '/';
267   } else {
268     $newre = '';
269   }
270
271   echo "<tr><td>" .
272     "<input type='text' name='link:new:regex' value='$newre'></td>".
273     "<td>" . mtrack_select_box("link:new:project", $projects) .
274     "</td><td>Add new link</td></tr>\n";
275
276   echo "</table>";
277 }
278
279 echo "<button>Save Changes</button></form>";
280
281 mtrack_foot();
282