jenkins-bot has submitted this change and it was merged.
Change subject: Update sync-group.php to use Maintenance class
......................................................................
Update sync-group.php to use Maintenance class
Change-Id: I8d7647d5bbb179c8d469437a450a166890b676bf
---
M scripts/sync-group.php
1 file changed, 220 insertions(+), 146 deletions(-)
Approvals:
Nikerabbit: Looks good to me, approved
jenkins-bot: Verified
diff --git a/scripts/sync-group.php b/scripts/sync-group.php
index a3473fd..9325a6b 100644
--- a/scripts/sync-group.php
+++ b/scripts/sync-group.php
@@ -11,161 +11,235 @@
* @file
*/
-/// @cond
-
-$options = array( 'git' );
-$optionsWithArgs = array( 'group', 'lang', 'start', 'end' );
-require __DIR__ . '/cli.inc';
+// Standard boilerplate to define $IP
+if ( getenv( 'MW_INSTALL_PATH' ) !== false ) {
+ $IP = getenv( 'MW_INSTALL_PATH' );
+} else {
+ $dir = __DIR__;
+ $IP = "$dir/../../..";
+}
+require_once "$IP/maintenance/Maintenance.php";
# Override the memory limit for wfShellExec, 100 MB seems to be too little for
svn
$wgMaxShellMemory = 1024 * 200;
-function showUsage() {
- STDERR( <<<EOT
-Options:
- --group Comma separated list of group IDs (can use * as wildcard)
- --git Use git to retrieve last modified date of i18n files. Will use
- subversion by default and fallback on filesystem timestamp
- --lang Comma separated list of language codes or *
- --norc Do not add entries to recent changes table
- --help This help message
- --noask Skip all conflicts
- --start Start of the last export (changes in wiki after will conflict)
- --end End of the last export (changes in source after will conflict)
- --nocolor Without colors
-EOT
- );
- exit( 1 );
-}
-
-if ( isset( $options['help'] ) ) {
- showUsage();
-}
-
-if ( !isset( $options['group'] ) ) {
- STDERR( "ESG1: Message group id must be supplied with group parameter."
);
- exit( 1 );
-}
-
-$groupIds = explode( ',', trim( $options['group'] ) );
-$groupIds = MessageGroups::expandWildcards( $groupIds );
-$groups = MessageGroups::getGroupsById( $groupIds );
-
-if ( !count( $groups ) ) {
- STDERR( "ESG2: No valid message groups identified." );
- exit( 1 );
-}
-
-if ( !isset( $options['lang'] ) || strval( $options['lang'] ) === '' ) {
- STDERR( "ESG3: List of language codes must be supplied with lang
parameter." );
- exit( 1 );
-}
-
-$start = isset( $options['start'] ) ? strtotime( $options['start'] ) : false;
-$end = isset( $options['end'] ) ? strtotime( $options['end'] ) : false;
-
-STDOUT( "Conflict times: " . wfTimestamp( TS_ISO_8601, $start ) . " - " .
- wfTimestamp( TS_ISO_8601, $end ) );
-
-$codes = array_filter( array_map( 'trim', explode( ',', $options['lang'] ) ) );
-
-$supportedCodes = array_keys( TranslateUtils::getLanguageNames( 'en' ) );
-ksort( $supportedCodes );
-
-if ( $codes[0] === '*' ) {
- $codes = $supportedCodes;
-}
-
-/**
- * @var MessageGroup $group
- */
-foreach ( $groups as &$group ) {
- // No sync possible for meta groups
- if ( $group->isMeta() ) {
- continue;
+class SyncGroup extends Maintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Import or update source messages and
translations into ' .
+ 'the wiki database.';
+ $this->addOption(
+ 'git',
+ '(optional) Use git to retrieve last modified date of
i18n files. Will use subversion ' .
+ 'by default and fallback on filesystem timestamp',
+ false, /*required*/
+ false /*has arg*/
+ );
+ $this->addOption(
+ 'group',
+ 'Comma separated list of group IDs (can use * as
wildcard).',
+ true, /*required*/
+ true /*has arg*/
+ );
+ $this->addOption(
+ 'lang',
+ '(optional) Comma separated list of language codes or
*',
+ false, /*required*/
+ true /*has arg*/
+ );
+ $this->addOption(
+ 'norc',
+ '(optional) Do not add entries to recent changes table',
+ false, /*required*/
+ false /*has arg*/
+ );
+ $this->addOption(
+ 'noask',
+ '(optional) Skip all conflicts',
+ false, /*required*/
+ false /*has arg*/
+ );
+ $this->addOption(
+ 'start',
+ '(optional) Start of the last export (changes in wiki
after will conflict)',
+ false, /*required*/
+ true /*has arg*/
+ );
+ $this->addOption(
+ 'end',
+ '(optional) End of the last export (changes in source
after will conflict)',
+ false, /*required*/
+ true /*has arg*/
+ );
+ $this->addOption(
+ 'nocolor',
+ '(optional) Without colors',
+ false, /*required*/
+ false /*has arg*/
+ );
+ $this->addOption(
+ 'core-meta',
+ '(optional) Allow export of specific MediaWiki core
meta groups ' .
+ '(translatewiki.net specific)',
+ false, /*required*/
+ false /*has arg*/
+ );
}
- STDOUT( "{$group->getLabel()} ", $group );
+ public function execute() {
+ $groupIds = explode( ',', trim( $this->getOption( 'group' ) ) );
+ $groupIds = MessageGroups::expandWildcards( $groupIds );
+ $groups = MessageGroups::getGroupsById( $groupIds );
- foreach ( $codes as $code ) {
- // No sync possible for unsupported language codes.
- if ( !in_array( $code, $supportedCodes ) ) {
- STDOUT( "Unsupported code " . $code . ": skipping." );
- continue;
+ if ( !count( $groups ) ) {
+ $this->error( "ESG2: No valid message groups
identified.", 1 );
}
- if ( $group instanceof FileBasedMessageGroup ) {
- /**
- * @var FileBasedMessageGroup $group
- */
- $file = $group->getSourceFilePath( $code );
- } else {
- /**
- * @var MessageGroupOld $group
- */
- $file = $group->getMessageFileWithPath( $code );
+ $start = $this->getOption( 'start' ) ? strtotime(
$this->getOption( 'start' ) ) : false;
+ $end = $this->getOption( 'end' ) ? strtotime( $this->getOption(
'end' ) ) : false;
+
+ $this->output( "Conflict times: " . wfTimestamp( TS_ISO_8601,
$start ) . " - " .
+ wfTimestamp( TS_ISO_8601, $end ) . "\n" );
+
+ $codes = array_filter( array_map( 'trim', explode( ',',
$this->getOption( 'lang' ) ) ) );
+
+ $supportedCodes = array_keys( TranslateUtils::getLanguageNames(
'en' ) );
+ ksort( $supportedCodes );
+
+ if ( $codes[0] === '*' ) {
+ $codes = $supportedCodes;
}
- if ( !$file ) {
- continue;
- }
+ $coreMeta = $this->hasOption( 'core-meta' );
- if ( !file_exists( $file ) ) {
- continue;
- }
+ /** @var MessageGroup $group */
+ foreach ( $groups as $groupId => &$group ) {
+ if ( $group->isMeta() ) {
+ if ( !$coreMeta ) {
+ $this->output( "Skipping meta message
group $groupId.\n" );
+ continue;
+ }
- $cs = new ChangeSyncer( $group );
- if ( isset( $options['norc'] ) ) {
- $cs->norc = true;
- }
+ // Special case for MediaWiki core branches
with pattern "core-1*"
+ if ( strstr( $group->getId(), 'core-1', true )
!== '' ) {
+ $this->output( "Skipping meta message
group $groupId.\n" );
+ continue;
+ }
+ }
- if ( isset( $options['noask'] ) ) {
- $cs->interactive = false;
- }
+ $this->output( "{$group->getLabel()} ", $group );
- if ( isset( $options['nocolor'] ) ) {
- $cs->nocolor = true;
- }
+ foreach ( $codes as $code ) {
+ // No sync possible for unsupported language
codes.
+ if ( !in_array( $code, $supportedCodes ) ) {
+ $this->output( "Unsupported code " .
$code . ": skipping.\n" );
+ continue;
+ }
- # Guess last modified date of the file from either git, svn or
filesystem
- $ts = false;
- if ( isset( $options['git'] ) ) {
- $ts = $cs->getTimestampsFromGit( $file );
- } else {
- $ts = $cs->getTimestampsFromSvn( $file );
- }
- if ( !$ts ) {
- $ts = $cs->getTimestampsFromFs( $file );
- }
+ if ( $group instanceof FileBasedMessageGroup ) {
+ /** @var FileBasedMessageGroup $group */
+ $file = $group->getSourceFilePath(
$code );
+ } else {
+ /** @var MessageGroupOld $group */
+ $file = $group->getMessageFileWithPath(
$code );
+ }
- STDOUT( "Modify time for $code: " . wfTimestamp( TS_ISO_8601,
$ts ) );
+ if ( !$file ) {
+ continue;
+ }
- $cs->checkConflicts( $code, $start, $end, $ts );
+ if ( !file_exists( $file ) ) {
+ continue;
+ }
+
+ $cs = new ChangeSyncer( $group, $this );
+ $cs->setProgressCallback( array( $this,
'myOutput' ) );
+ $cs->interactive = !$this->hasOption( 'noask' );
+ $cs->nocolor = $this->hasOption( 'nocolor' );
+ $cs->norc = $this->hasOption( 'norc' );
+
+ # @todo FIXME: Make this auto detect.
+ # Guess last modified date of the file from
either git, svn or filesystem
+ if ( $this->hasOption( 'git' ) ) {
+ $ts = $cs->getTimestampsFromGit( $file
);
+ } else {
+ $ts = $cs->getTimestampsFromSvn( $file
);
+ }
+ if ( !$ts ) {
+ $ts = $cs->getTimestampsFromFs( $file );
+ }
+
+ $this->output( "Modify time for $code: " .
wfTimestamp( TS_ISO_8601, $ts ) . "\n" );
+
+ $cs->checkConflicts( $code, $start, $end, $ts );
+ }
+
+ unset( $group );
+ }
+ // Print timestamp if the user wants to store it
+ $this->output( wfTimestamp( TS_RFC2822 ) . "\n" );
}
- unset( $group );
+ /**
+ * Public alternative for protected Maintenance::output() as we need to
get
+ * messages from the ChangeSyncer class to the commandline.
+ * @param string $text The text to show to the user
+ * @param string $channel Unique identifier for the channel.
+ * @param bool $error Whether this is an error message
+ */
+ public function myOutput( $text, $channel = null, $error = false ) {
+ if ( $error ) {
+ $this->error( $text, $channel );
+ } else {
+ $this->output( $text, $channel );
+ }
+ }
}
-
-/// @endcond
/**
* Simple external changes syncer and conflict resolution.
*/
class ChangeSyncer {
- public $group; ///< \type{MessageGroup}
- public $norc = false; ///< \bool Don't list changes in recent changes
table.
- public $interactive = true; ///< \bool Whether the script can ask
questions.
- public $nocolor = false; ///< \bool Disable color output.
+ /** @var callable Function to report progress updates */
+ protected $progressCallback;
+ /** @var bool Don't list changes in recent changes table. */
+ public $norc = false;
+
+ /** @var bool Whether the script can ask questions. */
+ public $interactive = true;
+
+ /** @var bool Disable color output. */
+ public $nocolor = false;
+
+ /** @var MessageGroup */
+ protected $group;
+
+ /**
+ * @param MessageGroup $group Message group to synchronise.
+ * can be relayed back.
+ */
public function __construct( MessageGroup $group ) {
$this->group = $group;
+ }
+
+ public function setProgressCallback( $callback ) {
+ $this->progressCallback = $callback;
+ }
+
+ /// @see Maintenance::output for param docs
+ protected function reportProgress( $text, $channel, $severity =
'status' ) {
+ if ( is_callable( $this->progressCallback ) ) {
+ $useErrorOutput = $severity === 'error';
+ call_user_func( $this->progressCallback, $text,
$channel, $useErrorOutput );
+ }
}
// svn component from pecl doesn't seem to have this in quick sight
/**
* Fetch last changed timestamp for a versioned file for conflict
resolution.
- * @param $file \string Filename with full path.
- * @return \string Timestamp or false.
+ * @param string $file Filename with full path.
+ * @return string Timestamp or false.
*/
public function getTimestampsFromSvn( $file ) {
$file = escapeshellarg( $file );
@@ -192,8 +266,8 @@
/**
* Fetch last changed timestamp for a versioned file for conflict
resolution.
- * @param $file \string Filename with full path.
- * @return \string Timestamp or false.
+ * @param string $file Filename with full path.
+ * @return string|bool Timestamp or false.
*/
public function getTimestampsFromGit( $file ) {
$file = escapeshellarg( $file );
@@ -209,8 +283,8 @@
/**
* Fetch last changed timestamp for any file for conflict resolution.
- * @param $file \string Filename with full path.
- * @return \string Timestamp or false.
+ * @param string $file Filename with full path.
+ * @return string Timestamp or false.
*/
public function getTimestampsFromFs( $file ) {
if ( !file_exists( $file ) ) {
@@ -244,7 +318,6 @@
foreach ( $messages as $key => $translation ) {
if ( !isset( $collection[$key] ) ) {
- // STDOUT( "Unknown key $key" );
continue;
}
@@ -258,7 +331,7 @@
$page = $title->getPrefixedText();
if ( $collection[$key]->translation() === null ) {
- STDOUT( "Importing $page as a new translation"
);
+ $this->reportProgress( "Importing $page as a
new translation\n", 'importing' );
$this->import( $title, $translation, 'Importing
a new translation' );
continue;
}
@@ -269,7 +342,7 @@
continue;
}
- STDOUT( "Conflict in " . $this->color( 'bold', $page )
. "!", $page );
+ $this->reportProgress( "Conflict in " . $this->color(
'bold', $page ) . "!", $page );
$iso = 'xnY-xnm-xnd"T"xnH:xni:xns';
$lang = RequestContext::getMain()->getLanguage();
@@ -300,10 +373,10 @@
if ( $changeTs ) {
if ( $wikiTs > $startTs && $changeTs <= $endTs
) {
- STDOUT( " →Changed in wiki after
export: IGNORE", $page );
+ $this->reportProgress( " →Changed in
wiki after export: IGNORE", $page );
continue;
} elseif ( !$wikiTs || ( $changeTs > $endTs &&
$wikiTs < $startTs ) ) {
- STDOUT( " →Changed in source after
export: IMPORT", $page );
+ $this->reportProgress( " →Changed in
source after export: IMPORT", $page );
$this->import(
$title,
$translation,
@@ -317,14 +390,15 @@
continue;
}
- STDOUT( " →Needs manual resolution", $page );
- STDOUT( "Source translation at $changeDate:" );
- STDOUT( $this->color( 'blue', $translation ) . "\n" );
- STDOUT( "Wiki translation at $wikiDate:" );
- STDOUT( $this->color( 'green', $current ) . "\n" );
+ $this->reportProgress( " →Needs manual resolution",
$page );
+ $this->reportProgress( "Source translation at
$changeDate:", 'source' );
+ $this->reportProgress( $this->color( 'blue',
$translation ), 'source' );
+ $this->reportProgress( "Wiki translation at
$wikiDate:", 'translation' );
+ $this->reportProgress( $this->color( 'green', $current
), 'translation' );
do {
- STDOUT( "Resolution: [S]kip [I]mport
[C]onflict: ", 'foo' );
+ $this->reportProgress( "Resolution: [S]kip
[I]mport [C]onflict: ", 'foo' );
+ // @todo Find an elegant way to use
Maintenance::readconsole().
$action = fgets( STDIN );
$action = strtoupper( trim( $action ) );
@@ -355,9 +429,9 @@
/**
* Colors text for shell output
- * @param $color \string Either blue, green or bold.
- * @param $text \string
- * @return \string
+ * @param string $color Either blue, green or bold.
+ * @param string $text
+ * @return string
*/
public function color( $color, $text ) {
switch ( $color ) {
@@ -403,9 +477,9 @@
/**
* Does the actual edit.
- * @param $title Title
- * @param $translation \string
- * @param $comment \string Edit summary.
+ * @param Title $title
+ * @param string $translation
+ * @param string $comment Edit summary.
*/
public function import( $title, $translation, $comment ) {
$flags = EDIT_FORCE_BOT;
@@ -414,14 +488,14 @@
}
$wikipage = new WikiPage( $title );
- STDOUT( "Importing {$title->getPrefixedText()}: ", $title );
+ $this->reportProgress( "Importing {$title->getPrefixedText()}:
", $title );
$status = $wikipage->doEdit(
$translation, $comment, $flags, false,
FuzzyBot::getUser()
);
$success = $status === true || ( is_object( $status ) &&
$status->isOK() );
- STDOUT( $success ? 'OK' : 'FAILED', $title );
+ $this->reportProgress( $success ? 'OK' : 'FAILED', $title );
}
}
-// Print timestamp if the user wants to store it
-STDOUT( wfTimestamp( TS_RFC2822 ) );
+$maintClass = 'SyncGroup';
+require_once RUN_MAINTENANCE_IF_MAIN;
--
To view, visit https://gerrit.wikimedia.org/r/88985
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I8d7647d5bbb179c8d469437a450a166890b676bf
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/extensions/Translate
Gerrit-Branch: master
Gerrit-Owner: Siebrand <[email protected]>
Gerrit-Reviewer: Nikerabbit <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits