~rootmos/fetch

3d37a27f961f398b1920a45c4afe784f9f226f2a — Gustav Behm 9 months ago c2ba0c1 master
Add a command to steal this script
2 files changed, 54 insertions(+), 9 deletions(-)

M README.md
M fetch
M README.md => README.md +4 -4
@@ 6,19 6,19 @@ File download helpers

## Usage
```
usage: fetch [-h] [--log LOG] [--log-file FILE] [--root ROOT]
usage: fetch [-h] [-v] [--log LOG] [--root ROOT]
             [--manifest-filename FILENAME] [--manifest PATH]
             {add,download} ...
             {add,download,steal-this-script} ...

One script to fetch them all and in /tmp bind them

positional arguments:
  {add,download}
  {add,download,steal-this-script}

options:
  -h, --help            show this help message and exit
  -v, --version         show program's version number and exit
  --log LOG             set log level (default: WARN)
  --log-file FILE       redirect stdout and stderr to FILE (default: None)
  --root ROOT           act relative the directory ROOT (default: .)
  --manifest-filename FILENAME
                        load manifest from FILENAME (relative to the ROOT)

M fetch => fetch +50 -5
@@ 1,11 1,14 @@
#!/usr/bin/env python3

import argparse
import datetime
import hashlib
import json
import os
import shutil
import sys
import stat
import urllib.request
import datetime
import json

import logging
logger = logging.getLogger(__name__)


@@ 16,13 19,30 @@ env_prefix = f"{whoami.upper()}_"
def env(var, default=None):
    return os.environ.get(env_prefix + var, default)

def chmod_plus_x(path):
    umask = os.umask(0)
    os.umask(umask)
    os.chmod(path, os.stat(path).st_mode | ((stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) & ~umask))

def figure_out_version():
    with open(__file__, "rb") as this:
        ls = this.readlines()
        shebang = ls[0]
        assert(shebang.startswith(b"#!"))

        h = hashlib.sha256()
        for l in ls[1:]:
            h.update(l)
        return h.hexdigest()

def parse_args():
    parser = argparse.ArgumentParser(
            description="One script to fetch them all and in /tmp bind them",
            formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument("-v", "--version", action="version", version=figure_out_version())

    parser.add_argument("--log", default=env("LOG_LEVEL", "WARN"), help="set log level")
    parser.add_argument("--log-file", metavar="FILE", default=env("LOG_FILE"), help="redirect stdout and stderr to FILE")

    default_root = env("ROOT", ".")
    default_manifest_filename = env("MANIFEST_FILENAME", f".{whoami}.json")


@@ 40,6 60,9 @@ def parse_args():
    download_cmd = subparsers.add_parser("download")
    download_cmd.add_argument("target", metavar="TARGET", nargs="*")

    steal_this_script_cmd = subparsers.add_parser("steal-this-script")
    steal_this_script_cmd.add_argument("output", metavar="OUTPUT", nargs="?")

    return parser.parse_args()

def setup_logger(level):


@@ 202,8 225,6 @@ class Item:

def main():
    args = parse_args()
    if args.log_file is not None:
        sys.stderr = sys.stdout = open(args.log_file, "a")
    logger = setup_logger(args.log.upper())
    logger.debug(f"args: {args}")



@@ 241,6 262,30 @@ def main():
            else:
                i.download(root=root)
            print(os.path.relpath(i.local, start=root))
    elif args.cmd == "steal-this-script":
        dst = sys.stdout.buffer
        if args.output is not None:
            dst = open(args.output, "wb")

        with open(__file__, "rb") as src:
            ls = src.readlines()
            shebang = ls[0]
            assert(shebang.startswith(b"#!"))
            dst.write(shebang)

            h = hashlib.sha256()
            for l in ls[1:]:
                h.update(l)
            sha256 = h.hexdigest()

            now = datetime.datetime.now().astimezone().isoformat(timespec="seconds")
            dst.write(f"# {now} SHA-256:{sha256}\n".encode("UTF-8"))

            for l in ls[1:]:
                dst.write(l)

        if dst != sys.stdout.buffer:
            chmod_plus_x(dst.name)
    else:
        raise RuntimeError(f"unexpected command: {args.cmd}")