summaryrefslogtreecommitdiff
path: root/lib/diff.tcl
AgeCommit message (Collapse)AuthorFilesLines
2010-01-23git-gui: Support applying a range of changes at onceLibravatar Jeff Epler1-101/+141
Multiple lines can be selected in the diff viewer and applied all at once, rather than selecting "Stage Line For Commit" on each individual line. Signed-off-by: Jeff Epler <jepler@unpythonic.net> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23git-gui: Use git diff --submodule when availableLibravatar Jens Lehmann1-4/+13
Doing so is much faster and gives the same output. Here are some numbers: $ time git submodule summary real 0m0.219s user 0m0.050s sys 0m0.111s $ time git diff --submodule real 0m0.012s user 0m0.003s sys 0m0.009s Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2010-01-23git-gui: Fix applying a line when all following lines are deletionsLibravatar Jeff Epler1-0/+1
If a diff looked like: @@ context -del1 -del2 and you wanted to stage the deletion 'del1', the generated patch wouldn't apply because it was missing the line 'del2' converted to context, but this line was counted in the @@-line Signed-off-by: Jeff Epler <jepler@unpythonic.net> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-26git-gui: Ensure submodule path is quoted properlyLibravatar Shawn O. Pearce1-2/+2
When quoting an arbitrary user string in Tcl, its better to use [list ...] than to use {...}, in case the user string has spaces or { embedded within it. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-26git-gui: fix diff for partially staged submodule changesLibravatar Jens Lehmann1-4/+6
When a submodule commit had already been staged and another commit had been checked out inside the submodule, the diff always displayed the submodule commit log messages between the last supermodule commit and the working tree, totally ignoring the commit in the index. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-08-10git-gui: display summary when showing diff of a submoduleLibravatar Jens Lehmann1-2/+28
As it is hard to say what changed in a submodule by looking at the hashes, let's show the colored submodule summary instead. Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2009-02-08git-gui: Avoid an infinite rescan loop in handle_empty_diff.Libravatar Alexander Gavrilov1-0/+9
If the index update machinery and git diff happen to disagree on whether a particular file is modified, it may cause git-gui to enter an infinite index rescan loop, where an empty diff starts a rescan, which finds the same set of files modified, and tries to display the diff for the first one, which happens to be the empty one. A current example of a possible disagreement point is the autocrlf filter. This patch breaks the loop by using a global counter to track the auto-rescans. The variable is reset whenever a non-empty diff is displayed. Another suggested approach, which is based on giving the --exit-code argument to git diff, cannot be used, because diff-files seems to trust the timestamps in the index, and returns a non-zero code even if the file is actually unchanged, which essentially defeats the purpose of the auto-rescan logic. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-11-16git-gui: Fix the after callback execution in rescan.Libravatar Alexander Gavrilov1-3/+3
The rescan function receives a callback command as its parameter, which is supposed to be executed after the scan finishes. It is generally used to update status. However, rescan may initiate a loading of a diff, which always calls ui_ready after completion. If the after handler is called before that, ui_ready will override the new status. This commit ensures that the after callback is properly threaded through the diff machinery. Since it uncovered the fact that force_first_diff actually didn't work due to an undeclared global variable, and the desired effects appeared only because of the race condition between the diff system and the rescan callback, I also reimplement this function to make it behave as originally intended. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-11-01git-gui: Do not munge conflict marker lines in a normal diffLibravatar Johannes Sixt1-1/+0
Previously, conflict markers were highlighted in two ways: (1) They received a distinguishing color; and (2) they had the '+' removed at the beginning of the line. However, by doing (2), a hunk that contained conflict markers could not be staged or unstaged because the resulting patch was corrupted. With this change we no longer modify the diff text of a 2-way diff, so that "Stage Hunk" and friends work. Note that 3-way diff of a conflicted file is unaffected by this change, and '++' before conflict markers is still removed. But this has no negative impact because in this mode staging hunks or lines is disabled anyway. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-10-10git-gui: Mark-up strings in show_{other,unmerged}_diff() for localizationLibravatar Johannes Sixt1-11/+11
Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-10-10git-gui: Show a round number of bytes of large untracked text filesLibravatar Johannes Sixt1-1/+1
If an untracked text file is selected, then its contents are displayed instead of a diff. If the file is large, then the following hint is inserted at the top: * Untracked file is 14774881 bytes. * Showing only first 131072 bytes. Why exactly 131072 bytes? With this patch it is 100000 bytes. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-24git-gui: Reenable staging unmerged files by clicking the icon.Libravatar Alexander Gavrilov1-17/+35
This restores functionality of the file icon for unmerged files. Safety is enforced by loading the diff and checking for lines that look like conflict markers. If such lines are found, or the conflict involves deletion and/or symlinks, a confirmation dialog is presented. Otherwise, the icon immediately stages the working copy version of the file. Includes a revert of 2fe5b2ee42897a3acc78e5ddaace3775eb2713ca (Restore ability to Stage Working Copy for conflicts) Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Tested-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-24git-gui: Allow forcing display encoding for diffs using a submenu.Libravatar Alexander Gavrilov1-0/+9
Add a submenu to allow dynamically changing the encoding to use for diffs. Encoding settings are remembered while git-gui runs. The rules are: 1) Encoding set for a specific file overrides gitattributes. 2) Last explicitly set value of the encoding overrides gui.encoding Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Tested-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-24git-gui: Cleanup handling of the default encoding.Libravatar Alexander Gavrilov1-5/+6
- Make diffs and blame default to the system (locale) encoding instead of hard-coding UTF-8. - Add a gui.encoding option to allow overriding it. - gitattributes still have the final word. The rationale for this is Windows support: 1) Windows people are accustomed to using legacy encodings for text files. For many of them defaulting to utf-8 will be counter-intuitive. 2) Windows doesn't support utf-8 locales, and switching the system encoding is a real pain. Thus the option. This patch also adds proper encoding conversion to Apply Hunk/Line. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Tested-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-24git-gui: Use gitattribute "encoding" for file content displayLibravatar Shawn O. Pearce1-3/+6
Most folks using git-gui on internationalized files have complained that it doesn't recognize UTF-8 correctly. In the past we have just ignored the problem and showed the file contents as binary/US-ASCII, which is wrong no matter how you look at it. This really should be a per-file attribute, managed by .gitattributes, so we now pull the "encoding" attribute data for the given path from the .gitattributes (if available) and use that, falling back to UTF-8 if the attributes are unavailable, git-check-attr is broken, or an encoding for this path not specified. We apply the encoding anytime we show file content, which currently is limited to only the diff viewer and the blame viewer. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-04Merge branch 'maint'Libravatar Shawn O. Pearce1-7/+11
* maint: git-gui: Fix diff parsing for lines starting with "--" or "++"
2008-09-04git-gui: Fix diff parsing for lines starting with "--" or "++"Libravatar Shawn O. Pearce1-7/+11
Languages like Lua and SQL use "--" to mark a line as commented out. If this appears at column 0 and is part of the pre-image we may see "--- foo" in the diff, indicating that the line whose content is "-- foo" has been removed from the new version. git-gui was incorrectly parsing "--- foo" as the old file name in the file header, causing it to generate a bad patch file when the user tried to stage or unstage a hunk or the selected line. We need to keep track of where we are in the parsing so that we do not misread a deletion or addition record as part of the header. Reported-by: Alexander Gladysh <agladysh@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-04git-gui: Show special diffs for complex conflict cases.Libravatar Alexander Gavrilov1-5/+89
Add special handling for displaying diffs of modified/deleted, and symlink/mode conflicts. Currently the display is completely unusable for deciding how to resolve the conflict. New display modes: 1) Deleted/Modified conflict: e.g. LOCAL: deleted REMOTE: [diff :1:$path :3:$path] 2) Conflict involving symlinks: LOCAL: [diff :1:$path :2:$path] REMOTE: [diff :1:$path :3:$path] In order to be able to display multiple diffs, this patch adds a queue of commands to call. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-04git-gui: Reimplement and enhance auto-selection of diffs.Libravatar Alexander Gavrilov1-6/+12
Generalize the next_diff system, and implement auto-reselection for merge tool resolution and reshow_diff. Also add auto-selection of diffs after rescan, if no diff is already selected. New auto-select rules: - Rescan auto-selects the first conflicting file, or if none a modified tracked file, if nothing was selected previously. - Resolving a conflict auto-selects the nearest conflicting file, or nothing if everything is resolved. - Staging the last remaining hunk auto-selects the nearest modified staged file. - Staging a file through its icon auto-selects the nearest file. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-04git-gui: Support conflict states _U & UT.Libravatar Alexander Gavrilov1-1/+1
Support _U (local deleted, remote modified) and UT (file type changed in conflict) modes. Note that 'file type changed' does not refer to changes in the executable bit, instead it denotes replacing a file with a link, or vice versa. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-09-01git gui: show diffs with a minimum of 1 context lineLibravatar Clemens Buchacher1-1/+1
Staging hunks without context does not work, because line number information would have to be recomputed for individual hunks. Since it is already possible to stage individual lines using 'Stage Line for Commit', zero context diffs are not really necessary for git gui. Signed-off-by: Clemens Buchacher <drizzd@aon.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-27git-gui: Preserve scroll position on reshow_diff.Libravatar Alexander Gavrilov1-4/+14
It is especially useful for Stage/Unstage Line, because they invoke full state scan and diff reload, which originally would reset the scroll position to the top of the file. Signed-off-by: Alexander Gavrilov <angavrilov@gmail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-26git-gui: "Stage Line": Treat independent changes in adjacent lines betterLibravatar Johannes Sixt1-3/+58
Assume that we want to commit these states: Old state == HEAD Intermediate state New state -------------------------------------------------------- context before context before context before old 1 new 1 new 1 old 2 old 2 new 2 context after context after context after that is, want to commit two changes in this order: 1. transform "old 1" into "new 1" 2. transform "old 2" into "new 2" [This discussion and this patch is about this very case and one other case as outlined below; any other intermediate states that one could imagine are not affected by this patch.] Now assume further, that we have not staged and commited anything, but we have already changed the working file to the new state. Then we will see this hunk in the "Unstaged Changes": @@ -1,4 +1,4 @@ context before -old 1 -old 2 +new 1 +new 2 context after The obvious way to stage the intermediate state is to apply "Stage This Line" to "-old 1" and "+new 1". Unfortunately, this resulted in this intermediate state: context before old 2 new 1 context after which is not what we wanted. In fact, it was impossible to stage the intermediate state using "Stage Line". The crux was that if a "+" line was staged, then the "-" lines were converted to context lines and arranged *before* the "+" line in the forged hunk that we fed to 'git apply'. With this patch we now treat "+" lines that are staged differently. In particular, the "-" lines before the "+" block are moved *after* the staged "+" line. Now it is possible to get the correct intermediate state by staging "-old 1" and "+new 1". Problem solved. But there is a catch. Noticing that we didn't get the right intermediate state by staging "-old 1" and "+new 1", we could have had the idea to stage the complete hunk and to *unstage* "-old 2" and "+new 2". But... the result is the same. The reason is that there is the exact symmetric problem with unstaging the last "-" and "+" line that are in adjacent blocks of "-" and "+" lines. This patch does *not* change the way in which "-" lines are *unstaged*. Why? Because if we did (i.e. move "+" lines before the "-" line after converting them to context lines), then it would be impossible to stage this intermediate state: context before old 1 new 2 context after that is, it would be impossible to stage the two independet changes in the opposite order. Let's look at this case a bit further: The obvious way to get this intermediate state would be to apply "Stage This Line" to "-old 2" and "+new 2". Before this patch, this worked as expected. With this patch, it does not work as expected, but it can still be achieved by first staging the entire hunk, then *unstaging* "-old 1" and "+new 1". In summary, this patch makes a common case possible, at the expense that a less common case is made more complicated for the user. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-26git-gui: Fix "Stage/Unstage Line" with one line of context.Libravatar Johannes Sixt1-0/+3
To "Stage/Unstage Line" we construct a patch that contains exactly one change (either addition or removal); the hunk header was forged by counting the old side and adjusting the count by +/-1 for the new side. But when we counted the context we never counted the changed line itself. If the hunk had only one removal line and one line of context, like this: @@ -1,3 +1,2 @@ context 1 -removal context 2 We had constructed this patch: @@ -1,2 +1,1 @@ context 1 -removal context 2 which does not apply because git apply deduces that it must apply at the end of the file. ("context 2" is considered garbage and ignored.) The fix is that removal lines must be counted towards the context of the old side. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-07-02git-gui: Implement "Stage/Unstage Line"Libravatar Johannes Sixt1-0/+87
This adds a context menu entry below "Stage/Unstage Hunk" that stages or unstages just the line under the mouse pointer. This is by itself useful, for example, if there are unrelated changes in the same hunk and the hunk cannot be split by reducing the context. The feature can also be used to split a hunk by staging a number of additions (or unstaging a number of removals) until there are enough context lines that the hunk gets split. The implementation reads the complete hunk that the line lives in, and constructs a new hunk by picking existing context lines, removing unneeded change lines and transforming other change lines to context lines. The resulting hunk is fed through 'git apply' just like in the "Stage/Unstage Hunk" case. Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2008-01-16git-gui: Refresh file status description after hunk applicationLibravatar Shawn O. Pearce1-0/+2
If we apply a hunk in either direction this may change the file's status. For example if a file is completely unstaged, and has at least two hunks in it and the user stages one hunk the file will change from "Modified, not staged" to "Portions staged for commit". Resetting the file path causes our trace on this variable to fire; that trace is used to update the file header in the diff viewer to the file's current status. Noticed by Johannes Sixt. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-12-14git-gui: Handle file mode changes (644->755) in diff viewerLibravatar Shawn O. Pearce1-0/+1
Johannes Sixt pointed out the diff headers "old mode ..." and "new mode ..." were not being parsed properly by git-gui. We now include them in the diff viewer for a file. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-09-14git-gui: Paper bag fix missing translated stringsLibravatar Shawn O. Pearce1-2/+2
The Tcl expression "[append [mc Foo] Bar]" does not return the string "FooBar" after translation; instead it is setting the variable Foo to the value Bar, or if Foo is already defined it is appending Bar onto the end of it. This is *not* what we wanted to have happen here. Tcl's join function is actually the correct function but its default joinStr argument is a single space. Unfortunately all of our call sites do not want an extra space added to their string. So we need a small wrapper function to make the call to join with an empty join string. In C this is (roughly) the job of the strcat function. Since strcat is not yet used at the global level it is a reasonable name to use here. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-09-13git-gui: add some strings to translationLibravatar Michele Ballabio1-4/+4
Most of these changes were suggested by Shawn Pearce in an answer to Johannes Schindelin. Some strings for the blame module were added too. [sp: Minor edits in blame module formatting] Signed-off-by: Michele Ballabio <barra_cuda@katamail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-09-09Merge branch 'maint'Libravatar Shawn O. Pearce1-6/+30
* maint: git-gui: Trim trailing slashes from untracked submodule names git-gui: Assume untracked directories are Git submodules git-gui: handle "deleted symlink" diff marker git-gui: show unstaged symlinks in diff viewer
2007-09-09git-gui: Assume untracked directories are Git submodulesLibravatar Shawn O. Pearce1-3/+18
If `git ls-files --others` returned us the name of a directory then it is because Git has decided that this directory itself contains a valid Git repository and its files shouldn't be listed as untracked for this repository. In such a case we should label the object as a Git repository and not just as a directory. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-09-09git-gui: handle "deleted symlink" diff markerLibravatar Michele Ballabio1-0/+1
Signed-off-by: Michele Ballabio <barra_cuda@katamail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-09-09git-gui: show unstaged symlinks in diff viewerLibravatar Michele Ballabio1-5/+10
git-gui has a minor problem with regards to symlinks that point to directories. git init mkdir realdir ln -s realdir linkdir git gui Now clicking on file names in the "unstaged changes" window, there's a problem coming from the "linkdir" symlink: git-gui complains with error reading "file4": illegal operation on a directory ...even though git-gui can add that same symlink to the index just fine. This patch fix this by adding a check. [sp: Minor fix to use {link} instead of "link" in condition and to only open the path if it is not a symlink.] Signed-off-by: Michele Ballabio <barra_cuda@katamail.com> Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-09-02Mark strings for translation.Libravatar Christian Stimming1-8/+8
The procedure [mc ...] will translate the strings through msgcat. Strings must be enclosed in quotes, not in braces, because otherwise xgettext cannot extract them properly, although on the Tcl side both delimiters would work fine. [jes: I merged the later patches to that end.] Signed-off-by: Christian Stimming <stimming@tuhh.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
2007-07-17git-gui: Always disable the Tcl EOF character when readingLibravatar Shawn O. Pearce1-0/+1
On Windows (which includes Cygwin) Tcl defaults to leaving the EOF character of input file streams set to the ASCII EOF character, but if that character were to appear in the data stream then Tcl will close the channel early. So we have to disable eofchar on Windows. Since the default is disabled on all platforms except Windows, we can just disable it everywhere to prevent any sort of read problem. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-07-09git-gui: Always use absolute path to all git executablesLibravatar Shawn O. Pearce1-4/+4
Rather than making the C library search for git every time we want to execute it we now search for the main git wrapper at startup, do symlink resolution, and then always use the absolute path that we found to execute the binary later on. This should save us some cycles, especially on stat challenged systems like Cygwin/Win32. While I was working on this change I also converted all of our existing pipes ([open "| git ..."]) to use two new pipe wrapper functions. These functions take additional options like --nice and --stderr which instructs Tcl to take special action, like running the underlying git program through `nice` (if available) or redirect stderr to stdout for capture in Tcl. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-07-08git-gui: Refactor our ui_status_value update techniqueLibravatar Shawn O. Pearce1-9/+9
I'm really starting to dislike global variables. The ui_status_value global varible is just one of those that seems to appear in a lot of code and in many cases we didn't even declare it "global" within the proc that updates it so we haven't always been getting all of the updates we expected to see. This change introduces two new global procs: ui_status $msg; # Sets the status bar to show $msg. ui_ready; # Changes the status bar to show "Ready." The second (special) form is used because we often update the area with this message once we are done processing a block of work and want the user to know we have completed it. I'm not fixing the cases that appear in lib/branch.tcl right now as I'm actually in the middle of a huge refactoring of that code to support making a detached HEAD checkout. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-05-31git-gui: Allow as few as 0 lines of diff contextLibravatar Shawn O. Pearce1-1/+1
Johannes Sixt pointed out that dropping to 0 lines of context does allow the user to get more fine-grained hunk selection, especially since we don't currently support "highlight and apply (or revert)". Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
2007-05-07git-gui: Refactor into multiple files to save my sanityLibravatar Shawn O. Pearce1-0/+336
I'm finding it difficult to work with a 6,000+ line Tcl script and not go insane while looking for a particular block of code. Since most of the program is organized into different units of functionality and not all users will need all units immediately on startup we can improve things by splitting procs out into multiple files and let auto_load handle things for us. This should help not only to better organize the source, but it may also improve startup times for some users as the Tcl parser does not need to read as much script before it can show the UI. In many cases the user can avoid reading at least half of git-gui now. Unfortunately we now need a library directory in our runtime location. This is currently assumed to be $(sharedir)/git-gui/lib and its expected that the Makefile invoker will setup some sort of reasonable sharedir value for us, or let us assume its going to be $(gitexecdir)/../share. We now also require a tclsh (in TCL_PATH) to just run the Makefile, as we use tclsh to generate the tclIndex for our lib directory. I'm hoping this is not an unncessary burden on end-users who are building from source. I haven't really made any functionality changes here, this is just a huge migration of code from one file to many smaller files. All of the new changes are to setup the library path and install the library files. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>