docs: def scan_file(fullpath, relpath, assign_id):
      """ scan a file and put it into the index """
      # pylint: disable=too-many-branches,too-many-statements,too-many-locals
  
      # Since a file has changed, the lrucache is invalid.
      load_message.cache_clear()
  
      try:
          entry = load_message(fullpath)
      except FileNotFoundError:
          # The file doesn't exist, so remove it from the index
          record = model.Entry.get(file_path=fullpath)
          if record:
              expire_record(record)
          return True
  
      entry_id = get_entry_id(entry, fullpath, assign_id)
      if entry_id is None:
          return False
  
      fixup_needed = False
  
      basename = os.path.basename(relpath)
      title = entry['title'] or guess_title(basename)
  
      values = {
          'file_path': fullpath,
          'category': entry.get('Category', utils.get_category(relpath)),
          'status': model.PublishStatus[entry.get('Status', 'SCHEDULED').upper()].value,
          'entry_type': entry.get('Entry-Type', ''),
          'slug_text': make_slug(entry.get('Slug-Text', title)),
          'redirect_url': entry.get('Redirect-To', ''),
          'title': title,
          'sort_title': entry.get('Sort-Title', title),
          'entry_template': entry.get('Entry-Template', '')
      }
  
      entry_date = None
      if 'Date' in entry:
          try:
              entry_date = arrow.get(entry['Date'], tzinfo=config.timezone)
          except arrow.parser.ParserError:
              entry_date = None
      if entry_date is None:
          del entry['Date']
          entry_date = arrow.get(
              os.stat(fullpath).st_ctime).to(config.timezone)
          entry['Date'] = entry_date.format()
          fixup_needed = True
  
      if 'Last-Modified' in entry:
          last_modified_str = entry['Last-Modified']
          try:
              last_modified = arrow.get(
                  last_modified_str, tzinfo=config.timezone)
          except arrow.parser.ParserError:
              last_modified = arrow.get()
              del entry['Last-Modified']
              entry['Last-Modified'] = last_modified.format()
              fixup_needed = True
  
      values['display_date'] = entry_date.isoformat()
      values['utc_date'] = entry_date.to('utc').datetime
      values['local_date'] = entry_date.naive
  
      logger.debug("getting entry %s with id %d", fullpath, entry_id)
      record = model.Entry.get(id=entry_id)
      if record:
          logger.debug("Reusing existing entry %d", record.id)
          record.set(**values)
      else:
          record = model.Entry(id=entry_id, **values)
  
      # Update the entry ID
      if str(record.id) != entry['Entry-ID']:
          del entry['Entry-ID']
          entry['Entry-ID'] = str(record.id)
          fixup_needed = True
  
      if 'UUID' not in entry:
          entry['UUID'] = str(uuid.uuid5(
              uuid.NAMESPACE_URL, 'file://' + fullpath))
          fixup_needed = True
  
      # add other relationships to the index
      path_alias.remove_aliases(record)
      if record.visible:
          for alias in entry.get_all('Path-Alias', []):
              path_alias.set_alias(alias, entry=record)
  
      with orm.db_session:
          set_tags = {
              t.lower()
              for t in entry.get_all('Tag', [])
              + entry.get_all('Hidden-Tag', [])
          }
  
          for tag in record.tags:
              if tag.key in set_tags:
                  set_tags.remove(tag.key)
              else:
                  tag.delete()
          for tag in set_tags:
              model.EntryTag(entry=record, key=tag)
          orm.commit()
  
      if record.status == model.PublishStatus.DRAFT.value:
          logger.info("Not touching draft entry %s", fullpath)
      elif fixup_needed:
          logger.info("Fixing up entry %s", fullpath)
          save_file(fullpath, entry)
  
      return record