Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15343762
D10327.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D10327.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
@@ -1578,6 +1578,7 @@
'PhabricatorFileUploadException' => 'applications/files/exception/PhabricatorFileUploadException.php',
'PhabricatorFilesApplication' => 'applications/files/application/PhabricatorFilesApplication.php',
'PhabricatorFilesConfigOptions' => 'applications/files/config/PhabricatorFilesConfigOptions.php',
+ 'PhabricatorFilesManagementCompactWorkflow' => 'applications/files/management/PhabricatorFilesManagementCompactWorkflow.php',
'PhabricatorFilesManagementEnginesWorkflow' => 'applications/files/management/PhabricatorFilesManagementEnginesWorkflow.php',
'PhabricatorFilesManagementMigrateWorkflow' => 'applications/files/management/PhabricatorFilesManagementMigrateWorkflow.php',
'PhabricatorFilesManagementPurgeWorkflow' => 'applications/files/management/PhabricatorFilesManagementPurgeWorkflow.php',
@@ -4430,6 +4431,7 @@
'PhabricatorFileUploadException' => 'Exception',
'PhabricatorFilesApplication' => 'PhabricatorApplication',
'PhabricatorFilesConfigOptions' => 'PhabricatorApplicationConfigOptions',
+ 'PhabricatorFilesManagementCompactWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementEnginesWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementMigrateWorkflow' => 'PhabricatorFilesManagementWorkflow',
'PhabricatorFilesManagementPurgeWorkflow' => 'PhabricatorFilesManagementWorkflow',
diff --git a/src/applications/files/management/PhabricatorFilesManagementCompactWorkflow.php b/src/applications/files/management/PhabricatorFilesManagementCompactWorkflow.php
new file mode 100644
--- /dev/null
+++ b/src/applications/files/management/PhabricatorFilesManagementCompactWorkflow.php
@@ -0,0 +1,133 @@
+<?php
+
+final class PhabricatorFilesManagementCompactWorkflow
+ extends PhabricatorFilesManagementWorkflow {
+
+ public function didConstruct() {
+ $this
+ ->setName('compact')
+ ->setSynopsis(
+ pht(
+ 'Merge identical files to share the same storage. In some cases, '.
+ 'this can repair files with missing data.'))
+ ->setArguments(
+ array(
+ array(
+ 'name' => 'dry-run',
+ 'help' => pht('Show what would be compacted.'),
+ ),
+ array(
+ 'name' => 'all',
+ 'help' => pht('Compact all files.'),
+ ),
+ array(
+ 'name' => 'names',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $console = PhutilConsole::getConsole();
+
+ $iterator = $this->buildIterator($args);
+ if (!$iterator) {
+ throw new PhutilArgumentUsageException(
+ pht(
+ 'Either specify a list of files to compact, or use `--all` '.
+ 'to compact all files.'));
+ }
+
+ $is_dry_run = $args->getArg('dry-run');
+
+ foreach ($iterator as $file) {
+ $monogram = $file->getMonogram();
+
+ $hash = $file->getContentHash();
+ if (!$hash) {
+ $console->writeOut(
+ "%s\n",
+ pht('%s: No content hash.', $monogram));
+ continue;
+ }
+
+ // Find other files with the same content hash. We're going to point
+ // them at the data for this file.
+ $similar_files = id(new PhabricatorFile())->loadAllWhere(
+ 'contentHash = %s AND id != %d AND
+ (storageEngine != %s OR storageHandle != %s)',
+ $hash,
+ $file->getID(),
+ $file->getStorageEngine(),
+ $file->getStorageHandle());
+ if (!$similar_files) {
+ $console->writeOut(
+ "%s\n",
+ pht('%s: No other files with the same content hash.', $monogram));
+ continue;
+ }
+
+ // Only compact files into this one if we can load the data. This
+ // prevents us from breaking working files if we're missing some data.
+ try {
+ $data = $file->loadFileData();
+ } catch (Exception $ex) {
+ $data = null;
+ }
+
+ if ($data === null) {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ '%s: Unable to load file data; declining to compact.',
+ $monogram));
+ continue;
+ }
+
+ foreach ($similar_files as $similar_file) {
+ if ($is_dry_run) {
+ $console->writeOut(
+ "%s\n",
+ pht(
+ '%s: Would compact storage with %s.',
+ $monogram,
+ $similar_file->getMonogram()));
+ continue;
+ }
+
+ $console->writeOut(
+ "%s\n",
+ pht(
+ '%s: Compacting storage with %s.',
+ $monogram,
+ $similar_file->getMonogram()));
+
+ $old_instance = null;
+ try {
+ $old_instance = $similar_file->instantiateStorageEngine();
+ $old_engine = $similar_file->getStorageEngine();
+ $old_handle = $similar_file->getStorageHandle();
+ } catch (Exception $ex) {
+ // If the old stuff is busted, we just won't try to delete the
+ // old data.
+ phlog($ex);
+ }
+
+ $similar_file
+ ->setStorageEngine($file->getStorageEngine())
+ ->setStorageHandle($file->getStorageHandle())
+ ->save();
+
+ if ($old_instance) {
+ $similar_file->deleteFileDataIfUnused(
+ $old_instance,
+ $old_engine,
+ $old_handle);
+ }
+ }
+ }
+
+ return 0;
+ }
+
+}
diff --git a/src/applications/files/storage/PhabricatorFile.php b/src/applications/files/storage/PhabricatorFile.php
--- a/src/applications/files/storage/PhabricatorFile.php
+++ b/src/applications/files/storage/PhabricatorFile.php
@@ -455,7 +455,7 @@
* Destroy stored file data if there are no remaining files which reference
* it.
*/
- private function deleteFileDataIfUnused(
+ public function deleteFileDataIfUnused(
PhabricatorFileStorageEngine $engine,
$engine_identifier,
$handle) {
@@ -644,7 +644,7 @@
return $supported;
}
- protected function instantiateStorageEngine() {
+ public function instantiateStorageEngine() {
return self::buildEngine($this->getStorageEngine());
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 11, 12:48 AM (1 d, 26 m ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7485602
Default Alt Text
D10327.diff (6 KB)
Attached To
Mode
D10327: Add `bin/files compact` for sharing file data storage
Attached
Detach File
Event Timeline
Log In to Comment