Nikerabbit has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/394864 )
Change subject: Add rudimentary state synchronization ...................................................................... Add rudimentary state synchronization The purpose is to prevent accidental overriding of commits that happen between our last synchronization to translatewiki.net and us exporting those changes. For example: 1. Update read-only repo 2. Synchronize into the wiki 3. Update read-write repo 4. Export and commit translations In step 3 the read-write repo could get ahead of the read-only repo. Now, if possible, we read the git commit from step 1 to reduce the likelyhood. This is not completely safe yet, because there is no guarantee that step 2 has happened. For humans this should be fairly obvious, because our scripts always alert after step 1 (which is automatized) that there are pending changes to check. For fully automatic exports this is not safe enough. Step 4 is amended to attempt automatic rebase before pushing to avoid failing on non-conflicting changes. Removed update-reset-repo which is now enhanced and inlined in clupdate-git-repo. State synchronization is not really possible when we are committing to a different branch or repository. Different branch is detected automatically and state is not synchronized then. For different repos there is new option no-state-sync that can be set to disable synching. This commit uses the null coalescing operator (??) available in PHP7 and HHVM. Change-Id: I979cbc20f31cf827a58bfd0fdd9ca2a7803ae345 --- M bin/clupdate-git-repo D bin/update-reset-repo M repoconfig.yaml M repong/repong.php 4 files changed, 47 insertions(+), 43 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/translatewiki refs/changes/64/394864/1 diff --git a/bin/clupdate-git-repo b/bin/clupdate-git-repo index bff3343..018362b 100755 --- a/bin/clupdate-git-repo +++ b/bin/clupdate-git-repo @@ -10,11 +10,17 @@ URL=$1 DIR=$2 BRANCH=${3:-master} +COMMIT=${4:-origin/$BRANCH} if [ -d "$DIR/.git" ] -then - "$DIRSCRIPT/update-reset-repo" "$DIR" "" "$BRANCH" -else +then ( + cd $DIR + git rebase --abort &>/dev/null || : + git checkout -qf "$BRANCH" + git fetch -q + git reset -q --hard "$COMMIT" + git clean -q -f -d &>/dev/null +) else git clone "$URL" "$DIR" -b "$BRANCH" if [ "$ME" = 'clupdate-gerrit-repo' ] diff --git a/bin/update-reset-repo b/bin/update-reset-repo deleted file mode 100755 index 900fb56..0000000 --- a/bin/update-reset-repo +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -set -e - -# Allow for passing a base path and repo folder name in two parameters -# or a single full path as parameter. -if [ $# -eq 2 ] -then - # Concatenate base path and folder name - DIR=$1/$2 -else - DIR=$1 -fi - -BRANCH=${3:-master} - -# Updates the repository in the current directory and resets it. -# Sets OUTPUT to the output of the git operations -# Sets CODE to the return value of the pipeline. -update_reset() { - OUTPUT=$(git fetch -q && git reset -q --hard origin/$BRANCH && git clean -q -f -d 2>&1 >&-) - CODE=$? -} - -cd $DIR -update_reset - -if [ $CODE -ne 0 ]; then - cd $DIR - echo "Retry $DIR" - update_reset - if [ $CODE -ne 0 ]; then - printf "\033[31m%s failed to update\033[0m\n" "$DIR"; - echo $OUTPUT; - fi -fi diff --git a/repoconfig.yaml b/repoconfig.yaml index 9493bb9..a7c718b 100644 --- a/repoconfig.yaml +++ b/repoconfig.yaml @@ -2,6 +2,7 @@ '@meta': export: php /srv/mediawiki/targets/production/extensions/Translate/scripts/export.php expand: php /srv/mediawiki/targets/production/extensions/Translate/scripts/expand-groupspec.php --exportable + state-directory|export: /resources/projects blockly: group: out-blockly* diff --git a/repong/repong.php b/repong/repong.php index 9b4ab4c..c034271 100644 --- a/repong/repong.php +++ b/repong/repong.php @@ -235,15 +235,41 @@ protected function execute( InputInterface $input, OutputInterface $output ) { $project = $input->getArgument( 'project' ); $variant = $input->getOption( 'variant' ) ?: $this->defaultVariant; + $defaultConfig = $this->getConfig( $project, $this->defaultVariant ); $config = $this->getConfig( $project, $variant ); + $meta = $this->getConfig( '@meta', $variant ); $base = $this->getBase(); $bindir = $this->bindir; + // Without state synchronization, the repository we make commits + // could be ahead of the state that has been processed in the wiki. + // With state synchronization we ensure we do not overwrite any + // changes that have been made in the between. + $stateDir = isset( $meta[ 'state-directory' ] ) ? $meta[ 'state-directory' ] : false; $processes = new SplObjectStorage(); foreach ( $config['repos'] as $name => $repo ) { $type = $repo['type']; - $branch = isset( $repo['branch'] ) ? $repo['branch'] : 'master'; + $branch = $repo['branch'] ?? 'master'; + + // Check if we can use state synchronization for this repo + $defaultConfigBranch = $defaultConfig[ 'repos' ][ $name ][ 'branch' ] ?? 'master'; + $branchCompatible = $branch === $defaultConfigBranch; + $syncState = $stateDir && $branchCompatible && !isset( $repo[ 'no-state-sync' ] ); + + // Determine the state to use, if possible + $state = null; + if ( $syncState && in_array( $type, [ 'git', 'github', 'wmgerrit' ] ) ) { + $process = new Process( 'git log --pretty="%H" -n 1' ); + $process->setWorkingDirectory( "$stateDir/$name" ); + $process->setTimeout( 5 ); + $process->run(); + if ( $process->isSuccessful() ) { + $state = trim( $process->getOutput() ); + } else { + throw new ProcessFailedException( $process ); + } + } if ( $type === 'git' ) { $userName = get_current_user(); @@ -260,12 +286,16 @@ } elseif ( $type === 'wmgerrit' ) { $command = "$bindir/clupdate-gerrit-repo '{$repo['url']}' '$base/$name' '$branch'"; } elseif ( $type === 'svn' ) { - $command = "$bindir/clupdate-svn-repo '{$repo['url']}' '$base/$name'"; + $command = "$bindir/clupdate-svn-repo '{$repo['url']}' '$base/$name'"; } elseif ( $type === 'bzr' ) { - $command = "$bindir/clupdate-bzr-repo '{$repo['url']}' '$base/$name' '$branch'"; + $command = "$bindir/clupdate-bzr-repo '{$repo['url']}' '$base/$name' '$branch'"; } else { $config = yaml_emit( [ $name => $repo ] ); throw new RuntimeException( "Unknown repo type:\n$config" ); + } + + if ( $state ) { + $command .= " '$state'"; } $process = new Process( $command ); @@ -370,12 +400,14 @@ $branch = isset( $repo['branch'] ) ? $repo['branch'] : 'master'; $command = "cd '$dir'; git add .; if ! git diff --cached --quiet; " . - "then git commit -m '$message'; git push origin '$branch'; fi"; + "then git commit -m '$message'; " . + "git rebase 'origin/$branch' && git push origin '$branch'; fi"; } elseif ( $repo['type'] === 'wmgerrit' ) { $dir = "$base/$name"; $command = "cd '$dir'; git add .; if ! git diff --cached --quiet; " . - "then git commit -m '$message'; git review -r origin -t L10n; fi"; + "then git commit -m '$message' " . + "git rebase 'origin/$branch' && git review -r origin -t L10n; fi"; } elseif ( $repo['type'] === 'svn' ) { $dir = "$base/$name"; $extra = ''; -- To view, visit https://gerrit.wikimedia.org/r/394864 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I979cbc20f31cf827a58bfd0fdd9ca2a7803ae345 Gerrit-PatchSet: 1 Gerrit-Project: translatewiki Gerrit-Branch: master Gerrit-Owner: Nikerabbit <niklas.laxst...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits