Page MenuHomePhabricator

D10327.diff
No OneTemporary

D10327.diff

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

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)

Event Timeline