diff --git a/resources/celerity/map.php b/resources/celerity/map.php --- a/resources/celerity/map.php +++ b/resources/celerity/map.php @@ -424,7 +424,7 @@ 'rsrc/js/application/maniphest/behavior-line-chart.js' => 'e4232876', 'rsrc/js/application/maniphest/behavior-list-edit.js' => 'a9f88de2', 'rsrc/js/application/maniphest/behavior-subpriorityeditor.js' => '71237763', - 'rsrc/js/application/owners/OwnersPathEditor.js' => 'aa1733d0', + 'rsrc/js/application/owners/OwnersPathEditor.js' => '996d62b9', 'rsrc/js/application/owners/owners-path-editor.js' => '7a68dda3', 'rsrc/js/application/passphrase/passphrase-credential-control.js' => '3cb0b2fc', 'rsrc/js/application/pholio/behavior-pholio-mock-edit.js' => 'bee502c8', @@ -764,7 +764,7 @@ 'maniphest-task-edit-css' => 'fda62a9b', 'maniphest-task-summary-css' => '11cc5344', 'multirow-row-manager' => 'b5d57730', - 'owners-path-editor' => 'aa1733d0', + 'owners-path-editor' => '996d62b9', 'owners-path-editor-css' => '2f00933b', 'paste-css' => '9fcc9773', 'path-typeahead' => 'f7fc67ec', @@ -1676,6 +1676,14 @@ 'javelin-mask', 'phabricator-drag-and-drop-file-upload', ), + '996d62b9' => array( + 'multirow-row-manager', + 'javelin-install', + 'path-typeahead', + 'javelin-dom', + 'javelin-util', + 'phabricator-prefab', + ), '9a6dd75c' => array( 'javelin-behavior', 'javelin-stratcom', @@ -1766,14 +1774,6 @@ 'javelin-fx', 'javelin-util', ), - 'aa1733d0' => array( - 'multirow-row-manager', - 'javelin-install', - 'path-typeahead', - 'javelin-dom', - 'javelin-util', - 'phabricator-prefab', - ), 'ab2f381b' => array( 'javelin-request', 'javelin-behavior', diff --git a/src/applications/owners/controller/PhabricatorOwnersDetailController.php b/src/applications/owners/controller/PhabricatorOwnersDetailController.php --- a/src/applications/owners/controller/PhabricatorOwnersDetailController.php +++ b/src/applications/owners/controller/PhabricatorOwnersDetailController.php @@ -279,7 +279,7 @@ $href = $repo->generateURI( array( 'branch' => $repo->getDefaultBranch(), - 'path' => $path->getPath(), + 'path' => $path->getPathDisplay(), 'action' => 'browse', )); @@ -288,7 +288,7 @@ array( 'href' => (string)$href, ), - $path->getPath()); + $path->getPathDisplay()); $rows[] = array( ($path->getExcluded() ? '-' : '+'), diff --git a/src/applications/owners/engineextension/PhabricatorOwnersPathsSearchEngineAttachment.php b/src/applications/owners/engineextension/PhabricatorOwnersPathsSearchEngineAttachment.php --- a/src/applications/owners/engineextension/PhabricatorOwnersPathsSearchEngineAttachment.php +++ b/src/applications/owners/engineextension/PhabricatorOwnersPathsSearchEngineAttachment.php @@ -22,7 +22,7 @@ foreach ($paths as $path) { $list[] = array( 'repositoryPHID' => $path->getRepositoryPHID(), - 'path' => $path->getPath(), + 'path' => $path->getPathDisplay(), 'excluded' => (bool)$path->getExcluded(), ); } diff --git a/src/applications/owners/storage/PhabricatorOwnersPath.php b/src/applications/owners/storage/PhabricatorOwnersPath.php --- a/src/applications/owners/storage/PhabricatorOwnersPath.php +++ b/src/applications/owners/storage/PhabricatorOwnersPath.php @@ -49,6 +49,7 @@ return array( 'repositoryPHID' => $this->getRepositoryPHID(), 'path' => $this->getPath(), + 'display' => $this->getPathDisplay(), 'excluded' => (int)$this->getExcluded(), ); } diff --git a/src/applications/owners/xaction/PhabricatorOwnersPackagePathsTransaction.php b/src/applications/owners/xaction/PhabricatorOwnersPackagePathsTransaction.php --- a/src/applications/owners/xaction/PhabricatorOwnersPackagePathsTransaction.php +++ b/src/applications/owners/xaction/PhabricatorOwnersPackagePathsTransaction.php @@ -103,6 +103,26 @@ $paths = $object->getPaths(); + // We store paths in a normalized format with a trailing slash, regardless + // of whether the user enters "path/to/file.c" or "src/backend/". Normalize + // paths now. + + $display_map = array(); + foreach ($new as $key => $spec) { + $display_path = $spec['path']; + $raw_path = rtrim($display_path, '/').'/'; + + // If the user entered two paths which normalize to the same value + // (like "src/main.c" and "src/main.c/"), discard the duplicates. + if (isset($display_map[$raw_path])) { + unset($new[$key]); + continue; + } + + $new[$key]['path'] = $raw_path; + $display_map[$raw_path] = $display_path; + } + $diffs = PhabricatorOwnersPath::getTransactionValueChanges($old, $new); list($rem, $add) = $diffs; @@ -111,12 +131,24 @@ $ref = $path->getRef(); if (PhabricatorOwnersPath::isRefInSet($ref, $set)) { $path->delete(); + continue; + } + + // If the user has changed the display value for a path but the raw + // storage value hasn't changed, update the display value. + + if (isset($display_map[$path->getPath()])) { + $path + ->setPathDisplay($display_map[$path->getPath()]) + ->save(); + continue; } } foreach ($add as $ref) { $path = PhabricatorOwnersPath::newFromRef($ref) ->setPackageID($object->getID()) + ->setPathDisplay($display_map[$ref['path']]) ->save(); } } diff --git a/webroot/rsrc/js/application/owners/OwnersPathEditor.js b/webroot/rsrc/js/application/owners/OwnersPathEditor.js --- a/webroot/rsrc/js/application/owners/OwnersPathEditor.js +++ b/webroot/rsrc/js/application/owners/OwnersPathEditor.js @@ -115,7 +115,7 @@ JX.copy( path_input, { - value : path_ref.path || '', + value : path_ref.display || '', name : 'path[' + this._count + ']' });