simple, throw an exception with the error message on an error return code.

    this function may be moved to the command module, spliced with
    'cmd.run_all', and used as an alternative to 'cmd.run_all'. Some
    commands don't return proper retcodes, so this can't replace 'cmd.run_all'.

def _git_run(command, cwd=None, user=None, password=None, identity=None,
             ignore_retcode=False, failhard=True, redirect_stderr=False,
             saltenv='base', output_encoding=None, **kwargs):
    '''
    simple, throw an exception with the error message on an error return code.

    this function may be moved to the command module, spliced with
    'cmd.run_all', and used as an alternative to 'cmd.run_all'. Some
    commands don't return proper retcodes, so this can't replace 'cmd.run_all'.
    '''
    env = {}

    if identity:
        _salt_cli = __opts__.get('__cli', '')
        errors = []
        missing_keys = []

        # if the statefile provides multiple identities, they need to be tried
        # (but also allow a string instead of a list)
        if not isinstance(identity, list):
            # force it into a list
            identity = [identity]

        # try each of the identities, independently
        tmp_identity_file = None
        for id_file in identity:
            if 'salt://' in id_file:
                with salt.utils.files.set_umask(0o077):
                    tmp_identity_file = salt.utils.files.mkstemp()
                    _id_file = id_file
                    id_file = __salt__['cp.get_file'](id_file,
                                                      tmp_identity_file,
                                                      saltenv)
                if not id_file:
                    log.error('identity %s does not exist.', _id_file)
                    __salt__['file.remove'](tmp_identity_file)
                    continue
                else:
                    if user:
                        os.chown(id_file,
                                 __salt__['file.user_to_uid'](user),
                                 -1)
            else:
                if not __salt__['file.file_exists'](id_file):
                    missing_keys.append(id_file)
                    log.error('identity %s does not exist.', id_file)
                    continue

            env = {
                'GIT_IDENTITY': id_file
            }

            # copy wrapper to area accessible by ``runas`` user
            # currently no support in windows for wrapping git ssh
            ssh_id_wrapper = os.path.abspath(os.path.join(
                salt.utils.templates.TEMPLATE_DIRNAME,
                'git/ssh-id-wrapper'
            ))
            tmp_ssh_wrapper = None
            if salt.utils.platform.is_windows():
                ssh_exe = _find_ssh_exe()
                if ssh_exe is None:
                    raise CommandExecutionError(
                        'Failed to find ssh.exe, unable to use identity file'
                    )
                env['GIT_SSH_EXE'] = ssh_exe
                # Use the windows batch file instead of the bourne shell script
                ssh_id_wrapper += '.bat'
                env['GIT_SSH'] = ssh_id_wrapper
            elif not user or _path_is_executable_others(ssh_id_wrapper):
                env['GIT_SSH'] = ssh_id_wrapper
            else:
                tmp_ssh_wrapper = salt.utils.files.mkstemp()
                salt.utils.files.copyfile(ssh_id_wrapper, tmp_ssh_wrapper)
                os.chmod(tmp_ssh_wrapper, 0o500)
                os.chown(tmp_ssh_wrapper, __salt__['file.user_to_uid'](user), -1)
                env['GIT_SSH'] = tmp_ssh_wrapper

            if 'salt-call' not in _salt_cli \
                    and __utils__['ssh.key_is_encrypted'](id_file):
                errors.append(
                    'Identity file {0} is passphrase-protected and cannot be '
                    'used in a non-interactive command. Using salt-call from '
                    'the minion will allow a passphrase-protected key to be '
                    'used.'.format(id_file)
                )
                continue

            log.info(
                'Attempting git authentication using identity file %s',
                id_file
            )

            try:
                result = __salt__['cmd.run_all'](
                    command,
                    cwd=cwd,
                    runas=user,
                    password=password,
                    env=env,
                    python_shell=False,
                    log_callback=salt.utils.url.redact_http_basic_auth,
                    ignore_retcode=ignore_retcode,
                    redirect_stderr=redirect_stderr,
                    output_encoding=output_encoding,
                    **kwargs)
            finally:
                if tmp_ssh_wrapper:
                    # Cleanup the temporary ssh wrapper file
                    try:
                        __salt__['file.remove'](tmp_ssh_wrapper)
                        log.debug('Removed ssh wrapper file %s', tmp_ssh_wrapper)
                    except AttributeError:
                        # No wrapper was used
                        pass
                    except (SaltInvocationError, CommandExecutionError) as exc:
                        log.warning(
                            'Failed to remove ssh wrapper file %s: %s',
                            tmp_ssh_wrapper, exc
                        )

                if tmp_identity_file:
                    # Cleanup the temporary identity file
                    try:
                        __salt__['file.remove'](tmp_identity_file)
                        log.debug('Removed identity file %s', tmp_identity_file)
                    except AttributeError:
                        # No identify file was used
                        pass
                    except (SaltInvocationError, CommandExecutionError) as exc:
                        log.warning(
                            'Failed to remove identity file %s: %s',
                            tmp_identity_file, exc
                        )

            # If the command was successful, no need to try additional IDs
            if result['retcode'] == 0:
                return result
            else:
                err = result['stdout' if redirect_stderr else 'stderr']
                if err:
                    errors.append(salt.utils.url.redact_http_basic_auth(err))

        # We've tried all IDs and still haven't passed, so error out
        if failhard:
            msg = (
                'Unable to authenticate using identity file:\n\n{0}'.format(
                    '\n'.join(errors)
                )
            )
            if missing_keys:
                if errors:
                    msg += '\n\n'
                msg += (
                    'The following identity file(s) were not found: {0}'
                    .format(', '.join(missing_keys))
                )
            raise CommandExecutionError(msg)
        return result

    else:
        result = __salt__['cmd.run_all'](
            command,
            cwd=cwd,
            runas=user,
            password=password,
            env=env,
            python_shell=False,
            log_callback=salt.utils.url.redact_http_basic_auth,
            ignore_retcode=ignore_retcode,
            redirect_stderr=redirect_stderr,
            output_encoding=output_encoding,
            **kwargs)

        if result['retcode'] == 0:
            return result
        else:
            if failhard:
                gitcommand = ' '.join(command) \
                    if isinstance(command, list) \
                    else command
                msg = 'Command \'{0}\' failed'.format(
                    salt.utils.url.redact_http_basic_auth(gitcommand)
                )
                err = result['stdout' if redirect_stderr else 'stderr']
                if err:
                    msg += ': {0}'.format(
                        salt.utils.url.redact_http_basic_auth(err)
                    )
                raise CommandExecutionError(msg)
            return result