docs: def collect(args):
      """Collect coverage reports."""
      excl_paths = exclude_paths(args)
  
      report = {}
      if args.repo_token:
          report['repo_token'] = args.repo_token
  
      report['service_name'] = args.service_name
      report['service_job_id'] = args.service_job_id
  
      if os.getenv('COVERALLS_PARALLEL', False):
          report['parallel'] = 'true'
  
      args.exclude_lines_pattern.extend([
          r'\bLCOV_EXCL_LINE\b',
          r'^\s*};?\s*$',
          r'^\s*(inline|static)'
          ])
  
      discovered_files = set()
      src_files = {}
      abs_root = os.path.abspath(args.root)
      if args.lcov_file:
          info_lines = [line.rstrip('\n') for line in open(args.lcov_file, 'r')]
          line_iter = iter(info_lines)
          new_file_re = re.compile('SF:(.*)')
          line_coverage_re = re.compile('DA:(\d+),(\d+)');
          for line in line_iter:
              new_file_match = new_file_re.match(line)
              if new_file_match:
                  src_report = {}
                  filepath = new_file_match.group(1)
                  if args.root:
                      filepath = os.path.relpath(filepath, args.root)
                  abs_filepath = os.path.join(abs_root, filepath)
                  src_report['name'] = str(posix_path(filepath))
                  with io.open(abs_filepath, mode='rb') as src_file:
                      src_report['source_digest'] = hashlib.md5(src_file.read()).hexdigest()
                  src_report['coverage'] = parse_lcov_file_info(args, abs_filepath, line_iter, line_coverage_re, "end_of_record")
                  src_files[filepath] = src_report
              elif line != "TN:":
                  print('Invalid info file')
                  print('line: ' + line)
                  sys.exit(0)
      else:
          for root, dirs, files in os.walk(args.root, followlinks=args.follow_symlinks):
              dirs[:] = filter_dirs(root, dirs, excl_paths)
  
              root_is_libtool_dir = is_libtool_dir(root)
              for filepath in files:
                  if os.path.splitext(filepath)[1] == '.gcov':
                      gcov_path = os.path.join(os.path.join(root, filepath))
                      with open(gcov_path, mode='rb') as fobj:
                          source_file_line = fobj.readline().decode('utf-8', 'replace')
                          source_file_path = source_file_line.split(':')[-1].strip()
                          if not os.path.isabs(source_file_path):
                              if args.build_root:
                                  source_file_path = os.path.join(
                                      args.build_root, source_file_path)
                              elif root_is_libtool_dir:
                                  source_file_path = os.path.abspath(
                                      libtool_source_file_path(
                                          root, source_file_path))
                              else:
                                  if not source_file_path.startswith(os.path.pardir + os.path.sep) and \
                                          os.path.dirname(source_file_path):
                                      the_root = abs_root
                                  else:
                                      the_root = root
                                  source_file_path = os.path.abspath(
                                      os.path.join(the_root, source_file_path))
                          src_path = os.path.relpath(source_file_path, abs_root)
                          if src_path.startswith(os.path.pardir + os.path.sep):
                              continue
                          if is_excluded_path(args, source_file_path):
                              continue
  
                          src_report = {}
                          src_report['name'] = posix_path(src_path)
                          discovered_files.add(src_path)
                          with io.open(source_file_path, mode='rb') as src_file:
                              src_report['source_digest'] = hashlib.md5(src_file.read()).hexdigest()
  
                          src_report['coverage'] = parse_gcov_file(args, fobj, gcov_path)
                          if src_path in src_files:
                              src_files[src_path] = combine_reports(src_files[src_path], src_report)
                          else:
                              src_files[src_path] = src_report
  
      report['source_files'] = list(src_files.values())
      # Also collects the source files that have no coverage reports.
      if not args.lcov_file:
          report['source_files'].extend(
              collect_non_report_files(args, discovered_files))
  
      # Use the root directory to get information on the Git repository
      report['git'] = gitrepo.gitrepo(abs_root)
      return report