From 9b02dc95fac4690f4edb742b649d0a26fa0728e6 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Wed, 14 Mar 2012 21:30:26 +0000 Subject: [PATCH] [FileRepo] * Added getReadOnlyReason() function to FileRepo to check read-only status. Added such checks to the File object functions that mutate files in storage. This should make read-only mode more tolerable (which is needed at least briefly when switching backends). * Added lock()/unlock() calls to File restore() function. * Use proper isOK() accessor for Status objects. --- includes/filerepo/FileRepo.php | 9 +++++ includes/filerepo/file/LocalFile.php | 56 ++++++++++++++++++++++------ languages/messages/MessagesEn.php | 3 ++ maintenance/language/messages.inc | 1 + 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index 0dd5466bc8..1475043116 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -119,6 +119,15 @@ class FileRepo { return $this->backend; } + /** + * Get an explanatory message if this repo is read-only + * + * @return string|bool Returns false if the repo is not read-only + */ + public function getReadOnlyReason() { + return $this->backend->getReadOnlyReason(); + } + /** * Prepare a single zone or list of zones for usage. * See initDeletedDir() for additional setup needed for the 'deleted' zone. diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index ea8d7a324d..27c412f545 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -908,9 +908,13 @@ class LocalFile extends File { */ function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null ) { global $wgContLang; + + if ( $this->getRepo()->getReadOnlyReason() !== false ) { + return $this->readOnlyFatalStatus(); + } + // truncate nicely or the DB will do it for us - // non-nicely (dangling multi-byte chars, non-truncated - // version in cache). + // non-nicely (dangling multi-byte chars, non-truncated version in cache). $comment = $wgContLang->truncate( $comment, 255 ); $this->lock(); // begin $status = $this->publish( $srcPath, $flags ); @@ -1175,6 +1179,10 @@ class LocalFile extends File { * archive name, or an empty string if it was a new file. */ function publishTo( $srcPath, $dstRel, $flags = 0 ) { + if ( $this->getRepo()->getReadOnlyReason() !== false ) { + return $this->readOnlyFatalStatus(); + } + $this->lock(); // begin $archiveName = wfTimestamp( TS_MW ) . '!'. $this->getName(); @@ -1211,6 +1219,10 @@ class LocalFile extends File { * @return FileRepoStatus object. */ function move( $target ) { + if ( $this->getRepo()->getReadOnlyReason() !== false ) { + return $this->readOnlyFatalStatus(); + } + wfDebugLog( 'imagemove', "Got request to move {$this->name} to " . $target->getText() ); $this->lock(); // begin @@ -1250,6 +1262,10 @@ class LocalFile extends File { * @return FileRepoStatus object. */ function delete( $reason, $suppress = false ) { + if ( $this->getRepo()->getReadOnlyReason() !== false ) { + return $this->readOnlyFatalStatus(); + } + $this->lock(); // begin $batch = new LocalFileDeleteBatch( $this, $reason, $suppress ); @@ -1266,7 +1282,7 @@ class LocalFile extends File { } $status = $batch->execute(); - if ( $status->ok ) { + if ( $status->isOK() ) { // Update site_stats $site_stats = $dbw->tableName( 'site_stats' ); $dbw->query( "UPDATE $site_stats SET ss_images=ss_images-1", __METHOD__ ); @@ -1293,6 +1309,10 @@ class LocalFile extends File { * @return FileRepoStatus object. */ function deleteOld( $archiveName, $reason, $suppress = false ) { + if ( $this->getRepo()->getReadOnlyReason() !== false ) { + return $this->readOnlyFatalStatus(); + } + $this->lock(); // begin $batch = new LocalFileDeleteBatch( $this, $reason, $suppress ); @@ -1302,7 +1322,7 @@ class LocalFile extends File { $this->unlock(); // done - if ( $status->ok ) { + if ( $status->isOK() ) { $this->purgeDescription(); $this->purgeHistory(); } @@ -1322,6 +1342,12 @@ class LocalFile extends File { * @return FileRepoStatus */ function restore( $versions = array(), $unsuppress = false ) { + if ( $this->getRepo()->getReadOnlyReason() !== false ) { + return $this->readOnlyFatalStatus(); + } + + $this->lock(); // begin + $batch = new LocalFileRestoreBatch( $this, $unsuppress ); if ( !$versions ) { @@ -1332,14 +1358,14 @@ class LocalFile extends File { $status = $batch->execute(); - if ( !$status->isGood() ) { - return $status; + if ( $status->isGood() ) { + $cleanupStatus = $batch->cleanup(); + $cleanupStatus->successCount = 0; + $cleanupStatus->failCount = 0; + $status->merge( $cleanupStatus ); } - $cleanupStatus = $batch->cleanup(); - $cleanupStatus->successCount = 0; - $cleanupStatus->failCount = 0; - $status->merge( $cleanupStatus ); + $this->unlock(); // done return $status; } @@ -1443,6 +1469,14 @@ class LocalFile extends File { $dbw = $this->repo->getMasterDB(); $dbw->rollback( __METHOD__ ); } + + /** + * @return Status + */ + protected function readOnlyFatalStatus() { + return $this->getRepo()->newFatal( 'filereadonlyerror', $this->getName(), + $this->getRepo()->getName(), $this->getRepo()->getReadOnlyReason() ); + } } // LocalFile class # ------------------------------------------------------------------------------ @@ -1710,7 +1744,7 @@ class LocalFileDeleteBatch { $this->status->merge( $status ); } - if ( !$this->status->ok ) { + if ( !$this->status->isOK() ) { // Critical file deletion error // Roll back inserts, release lock and abort // TODO: delete the defunct filearchive rows if we are using a non-transactional DB diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index fc876e2d3d..9af73a7221 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -997,6 +997,9 @@ Please report this to an [[Special:ListUsers/sysop|administrator]], making note 'directorycreateerror' => 'Could not create directory "$1".', 'filenotfound' => 'Could not find file "$1".', 'fileexistserror' => 'Unable to write to file "$1": File exists.', +'filereadonlyerror' => 'Unable to the modify the file "$1" because the file repository "$2" is in read-only mode. + +The administrator who locked it offered this explanation: "$3".', 'unexpected' => 'Unexpected value: "$1"="$2".', 'formerror' => 'Error: Could not submit form.', 'badarticleerror' => 'This action cannot be performed on this page.', diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index 6e6e8d0bc5..093305eb2d 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -408,6 +408,7 @@ $wgMessageStructure = array( 'customjsprotected', 'ns-specialprotected', 'titleprotected', + 'filereadonlyerror' ), 'virus' => array( 'virus-badscanner', -- 2.20.1