/usr/bin/sstream-mirror is in simplestreams 0.1.0~bzr426-0ubuntu1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | #!/usr/bin/python3
# Copyright (C) 2013 Canonical Ltd.
#
# Author: Scott Moser <scott.moser@canonical.com>
#
# Simplestreams is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# Simplestreams is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
# License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with Simplestreams. If not, see <http://www.gnu.org/licenses/>.
import argparse
import sys
from simplestreams import filters
from simplestreams import log
from simplestreams import mirrors
from simplestreams import objectstores
from simplestreams import util
class DotProgress(object):
def __init__(self, expected=None, columns=80):
self.curpath = None
self.printed = None
self.expected = expected
self.bytes_read = 0
self.columns = columns
def write_progress(self, path, cur, total):
if self.curpath != path:
self.printed = 0
self.curpath = path
status = ""
if self.expected:
status = (" %02s%%" %
(int(self.bytes_read * 100 / self.expected)))
sys.stderr.write('=> %s [%s]%s\n' % (path, total, status))
if cur == total:
sys.stderr.write("\n")
if self.expected:
self.bytes_read += total
return
toprint = int(cur * self.columns / total) - self.printed
if toprint <= 0:
return
sys.stderr.write('.' * toprint)
sys.stderr.flush()
self.printed += toprint
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--keep', action='store_true', default=False,
help='keep items in target up to MAX items '
'even after they have fallen out of the source')
parser.add_argument('--max', type=int, default=None,
help='store at most MAX items in the target')
parser.add_argument('--path', default=None,
help='sync from index or products file in mirror')
parser.add_argument('--no-item-download', action='store_true',
default=False,
help='do not download items with a "path"')
parser.add_argument('--dry-run', action='store_true', default=False,
help='only report what would be done')
parser.add_argument('--progress', action='store_true', default=False,
help='show progress for downloading files')
parser.add_argument('--mirror', action='append', default=[],
dest="mirrors",
help='additional mirrors to find referenced files')
parser.add_argument('--verbose', '-v', action='count', default=0)
parser.add_argument('--log-file', default=sys.stderr,
type=argparse.FileType('w'))
parser.add_argument('--keyring', action='store', default=None,
help='keyring to be specified to gpg via --keyring')
parser.add_argument('--no-verify', '-U', action='store_false',
dest='verify', default=True,
help="do not gpg check signed json files")
parser.add_argument('--no-checksumming-reader', action='store_false',
dest='checksumming_reader', default=True,
help=("do not call 'insert_item' with a reader"
" that does checksumming."))
parser.add_argument('source_mirror')
parser.add_argument('output_d')
parser.add_argument('filters', nargs='*', default=[])
args = parser.parse_args()
(mirror_url, initial_path) = util.path_from_mirror_url(args.source_mirror,
args.path)
def policy(content, path):
if initial_path.endswith('sjson'):
return util.read_signed(content,
keyring=args.keyring,
checked=args.verify)
else:
return content
filter_list = filters.get_filters(args.filters)
mirror_config = {'max_items': args.max, 'keep_items': args.keep,
'filters': filter_list,
'item_download': not args.no_item_download,
'checksumming_reader': args.checksumming_reader}
level = (log.ERROR, log.INFO, log.DEBUG)[min(args.verbose, 2)]
log.basicConfig(stream=args.log_file, level=level)
smirror = mirrors.UrlMirrorReader(mirror_url, mirrors=args.mirrors,
policy=policy)
tstore = objectstores.FileStore(args.output_d)
drmirror = mirrors.DryRunMirrorWriter(config=mirror_config,
objectstore=tstore)
drmirror.sync(smirror, initial_path)
def print_diff(char, items):
for pedigree, path, size in items:
fmt = "{char} {pedigree} {path} {size} Mb\n"
size = int(size / (1024 * 1024))
sys.stderr.write(fmt.format(
char=char, pedigree=' '.join(pedigree), path=path, size=size))
print_diff('+', drmirror.downloading)
print_diff('-', drmirror.removing)
sys.stderr.write("%d Mb change\n" % (drmirror.size / (1024 * 1024)))
if args.dry_run:
return True
if args.progress:
callback = DotProgress(expected=drmirror.size).write_progress
else:
callback = None
tstore = objectstores.FileStore(args.output_d, complete_callback=callback)
tmirror = mirrors.ObjectFilterMirror(config=mirror_config,
objectstore=tstore)
tmirror.sync(smirror, initial_path)
if __name__ == '__main__':
main()
# vi: ts=4 expandtab syntax=python
|