blob: c2204f03d2e36c835ce6fa7c664003117b0e00ee [file] [log] [blame]
#!/usr/bin/python -b
# Copyright 2010-2014 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] ' + \
'<src_pkg_dir> <snapshot_dir> <snapshot_uri> <binhost_dir>'
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))