Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15396038
D8646.id20792.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
23 KB
Referenced Files
None
Subscribers
None
D8646.id20792.diff
View Options
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -2497,6 +2497,7 @@
'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php',
'ReleephBranchAccessController' => 'applications/releeph/controller/branch/ReleephBranchAccessController.php',
'ReleephBranchCommitFieldSpecification' => 'applications/releeph/field/specification/ReleephBranchCommitFieldSpecification.php',
+ 'ReleephBranchController' => 'applications/releeph/controller/branch/ReleephBranchController.php',
'ReleephBranchCreateController' => 'applications/releeph/controller/branch/ReleephBranchCreateController.php',
'ReleephBranchEditController' => 'applications/releeph/controller/branch/ReleephBranchEditController.php',
'ReleephBranchEditor' => 'applications/releeph/editor/ReleephBranchEditor.php',
@@ -5479,12 +5480,13 @@
0 => 'ReleephDAO',
1 => 'PhabricatorPolicyInterface',
),
- 'ReleephBranchAccessController' => 'ReleephProjectController',
+ 'ReleephBranchAccessController' => 'ReleephBranchController',
'ReleephBranchCommitFieldSpecification' => 'ReleephFieldSpecification',
- 'ReleephBranchCreateController' => 'ReleephProjectController',
- 'ReleephBranchEditController' => 'ReleephProjectController',
+ 'ReleephBranchController' => 'ReleephController',
+ 'ReleephBranchCreateController' => 'ReleephProductController',
+ 'ReleephBranchEditController' => 'ReleephBranchController',
'ReleephBranchEditor' => 'PhabricatorEditor',
- 'ReleephBranchHistoryController' => 'ReleephProjectController',
+ 'ReleephBranchHistoryController' => 'ReleephBranchController',
'ReleephBranchNamePreviewController' => 'ReleephController',
'ReleephBranchPreviewView' => 'AphrontFormControl',
'ReleephBranchQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
@@ -5493,7 +5495,7 @@
'ReleephBranchTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'ReleephBranchViewController' =>
array(
- 0 => 'ReleephProjectController',
+ 0 => 'ReleephBranchController',
1 => 'PhabricatorApplicationSearchResultsControllerInterface',
),
'ReleephCommitFinderException' => 'Exception',
diff --git a/src/applications/releeph/controller/ReleephController.php b/src/applications/releeph/controller/ReleephController.php
--- a/src/applications/releeph/controller/ReleephController.php
+++ b/src/applications/releeph/controller/ReleephController.php
@@ -38,4 +38,13 @@
return $this->buildSideNavView(true)->getMenu();
}
+
+ protected function getProductViewURI(ReleephProject $product) {
+ return $this->getApplicationURI('project/'.$product->getID().'/');
+ }
+
+ protected function getBranchViewURI(ReleephBranch $branch) {
+ return $this->getApplicationURI('branch/'.$branch->getID().'/');
+ }
+
}
diff --git a/src/applications/releeph/controller/branch/ReleephBranchAccessController.php b/src/applications/releeph/controller/branch/ReleephBranchAccessController.php
--- a/src/applications/releeph/controller/branch/ReleephBranchAccessController.php
+++ b/src/applications/releeph/controller/branch/ReleephBranchAccessController.php
@@ -1,59 +1,81 @@
<?php
-final class ReleephBranchAccessController extends ReleephProjectController {
+final class ReleephBranchAccessController extends ReleephBranchController {
private $action;
+ private $branchID;
public function willProcessRequest(array $data) {
$this->action = $data['action'];
- parent::willProcessRequest($data);
+ $this->branchID = $data['branchID'];
}
public function processRequest() {
- $branch = $this->getReleephBranch();
$request = $this->getRequest();
+ $viewer = $request->getUser();
- $done_uri = $branch->getURI();
+ $branch = id(new ReleephBranchQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->branchID))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$branch) {
+ return new Aphront404Response();
+ }
+ $this->setBranch($branch);
- switch ($this->action) {
+ $action = $this->action;
+ switch ($action) {
case 'close':
- $is_active = false;
- $title_text = pht('Close Branch');
- $body_text = pht(
- 'Really close the branch "%s"?',
- $branch->getBasename());
- $button_text = pht('Close Branch');
- break;
case 're-open':
- $is_active = true;
- $title_text = pht('Reopen Branch');
- $body_text = pht(
- 'Really reopen the branch "%s"?',
- $branch->getBasename());
- $button_text = pht('Reopen Branch');
break;
default:
- throw new Exception("Unknown action '{$this->action}'!");
- break;
+ return new Aphront404Response();
}
- if ($request->isDialogFormPost()) {
+ $branch_uri = $this->getBranchViewURI($branch);
+ if ($request->isFormPost()) {
+
+ if ($action == 're-open') {
+ $is_active = 1;
+ } else {
+ $is_active = 0;
+ }
+
id(new ReleephBranchEditor())
->setActor($request->getUser())
->setReleephBranch($branch)
- ->changeBranchAccess($is_active ? 1 : 0);
+ ->changeBranchAccess($is_active);
- return id(new AphrontReloadResponse())->setURI($done_uri);
+ return id(new AphrontReloadResponse())->setURI($branch_uri);
}
- $dialog = new AphrontDialogView();
- $dialog
- ->setUser($request->getUser())
+ if ($action == 'close') {
+ $title_text = pht('Really Close Branch?');
+ $short = pht('Close Branch');
+ $body_text = pht(
+ 'Really close the branch "%s"?',
+ phutil_tag('strong', array(), $branch->getBasename()));
+ $button_text = pht('Close Branch');
+ } else {
+ $title_text = pht('Really Reopen Branch?');
+ $short = pht('Reopen Branch');
+ $body_text = pht(
+ 'Really reopen the branch "%s"?',
+ phutil_tag('strong', array(), $branch->getBasename()));
+ $button_text = pht('Reopen Branch');
+ }
+
+ return $this->newDialog()
->setTitle($title_text)
+ ->setShortTitle($short)
->appendChild($body_text)
->addSubmitButton($button_text)
- ->addCancelButton($done_uri);
-
- return id(new AphrontDialogResponse())->setDialog($dialog);
+ ->addCancelButton($branch_uri);
}
+
}
diff --git a/src/applications/releeph/controller/branch/ReleephBranchController.php b/src/applications/releeph/controller/branch/ReleephBranchController.php
new file mode 100644
--- /dev/null
+++ b/src/applications/releeph/controller/branch/ReleephBranchController.php
@@ -0,0 +1,35 @@
+<?php
+
+abstract class ReleephBranchController extends ReleephController {
+
+ private $branch;
+
+ public function setBranch($branch) {
+ $this->branch = $branch;
+ return $this;
+ }
+
+ public function getBranch() {
+ return $this->branch;
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+ $branch = $this->getBranch();
+ if ($branch) {
+ $product = $branch->getProduct();
+
+ $crumbs->addTextCrumb(
+ $product->getName(),
+ $this->getProductViewURI($product));
+
+ $crumbs->addTextCrumb(
+ $branch->getName(),
+ $this->getBranchViewURI($branch));
+ }
+
+ return $crumbs;
+ }
+
+}
diff --git a/src/applications/releeph/controller/branch/ReleephBranchCreateController.php b/src/applications/releeph/controller/branch/ReleephBranchCreateController.php
--- a/src/applications/releeph/controller/branch/ReleephBranchCreateController.php
+++ b/src/applications/releeph/controller/branch/ReleephBranchCreateController.php
@@ -1,23 +1,43 @@
<?php
-final class ReleephBranchCreateController extends ReleephProjectController {
+final class ReleephBranchCreateController extends ReleephProductController {
- public function processRequest() {
- $releeph_project = $this->getReleephProject();
+ private $productID;
+
+ public function willProcessRequest(array $data) {
+ $this->productID = $data['projectID'];
+ }
+ public function processRequest() {
$request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $product = id(new ReleephProjectQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->productID))
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->executeOne();
+ if (!$product) {
+ return new Aphront404Response();
+ }
+ $this->setProduct($product);
+
$cut_point = $request->getStr('cutPoint');
$symbolic_name = $request->getStr('symbolicName');
if (!$cut_point) {
- $repository = $releeph_project->loadPhabricatorRepository();
+ $repository = $product->loadPhabricatorRepository();
switch ($repository->getVersionControlSystem()) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_SVN:
break;
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
- $cut_point = $releeph_project->getTrunkBranch();
+ $cut_point = $product->getTrunkBranch();
break;
}
}
@@ -42,7 +62,7 @@
try {
$finder = id(new ReleephCommitFinder())
->setUser($request->getUser())
- ->setReleephProject($releeph_project);
+ ->setReleephProject($product);
$cut_commit = $finder->fromPartial($cut_point);
} catch (Exception $e) {
$e_cut = pht('Invalid');
@@ -52,7 +72,7 @@
if (!$errors) {
$branch = id(new ReleephBranchEditor())
- ->setReleephProject($releeph_project)
+ ->setReleephProject($product)
->setActor($request->getUser())
->newBranchFromCommit(
$cut_commit,
@@ -64,14 +84,7 @@
}
}
- $error_view = array();
- if ($errors) {
- $error_view = new AphrontErrorView();
- $error_view->setErrors($errors);
- }
-
- $project_id = $releeph_project->getID();
- $project_uri = $this->getApplicationURI("project/{$project_id}/");
+ $product_uri = $this->getProductViewURI($product);
$form = id(new AphrontFormView())
->setUser($request->getUser())
@@ -95,7 +108,12 @@
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Cut Branch'))
- ->addCancelButton($project_uri));
+ ->addCancelButton($product_uri));
+
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText(pht('New Branch'))
+ ->setFormErrors($errors)
+ ->appendChild($form);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('New Branch'));
@@ -103,8 +121,7 @@
return $this->buildApplicationPage(
array(
$crumbs,
- $error_view,
- $form,
+ $box,
),
array(
'title' => pht('New Branch'),
diff --git a/src/applications/releeph/controller/branch/ReleephBranchEditController.php b/src/applications/releeph/controller/branch/ReleephBranchEditController.php
--- a/src/applications/releeph/controller/branch/ReleephBranchEditController.php
+++ b/src/applications/releeph/controller/branch/ReleephBranchEditController.php
@@ -1,27 +1,46 @@
<?php
-final class ReleephBranchEditController extends ReleephProjectController {
+final class ReleephBranchEditController extends ReleephBranchController {
+
+ private $branchID;
+
+ public function willProcessRequest(array $data) {
+ $this->branchID = $data['branchID'];
+ }
public function processRequest() {
$request = $this->getRequest();
- $releeph_branch = $this->getReleephBranch();
+ $viewer = $request->getUser();
+
+ $branch = id(new ReleephBranchQuery())
+ ->setViewer($viewer)
+ ->requireCapabilities(
+ array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->withIDs(array($this->branchID))
+ ->executeOne();
+ if (!$branch) {
+ return new Aphront404Response();
+ }
+ $this->setBranch($branch);
+
$symbolic_name = $request->getStr(
'symbolicName',
- $releeph_branch->getSymbolicName());
-
- $errors = array();
+ $branch->getSymbolicName());
if ($request->isFormPost()) {
$existing_with_same_symbolic_name =
id(new ReleephBranch())
->loadOneWhere(
'id != %d AND releephProjectID = %d AND symbolicName = %s',
- $releeph_branch->getID(),
- $releeph_branch->getReleephProjectID(),
+ $branch->getID(),
+ $branch->getReleephProjectID(),
$symbolic_name);
- $releeph_branch->openTransaction();
- $releeph_branch
+ $branch->openTransaction();
+ $branch
->setSymbolicName($symbolic_name);
if ($existing_with_same_symbolic_name) {
@@ -30,17 +49,17 @@
->save();
}
- $releeph_branch->save();
- $releeph_branch->saveTransaction();
+ $branch->save();
+ $branch->saveTransaction();
return id(new AphrontRedirectResponse())
- ->setURI($releeph_branch->getURI());
+ ->setURI($this->getBranchViewURI($branch));
}
$phids = array();
- $phids[] = $creator_phid = $releeph_branch->getCreatedByUserPHID();
- $phids[] = $cut_commit_phid = $releeph_branch->getCutPointCommitPHID();
+ $phids[] = $creator_phid = $branch->getCreatedByUserPHID();
+ $phids[] = $cut_commit_phid = $branch->getCutPointCommitPHID();
$handles = id(new PhabricatorHandleQuery())
->setViewer($request->getUser())
@@ -52,7 +71,7 @@
->appendChild(
id(new AphrontFormStaticControl())
->setLabel(pht('Branch Name'))
- ->setValue($releeph_branch->getName()))
+ ->setValue($branch->getName()))
->appendChild(
id(new AphrontFormMarkupControl())
->setLabel(pht('Cut Point'))
@@ -70,29 +89,24 @@
'(e.g. "LATEST")')))
->appendChild(
id(new AphrontFormSubmitControl())
- ->addCancelButton($releeph_branch->getURI())
- ->setValue(pht('Save')));
-
- $error_view = null;
- if ($errors) {
- $error_view = id(new AphrontErrorView())
- ->setSeverity(AphrontErrorView::SEVERITY_ERROR)
- ->setErrors($errors)
- ->setTitle(pht('Errors'));
- }
+ ->addCancelButton($this->getBranchViewURI($branch))
+ ->setValue(pht('Save Branch')));
$title = pht(
'Edit Branch %s',
- $releeph_branch->getDisplayNameWithDetail());
+ $branch->getDisplayNameWithDetail());
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('Edit'));
+ $box = id(new PHUIObjectBoxView())
+ ->setHeaderText($title)
+ ->appendChild($form);
+
return $this->buildApplicationPage(
array(
$crumbs,
- $error_view,
- $form,
+ $box,
),
array(
'title' => $title,
diff --git a/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php b/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php
--- a/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php
+++ b/src/applications/releeph/controller/branch/ReleephBranchHistoryController.php
@@ -1,12 +1,15 @@
<?php
-final class ReleephBranchHistoryController extends ReleephProjectController {
+final class ReleephBranchHistoryController extends ReleephBranchController {
- private $id;
+ private $branchID;
+
+ public function shouldAllowPublic() {
+ return true;
+ }
public function willProcessRequest(array $data) {
- $this->id = $data['branchID'];
- parent::willProcessRequest($data);
+ $this->branchID = $data['branchID'];
}
public function processRequest() {
@@ -15,11 +18,12 @@
$branch = id(new ReleephBranchQuery())
->setViewer($viewer)
- ->withIDs(array($this->id))
+ ->withIDs(array($this->branchID))
->executeOne();
if (!$branch) {
return new Aphront404Response();
}
+ $this->setBranch($branch);
$xactions = id(new ReleephBranchTransactionQuery())
->setViewer($viewer)
@@ -29,7 +33,8 @@
$timeline = id(new PhabricatorApplicationTransactionView())
->setUser($viewer)
->setObjectPHID($branch->getPHID())
- ->setTransactions($xactions);
+ ->setTransactions($xactions)
+ ->setShouldTerminate(true);
$crumbs = $this->buildApplicationCrumbs();
$crumbs->addTextCrumb(pht('History'));
diff --git a/src/applications/releeph/controller/branch/ReleephBranchViewController.php b/src/applications/releeph/controller/branch/ReleephBranchViewController.php
--- a/src/applications/releeph/controller/branch/ReleephBranchViewController.php
+++ b/src/applications/releeph/controller/branch/ReleephBranchViewController.php
@@ -1,22 +1,32 @@
<?php
-final class ReleephBranchViewController extends ReleephProjectController
+final class ReleephBranchViewController extends ReleephBranchController
implements PhabricatorApplicationSearchResultsControllerInterface {
private $queryKey;
+ private $branchID;
public function shouldAllowPublic() {
return true;
}
public function willProcessRequest(array $data) {
- parent::willProcessRequest($data);
+ $this->branchID = $data['branchID'];
$this->queryKey = idx($data, 'queryKey');
}
-
public function processRequest() {
$request = $this->getRequest();
+ $viewer = $request->getUser();
+
+ $branch = id(new ReleephBranchQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($this->branchID))
+ ->executeOne();
+ if (!$branch) {
+ return new Aphront404Response();
+ }
+ $this->setBranch($branch);
$controller = id(new PhabricatorApplicationSearchController($request))
->setPreface($this->renderPreface())
@@ -34,11 +44,10 @@
assert_instances_of($requests, 'ReleephRequest');
$viewer = $this->getRequest()->getUser();
- $releeph_branch = $this->getReleephBranch();
- $releeph_project = $this->getReleephProject();
+ $branch = $this->getBranch();
- // TODO: Really gross.
- $releeph_branch->populateReleephRequestHandles(
+ // TODO: Really really gross.
+ $branch->populateReleephRequestHandles(
$viewer,
$requests);
@@ -46,8 +55,8 @@
->setOriginType('branch')
->setUser($viewer)
->setAphrontRequest($this->getRequest())
- ->setReleephProject($releeph_project)
- ->setReleephBranch($releeph_branch)
+ ->setReleephProject($branch->getProduct())
+ ->setReleephBranch($branch)
->setReleephRequests($requests);
return $list;
@@ -59,7 +68,6 @@
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
-
$this->getSearchEngine()->addNavigationItems($nav->getMenu());
$nav->selectFilter(null);
@@ -68,45 +76,43 @@
}
private function getSearchEngine() {
- $branch = $this->getReleephBranch();
+ $branch = $this->getBranch();
return id(new ReleephRequestSearchEngine())
->setBranch($branch)
- ->setBaseURI($branch->getURI())
+ ->setBaseURI($this->getApplicationURI('branch/'.$branch->getID().'/'))
->setViewer($this->getRequest()->getUser());
}
public function buildApplicationCrumbs() {
- $releeph_branch = $this->getReleephBranch();
-
$crumbs = parent::buildApplicationCrumbs();
- if ($releeph_branch->isActive()) {
- $create_uri = $releeph_branch->getURI('request/');
- $crumbs->addAction(
- id(new PHUIListItemView())
- ->setHref($create_uri)
- ->setName(pht('Request Pick'))
- ->setIcon('create'));
- }
+ $branch = $this->getBranch();
+ $create_uri = $branch->getURI('request/');
+ $crumbs->addAction(
+ id(new PHUIListItemView())
+ ->setHref($create_uri)
+ ->setName(pht('New Pull Request'))
+ ->setIcon('create')
+ ->setDisabled(!$branch->isActive()));
return $crumbs;
}
private function renderPreface() {
- $branch = $this->getReleephBranch();
$viewer = $this->getRequest()->getUser();
+ $branch = $this->getBranch();
$id = $branch->getID();
$header = id(new PHUIHeaderView())
- ->setHeader($branch->getDisplayName());
-
- if (!$branch->getIsActive()) {
- $header->addTag(
- id(new PHUITagView())
- ->setType(PHUITagView::TYPE_STATE)
- ->setBackgroundColor(PHUITagView::COLOR_BLACK)
- ->setName(pht('Closed')));
+ ->setHeader($branch->getDisplayName())
+ ->setUser($viewer)
+ ->setPolicyObject($branch);
+
+ if ($branch->getIsActive()) {
+ $header->setStatus('oh-ok', '', pht('Active'));
+ } else {
+ $header->setStatus('policy-noone', '', pht('Closed'));
}
$actions = id(new PhabricatorActionListView())
@@ -119,11 +125,9 @@
$branch,
PhabricatorPolicyCapability::CAN_EDIT);
- $edit_uri = $branch->getURI('edit/');
- $close_uri = $branch->getURI('close/');
- $reopen_uri = $branch->getURI('re-open/');
-
- $id = $branch->getID();
+ $edit_uri = $this->getApplicationURI("branch/edit/{$id}/");
+ $close_uri = $this->getApplicationURI("branch/close/{$id}/");
+ $reopen_uri = $this->getApplicationURI("branch/re-open/{$id}/");
$history_uri = $this->getApplicationURI("branch/{$id}/history/");
$actions->addAction(
@@ -149,7 +153,6 @@
->setHref($reopen_uri)
->setIcon('new')
->setUser($viewer)
- ->setRenderAsForm(true)
->setDisabled(!$can_edit)
->setWorkflow(true));
}
diff --git a/src/applications/releeph/controller/project/ReleephProductController.php b/src/applications/releeph/controller/project/ReleephProductController.php
--- a/src/applications/releeph/controller/project/ReleephProductController.php
+++ b/src/applications/releeph/controller/project/ReleephProductController.php
@@ -13,10 +13,6 @@
return $this->product;
}
- protected function getProductViewURI(ReleephProject $product) {
- return $this->getApplicationURI('project/'.$product->getID().'/');
- }
-
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
diff --git a/src/applications/releeph/controller/project/ReleephProductHistoryController.php b/src/applications/releeph/controller/project/ReleephProductHistoryController.php
--- a/src/applications/releeph/controller/project/ReleephProductHistoryController.php
+++ b/src/applications/releeph/controller/project/ReleephProductHistoryController.php
@@ -4,6 +4,10 @@
private $id;
+ public function shouldAllowPublic() {
+ return true;
+ }
+
public function willProcessRequest(array $data) {
$this->id = $data['projectID'];
}
diff --git a/src/applications/releeph/controller/project/ReleephProductViewController.php b/src/applications/releeph/controller/project/ReleephProductViewController.php
--- a/src/applications/releeph/controller/project/ReleephProductViewController.php
+++ b/src/applications/releeph/controller/project/ReleephProductViewController.php
@@ -99,7 +99,7 @@
$item = id(new PHUIObjectItemView())
->setHeader($branch->getDisplayName())
- ->setHref($branch->getURI())
+ ->setHref($this->getApplicationURI('branch/'.$branch->getID().'/'))
->addAttribute($branch_link);
if (!$branch->getIsActive()) {
diff --git a/src/applications/releeph/storage/ReleephBranch.php b/src/applications/releeph/storage/ReleephBranch.php
--- a/src/applications/releeph/storage/ReleephBranch.php
+++ b/src/applications/releeph/storage/ReleephBranch.php
@@ -162,6 +162,10 @@
return $this->assertAttached($this->project);
}
+ public function getProduct() {
+ return $this->getProject();
+ }
+
public function attachCutPointCommit(
PhabricatorRepositoryCommit $commit = null) {
$this->cutPointCommit = $commit;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 17, 11:24 AM (2 w, 2 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7229636
Default Alt Text
D8646.id20792.diff (23 KB)
Attached To
Mode
D8646: Move Releeph branch controllers toward a modern/stable state
Attached
Detach File
Event Timeline
Log In to Comment