diff --git a/.github/labels.yml b/.github/labels.yml index 725e30cae..eae6ef199 100644 --- a/.github/labels.yml +++ b/.github/labels.yml @@ -41,8 +41,6 @@ - modules/twinklexfd.js Tests: - tests/* - - scripts/patch-test.js - - scripts/server.js Docs: - "*.md" Gadget: diff --git a/package.json b/package.json index ea82dc136..6b423d398 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,6 @@ "start": "node scripts/dev-server.js", "lint": "eslint .", "lint:fix": "eslint . --fix", - "patchtest": "node scripts/patch-test.js", - "server": "node scripts/server.js", "sync": "perl scripts/sync.pl", "test": "jest", "deployall": "perl scripts/sync.pl --mode=deploy --all" diff --git a/scripts/draftRelease.sh b/scripts/draftRelease.sh deleted file mode 100755 index b4fb81c20..000000000 --- a/scripts/draftRelease.sh +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env bash -# draftRelease.sh by Amory Meltzer, 2020 -# Licensed under the WTFPL http://www.wtfpl.net/ -# Collect draft of items to announce at WT:TW - - -# When double quoted, * means IFS separation and @ means word -# Keep that in mind lest ye go mad - -function usage { - cat < 2020-01-01.wikitext\`, as it will need sorting, editing, and formatting. - -An optional second commit can be used to identify the ending commit, i.e. the last commit to include in this list. Default is HEAD. -END_USAGE -} - -while getopts 'hH' opt; do - case $opt in - h|H) usage "$0" - exit 0;; - esac -done - -# The readarray below implies bash>=4, which is not/will never be the default -# on OS X/macOS, but everyone should be on it anyway. If we wanted to make it -# fine on bash v3, this would have to be converted to something like -### log=$(git log --no-merges --topo-order --reverse --format="%H;;%an;;%s" HEAD~6..HEAD -- . ":(glob)**/*.*s") -### IFS=$'\n' log=($log) -# and would also require parsing out mergeParents for the merge-base call, as -# the space between the %P parents throws a wrench in the whole thang. -# Likewise, we could do -### while IFS='\n' read log; -### ... -### done < <(git log --no-merges --topo-order --reverse --format="%H;;%an;;%s" $prior..$end -- . ":(glob)**/*.*s") -if [[ "${BASH_VERSINFO[0]}" -lt 4 ]]; then - echo "bash version 4 or greater is required" - exit 1 -fi - - -# Parse arguments, ensure at least one is given, and either are valid objects -# Could use commit but -e/-t allows for tags -prior=$1 -if ! git cat-file -e "$prior" &>/dev/null; then - echo "$0 needs a valid object" - exit 1; -fi -end='HEAD' -if git cat-file -e "$2" &>/dev/null; then - end=$2 -fi - -# Run from toplevel, matters for glob -top="$(git rev-parse --show-toplevel 2>/dev/null)" -if [[ -d "$top" ]]; then - cd "$top" -else - echo "Unable to find top-level directory" - exit 1; -fi - -# Limit to js and css files; include author and message for later use, uniquely separated -# Should probably be better about excluding pathspecs -readarray -t log < <(git log --no-merges --topo-order --reverse --format="%H;;%an;;%s" "$prior".."$end" . ":(glob)**/*.s" ":(exclude)*.json" ":(exclude)scripts/**" ":(exclude)tests/**" ":(exclude).github/**") -for item in "${log[@]}"; do - sha="${item%%';;'*}" - - files=$(git diff --name-only "$sha~" "$sha") - if [[ -z "$files" ]]; then - continue - fi - - # Clean up a bit - files=$(echo "$files" | sed 's/modules\///' | perl -pe 's/(?:twinkle|friendly)?\B(.+)\.(?:j|cs)s$/$1/' | sort | uniq) - - item="${item#*';;'}" - author="${item%';;'*}" - message="${item#*';;'}" - - # Don't transclude templates - message="${message//{{/{{tl|}" - - # Multiple files edited - # Should probably be updated to sort module+twinkleconfig under module - if [[ $(echo "$files" | wc -l | tr -d ' ') -gt 1 ]]; then - files=$(echo -n "$files" | tr -u '\n' ' ') - files="Multiple ($files)" - else - # Remove likely repetitive file prefix - message="${message/$files: }" - # Rename some confusing modules - files="${files/fluff/revert and rollback}" - files="${files/config/prefs}" - fi - - # Find the associated merge commit and grep the GitHub PR number for linking - info='' - pr='' - # Try to process squash-merge items first - if [[ "$message" =~ "(#"[[:digit:]]+")" ]]; then - pr=$(grep -o "(#\d\+)" <<< "$message" | grep -o "\d\+") - # Cleanup message - message="${message/ (#$pr)}" - else - # -n is processed before things like --reverse, so we need to pipe to head - merge=$(git log "$sha".."$end" --ancestry-path --merges --reverse --format='%H;;%s;;%P' | head -n 1) - if [[ -n "$merge" ]]; then - mergeCommit="${merge%%';;'*}" - merge="${merge#*';;'}" - mergeMessage="${merge%';;'*}" # technically unnecessary... - mergeParents="${merge#*';;'}" - # The ancestry-path check isn't sufficient, as commits directly - # commited to master (i.e. not part of a PR/merge) will report the - # prior merge commit. This monstrosity: - # 1. Uses the parents of the merge commit (%P from above) - # 2. Finds the common base of those parents (merge-base) - # 3. Lists all the commits from the base to the merge commit (log..$mergeCommit) - # 4. Checks if our sha is in that list - # It's roundabout and ugly but I don't know a simpler or - # faster way without introducing some errors - if [[ -n $(git log $(git merge-base --octopus $mergeParents)..$mergeCommit --oneline --no-abbrev-commit | grep "$sha") ]]; then - # Merge via GitHub, typical - pr=$(grep -o "Merge pull request \#\d\+" <<< "$mergeMessage" | grep -o "\d\+") - # Merge via terminal, assumes a branch prefixed with the repo PR number (e.g. "666-") - if [[ -z "$pr" ]]; then - pr=$(grep -o "Merge branch \'\d\+-" <<< "$mergeMessage" | grep -o "\d\+") - fi - fi - fi - fi - - if [[ -n "$pr" ]]; then - info="[https://github.com/wikimedia-gadgets/twinkle/pull/$pr #$pr]" - fi - - # Avoid ego padding - author="${author/$(git config user.name)/}" - # Make a user link - if [[ -n "$author" ]]; then - # Convert unusual suspects - lcauthor="${author,,}" - if [[ "$lcauthor" =~ "siddharth vp" ]]; then - author="SD0001" - elif [[ "$lcauthor" =~ "michael daniels" ]]; then - author="Mdaniels5757" - elif [[ "$lcauthor" =~ "ankit" ]]; then - author="QEDK" - fi - author="[[User:$author|$author]]" - - if [[ -n "$info" ]]; then - info="$info, " - fi - info="$info""by $author" - fi - - # Dump into an array for sorting - results+=("*$files: $message${info:+ ($info)}") -done - -# Sort and print results, grouped by module -IFS=$'\n' results=($(sort <<<"${results[*]}")) -dupes=$(cut -f 1 -d ':' <<<"${results[*]}" | sort | uniq -d) -prior='' -for x in "${results[@]}"; do - file=$(cut -f 1 -d ':' <<<"${x}") - # Group items under headings - grep=$(grep "${file}" <<<"${dupes[@]}") - if [[ -n "$grep" ]]; then - line="${x/\*${file}: /}" - if [ "$file" != "$prior" ]; then - echo "${file}:" - fi - echo "**${line}" - else - echo "${x}" - fi - # Set for next round - prior=$file -done diff --git a/scripts/morebits-test.js b/scripts/morebits-test.js deleted file mode 100644 index 8cb497721..000000000 --- a/scripts/morebits-test.js +++ /dev/null @@ -1,183 +0,0 @@ -/* global Morebits */ - -// Script depends on jQuery dialog widget, loaded through jquery.ui after -// T219604 (1.35-wmf.2 circa 22 Oct 2019) -mw.loader.using('jquery.ui', function() { - // Construct object (to prevent namespace conflicts) - Twinkle.morebitsTest = { - - launchDialog: function(userInterface) { - userInterface.dialog('open'); - }, - - initSimpleWindow: function() { - var Window = new Morebits.simpleWindow(600, 400); - Window.setTitle('Test morebits.js'); - Window.display(); - var form = new Morebits.quickForm(null); - form.append({ - type: 'select', - name: 'main_group', - event: null - }); - var result = form.render(); - Window.setContent(result); - Window.display(); - result.main_group.root = result; - Morebits.status.init(result); - Morebits.wiki.actionCompleted.redirect = mw.config.get('wgPageName'); - Morebits.wiki.actionCompleted.notice = 'Test complete, reloading talk page in a few seconds'; - }, - - setPageOptions: function(page) { - page.setEditSummary($('#editSummary').val()); - if ($('#runTestForm input[name="followRedirect"]').attr('checked')) { - page.setFollowRedirect(true); - } - if ($('#runTestForm input[name="minorEdit"]').attr('checked')) { - page.setMinorEdit(true); - } - if ($('#runTestForm input[name="watchlist"]').attr('checked')) { - page.setWatchlist(true); - } - if ($('#runTestForm input[name="watchlistFromPreferences"]').attr('checked')) { - page.setWatchlistFromPreferences(true); - } - if ($('#runTestForm input[name="noRetries"]').attr('checked')) { - page.setMaxConflictRetries(0); - page.setMaxRetries(0); - } - var section = $('#runTestForm input[name="sectionNumber"]').val(); - if (section !== '') { - page.setPageSection(Number(section)); - } - page.setCreateOption(window.morebits_test_createOption); - - if ($('#runTestForm input[name="lookupCreation"]').attr('checked')) { - page.lookupCreation(Twinkle.morebitsTest.lookupCreationCallback); - } - }, - - loadCallbackInsert: function(page) { - var params = page.getCallbackParameters(); - var text = page.getPageText(); - var pos = text.indexOf(params.beforeText); - if (pos === -1) { - alert('Search text "' + params.beforeText + '" not found!'); - return; - } - page.setPageText(text.substr(0, pos) + params.newText + text.substr(pos)); - page.save(Twinkle.morebitsTest.finalSaveCallback); - }, - - loadCallbackReplace: function(page) { - var params = page.getCallbackParameters(); - page.setPageText(params.newText); - page.save(Twinkle.morebitsTest.finalSaveCallback); - }, - - lookupCreationCallback: function(page) { - alert('Page was created by: ' + page.getCreator() + ' at: ' + page.getCreationTimestamp()); - }, - - finalSaveCallback: function(page) { - Morebits.wiki.actionCompleted.redirect = page.getPageName(); // get result of redirects - }, - - initialize: function() { - - // Define runTest interface - // Can also use alternative syntax new to jQuery 1.4: - // $('
').html( 'Text to be added:' ) - // -> $('
', { css: { 'margin-top': '0.4em' }, text: 'Text to be added:' } ) - - window.morebits_test_createOption = null; - - Twinkle.morebitsTest.$runTests = $('
') - .append($('
').html('Text to be added:
').append($(''))) - .append($('
').html('Insert text before (for insert mode only):
').append($(''))) - .append($('
').html('Edit summary:
').append($(''))) - .append($('
').html('Section number: ')) - .append($('
').html(' Follow redirect')) - .append($('
').html(' Minor edit')) - .append($('
').html(' Add to watchlist')) - .append($('
').html(' Add to watchlist based on preference settings')) - .append($('
').html(' Disable retries')) - .append($('
').html(' Lookup page creator and timestamp
')) - .append($('
').html(' Create page if needed, unless deleted since loaded
')) - .append($('
').html(' Create page if needed
')) - .append($('
').html(' Only create a new page
')) - .append($('
').html(' Do not create a new page
')) - .dialog({ - width: 500, - autoOpen: false, - title: 'Test Morebits.wiki.page class', - modal: true, - buttons: { - 'Append': function() { - $(this).dialog('close'); - Twinkle.morebitsTest.initSimpleWindow(); - - var page = new Morebits.wiki.page(mw.config.get('wgPageName')); - page.setAppendText($('#message').val()); - Twinkle.morebitsTest.setPageOptions(page); - page.append(Twinkle.morebitsTest.finalSaveCallback); - }, - 'Prepend': function() { - $(this).dialog('close'); - Twinkle.morebitsTest.initSimpleWindow(); - - var page = new Morebits.wiki.page(mw.config.get('wgPageName')); - page.setPrependText($('#message').val()); - Twinkle.morebitsTest.setPageOptions(page); - page.prepend(Twinkle.morebitsTest.finalSaveCallback); - }, - 'Insert': function() { - if ($('#beforeText').val() === '') { - alert('Text to insert before must be specified!'); - return; - } - $(this).dialog('close'); - Twinkle.morebitsTest.initSimpleWindow(); - - var page = new Morebits.wiki.page(mw.config.get('wgPageName')); - page.setCallbackParameters({ - beforeText: $('#beforeText').val(), - newText: $('#message').val() - }); - Twinkle.morebitsTest.setPageOptions(page); - page.load(Twinkle.morebitsTest.loadCallbackInsert); - }, - 'Replace': function() { - $(this).dialog('close'); - Twinkle.morebitsTest.initSimpleWindow(); - - var page = new Morebits.wiki.page(mw.config.get('wgPageName')); - page.setCallbackParameters({ - newText: $('#message').val() - }); - Twinkle.morebitsTest.setPageOptions(page); - page.load(Twinkle.morebitsTest.loadCallbackReplace); - } - } - }); // close .dialog - - } // close initialize function - - }; // close Twinkle.morebitsTest object - - Twinkle.morebitsTest.initialize(); -}); // close mw.loader - -Twinkle.morebitsTestInit = function () { - if (mw.config.get('wgAction') === 'view' && mw.config.get('skin') === 'vector' && mw.config.get('wgNamespaceNumber') >= 0) { - Twinkle.addPortlet('javascript:Twinkle.morebitsTest.launchDialog(Twinkle.morebitsTest.$runTests)', 'Test', 'tw-test', 'Test morebits.js', ''); - } -}; - -// register initialization callback -var Twinkle; -if (typeof Twinkle === 'undefined') { - throw new Error('Attempt to load module "morebits-test" without having loaded Twinkle previously.'); -} -Twinkle.addInitCallback(Twinkle.morebitsTestInit); diff --git a/scripts/patch-test.js b/scripts/patch-test.js deleted file mode 100644 index eebe75b11..000000000 --- a/scripts/patch-test.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-env node, es6 */ - -/** - * Creates a file patch-test-loader.js with the necessary import statements - * to test the changes made in a pull request or in the current working state - * - * How to use: - * - Run `npm run patchtest` which generates patch-test-loader.js - * - Set up a localhost server (such as by using npm run server or by running - * php -S 127.0.0.1:5500) and load patch-test-loader.js in the wiki environment, - * using the browser console or the common.js page. - * - You can provide a different port by running `npm run patchtest -- 1234` - */ - -const fs = require('fs'); -const {execSync} = require('child_process'); - -const port = isNaN(Number(process.argv[2])) ? '5500' : process.argv[2]; -const server = 'http://127.0.0.1:' + port; - -// find the last common commit between this branch and master, and get the list -// of files changed since that commit -try { - let lastCommonCommit = execSync('git merge-base HEAD master').toString().trim(); - let changedFiles = execSync(`git diff ${lastCommonCommit} --name-only`).toString().split(/\r?\n/); - createTestLoader(changedFiles); -} catch (err) { - console.log(err.toString()); -} - -/** @param {string[]} changedFiles */ -function createTestLoader(changedFiles) { - - let importsCount = 0; // for the message written to the console in the ends - let importLine = function(file) { - if (!changedFiles.includes(file)) { - return ''; - } - if (file.endsWith('.js')) { - importsCount++; - if (file.startsWith('modules/')) { - return `mw.loader.getScript('${server}/${file}');`; - } - return `return mw.loader.getScript('${server}/${file}');`; - } else if (file.endsWith('.css')) { - importsCount++; - return `mw.loader.load('${server}/${file}', 'text/css');`; - } - return ''; - }; - - let jsLoaderSource = `// Wait for Twinkle gadget to load, so that we can then overwrite it - mw.loader.using('ext.gadget.Twinkle').then(function() { - ${importLine('morebits.css')} - ${importLine('morebits.js')} - - }).then(function() { - ${importLine('twinkle.css')} - ${importLine('twinkle.js')} - - }).then(function() { - ${importLine('modules/friendlyshared.js')} - ${importLine('modules/friendlytag.js')} - ${importLine('modules/friendlytalkback.js')} - ${importLine('modules/friendlywelcome.js')} - ${importLine('modules/twinklearv.js')} - ${importLine('modules/twinklebatchdelete.js')} - ${importLine('modules/twinklebatchprotect.js')} - ${importLine('modules/twinklebatchundelete.js')} - ${importLine('modules/twinkleblock.js')} - ${importLine('modules/twinkleconfig.js')} - ${importLine('modules/twinkledeprod.js')} - ${importLine('modules/twinklediff.js')} - ${importLine('modules/twinklefluff.js')} - ${importLine('modules/twinkleimage.js')} - ${importLine('modules/twinkleprod.js')} - ${importLine('modules/twinkleprotect.js')} - ${importLine('modules/twinklespeedy.js')} - ${importLine('modules/twinkleunlink.js')} - ${importLine('modules/twinklewarn.js')} - ${importLine('modules/twinklexfd.js')} - });`.replace(/^\t/mg, '').replace(/^\s*$/mg, ''); - - fs.writeFileSync('./scripts/patch-test-loader.js', jsLoaderSource, console.log); - - console.log(`Wrote import statements for ${importsCount} modified file${importsCount > 1 ? 's' : ''} to scripts/patch-test-loader.js`); -} diff --git a/scripts/server.js b/scripts/server.js deleted file mode 100644 index 719f4cfad..000000000 --- a/scripts/server.js +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-env node, es6 */ - -const http = require('http'); -const fs = require('fs'); - -const server = http.createServer((request, response) => { - const filePath = '.' + request.url; - let contentType; - if (request.url.endsWith('.js')) { - contentType = 'text/javascript'; - } else if (request.url.endsWith('.css')) { - contentType = 'text/css'; - } else { - contentType = 'text/plain'; - } - fs.readFile(filePath, function(error, content) { - if (error) { - response.end('Oops, something went wrong: ' + error.code + ' ..\n'); - } else { - response.writeHead(200, { 'Content-Type': contentType + '; charset=utf-8' }); - response.end(content, 'utf-8'); - } - }); -}); - -const hostname = '127.0.0.1'; -const port = isNaN(Number(process.argv[2])) ? '5500' : process.argv[2]; - -server.listen(port, hostname, () => { - console.log(`Server running at http://${hostname}:${port}/`); -});