def runJplag(opts, args, fileGlob=None):
    jarName = 'jplag-3.0.0-jar-with-dependencies.jar'
    jarFile = shell.pjoin(shell.dirname(__file__), '..', 'resources', jarName)
    print('Running jplag, this might take a while ...')
    res = shell.run(['java', '-jar', jarFile] + opts,
                    captureStdout=True,
                    stderrToStdout=True)
    haveMinScore = False
    for l in res.stdout.split('\n'):
        if 'no viable alternative at input' in l:
            pass
        elif 'nothing to parse for submission' in l:
            pass
        elif l.startswith('Comparing '):
            i = -1
            try:
                i = l.rindex(':')
            except ValueError:
                verbose(l)
            if i >= 0:
                score = float(l[i + 1:].strip())
                if score >= args.minScore:
                    haveMinScore = True
                    print(ansi.red(l))
                    if args.printDiff and score >= 99.99999999999999999:
                        printDiffForJplag(l, fileGlob)
        elif 'Writing results to' in l:
            print(ansi.blue(l + "/index.html"))
        else:
            verbose(l)
    if not haveMinScore:
        print(f'No submissions detected with similaries >= {args.minScore}')
def submit_changes(
    clock: util.Clock,
    server: GerritServer,
    changes: List[Change],
    num_retries: int = 0
) -> None:
  # Strip out merged changes.
  changes = [cl for cl in changes if cl.status != ChangeStatus.MERGED]

  # For any CL that doesn't have a CQ+1, run it now to speed things up.
  # As long as the CL isn't changed in the mean-time, it won't be tested
  # again when we finally get around to +2'ing it.
  #
  # We ignore the first one, because we are just about to +2 it anyway.
  for cl in changes[1:]:
    if cl.cq_votes() == 0:
      print("Setting CQ state of CL %d to dry-run." % cl.id)
      server.set_cq_state(cl.change_id, 1)

  # Submit the changes in order.
  for cl in changes:
    backoff = util.ExponentialBackoff(clock)
    max_attempts = num_retries + 1
    num_attempts = 0
    print()
    print("Submitting CL %d: %s" % (cl.id, cl.subject))

    while True:
      # Fetch the latest information about the CL.
      current_cl = server.fetch_change(cl.change_id)

      # Check it still exists.
      if current_cl is None:
        raise SubmitError("CL %s could not be found." % cl.id)

      # If it is merged, we are done.
      if current_cl.status == ChangeStatus.MERGED:
        break

      # If it is not in CQ, add it to CQ.
      if current_cl.cq_votes() < 2:
        if num_attempts == 0:
          print(ansi.gray("  Adding to CQ."))
        elif num_attempts < max_attempts:
          print(ansi.yellow("  CL failed in CQ. Retrying..."))
        else:
          print(ansi.red("  CL failed in CQ. Aborting."))
          return
        num_attempts += 1
        server.set_cq_state(cl.change_id, 2)

      # wait.
      backoff.wait()
      print(ansi.gray('  Polling...'))

    # Did we fail?
    print(ansi.green("  Submitted!"))
def printDiff(fst, snd, msg, printNoteForLongDiff=True):
    cmd = f"diff -u '{fst}' '{snd}'"
    r = shell.run(cmd, onError='ignore', captureStdout=True)
    out = r.stdout
    outLines = out.split('\n')
    changes = 0
    for l in outLines:
        if l.startswith('+') or l.startswith('-'):
            changes = changes + 1
    n = min(numberOfLines(fst), numberOfLines(snd))
    maxLines = max(12, int(n / 20.0))  # 5% of the minimal number of lines
    if changes > maxLines:
        if printNoteForLongDiff:
            print(f'Diff longer than {maxLines} lines: {cmd}')
    elif r.exitcode == 0:
        print(ansi.red(msg))
    else:
        print(out)