diff options
Diffstat (limited to 'letsencrypt-auto')
-rwxr-xr-x | letsencrypt-auto | 210 |
1 files changed, 122 insertions, 88 deletions
diff --git a/letsencrypt-auto b/letsencrypt-auto index 9218bdc52..86367a5c0 100755 --- a/letsencrypt-auto +++ b/letsencrypt-auto @@ -18,25 +18,31 @@ set -e # Work even if somebody does "sh thisscript.sh". XDG_DATA_HOME=${XDG_DATA_HOME:-~/.local/share} VENV_NAME="letsencrypt" VENV_PATH=${VENV_PATH:-"$XDG_DATA_HOME/$VENV_NAME"} -VENV_BIN=${VENV_PATH}/bin -LE_AUTO_VERSION="0.4.0" +VENV_BIN="$VENV_PATH/bin" +LE_AUTO_VERSION="0.4.1" # This script takes the same arguments as the main letsencrypt program, but it # additionally responds to --verbose (more output) and --debug (allow support # for experimental platforms) for arg in "$@" ; do - # This first clause is redundant with the third, but hedging on portability - if [ "$arg" = "-v" ] || [ "$arg" = "--verbose" ] || echo "$arg" | grep -E -- "-v+$" ; then - VERBOSE=1 - elif [ "$arg" = "--no-self-upgrade" ] ; then - # Do not upgrade this script (also prevents client upgrades, because each - # copy of the script pins a hash of the python client) - NO_SELF_UPGRADE=1 - elif [ "$arg" = "--os-packages-only" ] ; then - OS_PACKAGES_ONLY=1 - elif [ "$arg" = "--debug" ]; then - DEBUG=1 - fi + case "$arg" in + --debug) + DEBUG=1;; + --os-packages-only) + OS_PACKAGES_ONLY=1;; + --no-self-upgrade) + # Do not upgrade this script (also prevents client upgrades, because each + # copy of the script pins a hash of the python client) + NO_SELF_UPGRADE=1;; + --verbose) + VERBOSE=1;; + [!-]*|-*[!v]*|-) + # Anything that isn't -v, -vv, etc.: that is, anything that does not + # start with a -, contains anything that's not a v, or is just "-" + ;; + *) # -v+ remains. + VERBOSE=1;; + esac done # letsencrypt-auto needs root access to bootstrap OS dependencies, and @@ -91,21 +97,18 @@ ExperimentalBootstrap() { } DeterminePythonVersion() { - if command -v python2.7 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python2.7} - elif command -v python27 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python27} - elif command -v python2 > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python2} - elif command -v python > /dev/null ; then - export LE_PYTHON=${LE_PYTHON:-python} - else - echo "Cannot find any Pythons... please install one!" + for LE_PYTHON in "$LE_PYTHON" python2.7 python27 python2 python; do + # Break (while keeping the LE_PYTHON value) if found. + command -v "$LE_PYTHON" > /dev/null && break + done + if [ "$?" != "0" ]; then + echo "Cannot find any Pythons; please install one!" exit 1 fi + export LE_PYTHON - PYVER=`"$LE_PYTHON" --version 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` - if [ $PYVER -lt 26 ]; then + PYVER=`"$LE_PYTHON" -V 2>&1 | cut -d" " -f 2 | cut -d. -f1,2 | sed 's/\.//'` + if [ "$PYVER" -lt 26 ]; then echo "You have an ancient version of Python entombed in your operating system..." echo "This isn't going to work; you'll need at least version 2.6." exit 1 @@ -165,7 +168,7 @@ BootstrapDebCommon() { /bin/echo '(Backports are only installed if explicitly requested via "apt-get install -t wheezy-backports")' fi - sudo sh -c "echo $BACKPORT_SOURCELINE >> /etc/apt/sources.list.d/$BACKPORT_NAME.list" + $SUDO sh -c "echo $BACKPORT_SOURCELINE >> /etc/apt/sources.list.d/$BACKPORT_NAME.list" $SUDO apt-get update fi fi @@ -304,10 +307,11 @@ BootstrapArchCommon() { pkg-config " - missing=$("$SUDO" pacman -T $deps) + # pacman -T exits with 127 if there are missing dependencies + missing=$($SUDO pacman -T $deps) || true if [ "$missing" ]; then - "$SUDO" pacman -S --needed $missing + $SUDO pacman -S --needed $missing fi } @@ -324,19 +328,19 @@ BootstrapGentooCommon() { case "$PACKAGE_MANAGER" in (paludis) - "$SUDO" cave resolve --keep-targets if-possible $PACKAGES -x + $SUDO cave resolve --preserve-world --keep-targets if-possible $PACKAGES -x ;; (pkgcore) - "$SUDO" pmerge --noreplace $PACKAGES + $SUDO pmerge --noreplace --oneshot $PACKAGES ;; (portage|*) - "$SUDO" emerge --noreplace $PACKAGES + $SUDO emerge --noreplace --oneshot $PACKAGES ;; esac } BootstrapFreeBsd() { - "$SUDO" pkg install -Ay \ + $SUDO pkg install -Ay \ python \ py27-virtualenv \ augeas \ @@ -345,20 +349,27 @@ BootstrapFreeBsd() { BootstrapMac() { if ! hash brew 2>/dev/null; then - echo "Homebrew Not Installed\nDownloading..." + echo "Homebrew not installed.\nDownloading..." ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" fi - brew install augeas - brew install dialog + if [ -z "$(brew list --versions augeas)" ]; then + echo "augeas not installed.\nInstalling augeas from Homebrew..." + brew install augeas + fi - if ! hash pip 2>/dev/null; then - echo "pip Not Installed\nInstalling python from Homebrew..." + if [ -z "$(brew list --versions dialog)" ]; then + echo "dialog not installed.\nInstalling dialog from Homebrew..." + brew install dialog + fi + + if [ -z "$(brew list --versions python)" ]; then + echo "python not installed.\nInstalling python from Homebrew..." brew install python fi if ! hash virtualenv 2>/dev/null; then - echo "virtualenv Not Installed\nInstalling with pip" + echo "virtualenv not installed.\nInstalling with pip..." pip install virtualenv fi } @@ -412,9 +423,10 @@ TempDir() { -if [ "$NO_SELF_UPGRADE" = 1 ]; then +if [ "$1" = "--le-auto-phase2" ]; then # Phase 2: Create venv, install LE, and run. + shift 1 # the --le-auto-phase2 arg if [ -f "$VENV_BIN/letsencrypt" ]; then INSTALLED_VERSION=$("$VENV_BIN/letsencrypt" --version 2>&1 | cut -d " " -f 2) else @@ -609,10 +621,6 @@ traceback2==1.4.0 # sha256: IogqDkGMKE4fcYqCKzsCKUTVPS2QjhaQsxmp0-ssBXk unittest2==1.1.0 -# sha256: aUkbUwUVfDxuDwSnAZhNaud_1yn8HJrNJQd_HfOFMms -# sha256: 619wCpv8lkILBVY1r5AC02YuQ9gMP_0x8iTCW8DV9GI -Werkzeug==0.11.3 - # sha256: KCwRK1XdjjyGmjVx-GdnwVCrEoSprOK97CJsWSrK-Bo zope.component==4.2.2 @@ -638,22 +646,25 @@ zope.event==4.1.0 # sha256: sJyMHUezUxxADgGVaX8UFKYyId5u9HhZik8UYPfZo5I zope.interface==4.1.3 -# sha256: ilvjjTWOS86xchl0WBZ0YOAw_0rmqdnjNsxb1hq2RD8 -# sha256: T37KMj0TnsuvHIzCCmoww2fpfpOBTj7cd4NAqucXcpw -acme==0.4.0 - -# sha256: 33BQiANlNLGqGpirTfdCEElTF9YbpaKiYpTbK4zeGD8 -# sha256: lwsV1OdEzzlMeb08C_PRxaCXZ2vOk_1AI2755rZHmPM -letsencrypt==0.4.0 - -# sha256: D3YDaVFjLsMSEfjI5B5D5tn5FeWUtNHYXCObw3ih2tg -# sha256: VTgvsePYGRmI4IOSAnxoYFHd8KciD73bxIuIHtbVFd8 -letsencrypt-apache==0.4.0 - # sha256: uDndLZwRfHAUMMFJlWkYpCOphjtIsJyQ4wpgE-fS9E8 # sha256: j4MIDaoknQNsvM-4rlzG_wB7iNbZN1ITca-r57Gbrbw mock==1.0.1 +# THE LINES BELOW ARE EDITED BY THE RELEASE SCRIPT; +# ADD ALL DEPENDENCIES ABOVE + +# sha256: zd_qpRKPaFs00y5hex5Rbu5CVLWzed7pBGL28juxoHM +# sha256: 18Gfo85AbZXE46GyTkyePthTNiUeoGTQNcXlSvmRQvM +acme==0.4.1 + +# sha256: wIuGh8yh1TeOClXW0qLz70bKeM9Ax4bfFNrkKSDjbbo +# sha256: 7TeAUt8cZ0IZQuQNuUm8MoH8vPWlKaCrwWAkdCEs_5s +letsencrypt==0.4.1 + +# sha256: bnpKXJTXy9cFSktJLtvTCTovJJybc__Ivqs6XaXxk9U +# sha256: bcvJ6j5UB8sOJ_M88DAsqvmaLxD2UnAP9ys-_J6Bdcc +letsencrypt-apache==0.4.1 + UNLIKELY_EOF # ------------------------------------------------------------------------- cat << "UNLIKELY_EOF" > "$TEMP_DIR/peep.py" @@ -745,6 +756,7 @@ except ImportError: from pip.util import url_to_path # 0.7.0 except ImportError: from pip.util import url_to_filename as url_to_path # 0.6.2 +from pip.exceptions import InstallationError from pip.index import PackageFinder, Link try: from pip.log import logger @@ -763,7 +775,7 @@ except ImportError: DownloadProgressBar = DownloadProgressSpinner = NullProgressBar -__version__ = 3, 0, 0 +__version__ = 3, 1, 1 try: from pip.index import FormatControl # noqa @@ -781,6 +793,7 @@ ITS_FINE_ITS_FINE = 0 SOMETHING_WENT_WRONG = 1 # "Traditional" for command-line errors according to optparse docs: COMMAND_LINE_ERROR = 2 +UNHANDLED_EXCEPTION = 3 ARCHIVE_EXTENSIONS = ('.tar.bz2', '.tar.gz', '.tgz', '.tar', '.zip') @@ -1543,7 +1556,7 @@ def peep_install(argv): first_every_last(buckets[SatisfiedReq], *printers) return ITS_FINE_ITS_FINE - except (UnsupportedRequirementError, DownloadError) as exc: + except (UnsupportedRequirementError, InstallationError, DownloadError) as exc: out(str(exc)) return SOMETHING_WENT_WRONG finally: @@ -1563,16 +1576,23 @@ def peep_port(paths): print('Please specify one or more requirements files so I have ' 'something to port.\n') return COMMAND_LINE_ERROR + + comes_from = None for req in chain.from_iterable( _parse_requirements(path, package_finder(argv)) for path in paths): + req_path, req_line = path_and_line(req) hashes = [hexlify(urlsafe_b64decode((hash + '=').encode('ascii'))).decode('ascii') - for hash in hashes_above(*path_and_line(req))] + for hash in hashes_above(req_path, req_line)] + if req_path != comes_from: + print() + print('# from %s' % req_path) + print() + comes_from = req_path + if not hashes: print(req.req) - elif len(hashes) == 1: - print('%s --hash=sha256:%s' % (req.req, hashes[0])) else: - print('%s' % req.req, end='') + print('%s' % (req.link if getattr(req, 'link', None) else req.req), end='') for hash in hashes: print(' \\') print(' --hash=sha256:%s' % hash, end='') @@ -1617,7 +1637,7 @@ if __name__ == '__main__': exit(main()) except Exception: exception_handler(*sys.exc_info()) - exit(SOMETHING_WENT_WRONG) + exit(UNHANDLED_EXCEPTION) UNLIKELY_EOF # ------------------------------------------------------------------------- @@ -1630,8 +1650,10 @@ UNLIKELY_EOF # Report error. (Otherwise, be quiet.) echo "Had a problem while downloading and verifying Python packages:" echo "$PEEP_OUT" + rm -rf "$VENV_PATH" exit 1 fi + echo "Installation succeeded." fi echo "Requesting root privileges to run letsencrypt..." echo " " $SUDO "$VENV_BIN/letsencrypt" "$@" @@ -1653,10 +1675,11 @@ else exit 0 fi - echo "Checking for new version..." - TEMP_DIR=$(TempDir) - # --------------------------------------------------------------------------- - cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" + if [ "$NO_SELF_UPGRADE" != 1 ]; then + echo "Checking for new version..." + TEMP_DIR=$(TempDir) + # --------------------------------------------------------------------------- + cat << "UNLIKELY_EOF" > "$TEMP_DIR/fetch.py" """Do downloading and JSON parsing without additional dependencies. :: # Print latest released version of LE to stdout: @@ -1785,25 +1808,36 @@ if __name__ == '__main__': exit(main()) UNLIKELY_EOF - # --------------------------------------------------------------------------- - DeterminePythonVersion - REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` - if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then - echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." - - # Now we drop into Python so we don't have to install even more - # dependencies (curl, etc.), for better flow control, and for the option of - # future Windows compatibility. - "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" - - # Install new copy of letsencrypt-auto. This preserves permissions and - # ownership from the old copy. - # TODO: Deal with quotes in pathnames. - echo "Replacing letsencrypt-auto..." - echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" - $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$0" - # TODO: Clean up temp dir safely, even if it has quotes in its path. - rm -rf "$TEMP_DIR" - fi # should upgrade - "$0" --no-self-upgrade "$@" + # --------------------------------------------------------------------------- + DeterminePythonVersion + REMOTE_VERSION=`"$LE_PYTHON" "$TEMP_DIR/fetch.py" --latest-version` + if [ "$LE_AUTO_VERSION" != "$REMOTE_VERSION" ]; then + echo "Upgrading letsencrypt-auto $LE_AUTO_VERSION to $REMOTE_VERSION..." + + # Now we drop into Python so we don't have to install even more + # dependencies (curl, etc.), for better flow control, and for the option of + # future Windows compatibility. + "$LE_PYTHON" "$TEMP_DIR/fetch.py" --le-auto-script "v$REMOTE_VERSION" + + # Install new copy of letsencrypt-auto. + # TODO: Deal with quotes in pathnames. + echo "Replacing letsencrypt-auto..." + # Clone permissions with cp. chmod and chown don't have a --reference + # option on OS X or BSD, and stat -c on Linux is stat -f on OS X and BSD: + echo " " $SUDO cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" + $SUDO cp -p "$0" "$TEMP_DIR/letsencrypt-auto.permission-clone" + echo " " $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" + $SUDO cp "$TEMP_DIR/letsencrypt-auto" "$TEMP_DIR/letsencrypt-auto.permission-clone" + # Using mv rather than cp leaves the old file descriptor pointing to the + # original copy so the shell can continue to read it unmolested. mv across + # filesystems is non-atomic, doing `rm dest, cp src dest, rm src`, but the + # cp is unlikely to fail (esp. under sudo) if the rm doesn't. + echo " " $SUDO mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" + $SUDO mv -f "$TEMP_DIR/letsencrypt-auto.permission-clone" "$0" + # TODO: Clean up temp dir safely, even if it has quotes in its path. + rm -rf "$TEMP_DIR" + fi # A newer version is available. + fi # Self-upgrading is allowed. + + "$0" --le-auto-phase2 "$@" fi |