git-cola/git-cola — pull request #399 by living180 (2014-12-22 21:03:03+00:00)
Title: Rewrite DiffParser

This PR contains a full rewrite of the `cola.diffparser` module. The primary reason for this is to eliminate the ambiguity noted by @davvid in his comment on PR #329:

> Finding the text from the GUI selection in the full forward diff is actually ambiguous. In practice it's not a problem because usually the selection is unique, but in theory it can get confused since the selection might find an earlier (incorrect) match. I don't know of a way to go from the Qt selection to the lines in the text, which is why it's done that way, but if you happen to know a way then that would eliminate the one last ambiguous/dangerous part.

Finding the text from the GUI selection in the diff is no longer done, removing any ambiguity. Instead, since the Stage/Unstage/Revert operations all operate on lines as a whole, rework the code to operate in terms of lines. The `DiffEditor` widget has a new method, `selected_lines()`, which returns the indexes of the first and last selected lines (or of the line containing the cursor, if there is no selection). The `ApplyDiffSelection` command class and the `DiffParser` class were rewritten to operate in terms of these line indexes. To ensure that the correct lines are always included in the generated patch, `DiffParser` no longer calls out to `git` to get the diff, but instead uses the diff text from the model (otherwise if the file had changed on disk since git-cola refreshed its model, we can't be sure that the line numbers from the `DiffEditor` widget would correspond to the line numbers from `git diff`).

In addition, the rewritten `DiffParser` class has been made purely functional: its state is set in the initializer, and its methods operate in a purely functional manner on that state. All the imperative functionality (creating temporary files and applying the diff) has been moved into the `do()` method of the `ApplyDiffSelection` command class.