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

Commit d2422d3

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

File tree

7 files changed

+217
-9
lines changed

7 files changed

+217
-9
lines changed

delete.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
'<td data-label="Wiki" class="wiki"><a href="wikis/' . $wiki . '/w" title="' . $wiki . '">' . substr( $wiki, 0, 10 ) . '</a></td>' .
2929
'<td data-label="Patches" class="patches">' . $patches . '</td>' .
3030
'<td data-label="Linked tasks" class="linkedTasks">' . $linkedTasks . '</td>' .
31-
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'created' ] ) . '</td>' .
31+
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'updated' ] ) . '</td>' .
3232
( $useOAuth ? '<td data-label="Creator">' . ( $creator ? user_link( $creator ) : '?' ) . '</td>' : '' ) .
3333
'</tr>' .
3434
'</table>';

editcounts.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
],
4848
];
4949

50-
$results = $mysqli->query( 'SELECT wiki FROM wikis WHERE !deleted ORDER BY created DESC' );
50+
$results = $mysqli->query( 'SELECT wiki FROM wikis WHERE !deleted ORDER BY updated DESC' );
5151
if ( !$results ) {
5252
die( $mysqli->error );
5353
}

includes.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,21 @@ function insert_wiki_data( string $wiki, string $creator, int $created, string $
3636
global $mysqli;
3737
$stmt = $mysqli->prepare( '
3838
INSERT INTO wikis
39-
(wiki, creator, created, branch)
40-
VALUES(?, ?, FROM_UNIXTIME(?), ?)
39+
(wiki, creator, created, updated, branch)
40+
VALUES(?, ?, FROM_UNIXTIME(?), FROM_UNIXTIME(?), ?)
4141
' );
4242
if ( !$stmt ) {
4343
echo $mysqli->error;
4444
}
45-
$stmt->bind_param( 'ssis', $wiki, $creator, $created, $branch );
45+
$stmt->bind_param( 'ssis', $wiki, $creator, $created, $created, $branch );
46+
$stmt->execute();
47+
$stmt->close();
48+
}
49+
50+
function wiki_update_timestamp( string $wiki ) {
51+
global $mysqli;
52+
$stmt = $mysqli->prepare( 'UPDATE wikis SET updated = NOW() WHERE wiki = ?' );
53+
$stmt->bind_param( 's', $wiki );
4654
$stmt->execute();
4755
$stmt->close();
4856
}
@@ -77,7 +85,7 @@ function get_wiki_data( string $wiki ): array {
7785
global $mysqli;
7886

7987
$stmt = $mysqli->prepare( '
80-
SELECT wiki, creator, UNIX_TIMESTAMP( created ) created, patches, branch, announcedTasks, timeToCreate, deleted
88+
SELECT wiki, creator, UNIX_TIMESTAMP( created ) created, UNIX_TIMESTAMP( updated ) updated, patches, branch, announcedTasks, timeToCreate, deleted
8189
FROM wikis WHERE wiki = ?
8290
' );
8391
if ( !$stmt ) {

index.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,10 @@
281281
$username = $user ? $user->username : null;
282282

283283
$stmt = $mysqli->prepare( '
284-
SELECT wiki, creator, UNIX_TIMESTAMP( created ) created, patches, branch, announcedTasks, timeToCreate, deleted
284+
SELECT wiki, creator, UNIX_TIMESTAMP( updated ) updated, patches, branch, announcedTasks, timeToCreate, deleted
285285
FROM wikis
286286
WHERE !deleted
287-
ORDER BY IF( creator = ?, 1, 0 ) DESC, created DESC
287+
ORDER BY IF( creator = ?, 1, 0 ) DESC, updated DESC
288288
' );
289289
if ( !$stmt ) {
290290
die( $mysqli->error );
@@ -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 ) {
@@ -346,7 +347,7 @@
346347
'</td>' .
347348
'<td data-label="Patches" class="patches">' . $patches . '</td>' .
348349
'<td data-label="Linked tasks" class="linkedTasks">' . $linkedTasks . '</td>' .
349-
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'created' ] ) . '</td>' .
350+
'<td data-label="Time" class="date">' . date( 'Y-m-d H:i:s', $wikiData[ 'updated' ] ) . '</td>' .
350351
( $useOAuth ? '<td data-label="Creator">' . ( $creator ? user_link( $creator ) : '?' ) . '</td>' : '' ) .
351352
( $canAdmin ? '<td data-label="Time to create">' . ( $wikiData['timeToCreate'] ? $wikiData['timeToCreate'] . 's' : '' ) . '</td>' : '' ) .
352353
( count( $actions ) ?

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.

sql/patchdemo.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,9 @@ ALTER TABLE `tasks`
4242

4343
ALTER TABLE `wikis`
4444
ADD COLUMN IF NOT EXISTS `branch` VARCHAR(64) NOT NULL AFTER `patches`;
45+
46+
ALTER TABLE `wikis`
47+
ADD COLUMN `updated` DATETIME NOT NULL AFTER `created`,
48+
ADD INDEX `updated` (`updated`);
49+
50+
UPDATE wikis SET updated = created;

update.php

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

0 commit comments

Comments
 (0)