Index: branches/REL1_19/phase3/tests/phpunit/includes/filerepo/FileBackendTest.php |
— | — | @@ -1034,6 +1034,16 @@ |
1035 | 1035 | $this->doTestDoOperations(); |
1036 | 1036 | $this->tearDownFiles(); |
1037 | 1037 | |
| 1038 | + $this->backend = $this->singleBackend; |
| 1039 | + $this->tearDownFiles(); |
| 1040 | + $this->doTestDoOperationsFailing(); |
| 1041 | + $this->tearDownFiles(); |
| 1042 | + |
| 1043 | + $this->backend = $this->multiBackend; |
| 1044 | + $this->tearDownFiles(); |
| 1045 | + $this->doTestDoOperationsFailing(); |
| 1046 | + $this->tearDownFiles(); |
| 1047 | + |
1038 | 1048 | // @TODO: test some cases where the ops should fail |
1039 | 1049 | } |
1040 | 1050 | |
— | — | @@ -1057,9 +1067,9 @@ |
1058 | 1068 | |
1059 | 1069 | $status = $this->backend->doOperations( array( |
1060 | 1070 | array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ), |
1061 | | - // Now: A:<A>, B:<B>, C:<A>, D:<D> (file:<orginal contents>) |
| 1071 | + // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>) |
1062 | 1072 | array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ), |
1063 | | - // Now: A:<A>, B:<B>, C:<A>, D:<D> |
| 1073 | + // Now: A:<A>, B:<B>, C:<A>, D:<empty> |
1064 | 1074 | array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD, 'overwrite' => 1 ), |
1065 | 1075 | // Now: A:<A>, B:<B>, C:<empty>, D:<A> |
1066 | 1076 | array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC ), |
— | — | @@ -1109,6 +1119,68 @@ |
1110 | 1120 | "Correct file SHA-1 of $fileC" ); |
1111 | 1121 | } |
1112 | 1122 | |
| 1123 | + function doTestDoOperationsFailing() { |
| 1124 | + $base = $this->baseStorePath(); |
| 1125 | + |
| 1126 | + $fileA = "$base/unittest-cont2/a/b/fileA.txt"; |
| 1127 | + $fileAContents = '3tqtmoeatmn4wg4qe-mg3qt3 tq'; |
| 1128 | + $fileB = "$base/unittest-cont2/a/b/fileB.txt"; |
| 1129 | + $fileBContents = 'g-jmq3gpqgt3qtg q3GT '; |
| 1130 | + $fileC = "$base/unittest-cont2/a/b/fileC.txt"; |
| 1131 | + $fileCContents = 'eigna[ogmewt 3qt g3qg flew[ag'; |
| 1132 | + $fileD = "$base/unittest-cont2/a/b/fileD.txt"; |
| 1133 | + |
| 1134 | + $this->prepare( array( 'dir' => dirname( $fileA ) ) ); |
| 1135 | + $this->backend->create( array( 'dst' => $fileA, 'content' => $fileAContents ) ); |
| 1136 | + $this->prepare( array( 'dir' => dirname( $fileB ) ) ); |
| 1137 | + $this->backend->create( array( 'dst' => $fileB, 'content' => $fileBContents ) ); |
| 1138 | + $this->prepare( array( 'dir' => dirname( $fileC ) ) ); |
| 1139 | + $this->backend->create( array( 'dst' => $fileC, 'content' => $fileCContents ) ); |
| 1140 | + |
| 1141 | + $status = $this->backend->doOperations( array( |
| 1142 | + array( 'op' => 'copy', 'src' => $fileA, 'dst' => $fileC, 'overwrite' => 1 ), |
| 1143 | + // Now: A:<A>, B:<B>, C:<A>, D:<empty> (file:<orginal contents>) |
| 1144 | + array( 'op' => 'copy', 'src' => $fileC, 'dst' => $fileA, 'overwriteSame' => 1 ), |
| 1145 | + // Now: A:<A>, B:<B>, C:<A>, D:<empty> |
| 1146 | + array( 'op' => 'copy', 'src' => $fileB, 'dst' => $fileD, 'overwrite' => 1 ), |
| 1147 | + // Now: A:<A>, B:<B>, C:<A>, D:<B> |
| 1148 | + array( 'op' => 'move', 'src' => $fileC, 'dst' => $fileD ), |
| 1149 | + // Now: A:<A>, B:<B>, C:<A>, D:<empty> (failed) |
| 1150 | + array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileC, 'overwriteSame' => 1 ), |
| 1151 | + // Now: A:<A>, B:<B>, C:<A>, D:<empty> (failed) |
| 1152 | + array( 'op' => 'move', 'src' => $fileB, 'dst' => $fileA, 'overwrite' => 1 ), |
| 1153 | + // Now: A:<B>, B:<empty>, C:<A>, D:<empty> |
| 1154 | + array( 'op' => 'delete', 'src' => $fileD ), |
| 1155 | + // Now: A:<B>, B:<empty>, C:<A>, D:<empty> |
| 1156 | + array( 'op' => 'null' ), |
| 1157 | + // Does nothing |
| 1158 | + ), array( 'force' => 1 ) ); |
| 1159 | + |
| 1160 | + $this->assertNotEquals( array(), $status->errors, "Operation had warnings" ); |
| 1161 | + $this->assertEquals( true, $status->isOK(), "Operation batch succeeded" ); |
| 1162 | + $this->assertEquals( 8, count( $status->success ), |
| 1163 | + "Operation batch has correct success array" ); |
| 1164 | + |
| 1165 | + $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileB ) ), |
| 1166 | + "File does not exist at $fileB" ); |
| 1167 | + $this->assertEquals( false, $this->backend->fileExists( array( 'src' => $fileD ) ), |
| 1168 | + "File does not exist at $fileD" ); |
| 1169 | + |
| 1170 | + $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $fileA ) ), |
| 1171 | + "File does not exist at $fileA" ); |
| 1172 | + $this->assertEquals( true, $this->backend->fileExists( array( 'src' => $fileC ) ), |
| 1173 | + "File exists at $fileC" ); |
| 1174 | + $this->assertEquals( $fileBContents, |
| 1175 | + $this->backend->getFileContents( array( 'src' => $fileA ) ), |
| 1176 | + "Correct file contents of $fileA" ); |
| 1177 | + $this->assertEquals( strlen( $fileBContents ), |
| 1178 | + $this->backend->getFileSize( array( 'src' => $fileA ) ), |
| 1179 | + "Correct file size of $fileA" ); |
| 1180 | + $this->assertEquals( wfBaseConvert( sha1( $fileBContents ), 16, 36, 31 ), |
| 1181 | + $this->backend->getFileSha1Base36( array( 'src' => $fileA ) ), |
| 1182 | + "Correct file SHA-1 of $fileA" ); |
| 1183 | + } |
| 1184 | + |
1113 | 1185 | public function testGetFileList() { |
1114 | 1186 | $this->backend = $this->singleBackend; |
1115 | 1187 | $this->tearDownFiles(); |
Index: branches/REL1_19/phase3/tests/parser/parserTests.txt |
— | — | @@ -8483,6 +8483,16 @@ |
8484 | 8484 | !!end |
8485 | 8485 | |
8486 | 8486 | !! test |
| 8487 | +Edit comment with section link and text before it (non-local, eg in history list) |
| 8488 | +!! options |
| 8489 | +comment title=[[Main Page]] |
| 8490 | +!! input |
| 8491 | +pre-comment text /* External links */ removed bogus entries |
| 8492 | +!! result |
| 8493 | +pre-comment text - <a href="https://www.mediawiki.org/wiki/Main_Page#External_links" title="Main Page">→</a><span dir="auto"><span class="autocomment">External links: </span> removed bogus entries</span> |
| 8494 | +!!end |
| 8495 | + |
| 8496 | +!! test |
8487 | 8497 | Edit comment with section link (local, eg in diff view) |
8488 | 8498 | !! options |
8489 | 8499 | comment local title=[[Main Page]] |
Index: branches/REL1_19/phase3/includes/Linker.php |
— | — | @@ -1182,7 +1182,7 @@ |
1183 | 1183 | } |
1184 | 1184 | if ( $pre ) { |
1185 | 1185 | # written summary $presep autocomment (summary /* section */) |
1186 | | - $auto = wfMsgExt( 'autocomment-prefix', array( 'escapenoentities', 'content' ) ) . $auto; |
| 1186 | + $pre .= wfMsgExt( 'autocomment-prefix', array( 'escapenoentities', 'content' ) ); |
1187 | 1187 | } |
1188 | 1188 | if ( $post ) { |
1189 | 1189 | # autocomment $postsep written summary (/* section */ summary) |
Index: branches/REL1_19/phase3/includes/db/Database.php |
— | — | @@ -677,7 +677,7 @@ |
678 | 678 | $dbType = strtolower( $dbType ); |
679 | 679 | $class = 'Database' . ucfirst( $dbType ); |
680 | 680 | |
681 | | - if( in_array( $dbType, $canonicalDBTypes ) ) { |
| 681 | + if( in_array( $dbType, $canonicalDBTypes ) || ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) ) { |
682 | 682 | return new $class( |
683 | 683 | isset( $p['host'] ) ? $p['host'] : false, |
684 | 684 | isset( $p['user'] ) ? $p['user'] : false, |
— | — | @@ -686,8 +686,6 @@ |
687 | 687 | isset( $p['flags'] ) ? $p['flags'] : 0, |
688 | 688 | isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global' |
689 | 689 | ); |
690 | | - } elseif ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) { |
691 | | - return new $class( $p ); |
692 | 690 | } else { |
693 | 691 | return null; |
694 | 692 | } |
Property changes on: branches/REL1_19/phase3/includes/db/Database.php |
___________________________________________________________________ |
Modified: svn:mergeinfo |
695 | 693 | Merged /trunk/phase3/includes/db/Database.php:r113601,113617,113782 |
Index: branches/REL1_19/phase3/includes/filerepo/file/LocalFile.php |
— | — | @@ -763,7 +763,7 @@ |
764 | 764 | } |
765 | 765 | |
766 | 766 | # Delete the thumbnails |
767 | | - $this->repo->cleanupBatch( $purgeList ); |
| 767 | + $this->repo->cleanupBatch( $purgeList, FileRepo::SKIP_LOCKING ); |
768 | 768 | # Clear out the thumbnail directory if empty |
769 | 769 | $this->repo->getBackend()->clean( array( 'dir' => $dir ) ); |
770 | 770 | } |
Index: branches/REL1_19/phase3/includes/filerepo/file/ForeignAPIFile.php |
— | — | @@ -245,7 +245,7 @@ |
246 | 246 | } |
247 | 247 | |
248 | 248 | # Delete the thumbnails |
249 | | - $this->repo->cleanupBatch( $purgeList ); |
| 249 | + $this->repo->cleanupBatch( $purgeList, FileRepo::SKIP_LOCKING ); |
250 | 250 | # Clear out the thumbnail directory if empty |
251 | 251 | $this->repo->getBackend()->clean( array( 'dir' => $dir ) ); |
252 | 252 | } |
Index: branches/REL1_19/phase3/includes/filerepo/backend/FileOp.php |
— | — | @@ -81,6 +81,10 @@ |
82 | 82 | * 'allowStale' : Don't require the latest available data. |
83 | 83 | * This can increase performance for non-critical writes. |
84 | 84 | * This has no effect unless the 'force' flag is set. |
| 85 | + * |
| 86 | + * The resulting Status will be "OK" unless: |
| 87 | + * a) unexpected operation errors occurred (network partitions, disk full...) |
| 88 | + * b) significant operation errors occured and 'force' was not set |
85 | 89 | * |
86 | 90 | * @param $performOps Array List of FileOp operations |
87 | 91 | * @param $opts Array Batch operation options |
— | — | @@ -115,6 +119,11 @@ |
116 | 120 | } |
117 | 121 | } |
118 | 122 | |
| 123 | + if ( $ignoreErrors ) { |
| 124 | + # Treat all precheck() fatals as merely warnings |
| 125 | + $status->setResult( true, $status->value ); |
| 126 | + } |
| 127 | + |
119 | 128 | // Restart PHP's execution timer and set the timeout to safe amount. |
120 | 129 | // This handles cases where the operations take a long time or where we are |
121 | 130 | // already running low on time left. The old timeout is restored afterwards. |
Index: branches/REL1_19/phase3/includes/filerepo/backend/FileBackend.php |
— | — | @@ -184,8 +184,9 @@ |
185 | 185 | * Return value: |
186 | 186 | * This returns a Status, which contains all warnings and fatals that occured |
187 | 187 | * during the operation. The 'failCount', 'successCount', and 'success' members |
188 | | - * will reflect each operation attempted. The status will be "OK" unless any |
189 | | - * of the operations failed and the 'force' parameter was not set. |
| 188 | + * will reflect each operation attempted. The status will be "OK" unless: |
| 189 | + * a) unexpected operation errors occurred (network partitions, disk full...) |
| 190 | + * b) significant operation errors occured and 'force' was not set |
190 | 191 | * |
191 | 192 | * @param $ops Array List of operations to execute in order |
192 | 193 | * @param $opts Array Batch operation options |
Index: branches/REL1_19/phase3/includes/filerepo/FileRepo.php |
— | — | @@ -733,9 +733,11 @@ |
734 | 734 | * It will try to delete each file, but ignores any errors that may occur. |
735 | 735 | * |
736 | 736 | * @param $pairs array List of files to delete |
| 737 | + * @param $flags Integer: bitwise combination of the following flags: |
| 738 | + * self::SKIP_LOCKING Skip any file locking when doing the deletions |
737 | 739 | * @return void |
738 | 740 | */ |
739 | | - public function cleanupBatch( $files ) { |
| 741 | + public function cleanupBatch( $files, $flags = 0 ) { |
740 | 742 | $operations = array(); |
741 | 743 | $sourceFSFilesToDelete = array(); // cleanup for disk source files |
742 | 744 | foreach ( $files as $file ) { |
— | — | @@ -765,6 +767,9 @@ |
766 | 768 | } |
767 | 769 | // Actually delete files from storage... |
768 | 770 | $opts = array( 'force' => true ); |
| 771 | + if ( $flags & self::SKIP_LOCKING ) { |
| 772 | + $opts['nonLocking'] = true; |
| 773 | + } |
769 | 774 | $this->backend->doOperations( $operations, $opts ); |
770 | 775 | // Cleanup for disk source files... |
771 | 776 | foreach ( $sourceFSFilesToDelete as $file ) { |
Property changes on: branches/REL1_19/phase3/includes |
___________________________________________________________________ |
Modified: svn:mergeinfo |
772 | 777 | Merged /trunk/phase3/includes:r113412,113441,113601,113617,113782 |
Index: branches/REL1_19/phase3/resources/mediawiki/mediawiki.js |
— | — | @@ -586,11 +586,12 @@ |
587 | 587 | filter( 'ready', jobs[j].dependencies ), |
588 | 588 | jobs[j].dependencies ) ) |
589 | 589 | { |
590 | | - if ( $.isFunction( jobs[j].ready ) ) { |
591 | | - jobs[j].ready(); |
592 | | - } |
| 590 | + var callback = jobs[j].ready; |
593 | 591 | jobs.splice( j, 1 ); |
594 | 592 | j -= 1; |
| 593 | + if ( $.isFunction( callback ) ) { |
| 594 | + callback(); |
| 595 | + } |
595 | 596 | } |
596 | 597 | } |
597 | 598 | // Execute modules whose dependencies have just been met |
Property changes on: branches/REL1_19/phase3 |
___________________________________________________________________ |
Modified: svn:mergeinfo |
598 | 599 | Merged /trunk/phase3:r113412,113441,113601,113617,113782 |