code: def test_run_failure(path=None):
      ds = Dataset(path).create()
      subds = ds.create("sub")
  
      hexsha_initial = ds.repo.get_hexsha()
  
      if on_windows:
          # this does not do exactly the same as the cmd on other systems
          # but is close enough to make running the test worthwhile
          cmd_failing = "echo x>{} & false".format(
              op.join("sub", "grows")
          )
      else:
          cmd_failing = "echo x$(cat {0}) > {0} && false".format(
              op.join("sub", "grows")
          )
  
      with assert_raises(IncompleteResultsError):
          ds.run(cmd_failing, result_renderer=None)
      eq_(hexsha_initial, ds.repo.get_hexsha())
      ok_(ds.repo.dirty)
  
      msgfile = op.join(
          path, ds.repo.get_git_dir(ds.repo), "COMMIT_EDITMSG"
      )
      ok_exists(msgfile)
  
      ds.save(recursive=True, message_file=msgfile)
      assert_repo_status(ds.path)
      neq_(hexsha_initial, ds.repo.get_hexsha())
  
      outfile = op.join(subds.path, "grows")
      eq_("x \n" if on_windows else "x\n", open(outfile).read())
  
      if on_windows:
          # FIXME: Make the remaining code compatible with Windows.
          return
  
      # There is no CommandError on rerun if the non-zero error matches the
      # original code.
      ds.rerun()
      eq_("xx\n", open(outfile).read())
  
      # On the other hand, we fail if we rerun a command and there is a non-zero
      # error that doesn't match.
      ds.run("[ ! -e bar ] && echo c >bar")
      assert_repo_status(ds.path)
      assert_in_results(
          ds.rerun(result_renderer=None, on_failure="ignore"),
          action="run",
          status="error",
      )
  
      # We don't show instructions if the caller specified us not to save.
      remove(msgfile)
      with assert_raises(IncompleteResultsError):
          ds.run(
              "false", explicit=True, outputs=None, on_failure="stop"
          )
      assert_false(op.exists(msgfile))
  
imports: import logging
  import os.path
  import sys
  from io import StringIO
  from os import remove
  import pytest
  from unittest.mock import patch
  from datalad.api import install, run
  from datalad.core.local.run import run_command
  from datalad.core.local.tests.test_run import last_commit_msg
  from datalad.distribution.dataset import Dataset
  from datalad.local.rerun import diff_revision, get_run_info, new_or_modified
  from datalad.support.exceptions import CommandError, IncompleteResultsError
  from datalad.support.gitrepo import GitRepo
  from datalad.tests.utils_pytest import DEFAULT_BRANCH, DEFAULT_REMOTE, SkipTest, assert_dict_equal, assert_false, assert_in, assert_in_results, assert_not_in, assert_not_in_results, assert_raises, assert_repo_status, assert_result_count, assert_status, create_tree, eq_, known_failure_windows, neq_, ok_, ok_exists, ok_file_has_content, ok_file_under_git, skip_if_adjusted_branch, slow, swallow_logs, swallow_outputs, with_tempfile, with_tree
  from datalad.utils import Path, chpwd, on_windows
label_desc: Use image node_id 6 for calling a global function with example usage: test_run_failure(path) without return types