@@ 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)
@@ 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}")