code: def _diff(old, new, data_keys, with_missing=False):
      from dvc_data.index.diff import ADD, DELETE, MODIFY, RENAME
      from dvc_data.index.diff import diff as idiff
  
      ret: "Dict[str, List[Dict]]" = {
          "added": [],
          "deleted": [],
          "modified": [],
          "renamed": [],
          "not in cache": [],
      }
  
      def meta_cmp_key(meta):
          if not meta:
              return meta
          return meta.isdir
  
      for change in idiff(
          old,
          new,
          with_renames=True,
          meta_cmp_key=meta_cmp_key,
          roots=data_keys,
      ):
          if (
              change.old
              and change.old.isdir
              and not change.old.hash_info
          ) or (
              change.new
              and change.new.isdir
              and not change.new.hash_info
          ):
              continue
  
          if change.typ == ADD:
              ret["added"].append(
                  {
                      "path": _path(change.new),
                      "hash": _hash(change.new),
                  }
              )
          elif change.typ == DELETE:
              ret["deleted"].append(
                  {
                      "path": _path(change.old),
                      "hash": _hash(change.old),
                  }
              )
          elif change.typ == MODIFY:
              ret["modified"].append(
                  {
                      "path": _path(change.old),
                      "hash": {
                          "old": _hash(change.old),
                          "new": _hash(change.new),
                      },
                  }
              )
          elif change.typ == RENAME:
              ret["renamed"].append(
                  {
                      "path": {
                          "old": _path(change.old),
                          "new": _path(change.new),
                      },
                      "hash": _hash(change.old),
                  }
              )
  
          if (
              with_missing
              and change.old
              and change.old.hash_info
              and not old.storage_map.cache_exists(change.old)
          ):
              ret["not in cache"].append(
                  {
                      "path": _path(change.old),
                      "hash": _hash(change.old),
                  }
              )
  
      return ret if any(ret.values()) else {}
  
file_path: dvc/dvc/repo/diff.py
imports: import errno
  import os
  from collections import defaultdict
  from typing import Dict, List, Optional
  from dvc.log import logger
  from dvc.repo import locked
  from dvc.ui import ui
label_desc: Use image node_id 3 for calling a global function with example usage: _diff(old, new, data_keys, with_missing) and returns: unknown, meta, meta