code: def diff_dataset(
      dataset,
      fr,
      to,
      constant_refs,
      path=None,
      annex=None,
      untracked="normal",
      recursive=False,
      recursion_limit=None,
      reporting_order="depth-first",
      datasets_only=False,
  ):
      """Internal helper to diff a dataset
  
      Parameters
      ----------
      dataset : Dataset
        Dataset to perform the diff on. `fr` and `to` parameters are interpreted
        in the context of this dataset.
      fr : str
        Commit-ish to compare from.
      to : str
        Commit-ish to compare to.
      constant_refs : bool
        If True, `fr` and `to` will be passed on unmodified to diff operations
        on subdatasets. This can be useful with symbolic references like tags
        to report subdataset changes independent of superdataset changes.
        If False, `fr` and `to` will be translated to the subdataset commit-ish
        that match the given commit-ish in the superdataset.
      path : Path-like, optional
        Paths to constrain the diff to (see main diff() command).
      annex : str, optional
        Reporting mode for annex properties (see main diff() command).
      untracked : str, optional
        Reporting mode for untracked content (see main diff() command).
      recursive : bool, optional
        Flag to enable recursive operation (see main diff() command).
      recursion_limit : int, optional
        Recursion limit (see main diff() command).
      reporting_order : {'depth-first', 'breadth-first', 'bottom-up'}, optional
        By default, subdataset content records are reported after the record
        on the subdataset's submodule in a superdataset (depth-first).
        Alternatively, report all superdataset records first, before reporting
        any subdataset content records (breadth-first). Both 'depth-first'
        and 'breadth-first' both report dataset content before considering
        subdatasets. Alternative 'bottom-up' mode is similar to 'depth-first'
        but dataset content is reported after reporting on subdatasets.
      datasets_only : bool, optional
        Consider only changes to (sub)datasets but limiting operation only to
        paths of subdatasets.
        Note: ATM incompatible with explicit specification of `path`.
  
      Yields
      ------
      dict
        DataLad result records.
      """
      if reporting_order not in (
          "depth-first",
          "breadth-first",
          "bottom-up",
      ):
          raise ValueError(
              "Unknown reporting order: {}".format(reporting_order)
          )
  
      ds = require_dataset(
          dataset, check_installed=True, purpose="report difference"
      )
  
      # we cannot really perform any sorting of paths into subdatasets
      # or rejecting paths based on the state of the filesystem, as
      # we need to be able to compare with states that are not represented
      # in the worktree (anymore)
      if path:
          if datasets_only:
              raise NotImplementedError(
                  "Analysis of provided paths in datasets_only mode is not implemented"
              )
  
          ps = []
          # sort any path argument into the respective subdatasets
          for p in sorted(ensure_list(path)):
              # it is important to capture the exact form of the
              # given path argument, before any normalization happens
              # distinguish rsync-link syntax to identify
              # a dataset as whole (e.g. 'ds') vs its
              # content (e.g. 'ds/')
              # special case is the root dataset, always report its content
              # changes
              orig_path = str(p)
              resolved_path = resolve_path(p, dataset)
              p = (
                  resolved_path,
                  orig_path.endswith(op.sep)
                  or resolved_path == ds.pathobj,
              )
              str_path = str(p[0])
              root = get_dataset_root(str_path)
              if root is None:
                  # no root, not possibly underneath the refds
                  yield dict(
                      action="status",
                      path=str_path,
                      refds=ds.path,
                      status="error",
                      message="path not underneath this dataset",
                      logger=lgr,
                  )
                  continue
              if path_under_rev_dataset(ds, str_path) is None:
                  # nothing we support handling any further
                  # there is only a single refds
                  yield dict(
                      path=str_path,
                      refds=ds.path,
                      action="diff",
                      status="error",
                      message=(
                          "dataset containing given paths is not underneath "
                          "the reference dataset %s: %s",
                          ds,
                          str_path,
                      ),
                      logger=lgr,
                  )
                  continue
  
              ps.append(p)
          path = ps
  
      # TODO we might want to move away from the single-pass+immediate-yield
      # paradigm for this command. If we gather all information first, we
      # could do post-processing and detect when a file (same gitsha, or same
      # key) was copied/moved from another dataset. Another command (e.g.
      # save) could act on this information and also move/copy
      # availability information or at least enhance the respective commit
      # message with cross-dataset provenance info
  
      # cache to help avoid duplicate status queries
      content_info_cache = {}
      for res in _diff_ds(
          ds,
          fr,
          to,
          constant_refs,
          recursion_limit
          if recursion_limit is not None and recursive
          else -1
          if recursive
          else 0,
          # TODO recode paths to repo path reference
          origpaths=None if not path else dict(path),
          untracked=untracked,
          annexinfo=annex,
          cache=content_info_cache,
          order=reporting_order,
          datasets_only=datasets_only,
      ):
          res.update(
              refds=ds.path,
              logger=lgr,
              action="diff",
          )
          yield res
  
file_path: datalad/datalad/core/local/diff.py
imports: import logging
  import os.path
  from datalad.utils import ensure_list, ensure_unicode, get_dataset_root
  from datalad.interface.base import Interface, build_doc, eval_results
  from datalad.distribution.dataset import Dataset, datasetmethod, require_dataset, resolve_path, path_under_rev_dataset
  from datalad.support.constraints import EnsureNone, EnsureStr
  from datalad.support.param import Parameter
  from datalad.core.local.status import Status, _common_diffstatus_params
  from datalad.support.exceptions import InvalidGitReferenceError
label_desc: Use image node_id 1 for calling a global function with example usage: diff_dataset(dataset, fr, to, constant_refs, path, annex, untracked, recursive, recursion_limit, reporting_order, datasets_only) without return types