Page MenuHomePhabricator

D8671.id.diff
No OneTemporary

D8671.id.diff

diff --git a/src/applications/phragment/storage/PhragmentFragment.php b/src/applications/phragment/storage/PhragmentFragment.php
--- a/src/applications/phragment/storage/PhragmentFragment.php
+++ b/src/applications/phragment/storage/PhragmentFragment.php
@@ -71,6 +71,39 @@
$view_policy,
$edit_policy) {
+ // Calculate all preceding paths.
+ $path_components = explode('/', $path);
+ array_pop($path_components);
+ $path_preceding = array();
+ $path_buffer = '';
+ for ($i = 0; $i < count($path_components); $i++) {
+ $path_buffer .= $path_components[$i].'/';
+ $path_preceding[] = rtrim($path_buffer, '/');
+ }
+
+ // Query for preceding fragments (use omnipotent user so
+ // we don't double up on paths because the user can't see
+ // them).
+ $preceding_fragments = id(new PhragmentFragmentQuery())
+ ->setViewer(PhabricatorUser::getOmnipotentUser())
+ ->withPaths($path_preceding)
+ ->execute();
+ $preceding_fragments = mpull($preceding_fragments, null, 'getPath');
+
+ // Create preceding path fragments.
+ foreach ($path_preceding as $path_to_check) {
+ if (!array_key_exists($path_to_check, $preceding_fragments)) {
+ $fragment = id(new PhragmentFragment());
+ $fragment->setPath($path_to_check);
+ $fragment->setDepth(count(explode('/', $path_to_check)));
+ $fragment->setLatestVersionPHID(null);
+ $fragment->setViewPolicy($view_policy);
+ $fragment->setEditPolicy($edit_policy);
+ $fragment->save();
+ }
+ }
+
+ // Create the new fragment.
$fragment = id(new PhragmentFragment());
$fragment->setPath($path);
$fragment->setDepth(count(explode('/', $path)));
@@ -168,32 +201,26 @@
$mappings[$path] = $data;
}
- // We need to detect any directories that are in the ZIP folder that
- // aren't explicitly noted in the ZIP. This can happen if the file
- // entries in the ZIP look like:
+
+ // Sort the mappings by key in the dictionary, so that iterating over it
+ // will result in entries like:
//
- // * something/blah.png
- // * something/other.png
- // * test.png
+ // a/ => null
+ // a/e.txt => ...
+ // b/c.txt => ...
+ // b/d.txt => ...
//
- // Where there is no explicit "something/" entry.
- foreach ($mappings as $path_key => $data) {
- if ($data === null) {
- continue;
- }
- $directory = dirname($path_key);
- while ($directory !== '.') {
- if (!array_key_exists($directory, $mappings)) {
- $mappings[$directory] = null;
- }
- if (dirname($directory) === $directory) {
- // dirname() will not reduce this directory any further; to
- // prevent infinite loop we just break out here.
- break;
- }
- $directory = dirname($directory);
- }
- }
+ // This is important because if there are explicit directory entries in the
+ // ZIP, that might be because they are empty directories (in which case
+ // there's no call to self::createFromFile that would create them) or they
+ // could be out-of-order explicit directories where an unsorted list
+ // would cause a duplicate key exception. By sorting this, we ensure that
+ // explicit directories are always created before files that reside in them.
+ ksort($mappings);
+
+ // We no longer need to explicitly create directories that are not
+ // set in the ZIP. The self::createFromFile function automatically
+ // creates preceding directories for file entries.
// Adjust the paths relative to this fragment so we can look existing
// fragments up in the DB.
@@ -204,8 +231,8 @@
}
// FIXME: What happens when a child exists, but the current user
- // can't see it. We're going to create a new child with the exact
- // same path and then bad things will happen.
+ // can't see it. We're going to place a new child under a path
+ // that the current user can't access.
$children = id(new PhragmentFragmentQuery())
->setViewer($viewer)
->needLatestVersion(true)

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 28, 6:09 PM (2 w, 13 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7402107
Default Alt Text
D8671.id.diff (4 KB)

Event Timeline