docs: def check_manifest(source_tree='.', create=False, update=False,
                     python=sys.executable):
      """Compare a generated source distribution with list of files in a VCS.
  
      Returns True if the manifest is fine.
      """
      all_ok = True
      if os.path.sep in python:
          python = os.path.abspath(python)
      with cd(source_tree):
          if not is_package():
              raise Failure('This is not a Python project (no setup.py).')
          read_config()
          read_manifest()
          info_begin("listing source files under version control")
          all_source_files = sorted(get_vcs_files())
          source_files = strip_sdist_extras(all_source_files)
          info_continue(": %d files and directories" % len(source_files))
          if not all_source_files:
              raise Failure('There are no files added to version control!')
          info_begin("building an sdist")
          with mkdtemp('-sdist') as tempdir:
              run([python, 'setup.py', 'sdist', '-d', tempdir])
              sdist_filename = get_one_file_in(tempdir)
              info_continue(": %s" % os.path.basename(sdist_filename))
              sdist_files = sorted(normalize_names(strip_sdist_extras(
                  strip_toplevel_name(get_archive_file_list(sdist_filename)))))
              info_continue(": %d files and directories" % len(sdist_files))
              version = extract_version_from_filename(sdist_filename)
          existing_source_files = list(filter(os.path.exists, all_source_files))
          missing_source_files = sorted(set(all_source_files) - set(existing_source_files))
          if missing_source_files:
              warning("some files listed as being under source control are missing:\n%s"
                      % format_list(missing_source_files))
          info_begin("copying source files to a temporary directory")
          with mkdtemp('-sources') as tempsourcedir:
              copy_files(existing_source_files, tempsourcedir)
              if os.path.exists('MANIFEST.in') and 'MANIFEST.in' not in source_files:
                  # See https://github.com/mgedmin/check-manifest/issues/7
                  # if do this, we will emit a warning about MANIFEST.in not
                  # being in source control, if we don't do this, the user
                  # gets confused about their new manifest rules being
                  # ignored.
                  copy_files(['MANIFEST.in'], tempsourcedir)
              if 'setup.py' not in source_files:
                  # See https://github.com/mgedmin/check-manifest/issues/46
                  # if do this, we will emit a warning about setup.py not
                  # being in source control, if we don't do this, the user
                  # gets a scary error
                  copy_files(['setup.py'], tempsourcedir)
              info_begin("building a clean sdist")
              with cd(tempsourcedir):
                  with mkdtemp('-sdist') as tempdir:
                      os.environ['SETUPTOOLS_SCM_PRETEND_VERSION'] = version
                      run([python, 'setup.py', 'sdist', '-d', tempdir])
                      sdist_filename = get_one_file_in(tempdir)
                      info_continue(": %s" % os.path.basename(sdist_filename))
                      clean_sdist_files = sorted(normalize_names(strip_sdist_extras(
                          strip_toplevel_name(get_archive_file_list(sdist_filename)))))
                      info_continue(": %d files and directories" % len(clean_sdist_files))
          missing_from_manifest = set(source_files) - set(clean_sdist_files)
          missing_from_VCS = set(sdist_files + clean_sdist_files) - set(source_files)
          if not missing_from_manifest and not missing_from_VCS:
              info("lists of files in version control and sdist match")
          else:
              error("lists of files in version control and sdist do not match!\n%s"
                    % format_missing(missing_from_VCS, missing_from_manifest,
                                     "VCS", "sdist"))
              suggestions, unknowns = find_suggestions(missing_from_manifest)
              user_asked_for_help = update or (create and not
                                                  os.path.exists('MANIFEST.in'))
              if 'MANIFEST.in' not in existing_source_files:
                  if suggestions and not user_asked_for_help:
                      info("no MANIFEST.in found; you can run 'check-manifest -c' to create one")
                  else:
                      info("no MANIFEST.in found")
              if suggestions:
                  info("suggested MANIFEST.in rules:\n%s"
                       % format_list(suggestions))
                  if user_asked_for_help:
                      existed = os.path.exists('MANIFEST.in')
                      with open('MANIFEST.in', 'a') as f:
                          if not existed:
                              info("creating MANIFEST.in")
                          else:
                              info("updating MANIFEST.in")
                              f.write('\n# added by check_manifest.py\n')
                          f.write('\n'.join(suggestions) + '\n')
                      if unknowns:
                          info("don't know how to come up with rules matching\n%s"
                               % format_list(unknowns))
              elif user_asked_for_help:
                  info("don't know how to come up with rules"
                       " matching any of the files, sorry!")
              all_ok = False
          bad_ideas = find_bad_ideas(all_source_files)
          filtered_bad_ideas = [bad_idea for bad_idea in bad_ideas
                                if not file_matches(bad_idea, IGNORE_BAD_IDEAS)]
          if filtered_bad_ideas:
              warning("you have %s in source control!\nthat's a bad idea:"
                      " auto-generated files should not be versioned"
                      % filtered_bad_ideas[0])
              if len(filtered_bad_ideas) > 1:
                  warning("this also applies to the following:\n%s"
                          % format_list(filtered_bad_ideas[1:]))
              all_ok = False
      return all_ok