from __future__ import print_function
import os
import os.path
import urllib.error
import urllib.parse
import urllib.request
from django.conf import settings
from django.core.management.base import BaseCommand, CommandError
from oioioi.base.utils.execute import ExecuteError, execute
from oioioi.filetracker.client import get_client
[docs]DEFAULT_SANDBOXES_MANIFEST = getattr(
settings,
'SANDBOXES_MANIFEST',
'https://downloads.sio2project.mimuw.edu.pl/sandboxes/Manifest',
)
[docs]class Command(BaseCommand):
[docs] def add_arguments(self, parser):
parser.add_argument(
'-m',
'--manifest',
metavar='URL',
dest='manifest_url',
default=DEFAULT_SANDBOXES_MANIFEST,
help="Specifies URL with the Manifest file listing available sandboxes",
)
parser.add_argument(
'-c',
'--cache-dir',
metavar='DIR',
dest='cache_dir',
default=None,
help="Load cached sandboxes from a local directory",
)
parser.add_argument(
'-d',
'--download-dir',
metavar='DIR',
dest='download_dir',
default="sandboxes-download",
help="Temporary directory where the downloaded files will be stored",
)
parser.add_argument(
'--wget',
metavar='PATH',
dest='wget',
default="wget",
help="Specifies the wget binary to use",
)
parser.add_argument(
'-y',
'--yes',
dest='license_agreement',
default=False,
action='store_true',
help="Enabling this options means that you agree to the license "
"terms and conditions, so no license prompt will be "
"displayed",
)
parser.add_argument(
'-q',
'--quiet',
dest='quiet',
default=False,
action='store_true',
help="Disables wget interactive progress bars",
)
parser.add_argument(
'sandboxes', type=str, nargs='*', help='List of sandboxes to be downloaded'
)
[docs] help = "Downloads sandboxes and stores them in the Filetracker."
[docs] requires_model_validation = False
[docs] def display_license(self, license):
print("\nThe sandboxes are accompanied with a license:\n", file=self.stdout)
self.stdout.write(license)
msg = "\nDo you accept the license? (yes/no):"
confirm = input(msg)
while 1:
if confirm not in ('yes', 'no'):
confirm = input('Please enter either "yes" or "no": ')
continue
if confirm == 'no':
raise CommandError("License not accepted")
break
[docs] def handle(self, *args, **options):
print("--- Downloading Manifest ...", file=self.stdout)
try:
manifest_url = options['manifest_url']
manifest = (
urllib.request.urlopen(manifest_url).read().decode('utf-8')
)
manifest = manifest.strip().splitlines()
except Exception as e:
raise CommandError("Error downloading manifest: %s" % (e,))
print("--- Looking for license ...", file=self.stdout)
try:
license_url = urllib.parse.urljoin(manifest_url, 'LICENSE')
license = (
urllib.request.urlopen(license_url).read().decode('utf-8')
)
if not options['license_agreement']:
self.display_license(license)
except urllib.error.HTTPError as e:
if e.code != 404:
raise
args = options['sandboxes']
if not args:
args = manifest
print("--- Preparing ...", file=self.stdout)
urls = []
cached_args = []
for arg in args:
basename = arg + '.tar.gz'
if options['cache_dir']:
path = os.path.join(options['cache_dir'], basename)
if os.path.isfile(path):
cached_args.append(arg)
continue
if arg not in manifest:
raise CommandError(
"Sandbox '%s' not available (not in Manifest)" % (arg,)
)
urls.append(urllib.parse.urljoin(manifest_url, basename))
filetracker = get_client()
download_dir = options['download_dir']
if not os.path.exists(download_dir):
os.makedirs(download_dir)
try:
execute([options['wget'], '--version'])
except ExecuteError:
raise CommandError(
"Wget not working. Please specify a working "
"Wget binary using --wget option."
)
if len(urls) > 0:
print("--- Downloading sandboxes ...", file=self.stdout)
quiet_flag = ['-nv'] if options['quiet'] else []
execute(
[options['wget'], '-N', '--no-check-certificate', '-i', '-'] + quiet_flag,
stdin='\n'.join(urls).encode('utf-8'),
capture_output=False,
cwd=download_dir,
)
print("--- Saving sandboxes to the Filetracker ...", file=self.stdout)
for arg in args:
basename = arg + '.tar.gz'
if arg in cached_args:
local_file = os.path.join(options['cache_dir'], basename)
else:
local_file = os.path.join(download_dir, basename)
print(" ", basename, file=self.stdout)
filetracker.put_file('/sandboxes/' + basename, local_file)
if arg not in cached_args:
os.unlink(local_file)
try:
os.rmdir(download_dir)
except OSError:
print(
"--- Done, but couldn't remove the downloads directory.",
file=self.stdout,
)
else:
print("--- Done.", file=self.stdout)