#!/usr/bin/python # Copyright 2010-2013 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 import io import os import sys import textwrap try: from urllib.parse import urlparse except ImportError: from urlparse import urlparse from os import path as osp pym_path = osp.join(osp.dirname(osp.dirname(osp.realpath(__file__))), "pym") sys.path.insert(0, pym_path) import portage portage._internal_caller = True from portage.util._argparse import ArgumentParser def parse_args(argv): prog_name = os.path.basename(argv[0]) usage = prog_name + ' [options] ' + \ ' ' prog_desc = "This program will copy src_pkg_dir to snapshot_dir " + \ "and inside binhost_dir it will create a Packages index file " + \ "which refers to snapshot_uri. This is intended to solve race " + \ "conditions on binhosts as described at http://crosbug.com/3225." usage += "\n\n" for line in textwrap.wrap(prog_desc, 70): usage += line + "\n" usage += "\n" usage += "Required Arguments:\n\n" usage += " src_pkg_dir - the source $PKGDIR\n" usage += " snapshot_dir - destination snapshot " + \ "directory (must not exist)\n" usage += " snapshot_uri - URI which refers to " + \ "snapshot_dir from the\n" + \ " client side\n" usage += " binhost_dir - directory in which to " + \ "write Packages index with\n" + \ " snapshot_uri" parser = ArgumentParser(usage=usage) parser.add_argument('--hardlinks', help='create hardlinks (y or n, default is y)', choices=('y', 'n'), default='y') options, args = parser.parse_known_args(argv[1:]) if len(args) != 4: parser.error("Required 4 arguments, got %d" % (len(args),)) return parser, options, args def main(argv): parser, options, args = parse_args(argv) src_pkg_dir, snapshot_dir, snapshot_uri, binhost_dir = args src_pkgs_index = os.path.join(src_pkg_dir, 'Packages') if not os.path.isdir(src_pkg_dir): parser.error("src_pkg_dir is not a directory: '%s'" % (src_pkg_dir,)) if not os.path.isfile(src_pkgs_index): parser.error("src_pkg_dir does not contain a " + \ "'Packages' index: '%s'" % (src_pkg_dir,)) parse_result = urlparse(snapshot_uri) if not (parse_result.scheme and parse_result.netloc and parse_result.path): parser.error("snapshot_uri is not a valid URI: '%s'" % (snapshot_uri,)) if os.path.isdir(snapshot_dir): parser.error("snapshot_dir already exists: '%s'" % snapshot_dir) try: os.makedirs(os.path.dirname(snapshot_dir)) except OSError: pass if not os.path.isdir(os.path.dirname(snapshot_dir)): parser.error("snapshot_dir parent could not be created: '%s'" % \ os.path.dirname(snapshot_dir)) try: os.makedirs(binhost_dir) except OSError: pass if not os.path.isdir(binhost_dir): parser.error("binhost_dir could not be created: '%s'" % binhost_dir) cp_opts = 'RP' if options.hardlinks == 'n': cp_opts += 'p' else: cp_opts += 'l' cp_cmd = 'cp -%s %s %s' % ( cp_opts, portage._shell_quote(src_pkg_dir), portage._shell_quote(snapshot_dir) ) ret = os.system(cp_cmd) if not (os.WIFEXITED(ret) and os.WEXITSTATUS(ret) == os.EX_OK): return 1 infile = io.open(portage._unicode_encode(src_pkgs_index, encoding=portage._encodings['fs'], errors='strict'), mode='r', encoding=portage._encodings['repo.content'], errors='strict') outfile = portage.util.atomic_ofstream( os.path.join(binhost_dir, "Packages"), encoding=portage._encodings['repo.content'], errors='strict') for line in infile: if line[:4] == 'URI:': # skip existing URI line pass else: if not line.strip(): # end of header outfile.write("URI: %s\n\n" % snapshot_uri) break outfile.write(line) for line in infile: outfile.write(line) infile.close() outfile.close() return os.EX_OK if __name__ == "__main__": sys.exit(main(sys.argv))