def make_diff(self, merge_base, base, tip, include_files,
                  exclude_patterns):
        """Performs a diff on a particular branch range."""
        rev_range = "%s..%s" % (base, tip)

        if include_files:
            include_files = ['--'] + include_files

        git_cmd = [self.git]

        if self._supports_git_config_flag():
            git_cmd.extend(['-c', 'core.quotepath=false'])

        if self.type in ('svn', 'perforce'):
            diff_cmd_params = ['--no-color', '--no-prefix', '-r', '-u']
        elif self.type == 'git':
            diff_cmd_params = ['--no-color', '--full-index',
                               '--ignore-submodules']

            if self._supports_git_config_flag():
                git_cmd.extend(['-c', 'diff.noprefix=false'])

            if (self.capabilities is not None and
                self.capabilities.has_capability('diffs', 'moved_files')):
                diff_cmd_params.append('-M')
            else:
                diff_cmd_params.append('--no-renames')
        else:
            assert False

        # By default, don't allow using external diff commands. This prevents
        # things from breaking horribly if someone configures a graphical diff
        # viewer like p4merge or kaleidoscope. This can be overridden by
        # setting GIT_USE_EXT_DIFF = True in ~/.reviewboardrc
        if not self.config.get('GIT_USE_EXT_DIFF', False):
            diff_cmd_params.append('--no-ext-diff')

        diff_cmd = git_cmd + ['diff'] + diff_cmd_params

        if exclude_patterns:
            # If we have specified files to exclude, we will get a list of all
            # changed files and run `git diff` on each un-excluded file
            # individually.
            changed_files_cmd = git_cmd + ['diff-tree'] + diff_cmd_params
            if self.type == 'git':
                changed_files_cmd.append('-r')

            changed_files = execute(
                changed_files_cmd + [rev_range] + include_files,
                split_lines=True,
                with_errors=False,
                ignore_errors=True,
                none_on_ignored_error=True,
                log_output_on_error=False)

            # The output of git diff-tree will be a list of entries that have
            # changed between the two revisions that we give it. The last part
            # of the line is the name of the file that has changed.
            changed_files = remove_filenames_matching_patterns(
                (filename.split()[-1] for filename in changed_files),
                exclude_patterns, base_dir=self._get_root_directory())

            diff_lines = []

            for filename in changed_files:
                lines = execute(diff_cmd + [rev_range, '--', filename],
                                split_lines=True,
                                with_errors=False,
                                ignore_errors=True,
                                none_on_ignored_error=True,
                                log_output_on_error=False,
                                results_unicode=False)

                if lines is None:
                    logging.error(
                        'Could not get diff for all files (git-diff failed '
                        'for "%s"). Refusing to return a partial diff.' %
                        filename)

                    diff_lines = None
                    break

                diff_lines += lines

        else:
            diff_lines = execute(diff_cmd + [rev_range] + include_files,
                                 split_lines=True,
                                 with_errors=False,
                                 ignore_errors=True,
                                 none_on_ignored_error=True,
                                 log_output_on_error=False,
                                 results_unicode=False)

        if self.type == 'svn':
            return self.make_svn_diff(merge_base, diff_lines)
        elif self.type == 'perforce':
            return self.make_perforce_diff(merge_base, diff_lines)
        else:
            return b''.join(diff_lines)
dataset/ETHPy150Open reviewboard/rbtools/rbtools/clients/git.py/GitClient.make_diff/original