r49001 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r49000‎ | r49001 | r49002 >
Date:13:42, 29 March 2009
Author:vasilievvv
Status:ok (Comments)
Tags:
Comment:
Improve image moving error handling:
* Do image moving before page moving. That will allow to avoid situations when image page is moved, while image itself isn't.
* Add safeguard code that checks all files before moving them
* More debug logging
Modified paths:
  • /trunk/phase3/RELEASE-NOTES (modified) (history)
  • /trunk/phase3/includes/Status.php (modified) (history)
  • /trunk/phase3/includes/Title.php (modified) (history)
  • /trunk/phase3/includes/filerepo/FSRepo.php (modified) (history)
  • /trunk/phase3/includes/filerepo/FileRepo.php (modified) (history)
  • /trunk/phase3/includes/filerepo/LocalFile.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/Status.php
@@ -175,7 +175,10 @@
176176 $result = array();
177177 foreach ( $this->errors as $error ) {
178178 if ( $error['type'] == 'error' )
179 - $result[] = $error['message'];
 179+ if( $error['params'] )
 180+ $result[] = array_merge( array( $error['message'] ), $error['params'] );
 181+ else
 182+ $result[] = $error['message'];
180183 }
181184 return $result;
182185 }
Index: trunk/phase3/includes/filerepo/LocalFile.php
@@ -1789,6 +1789,11 @@
17901790 $status = $repo->newGood();
17911791 $triplets = $this->getMoveTriplets();
17921792
 1793+ $statusPreCheck = $this->checkFileExistance( 0 );
 1794+ if( !$statusPreCheck->isOk() ) {
 1795+ wfDebugLog( 'imagemove', "Move of {$this->file->name} aborted due to pre-move file existance check failure" );
 1796+ return $statusPreCheck;
 1797+ }
17931798 $statusDb = $this->doDBUpdates();
17941799 wfDebugLog( 'imagemove', "Renamed {$this->file->name} in database: {$statusDb->successCount} successes, {$statusDb->failCount} failures" );
17951800 $statusMove = $repo->storeBatch( $triplets, FSRepo::DELETE_SOURCE );
@@ -1796,7 +1801,14 @@
17971802 if( !$statusMove->isOk() ) {
17981803 wfDebugLog( 'imagemove', "Error in moving files: " . $statusMove->getWikiText() );
17991804 $this->db->rollback();
 1805+ } else {
 1806+ $statusPostCheck = $this->checkFileExistance( 1 );
 1807+ if( !$statusPostCheck->isOk() ) {
 1808+ // This clearly mustn't have happend. FSRepo::storeBatch should have given out an error in that case.
 1809+ wfDebugLog( 'imagemove', "ATTENTION! Move of {$this->file->name} has some files missing, while storeBatch() reported success" );
 1810+ }
18001811 }
 1812+
18011813 $status->merge( $statusDb );
18021814 $status->merge( $statusMove );
18031815 return $status;
@@ -1856,4 +1868,23 @@
18571869 }
18581870 return $triplets;
18591871 }
 1872+
 1873+ /*
 1874+ * Checks file existance.
 1875+ * Set $key = 0 for source files check
 1876+ * and $key = 1 for destination files check.
 1877+ */
 1878+ function checkFileExistance( $key = 0 ) {
 1879+ $files = array();
 1880+ foreach( array_merge( array( $this->cur ), $this->olds ) as $file )
 1881+ $files[$file[$key]] = $this->file->repo->getVirtualUrl() . '/public/' . rawurlencode( $file[$key] );
 1882+ $result = $this->file->repo->fileExistsBatch( $files, FSRepo::FILES_ONLY );
 1883+ $status = $this->file->repo->newGood();
 1884+ foreach( $result as $filename => $exists )
 1885+ if( !$exists ) {
 1886+ wfDebugLog( 'imagemove', "File {$filename} does not exist" );
 1887+ $status->fatal( 'filenotfound', $filename );
 1888+ }
 1889+ return $status;
 1890+ }
18601891 }
Index: trunk/phase3/includes/filerepo/FSRepo.php
@@ -213,6 +213,33 @@
214214 }
215215
216216 /**
 217+ * Checks existance of specified array of files.
 218+ *
 219+ * @param array $files URLs of files to check
 220+ * @param integer $flags Bitwise combination of the following flags:
 221+ * self::FILES_ONLY Mark file as existing only if it is a file (not directory)
 222+ * @return Either array of files and existance flags, or false
 223+ */
 224+ function fileExistsBatch( $files, $flags = 0 ) {
 225+ if ( !file_exists( $this->directory ) || !is_readable( $this->directory ) ) {
 226+ return false;
 227+ }
 228+ $result = array();
 229+ foreach ( $files as $key => $file ) {
 230+ if ( self::isVirtualUrl( $file ) ) {
 231+ $file = $this->resolveVirtualUrl( $file );
 232+ }
 233+ if( $flags & self::FILES_ONLY ) {
 234+ $result[$key] = is_file( $file );
 235+ } else {
 236+ $result[$key] = file_exists( $file );
 237+ }
 238+ }
 239+
 240+ return $result;
 241+ }
 242+
 243+ /**
217244 * Take all available measures to prevent web accessibility of new deleted
218245 * directories, in case the user has not configured offline storage
219246 */
Index: trunk/phase3/includes/filerepo/FileRepo.php
@@ -6,6 +6,7 @@
77 * @ingroup FileRepo
88 */
99 abstract class FileRepo {
 10+ const FILES_ONLY = 1;
1011 const DELETE_SOURCE = 1;
1112 const FIND_PRIVATE = 1;
1213 const FIND_IGNORE_REDIRECT = 2;
Index: trunk/phase3/includes/Title.php
@@ -2664,6 +2664,18 @@
26652665 return $err;
26662666 }
26672667
 2668+ // If it is a file, more it first. It is done before all other moving stuff is done because it's hard to revert
 2669+ $dbw = wfGetDB( DB_MASTER );
 2670+ if( $this->getNamespace() == NS_FILE ) {
 2671+ $file = wfLocalFile( $this );
 2672+ if( $file->exists() ) {
 2673+ $status = $file->move( $nt );
 2674+ if( !$status->isOk() ) {
 2675+ return $status->getErrorsArray();
 2676+ }
 2677+ }
 2678+ }
 2679+
26682680 $pageid = $this->getArticleID();
26692681 $protected = $this->isProtected();
26702682 if( $nt->exists() ) {
@@ -2690,7 +2702,6 @@
26912703 // we can't actually distinguish it from a default here, and it'll
26922704 // be set to the new title even though it really shouldn't.
26932705 // It'll get corrected on the next edit, but resetting cl_timestamp.
2694 - $dbw = wfGetDB( DB_MASTER );
26952706 $dbw->update( 'categorylinks',
26962707 array(
26972708 'cl_sortkey' => $nt->getPrefixedText(),
@@ -2873,18 +2884,6 @@
28742885 $redirectSuppressed = true;
28752886 }
28762887
2877 - # Move an image if this is a file
2878 - if( $this->getNamespace() == NS_FILE ) {
2879 - $file = wfLocalFile( $this );
2880 - if( $file->exists() ) {
2881 - $status = $file->move( $nt );
2882 - if( !$status->isOk() ) {
2883 - $dbw->rollback();
2884 - return $status->getErrorsArray();
2885 - }
2886 - }
2887 - }
2888 -
28892888 # Log the move
28902889 $log = new LogPage( 'move' );
28912890 $log->addEntry( 'move_redir', $this, $reason, array( 1 => $nt->getPrefixedText(), 2 => $redirectSuppressed ) );
@@ -2970,18 +2969,6 @@
29712970 $redirectSuppressed = true;
29722971 }
29732972
2974 - # Move an image if this is a file
2975 - if( $this->getNamespace() == NS_FILE ) {
2976 - $file = wfLocalFile( $this );
2977 - if( $file->exists() ) {
2978 - $status = $file->move( $nt );
2979 - if( !$status->isOk() ) {
2980 - $dbw->rollback();
2981 - return $status->getErrorsArray();
2982 - }
2983 - }
2984 - }
2985 -
29862973 # Log the move
29872974 $log = new LogPage( 'move' );
29882975 $log->addEntry( 'move', $this, $reason, array( 1 => $nt->getPrefixedText(), 2 => $redirectSuppressed ) );
Index: trunk/phase3/RELEASE-NOTES
@@ -308,6 +308,7 @@
309309 * (bug 18190) Proper parsing in MediaWiki:Sharedupload message
310310 * (bug 17617) HTML cleanup for ImagePage
311311 * (bug 17964) namespaceDupes.php no longer fails on an empty interwiki table
 312+* Improved error handling for image moving
312313
313314 == API changes in 1.15 ==
314315 * (bug 16858) Revamped list=deletedrevs to make listing deleted contributions

Follow-up revisions

RevisionCommit summaryAuthorDate
r51592Add fileExistsBatch method to FileRepo and derived classes (per comments on r...vasilievvv15:10, 8 June 2009

Comments

#Comment by Tim Starling (talk | contribs)   15:02, 3 June 2009
  • It's existence, not existance
  • Don't put functions in FSRepo without also putting them in the parent class, FileRepo.
  • Don't bother putting ATTENTION in a log that nobody is ever going to read. Report it to the user, in plain English. Add messages.
#Comment by VasilievVV (talk | contribs)   15:22, 8 June 2009
  • Typo fixed in r49021
  • fileExistsBatch method was added to FileRepo in r51592
  • "ATTENTION" entry was removed in r49896, since it's sort of 2 + 2 = 5 check

Status & tagging log