From 83693a5c039ca0077e5a145ec9d9bdebf9c7367e Mon Sep 17 00:00:00 2001 From: Nick Sweeting Date: Mon, 23 Nov 2020 16:52:15 -0500 Subject: [PATCH] add packaging setup with stdeb for debian and apt vendor the base32_crockford lib add build script for debain packages --- .gitignore | 14 ++- archivebox.egg-info/PKG-INFO | 32 +++--- archivebox.egg-info/SOURCES.txt | 1 + archivebox/base32_crockford.py | 172 ++++++++++++++++++++++++++++++++ archivebox/util.py | 2 +- assets/css/style.scss | 2 + bin/build.sh | 1 + bin/build_deb.sh | 42 ++++++++ bin/release.sh | 6 +- icon.png | Bin 0 -> 10717 bytes package.json | 2 +- setup.py | 2 +- stdeb.cfg | 6 ++ 13 files changed, 263 insertions(+), 19 deletions(-) create mode 100644 archivebox/base32_crockford.py create mode 100755 bin/build_deb.sh create mode 100644 icon.png create mode 100644 stdeb.cfg diff --git a/.gitignore b/.gitignore index 884e1da4..68717afb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,13 +4,21 @@ __pycache__/ .mypy_cache/ +# Python and Node dependencies venv/ .venv/ .docker-venv/ - -build/ -dist/ node_modules/ +# Packaging artifacts +archivebox-*.tar.gz +build/ +deb_dist/ +dist/ + +# Data folders data/ +data1/ +data2/ +data3/ output/ diff --git a/archivebox.egg-info/PKG-INFO b/archivebox.egg-info/PKG-INFO index eb80f48d..3940b731 100644 --- a/archivebox.egg-info/PKG-INFO +++ b/archivebox.egg-info/PKG-INFO @@ -14,7 +14,7 @@ Project-URL: Roadmap, https://github.com/ArchiveBox/ArchiveBox/wiki/Roadmap Project-URL: Community, https://github.com/ArchiveBox/ArchiveBox/wiki/Web-Archiving-Community Project-URL: Donate, https://github.com/ArchiveBox/ArchiveBox/wiki/Donations Description:
- +

ArchiveBox
The open-source self-hosted web archive.

▶️ Quickstart | @@ -41,7 +41,7 @@ Description:

- ArchiveBox is a powerful self-hosted internet archiving solution written in Python 3. You feed it URLs of pages you want to archive, and it saves them to disk in a varitety of formats depending on the configuration and the content it detects. ArchiveBox can be installed via [Docker](https://docs.docker.com/get-docker/) or [`pip3`](https://wiki.python.org/moin/BeginnersGuide/Download). + ArchiveBox is a powerful self-hosted internet archiving solution written in Python 3. You feed it URLs of pages you want to archive, and it saves them to disk in a varitety of formats depending on the configuration and the content it detects. ArchiveBox can be installed via [Docker](https://docs.docker.com/get-docker/) (recommended) or [`pip`](https://www.python.org/downloads/). It works on macOS, Windows, and Linux/BSD (both armv7 and amd64). Once installed, URLs can be added via the command line `archivebox add` or the built-in Web UI `archivebox server`. It can ingest bookmarks from a service like Pocket/Pinboard, your entire browsing history, RSS feeds, or URLs one at a time. @@ -51,19 +51,27 @@ Description:
#### Quickstart ```bash - docker run -d -it -v ~/archivebox:/data -p 8000:8000 archivebox/archivebox server --init 0.0.0.0:8000 - docker run -v ~/archivebox:/data -it archivebox/archivebox manage createsuperuser - docker run -v ~/archivebox:/data -it archivebox/archivebox add 'https://example.com' + # 1. Create a folder somewhere to hold your ArchiveBox data + mkdir ~/archivebox && cd ~/archivebox + docker run -v $PWD:/data -it archivebox/archivebox init - open http://127.0.0.1:8000/admin/login/ # then click "Add" in the navbar + # 2. Archive some URLs to get started + docker run -v $PWD:/data -t archivebox/archivebox add https://github.com/ArchiveBox/ArchiveBox + docker run -v $PWD:/data -t archivebox/archivebox add --depth=1 https://example.com + + # 3. Then view the snapshots of the URLs you added via the self-hosted web UI + docker run -v $PWD:/data -it archivebox/archivebox manage createsuperuser # create an admin acct + docker run -v $PWD:/data -p 8000:8000 archivebox/archivebox # start the web server + open http://127.0.0.1:8000/ # open the interactive admin panel + ls archive/*/index.html # or just browse snapshots on disk ```

- [DEMO: archivebox.zervice.io/](https://archivebox.zervice.io) - For more information, see the [full Quickstart guide](https://github.com/ArchiveBox/ArchiveBox/wiki/Quickstart), [Usage](https://github.com/ArchiveBox/ArchiveBox/wiki/Usage), and [Configuration](https://github.com/ArchiveBox/ArchiveBox/wiki/Configuration) docs. + DEMO: archivebox.zervice.io/ + For more information, see the full Quickstart guide, Usage, and Configuration docs.
--- @@ -82,7 +90,7 @@ Description:
open http://127.0.0.1:8000 ``` - The CLI is considered "stable", and the ArchiveBox Python API and REST APIs are in "beta". + The CLI is considered "stable", the ArchiveBox Python API and REST APIs are in "beta", and the [desktop app](https://github.com/ArchiveBox/desktop) is in "alpha" stage. At the end of the day, the goal is to sleep soundly knowing that the part of the internet you care about will be automatically preserved in multiple, durable long-term formats that will be accessible for decades (or longer). You can also self-host your archivebox server on a public domain to provide archive.org-style public access to your site snapshots. @@ -331,7 +339,7 @@ Description:
▶ **Check out our [community page](https://github.com/ArchiveBox/ArchiveBox/wiki/Web-Archiving-Community) for an index of web archiving initiatives and projects.** - The aim of ArchiveBox is to go beyond what the Wayback Machine and other public archiving services can do, by adding a headless browser to replay sessions accurately, and by automatically extracting all the content in multiple redundant formats that will survive being passed down to historians and archivists through many generations. + comparison The aim of ArchiveBox is to go beyond what the Wayback Machine and other public archiving services can do, by adding a headless browser to replay sessions accurately, and by automatically extracting all the content in multiple redundant formats that will survive being passed down to historians and archivists through many generations. #### User Interface & Intended Purpose @@ -362,7 +370,7 @@ Description:
_A collection of the most active internet archiving communities and initiatives._ - Check out the ArchiveBox [Roadmap](https://github.com/ArchiveBox/ArchiveBox/wiki/Roadmap) and [Changelog](https://github.com/ArchiveBox/ArchiveBox/wiki/Changelog) - Learn why archiving the internet is important by reading the "[On the Importance of Web Archiving](https://parameters.ssrc.org/2018/09/on-the-importance-of-web-archiving/)" blog post. - - Or reach out to me for questions and comments via [@theSquashSH](https://twitter.com/thesquashSH) on Twitter. + - Or reach out to me for questions and comments via [@ArchiveBoxApp](https://twitter.com/ArchiveBoxApp) or [@theSquashSH](https://twitter.com/thesquashSH) on Twitter. --- @@ -494,7 +502,7 @@ Description:

- +

diff --git a/archivebox.egg-info/SOURCES.txt b/archivebox.egg-info/SOURCES.txt index eee55cc5..8f0d5d48 100644 --- a/archivebox.egg-info/SOURCES.txt +++ b/archivebox.egg-info/SOURCES.txt @@ -6,6 +6,7 @@ archivebox/LICENSE archivebox/README.md archivebox/__init__.py archivebox/__main__.py +archivebox/base32_crockford.py archivebox/config.py archivebox/config_stubs.py archivebox/logging_util.py diff --git a/archivebox/base32_crockford.py b/archivebox/base32_crockford.py new file mode 100644 index 00000000..bafb69b4 --- /dev/null +++ b/archivebox/base32_crockford.py @@ -0,0 +1,172 @@ +""" +base32-crockford +================ + +A Python module implementing the alternate base32 encoding as described +by Douglas Crockford at: http://www.crockford.com/wrmg/base32.html. + +He designed the encoding to: + + * Be human and machine readable + * Be compact + * Be error resistant + * Be pronounceable + +It uses a symbol set of 10 digits and 22 letters, excluding I, L O and +U. Decoding is not case sensitive, and 'i' and 'l' are converted to '1' +and 'o' is converted to '0'. Encoding uses only upper-case characters. + +Hyphens may be present in symbol strings to improve readability, and +are removed when decoding. + +A check symbol can be appended to a symbol string to detect errors +within the string. + +""" + +import re +import sys + +PY3 = sys.version_info[0] == 3 + +if not PY3: + import string as str + + +__all__ = ["encode", "decode", "normalize"] + + +if PY3: + string_types = str, +else: + string_types = basestring, + +# The encoded symbol space does not include I, L, O or U +symbols = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' +# These five symbols are exclusively for checksum values +check_symbols = '*~$=U' + +encode_symbols = dict((i, ch) for (i, ch) in enumerate(symbols + check_symbols)) +decode_symbols = dict((ch, i) for (i, ch) in enumerate(symbols + check_symbols)) +normalize_symbols = str.maketrans('IiLlOo', '111100') +valid_symbols = re.compile('^[%s]+[%s]?$' % (symbols, + re.escape(check_symbols))) + +base = len(symbols) +check_base = len(symbols + check_symbols) + + +def encode(number, checksum=False, split=0): + """Encode an integer into a symbol string. + + A ValueError is raised on invalid input. + + If checksum is set to True, a check symbol will be + calculated and appended to the string. + + If split is specified, the string will be divided into + clusters of that size separated by hyphens. + + The encoded string is returned. + """ + number = int(number) + if number < 0: + raise ValueError("number '%d' is not a positive integer" % number) + + split = int(split) + if split < 0: + raise ValueError("split '%d' is not a positive integer" % split) + + check_symbol = '' + if checksum: + check_symbol = encode_symbols[number % check_base] + + if number == 0: + return '0' + check_symbol + + symbol_string = '' + while number > 0: + remainder = number % base + number //= base + symbol_string = encode_symbols[remainder] + symbol_string + symbol_string = symbol_string + check_symbol + + if split: + chunks = [] + for pos in range(0, len(symbol_string), split): + chunks.append(symbol_string[pos:pos + split]) + symbol_string = '-'.join(chunks) + + return symbol_string + + +def decode(symbol_string, checksum=False, strict=False): + """Decode an encoded symbol string. + + If checksum is set to True, the string is assumed to have a + trailing check symbol which will be validated. If the + checksum validation fails, a ValueError is raised. + + If strict is set to True, a ValueError is raised if the + normalization step requires changes to the string. + + The decoded string is returned. + """ + symbol_string = normalize(symbol_string, strict=strict) + if checksum: + symbol_string, check_symbol = symbol_string[:-1], symbol_string[-1] + + number = 0 + for symbol in symbol_string: + number = number * base + decode_symbols[symbol] + + if checksum: + check_value = decode_symbols[check_symbol] + modulo = number % check_base + if check_value != modulo: + raise ValueError("invalid check symbol '%s' for string '%s'" % + (check_symbol, symbol_string)) + + return number + + +def normalize(symbol_string, strict=False): + """Normalize an encoded symbol string. + + Normalization provides error correction and prepares the + string for decoding. These transformations are applied: + + 1. Hyphens are removed + 2. 'I', 'i', 'L' or 'l' are converted to '1' + 3. 'O' or 'o' are converted to '0' + 4. All characters are converted to uppercase + + A TypeError is raised if an invalid string type is provided. + + A ValueError is raised if the normalized string contains + invalid characters. + + If the strict parameter is set to True, a ValueError is raised + if any of the above transformations are applied. + + The normalized string is returned. + """ + if isinstance(symbol_string, string_types): + if not PY3: + try: + symbol_string = symbol_string.encode('ascii') + except UnicodeEncodeError: + raise ValueError("string should only contain ASCII characters") + else: + raise TypeError("string is of invalid type %s" % + symbol_string.__class__.__name__) + + norm_string = symbol_string.replace('-', '').translate(normalize_symbols).upper() + + if not valid_symbols.match(norm_string): + raise ValueError("string '%s' contains invalid characters" % norm_string) + + if strict and norm_string != symbol_string: + raise ValueError("string '%s' requires normalization" % symbol_string) + + return norm_string diff --git a/archivebox/util.py b/archivebox/util.py index ae827899..4e55e30d 100644 --- a/archivebox/util.py +++ b/archivebox/util.py @@ -16,7 +16,7 @@ from dateparser import parse as dateparser import requests from requests.exceptions import RequestException, ReadTimeout -from base32_crockford import encode as base32_encode # type: ignore +from .base32_crockford import encode as base32_encode # type: ignore from w3lib.encoding import html_body_declared_encoding, http_content_type_encoding try: diff --git a/assets/css/style.scss b/assets/css/style.scss index a4bd9890..44657267 100644 --- a/assets/css/style.scss +++ b/assets/css/style.scss @@ -6,11 +6,13 @@ div.shell { width: 80%; max-width: 1300px; + min-width: 300px; } span.banner-fix { width: 80%; max-width: 1300px; + min-width: 300px; } header h1 { diff --git a/bin/build.sh b/bin/build.sh index 7b1c3232..693c2bbe 100755 --- a/bin/build.sh +++ b/bin/build.sh @@ -16,6 +16,7 @@ cd "$REPO_DIR" ./bin/build_docs.sh ./bin/build_pip.sh +./bin/build_deb.sh ./bin/build_docker.sh echo "[√] Done. Install the built package by running:" diff --git a/bin/build_deb.sh b/bin/build_deb.sh new file mode 100755 index 00000000..6f5e418c --- /dev/null +++ b/bin/build_deb.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash + +### Bash Environment Setup +# http://redsymbol.net/articles/unofficial-bash-strict-mode/ +# https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html +# set -o xtrace +set -o errexit +set -o errtrace +set -o nounset +set -o pipefail +IFS=$'\n' + +REPO_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && cd .. && pwd )" + +source "$REPO_DIR/.venv/bin/activate" +cd "$REPO_DIR" + +VERSION="$(jq -r '.version' < "$REPO_DIR/package.json")" +DEBIAN_VERSION="1" +PGP_KEY_ID="7D5695D3B618872647861D51C38137A7C1675988" +# make sure you have this in ~/.dput.cf: +# [archivebox-ppa] +# fqdn: ppa.launchpad.net +# method: ftp +# incoming: ~archivebox/ubuntu/archivebox/ +# login: anonymous +# allow_unsigned_uploads: 0 + + +# cleanup build artifacts +rm -Rf build deb_dist dist archivebox-*.tar.gz + +# build source and binary packages +python3 setup.py --command-packages=stdeb.command \ + sdist_dsc --debian-version=$DEBIAN_VERSION \ + bdist_deb + +# sign the build with your PGP key ID +debsign -k "$PGP_KEY_ID" "deb_dist/archivebox_${VERSION}-${DEBIAN_VERSION}_source.changes" + +# push the build to launchpad ppa +# dput archivebox "deb_dist/archivebox_${VERSION}-${DEBIAN_VERSION}_source.changes" diff --git a/bin/release.sh b/bin/release.sh index f01eb1d3..d9c9b52d 100755 --- a/bin/release.sh +++ b/bin/release.sh @@ -42,6 +42,7 @@ echo "${contents}" > package.json # Build docs, python package, and docker image ./bin/build_docs.sh ./bin/build_pip.sh +./bin/build_deb.sh ./bin/build_docker.sh @@ -64,11 +65,14 @@ python3 -m twine upload --repository testpypi dist/* echo "[^] Uploading to pypi.org" python3 -m twine upload --repository pypi dist/* +echo "[^] Uploading to launchpad.net" +python3 -m dput archivebox "deb_dist/archivebox_${NEW_VERSION}-1_source.changes" + echo "[^] Uploading docker image" # docker login --username=nikisweeting # docker login docker.pkg.github.com --username=pirate docker push docker.io/nikisweeting/archivebox docker push docker.io/archivebox/archivebox -docker push docker.pkg.github.com/pirate/archivebox/archivebox +docker push docker.pkg.github.com/archivebox/archivebox/archivebox echo "[√] Done. Published version v$NEW_VERSION" diff --git a/icon.png b/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..04462b21cc1c72de4fba6a6534103e0805c2879c GIT binary patch literal 10717 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", "license": "MIT", diff --git a/setup.py b/setup.py index af643c9e..6b40b803 100755 --- a/setup.py +++ b/setup.py @@ -51,7 +51,6 @@ setuptools.setup( "requests==2.24.0", "atomicwrites==1.4.0", "mypy-extensions==0.4.3", - "base32-crockford==0.3.0", "django==3.0.8", "django-extensions==3.0.3", @@ -80,6 +79,7 @@ setuptools.setup( "recommonmark", "pytest", "bottle", + "stdeb", ], # 'redis': ['redis', 'django-redis'], # 'pywb': ['pywb', 'redis'], diff --git a/stdeb.cfg b/stdeb.cfg new file mode 100644 index 00000000..6eaa8f2d --- /dev/null +++ b/stdeb.cfg @@ -0,0 +1,6 @@ +[DEFAULT] +Package: archivebox +Suite: focal +Build-Depends: dh-python +Depends: nodejs, chromium-browser, wget, curl, git, ffmpeg, youtube-dl, python3-atomicwrites, python3-croniter, python3-crontab, python3-dateparser, python3-django, python3-django-extensions, python3-mypy-extensions, python3-requests, python3-w3lib +XS-Python-Version: >= 3.7