Skip to content
This repository was archived by the owner on Sep 23, 2023. It is now read-only.

Commit d0a598a

Browse files
committed
Allow patches to be updated
Fixes #54
1 parent d724828 commit d0a598a

File tree

3 files changed

+187
-0
lines changed

3 files changed

+187
-0
lines changed

index.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@
330330

331331
$actions = [];
332332
if ( $canDelete ) {
333+
$actions[] = '<a href="update.php?wiki=' . $wiki . '">Update</a>';
333334
$actions[] = '<a href="delete.php?wiki=' . $wiki . '">Delete</a>';
334335
}
335336
if ( $canCreate ) {

new/applypatch.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ set -ex
33

44
cd $PATCHDEMO/wikis/$NAME/$REPO
55

6+
# Required when updating an existing wiki
7+
git reset --hard origin/master
8+
69
git fetch origin $REF
710

811
# Apply $HASH and its parent commits up to $BASE on top of current HEAD.

update.php

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<?php
2+
3+
use Symfony\Component\Yaml\Yaml;
4+
5+
require_once "includes.php";
6+
7+
include "header.php";
8+
9+
ob_implicit_flush( true );
10+
11+
if ( $useOAuth && !$user ) {
12+
echo oauth_signin_prompt();
13+
die();
14+
}
15+
16+
$wiki = $_GET['wiki'];
17+
$wikiData = get_wiki_data( $wiki );
18+
19+
if ( !can_delete( $wikiData['creator'] ) ) {
20+
die( '<p>You are not allowed to update this wiki.</p>' );
21+
}
22+
23+
function abandon( string $errHtml ) {
24+
die( $errHtml );
25+
}
26+
27+
echo '<div class="consoleLog">';
28+
29+
$patchesApplied = [];
30+
$linkedTasks = [];
31+
$commands = [];
32+
$usedRepos = [];
33+
34+
foreach ( $wikiData['patchList'] as $patch => $patchData ) {
35+
$r = $patchData['r'];
36+
$data = gerrit_query( "changes/?q=change:$r&o=LABELS&o=CURRENT_REVISION", true );
37+
38+
// get the info
39+
$repo = $data[0]['project'];
40+
$base = 'origin/' . $data[0]['branch'];
41+
$revision = $data[0]['current_revision'];
42+
$ref = $data[0]['revisions'][$revision]['ref'];
43+
$id = $data[0]['id'];
44+
45+
$repos = get_repo_data();
46+
if ( !isset( $repos[ $repo ] ) ) {
47+
$repo = htmlentities( $repo );
48+
abandon( "Repository <em>$repo</em> not supported" );
49+
}
50+
$path = $repos[ $repo ];
51+
$usedRepos[] = $repo;
52+
53+
if (
54+
$config[ 'requireVerified' ] &&
55+
( $data[0]['labels']['Verified']['approved']['_account_id'] ?? null ) !== 75
56+
) {
57+
// The patch doesn't have V+2, check if the uploader is trusted
58+
$uploaderId = $data[0]['revisions'][$revision]['uploader']['_account_id'];
59+
$uploader = gerrit_query( 'accounts/' . $uploaderId, true );
60+
if ( !is_trusted_user( $uploader['email'] ) ) {
61+
abandon( "Patch must be approved (Verified+2) by jenkins-bot, or uploaded by a trusted user" );
62+
}
63+
}
64+
65+
$r = $patchData['r'];
66+
$pOld = (int)$patchData['p'];
67+
$pNew = $data[0]['revisions'][$revision]['_number'];
68+
if ( $pNew > $pOld ) {
69+
echo "<strong>Updating change $r from patchset $pOld to $pNew.</strong>";
70+
} else {
71+
echo "<strong>Change $r is already using the latest patchset ($pOld).</strong>";
72+
continue;
73+
}
74+
75+
$patchesApplied[] = $data[0]['_number'] . ',' . $data[0]['revisions'][$revision]['_number'];
76+
77+
$commands[] = [
78+
[
79+
'REPO' => $path,
80+
'REF' => $ref,
81+
'BASE' => $base,
82+
'HASH' => $revision,
83+
],
84+
__DIR__ . '/new/applypatch.sh'
85+
];
86+
87+
$relatedChanges = [];
88+
$relatedChanges[] = [ $data[0]['_number'], $data[0]['revisions'][$revision]['_number'] ];
89+
90+
// Look at all commits in this patch's tree for cross-repo dependencies to add
91+
$data = gerrit_query( "changes/$id/revisions/$revision/related", true );
92+
// Ancestor commits only, not descendants
93+
$foundCurr = false;
94+
foreach ( $data['changes'] as $change ) {
95+
if ( $foundCurr ) {
96+
// Querying by change number is allegedly deprecated, but the /related API doesn't return the 'id'
97+
$relatedChanges[] = [ $change['_change_number'], $change['_revision_number'] ];
98+
}
99+
$foundCurr = $foundCurr || $change['commit']['commit'] === $revision;
100+
}
101+
102+
foreach ( $relatedChanges as [ $c, $r ] ) {
103+
$data = gerrit_query( "changes/$c/revisions/$r/commit", true );
104+
105+
preg_match_all( '/^Depends-On: (.+)$/m', $data['message'], $m );
106+
foreach ( $m[1] as $changeid ) {
107+
if ( !in_array( $changeid, $patches, true ) ) {
108+
// The entry we add here will be processed by the topmost foreach
109+
$patches[] = $changeid;
110+
}
111+
}
112+
}
113+
}
114+
$usedRepos = array_unique( $usedRepos );
115+
116+
$baseEnv = [
117+
'PATCHDEMO' => __DIR__,
118+
'NAME' => $wiki,
119+
];
120+
121+
if ( !count( $commands ) ) {
122+
abandon( 'No patches to update.' );
123+
}
124+
125+
$error = shell_echo( __DIR__ . '/new/unlink.sh', $baseEnv );
126+
if ( $error ) {
127+
abandon( "Could not un-duplicate wiki." );
128+
}
129+
130+
foreach ( $commands as $i => $command ) {
131+
$error = shell_echo( $command[1], $baseEnv + $command[0] );
132+
if ( $error ) {
133+
abandon( "Could not apply patch {$patchesApplied[$i]}" );
134+
}
135+
}
136+
137+
$composerInstallRepos = Yaml::parse( file_get_contents( __DIR__ . '/repository-lists/composerinstall.yaml' ) );
138+
foreach ( $usedRepos as $repo ) {
139+
if ( in_array( $repo, $composerInstallRepos, true ) ) {
140+
$error = shell_echo( __DIR__ . '/new/composerinstall.sh',
141+
$baseEnv + [
142+
// Variable used by composer itself, not our script
143+
'COMPOSER_HOME' => __DIR__ . '/composer',
144+
'REPO_TARGET' => $repos[$repo],
145+
]
146+
);
147+
if ( $error ) {
148+
abandon( "Could not fetch dependencies for <em>$repo</em>" );
149+
}
150+
}
151+
}
152+
153+
$mainPage = "\n\nThis wiki was updated on ~~~~~ with the following newer patches:";
154+
foreach ( $patchesApplied as $patch ) {
155+
preg_match( '`([0-9]+),([0-9]+)`', $patch, $matches );
156+
list( $t, $r, $p ) = $matches;
157+
158+
$data = gerrit_query( "changes/$r/revisions/$p/commit", true );
159+
if ( $data ) {
160+
$t = $t . ': ' . $data[ 'subject' ];
161+
get_linked_tasks( $data['message'], $linkedTasks );
162+
}
163+
164+
$t = htmlentities( $t );
165+
166+
$mainPage .= "\n:* [{$config['gerritUrl']}/r/c/$r/$p <nowiki>$t</nowiki>]";
167+
}
168+
169+
$error = shell_echo( __DIR__ . '/new/postupdate.sh',
170+
$baseEnv + [
171+
'MAINPAGE' => $mainPage,
172+
]
173+
);
174+
if ( $error ) {
175+
abandon( "Could not update wiki content" );
176+
}
177+
178+
Update DB record with patches applied
179+
wiki_add_patches( $wiki, $patchesApplied );
180+
181+
echo "Done!";
182+
183+
echo '</div>';

0 commit comments

Comments
 (0)