docs: def copy(source_backend_names, bucket_names, static_bucket_name, s3_endpoint, s3_profile, s3_bucket_policy_file,
           rclone, output):
      """Copy files to S3.
  
      This command copies files to S3 and records the necessary database changes
      in a JSONL file.
  
      Multiple bucket names can be specified; in that case the bucket name can change
      based on the year a file was created in. The last bucket name will be the default,
      while any other bucket name must include a conditional indicating when to use it:
  
      \b
          -B '<2001:indico-pre-2001'
          -B '<2009:indico-<year>'
          -B 'indico-<year>-<month>'
  
      The static bucket name cannot contain any placeholders.
  
      The indico storage backend will get the same name as the bucket by default,
      but this can be overridden, e.g. `-B 'indico-<year>/s3-<year>'` would name
      the bucket 'indico-2018' but use a backend named 's3-2018'.  It is your
      responsibility to ensure that placeholders match between the two names.
  
      S3 credentials should be specified in the usual places, i.e.
      `~/.aws/credentials` for regular S3 access and `~/.config/rclone/rclone.conf`
      when using rclone.
      """
      bucket_names = [tuple(x.split('/', 1)) if '/' in x else (x, x.split(':', 1)[-1]) for x in bucket_names]
      if ':' in bucket_names[-1][0]:
          raise click.UsageError('Last bucket name cannot contain criteria')
      if not all(':' in x[0] for x in bucket_names[:-1]):
          raise click.UsageError('All but the last bucket name need to contain criteria')
      matches = [(re.match(r'^(<|>|==|<=|>=)\s*(\d{4}):(.+)$', name), backend) for name, backend in bucket_names[:-1]]
      if not all(x[0] for x in matches):
          raise click.UsageError("Could not parse '{}'".format(bucket_names[matches.index(None)]))
      criteria = [(match.groups(), backend) for match, backend in matches]
      # Build and compile a function to get the bucket/backend name to avoid
      # processing the criteria for every single file (can be millions for large
      # instances)
      code = ['def get_bucket_name(dt):']
      if criteria:
          for i, ((op, value, bucket), backend) in enumerate(criteria):
              code.append('    {}if dt.year {} {}:'.format('el' if i else '', op, value))
              code.append('        bucket, backend = {!r}'.format((bucket, backend)))
          code.append('    else:')
          code.append('        bucket, backend = {!r}'.format(bucket_names[-1]))
      else:
          code.append('    bucket, backend = {!r}'.format(bucket_names[-1]))
      code.append('    bucket = bucket.replace("<year>", dt.strftime("%Y"))')
      code.append('    bucket = bucket.replace("<month>", dt.strftime("%m"))')
      code.append('    bucket = bucket.replace("<week>", dt.strftime("%W"))')
      code.append('    backend = backend.replace("<year>", dt.strftime("%Y"))')
      code.append('    backend = backend.replace("<month>", dt.strftime("%m"))')
      code.append('    backend = backend.replace("<week>", dt.strftime("%W"))')
      code.append('    return bucket, backend')
      d = {}
      exec '\n'.join(code) in d
      if not source_backend_names:
          source_backend_names = [x for x in config.STORAGE_BACKENDS if not isinstance(get_storage(x), S3StorageBase)]
      if rclone:
          invalid = [x for x in source_backend_names if not isinstance(get_storage(x), FileSystemStorage)]
          if invalid:
              click.secho('Found unsupported storage backends: {}'.format(', '.join(sorted(invalid))), fg='yellow')
              click.secho('The backends might not work together with `--rclone`', fg='yellow')
              click.confirm('Continue anyway?', abort=True)
      s3_bucket_policy = s3_bucket_policy_file.read() if s3_bucket_policy_file else None
      imp = S3Importer(d['get_bucket_name'], static_bucket_name,
                       output, source_backend_names, rclone,
                       s3_endpoint, s3_profile, s3_bucket_policy)
      with monkeypatch_registration_file_time():
          imp.run()