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

Reply via email to