Page MenuHomePhabricator

D19379.diff
No OneTemporary

D19379.diff

diff --git a/resources/sql/autopatches/20180418.almanac.network.unique.php b/resources/sql/autopatches/20180418.almanac.network.unique.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180418.almanac.network.unique.php
@@ -0,0 +1,46 @@
+<?php
+
+$table = new AlmanacNetwork();
+$conn = $table->establishConnection('w');
+
+queryfx(
+ $conn,
+ 'LOCK TABLES %T WRITE',
+ $table->getTableName());
+
+$seen = array();
+foreach (new LiskMigrationIterator($table) as $network) {
+ $name = $network->getName();
+
+ // If this is the first copy of this row we've seen, mark it as seen and
+ // move on.
+ if (empty($seen[$name])) {
+ $seen[$name] = 1;
+ continue;
+ }
+
+ // Otherwise, rename this row.
+ while (true) {
+ $new_name = $name.'-'.$seen[$name];
+ if (empty($seen[$new_name])) {
+ $network->setName($new_name);
+ try {
+ $network->save();
+ break;
+ } catch (AphrontDuplicateKeyQueryException $ex) {
+ // New name is a dupe of a network we haven't seen yet.
+ }
+ }
+ $seen[$name]++;
+ }
+ $seen[$new_name] = 1;
+}
+
+queryfx(
+ $conn,
+ 'ALTER TABLE %T ADD UNIQUE KEY `key_name` (name)',
+ $table->getTableName());
+
+queryfx(
+ $conn,
+ 'UNLOCK TABLES');
diff --git a/src/applications/almanac/query/AlmanacNetworkQuery.php b/src/applications/almanac/query/AlmanacNetworkQuery.php
--- a/src/applications/almanac/query/AlmanacNetworkQuery.php
+++ b/src/applications/almanac/query/AlmanacNetworkQuery.php
@@ -5,6 +5,7 @@
private $ids;
private $phids;
+ private $names;
public function withIDs(array $ids) {
$this->ids = $ids;
@@ -20,6 +21,11 @@
return new AlmanacNetwork();
}
+ public function withNames(array $names) {
+ $this->names = $names;
+ return $this;
+ }
+
public function withNameNgrams($ngrams) {
return $this->withNgramsConstraint(
new AlmanacNetworkNameNgrams(),
@@ -47,6 +53,13 @@
$this->phids);
}
+ if ($this->names !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'network.name IN (%Ls)',
+ $this->names);
+ }
+
return $where;
}
diff --git a/src/applications/almanac/storage/AlmanacNetwork.php b/src/applications/almanac/storage/AlmanacNetwork.php
--- a/src/applications/almanac/storage/AlmanacNetwork.php
+++ b/src/applications/almanac/storage/AlmanacNetwork.php
@@ -24,8 +24,15 @@
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
- 'name' => 'text128',
+ 'name' => 'sort128',
'mailKey' => 'bytes20',
+
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_name' => array(
+ 'columns' => array('name'),
+ 'unique' => true,
+ ),
),
) + parent::getConfiguration();
}
diff --git a/src/applications/almanac/util/AlmanacNames.php b/src/applications/almanac/util/AlmanacNames.php
--- a/src/applications/almanac/util/AlmanacNames.php
+++ b/src/applications/almanac/util/AlmanacNames.php
@@ -6,57 +6,58 @@
if (strlen($name) < 3) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names must be '.
- 'at least 3 characters long.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'must be at least 3 characters long.'));
}
if (strlen($name) > 100) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names may not '.
- 'be more than 100 characters long.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'may not be more than 100 characters long.'));
}
if (!preg_match('/^[a-z0-9.-]+\z/', $name)) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names may only '.
- 'contain lowercase letters, numbers, hyphens, and periods.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'may only contain lowercase letters, numbers, hyphens, and '.
+ 'periods.'));
}
if (preg_match('/(^|\\.)\d+(\z|\\.)/', $name)) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names may not '.
- 'have any segments containing only digits.'));
+ 'Almanac service, device, network, property and namespace names '.
+ 'may not have any segments containing only digits.'));
}
if (preg_match('/\.\./', $name)) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names may not '.
- 'contain multiple consecutive periods.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'may not contain multiple consecutive periods.'));
}
if (preg_match('/\\.-|-\\./', $name)) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names may not '.
- 'contain hyphens adjacent to periods.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'may not contain hyphens adjacent to periods.'));
}
if (preg_match('/--/', $name)) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names may not '.
- 'contain multiple consecutive hyphens.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'may not contain multiple consecutive hyphens.'));
}
if (!preg_match('/^[a-z0-9].*[a-z0-9]\z/', $name)) {
throw new Exception(
pht(
- 'Almanac service, device, property and namespace names must begin '.
- 'and end with a letter or number.'));
+ 'Almanac service, device, property, network and namespace names '.
+ 'must begin and end with a letter or number.'));
}
}
diff --git a/src/applications/almanac/xaction/AlmanacNetworkNameTransaction.php b/src/applications/almanac/xaction/AlmanacNetworkNameTransaction.php
--- a/src/applications/almanac/xaction/AlmanacNetworkNameTransaction.php
+++ b/src/applications/almanac/xaction/AlmanacNetworkNameTransaction.php
@@ -38,6 +38,37 @@
pht('Network name is required.'));
}
+ foreach ($xactions as $xaction) {
+ $name = $xaction->getNewValue();
+
+ $message = null;
+ try {
+ AlmanacNames::validateName($name);
+ } catch (Exception $ex) {
+ $message = $ex->getMessage();
+ }
+
+ if ($message !== null) {
+ $errors[] = $this->newInvalidError($message, $xaction);
+ continue;
+ }
+
+ if ($name === $object->getName()) {
+ continue;
+ }
+
+ $other = id(new AlmanacNetworkQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withNames(array($name))
+ ->executeOne();
+ if ($other && ($other->getID() != $object->getID())) {
+ $errors[] = $this->newInvalidError(
+ pht('Almanac networks must have unique names.'),
+ $xaction);
+ continue;
+ }
+ }
+
return $errors;
}

File Metadata

Mime Type
text/plain
Expires
Sun, Nov 3, 8:36 AM (2 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6753329
Default Alt Text
D19379.diff (7 KB)

Event Timeline