Compare commits
No commits in common. "7e2487f0d354f2b2321a8d353db377122e16f4fc" and "1dfdac516b1489752e18da162e8aea86241b252e" have entirely different histories.
7e2487f0d3
...
1dfdac516b
@ -44,8 +44,6 @@ They should not assume the reader knows much beyond common terminal commands, an
|
|||||||
People should be able to read an article from the beginning, then keep going until the end, and then stop.
|
People should be able to read an article from the beginning, then keep going until the end, and then stop.
|
||||||
Articles should not take a detour through a chain of other articles of unknown size.
|
Articles should not take a detour through a chain of other articles of unknown size.
|
||||||
|
|
||||||
[Do not Jaquays documentation](https://splint.rs/posts/no_links)
|
|
||||||
|
|
||||||
## Be Opinionated
|
## Be Opinionated
|
||||||
|
|
||||||
- Guides should not ask the reader to select options half-way through.
|
- Guides should not ask the reader to select options half-way through.
|
||||||
|
@ -6,40 +6,36 @@ tags: [ "data" ]
|
|||||||
|
|
||||||
## New Machines
|
## New Machines
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git config --global user.email "$YOUR_EMAIL"
|
git config --global user.email "$YOUR_EMAIL"
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git config --global user.name "$YOUR_NAME"
|
git config --global user.name "$YOUR_NAME"
|
||||||
```
|
```
|
||||||
|
|
||||||
# New Git
|
# New Git
|
||||||
|
|
||||||
Decide on algorithm:
|
Start a git in directory `$DIR`:
|
||||||
|
|
||||||
- If you're scared of insecure hash-sums, go with `hash=sha256`.
|
```bash
|
||||||
- If you don't know what a hash sum is, go with `hash=sha1`.
|
mkdir $DIR && cd $DIR
|
||||||
|
```
|
||||||
|
|
||||||
## Init the Git
|
```bash
|
||||||
|
git init
|
||||||
Start a git in directory `${DIR}`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
git init --object-format=${hash} ${DIR}
|
|
||||||
cd ${DIR}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Make a file explaining what the project does, and tell `git` to track it:
|
Make a file explaining what the project does, and tell `git` to track it:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
echo "I hereby solemnly swear never to commit a binary file." > README.md
|
echo "I hereby solemnly swear never to commit a binary." > README.md
|
||||||
git add README.md
|
git add README.md
|
||||||
```
|
```
|
||||||
|
|
||||||
Then make the initial commit, explaining the change you just made:
|
Then make the initial commit, explaining the change you just made:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git commit
|
git commit
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -47,17 +43,17 @@ git commit
|
|||||||
|
|
||||||
Once you make a change to some file, add it and make a commit explaining it.
|
Once you make a change to some file, add it and make a commit explaining it.
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git add $FILE
|
git add $FILE
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git commit -m"change $FILE"
|
git commit -m"change $FILE"
|
||||||
```
|
```
|
||||||
|
|
||||||
Check your history:
|
Check your history:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git log
|
git log
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -68,20 +64,20 @@ Give it the same name as the `$DIR` directory, above.
|
|||||||
|
|
||||||
Add this as a remote:
|
Add this as a remote:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
REMOTE=gitlab
|
REMOTE=gitlab
|
||||||
git remote add $REMOTE https://gitlab.com/$USERNAME/$DIR
|
git remote add $REMOTE https://gitlab.com/$USERNAME/$DIR
|
||||||
```
|
```
|
||||||
|
|
||||||
Tell git you're pushing the branch "master" to the remote repo "origin":
|
Tell git you're pushing the branch "master" to the remote repo "origin":
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git push -u master origin
|
git push -u master origin
|
||||||
```
|
```
|
||||||
|
|
||||||
If someone makes a change on the remote, pull it down with:
|
If someone makes a change on the remote, pull it down with:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git pull
|
git pull
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -90,31 +86,31 @@ git pull
|
|||||||
A branch is a full copy of the project to test additional ideas.
|
A branch is a full copy of the project to test additional ideas.
|
||||||
You can make a new branch called 'featurez' like this:
|
You can make a new branch called 'featurez' like this:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git branch $FEATURE_BRANCH
|
git branch $FEATURE_BRANCH
|
||||||
```
|
```
|
||||||
|
|
||||||
Have a look at all your branches:
|
Have a look at all your branches:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git branch
|
git branch
|
||||||
```
|
```
|
||||||
|
|
||||||
Switch to your new branch:
|
Switch to your new branch:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git checkout $FEATURE_BRANCH
|
git checkout $FEATURE_BRANCH
|
||||||
```
|
```
|
||||||
|
|
||||||
And if your changes are rubbish, checkout the "master" branch again, then delete "featurez":
|
And if your changes are rubbish, checkout the "master" branch again, then delete "featurez":
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git branch -D $FEATURE_BRANCH
|
git branch -D $FEATURE_BRANCH
|
||||||
```
|
```
|
||||||
|
|
||||||
Or if it's a good branch, push it to the remote:
|
Or if it's a good branch, push it to the remote:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
remote=origin
|
remote=origin
|
||||||
git push $remote $FEATURE_BRANCH
|
git push $remote $FEATURE_BRANCH
|
||||||
```
|
```
|
||||||
@ -123,13 +119,13 @@ git push $remote $FEATURE_BRANCH
|
|||||||
|
|
||||||
Once you like the feature, merge it into the main branch. Switch to master then merge it:
|
Once you like the feature, merge it into the main branch. Switch to master then merge it:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git merge $FEATURE_BRANCH
|
git merge $FEATURE_BRANCH
|
||||||
```
|
```
|
||||||
|
|
||||||
And delete the branch, as you've already merged it:
|
And delete the branch, as you've already merged it:
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git branch -d $FEATURE_BRANCH
|
git branch -d $FEATURE_BRANCH
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -137,7 +133,7 @@ git branch -d $FEATURE_BRANCH
|
|||||||
|
|
||||||
## Pulling another git repo into a subtree
|
## Pulling another git repo into a subtree
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git subtree add -P config git@gitlab.com:bindrpg/config.git master
|
git subtree add -P config git@gitlab.com:bindrpg/config.git master
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -145,27 +141,27 @@ git subtree add -P config git@gitlab.com:bindrpg/config.git master
|
|||||||
|
|
||||||
## Delete All History
|
## Delete All History
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git checkout --orphan temp
|
git checkout --orphan temp
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git add -A
|
git add -A
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git commit -am "release the commits!"
|
git commit -am "release the commits!"
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git branch -D master
|
git branch -D master
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git branch -m master
|
git branch -m master
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git push -f origin master
|
git push -f origin master
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -173,21 +169,21 @@ Gitlab requires more changes, such as going to `settings > repository` and switc
|
|||||||
|
|
||||||
## Clean up Bloated Repo
|
## Clean up Bloated Repo
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git fsck --full
|
git fsck --full
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git gc --prune=now --aggressive
|
git gc --prune=now --aggressive
|
||||||
```
|
```
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git repack
|
git repack
|
||||||
```
|
```
|
||||||
|
|
||||||
## Find Binary Blobs
|
## Find Binary Blobs
|
||||||
|
|
||||||
```sh
|
```bash
|
||||||
git rev-list --objects --all \
|
git rev-list --objects --all \
|
||||||
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
|
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
|
||||||
| sed -n 's/^blob //p' \
|
| sed -n 's/^blob //p' \
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Interactive String Substitution"
|
|
||||||
tags: [ "data", "vim", "substitution" ]
|
|
||||||
---
|
|
||||||
|
|
||||||
Want to find and replace, but also confirm each instance?
|
|
||||||
|
|
||||||
```sh
|
|
||||||
vim -c "%s/${pattern}/${replacement}/gc" -c 'wq' ${file}
|
|
||||||
```
|
|
||||||
|
|
||||||
Notice that double-quotes (`"`) in the first command (`-c`).
|
|
||||||
|
|
||||||
Alternatively, check with an example string:
|
|
||||||
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sed "s/${pattern}/ARGLEBARGLE/g" ${file} | grep 'ARGLEBARGLE'
|
|
||||||
```
|
|
@ -1,34 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Taskwarrior Contexts"
|
|
||||||
tags: [ "data", "task" ]
|
|
||||||
requires: [ "Taskwarrior" ]
|
|
||||||
---
|
|
||||||
|
|
||||||
# Contexts
|
|
||||||
|
|
||||||
Set three contexts by their tags:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context define work +sa or +hr
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context define study +ed or +void or +rat
|
|
||||||
```
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context define home -sa -hr -ed -void -rat
|
|
||||||
```
|
|
||||||
|
|
||||||
Change to the first context.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context work
|
|
||||||
```
|
|
||||||
|
|
||||||
Then stop.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task context none
|
|
||||||
```
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Taskwarrior Configuration"
|
|
||||||
tags: [ "data", "task" ]
|
|
||||||
requires: [ "Taskwarrior" ]
|
|
||||||
---
|
|
||||||
|
|
||||||
Show your current config:
|
|
||||||
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task show
|
|
||||||
```
|
|
||||||
|
|
||||||
Use machine-readable output to make a config file with all configuration keys shown, then make it your configuration file.
|
|
||||||
|
|
||||||
```sh
|
|
||||||
task _show > ${file}
|
|
||||||
mv ${file} ~/.config/task/taskrc
|
|
||||||
```
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: "Taskwarrior"
|
title: "task"
|
||||||
tags: [ "data", "organization" ]
|
tags: [ "organization" ]
|
||||||
---
|
---
|
||||||
|
|
||||||
Set up the configuration file:
|
Set up the configuration file:
|
||||||
@ -9,18 +9,6 @@ Set up the configuration file:
|
|||||||
task
|
task
|
||||||
```
|
```
|
||||||
|
|
||||||
Taskwarrior published a new feature to synchronize tasks others, but the feature was not ready.
|
|
||||||
The server's default installation instructions assume that users pay for hosting services.
|
|
||||||
All listed providers run proprietary software and actively support genocide.
|
|
||||||
|
|
||||||
|
|
||||||
To ignore the synchronization, tell the configuration file to use a local synchronization file.
|
|
||||||
|
|
||||||
```
|
|
||||||
task config sync.local.server_dir
|
|
||||||
task config data.location ~/.local/state/
|
|
||||||
```
|
|
||||||
|
|
||||||
Add a task:
|
Add a task:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
@ -56,16 +44,18 @@ task add project:house buy potted plant
|
|||||||
task add proj:house.repair buy screwdriver
|
task add proj:house.repair buy screwdriver
|
||||||
task add proj:house.repair buy shelf brackets
|
task add proj:house.repair buy shelf brackets
|
||||||
task add pro:house.paint buy white paint
|
task add pro:house.paint buy white paint
|
||||||
|
task add pro:house.paint buy red paint
|
||||||
for t in "buy red paint" "buy black paint" "buy brushes" ; do
|
task add pro:house.paint buy black paint
|
||||||
task add pro:house.paint $t
|
task add pro:house.paint buy brushes
|
||||||
done
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task pro:house sum
|
task pro:house sum
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
task burndown.daily pro:house
|
task burndown.daily pro:house
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -73,12 +63,44 @@ The summaries will show how fast a project is being completed, and when you can
|
|||||||
|
|
||||||
# Tags
|
# Tags
|
||||||
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task add +buy toothbrush
|
task add +buy toothbrush
|
||||||
|
```
|
||||||
|
|
||||||
|
You can then see only tasks which involve buying something with:
|
||||||
|
|
||||||
|
```sh
|
||||||
task +buy
|
task +buy
|
||||||
```
|
```
|
||||||
|
|
||||||
|
# Contexts
|
||||||
|
|
||||||
|
Set three contexts by their tags:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context define work +sa or +hr
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context define study +ed or +void or +rat
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context define home -sa -hr -ed -void -rat
|
||||||
|
```
|
||||||
|
|
||||||
|
Change to the first context.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context work
|
||||||
|
```
|
||||||
|
|
||||||
|
Then stop.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
task context none
|
||||||
|
```
|
||||||
|
|
||||||
# Review
|
# Review
|
||||||
|
|
||||||
View list of tasks completed in the last week:
|
View list of tasks completed in the last week:
|
||||||
@ -89,17 +111,21 @@ task end.after:today-1wk completed
|
|||||||
|
|
||||||
# User Defined Attributes
|
# User Defined Attributes
|
||||||
|
|
||||||
Define a new attribute for tasks called 'size'.
|
Make a UDA 'size'.
|
||||||
The 'user defined attribute' (UDA) needs a `type` and `label`.
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task config uda.size.type string
|
task config uda.size.type string
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
task config uda.size.label Size
|
task config uda.size.label Size
|
||||||
```
|
```
|
||||||
You can also ensure task tasks can only be `large`, `medium`, or `small`, then set a default.
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
task config uda.size.values large,medium,small
|
task config uda.size.values large,medium,small
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
uda.size.default=medium
|
uda.size.default=medium
|
||||||
```
|
```
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Port Scan"
|
|
||||||
tags: [ "networking" ]
|
|
||||||
repo: 'https://github.com/mrjackwills/havn/'
|
|
||||||
---
|
|
||||||
|
|
||||||
`havn` scans ports.
|
|
||||||
It's not in many repos, but if you can `cargo install havn`.
|
|
||||||
|
|
||||||
|
|
||||||
```sh
|
|
||||||
havn -h
|
|
||||||
havn -a
|
|
||||||
domain=splint.rs
|
|
||||||
havn -p 19-90 ${domain}
|
|
||||||
```
|
|
||||||
|
|
||||||
That last command doesn't work reliably, so increase the number of retries (`-r`), or decrease concurrent requests (`-c`).
|
|
||||||
|
|
||||||
|
|
||||||
```sh
|
|
||||||
havn -p 19-443 -r 6 ${domain}
|
|
||||||
havn -p 1-1000 -c 500 -r 5 ${domain}
|
|
||||||
```
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
title: "Makefile Patterns"
|
title: "Makefile Patterns"
|
||||||
tags: [ "system", "make" ]
|
tags: [ "system", "make" ]
|
||||||
|
@ -1,98 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Python Projects with Makefiles"
|
|
||||||
tags: [ "tutorial", "system", "makefiles", "graphviz", "python" ]
|
|
||||||
requires: [ "Makefiles" ]
|
|
||||||
---
|
|
||||||
|
|
||||||
If you have a python script which requires a packages - e.g. `graphviz` - you can automate the setup with a `Makefile`.
|
|
||||||
The `Makefile` will:
|
|
||||||
|
|
||||||
1. Make three copies of an 8-line installer script.
|
|
||||||
2. Use one of the installer script to install local packages.
|
|
||||||
3. Install a symbolic link to python.
|
|
||||||
3. Make a script called `activate`, which tells python to use
|
|
||||||
|
|
||||||
# Context
|
|
||||||
|
|
||||||
Python coders don't like updating their projects, they just expect everyone to install the same version of everything that they have.
|
|
||||||
Historically, people dealt with this by installing only half a dozen copies of `graphviz`; but now each python project uses a local environment, with a local copy of `graphviz`, which means everyone gets to install a new copy of `graphviz` every time they try out a project.
|
|
||||||
|
|
||||||
Downloading 40MB of software for each 40-line script you write is called 'virtual environments' because it sounds cool.
|
|
||||||
We can make it even cooler with `make`, but not yet, because python - like the fae of old - will not fetch anything until you know its true name.
|
|
||||||
|
|
||||||
# Setup
|
|
||||||
|
|
||||||
```sh
|
|
||||||
command -v python
|
|
||||||
realpath `!!`
|
|
||||||
```
|
|
||||||
|
|
||||||
You must reveal that true path, because `python` is always a relative symbolic link, to an absolute symbolic link, which leads to a shortcut.
|
|
||||||
We can finally let `make` know how to invoke python, and where it will install `graphviz`.
|
|
||||||
|
|
||||||
If your python's version is '3.14', then python needs its packages placed in `${somewhere}/lib/python3.14/site-packages/`.
|
|
||||||
You must create a new, local, name for these packages, because - like the fey of old - python demands a private name in return for revealing its true name.
|
|
||||||
|
|
||||||
I'll call mine `camelot`, because the path is long and arduous.
|
|
||||||
Set up the Makefiles like this:
|
|
||||||
|
|
||||||
```make
|
|
||||||
py_link != command -v python
|
|
||||||
py != realpath $(py_link)
|
|
||||||
version != basename $(py)
|
|
||||||
|
|
||||||
virtenv = camelot
|
|
||||||
```
|
|
||||||
|
|
||||||
Now you can ask for a local `pip` script, which can install the python packages:
|
|
||||||
|
|
||||||
```make
|
|
||||||
[...]
|
|
||||||
|
|
||||||
$(virtenv)/bin/pip:
|
|
||||||
$(py) -m venv $(virtenv)
|
|
||||||
```
|
|
||||||
|
|
||||||
Finally, list the packages you want in `requirements.txt`, and make `pip` install from it.
|
|
||||||
|
|
||||||
|
|
||||||
```sh
|
|
||||||
ppkg=graphviz
|
|
||||||
echo ${ppkg} > requirements.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
```make
|
|
||||||
[...]
|
|
||||||
|
|
||||||
pkgs = $(virtenv)/lib/$(version)/site-packages/
|
|
||||||
|
|
||||||
$(pkgs): $(virtenv)/bin/pip
|
|
||||||
$(pkgs): requirements.txt
|
|
||||||
$(virtenv)/bin/pip install -r $<
|
|
||||||
```
|
|
||||||
|
|
||||||
The complete Makefile looks like this:
|
|
||||||
|
|
||||||
|
|
||||||
```make
|
|
||||||
all: .default
|
|
||||||
|
|
||||||
py_link != command -v python
|
|
||||||
py != realpath $(py_link)
|
|
||||||
version != basename $(py)
|
|
||||||
|
|
||||||
virtenv = camelot
|
|
||||||
|
|
||||||
$(virtenv)/bin/pip:
|
|
||||||
$(py) -m venv $(virtenv)
|
|
||||||
|
|
||||||
pkgs = $(virtenv)/lib/$(version)/site-packages/
|
|
||||||
|
|
||||||
$(pkgs): $(virtenv)/bin/pip
|
|
||||||
$(pkgs): requirements.txt
|
|
||||||
$(virtenv)/bin/pip install -r $<
|
|
||||||
|
|
||||||
.PHONY: .default
|
|
||||||
.default: $(pkgs)
|
|
||||||
```
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
title: "LaTeX Packages"
|
title: "LaTeX Setup the Hard Way"
|
||||||
tags: [ "writing" ]
|
tags: [ "writing" ]
|
||||||
---
|
---
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ ls /opt/texlive/${YEAR}/texmf-dist/scripts/texlive/tlmgr.pl
|
|||||||
```
|
```
|
||||||
|
|
||||||
Double-check the year.
|
Double-check the year.
|
||||||
It should *not* match the current year, it should match the `texlive`.
|
It should *not* match the real year, it should match the `texlive`.
|
||||||
|
|
||||||
## Problems along the Path
|
## Problems along the Path
|
||||||
|
|
@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Calendar"
|
|
||||||
tags: [ "writing", "tex", "fun" ]
|
|
||||||
requires: [ "LaTeX Packages" ]
|
|
||||||
---
|
|
||||||
|
|
||||||
```sh
|
|
||||||
yplan $(date +%Y) > ${file}.tex
|
|
||||||
pdflatex -output-directory=/tmp/ ${file}.tex
|
|
||||||
mv /tmp/${file}.pdf .
|
|
||||||
```
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user