3.1. Software package mirrors (软件包管理器镜像)

We also have a NPM Node.js package https://www.npmjs.com/package/china-dictatorship. After installing NPM, you can be use it as:

npm i -g china-dictatorship
china-dictatorship > README.html

This forces China to also block/curate package managers to block this repo. The package is already available in the following NPM Chinese mirrors, both which were blocked at some point:

There is actually a cnpm tool to install from Chinese mirrors: https://github.com/cnpm/cnpm.

We also managed to upload a Python PyPi package at: https://pypi.org/project/china-dictatorship/ Is as:

python3 -m pip install --user --upgrade china-dictatorship
china-dictatorship.py > README.html

This package was deleted by pypi in 2023 without any warning or notification:

and re-attempting upload fails with:

ERROR    HTTPError: 400 Bad Request from https://upload.pypi.org/legacy/
         The name 'china-dictatorship' isn't allowed. See https://pypi.org/help/#project-name for more information.

Bastanrds and Cowards.

Like NPM, this will also have Chinese mirrors that will need to be censored by their admins ovrview https://titanwolf.org/Network/Articles/Article?AID=25a20c20-c97b-4bfe-af67-760861343658 :

We later found on Google by chance that libraries.io picked it up and rendered the README.adoc nicely as well: https://libraries.io/pypi/china-dictatorship (archive). This is why packaging is a good idea.

A programmatic interface is also exposed on those packages, making it easy to quickly add a --china option to your project, e.g. from Python:

import china_dictatorship
assert "Tiananmen Square protests" in china_dictatorship.get_data()

print(china_dictatorship.get_data())

or from Node.js:

const china_dictatorship = require('china-dictatorship');
if (!china_dictatorship.get_data().includes("Tiannmen Square protests")) throw 0;

console.log(china_dictatorship.get_data());

You have to do the assert after the imports because otherwise Chinese mirrors could replace the real package with dummy packages to not break imports, as was already done once at https://registry.npm.taobao.org/china-dictatorship.

This outputs the rendered HTML, which end users should the pipe into a file:

./your-program --china > README.html
xdg-open README.html

Concrete examples:

These also offer great plausible deniability: a citizen in China could always argue that they were just interested in the software itself, and had no choice but to download it.

TODO: create an Ubuntu PPA and Ruby gem as well.

Create tags,and update all mirrors in one go with: push-mirrors:

sudo apt install python3-setuptools
python3 -m pip install --user setuptools wheel twine
./push-mirrors

In particular, that script calls push:

./push

which is more lightweight and pushes just to GitHub and GitLab Pages, so we are going to be using that more often to avoid overloading package managers too much.

./push is used to publish every commit.

There is no need to update package versions or add git tags, all of that gets done automatically by the script!

See also: Protestware.