Skip to content

eliminate support for ancient git and Tk #22

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 33 commits into
base: master
Choose a base branch
from

Conversation

mark987
Copy link
Contributor

@mark987 mark987 commented Jul 9, 2025

Based upon j6t/testing to avoid conflicts with inflight topics.

  • sets minimum git at 2.20 following prior exchange. Latest advisory touches only back to 2.43, so 2.20 predates anything the project supports. But, updating to anything beyond 1.72 eliminates all version checks and git workarounds, so 2.20 is sufficient for that.
  • eliminates non-ttk code paths to simplify code, now compatible with inflight topics, depends upon Tk >= 8.6. Removes many alternate code paths.

The "33 commits" notion above is nonsense: there are 5 commits I'm adding on top of j6t/testing

Johannes Sixt and others added 30 commits November 24, 2024 13:27
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
When a 'git cherry-pick' or 'git revert' fails, it leaves behind
corresponding "*_HEAD" files that can be treated analogous to MERGE_HEAD.
Show the symmetric difference between those commits and HEAD when the
--merge option is given in the same way that a conflicted merge is shown.

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
gitk runs under wish, so naturally has Tcl and Tk available, and of the
same version. gitk sets a requirement on Tk version >= 8.4, but this is
very outdated, and not shipping on any current OS.  As 8.7 is in alpha
test, and is generally compatible with 8.x, we should allow that, but
9.0 has planned compatibility breaking changes so is not yet supported.

Also, as git-gui requires at least 8.5, and gitk and git-gui can launch
each other, the minimum requirement should be at least 8.5.  But, no
currently supported OS is shipping 8.5, much less 8.4, and 9.0 is
already released.  So, even 8.5 is essentially an untestable
requirement: 8.6 is a more reasonable minimum requirement.

So, we should allow 8.6-8.7 but not 9.0. As we are using wish, we only
need to check the version of Tcl or of Tk as these must be the same.
Let's put this at the top of file so the requirements are obvious.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Tk through 8.6 has different approaches for handling mouse wheel /
touchpad scrolling events on the different platforms, and gitk has
separate code for these. But, some x11 bindings are applied on aqua as
we do not have these in a clean if / then / else tree based upon
platform.  Let's split these bindings apart.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
This patch adds a basic support of SHA256 Git repository to Gitk, so
that Gitk can show and operate on both SHA1 and SHA256 repos
gracefully.  Since SHA256 has a longer ID length (64 char) than SHA1
(40 char), many field widths are adjusted to fit with it.

A caveat is that the configuration of auto selection length is shared
between SHA1 and SHA256 repos.  That is, once when this value is saved
and read, it's applied to both repo types, which may result in shorter
selection than the full SHA256 ID.  We may introduce another
individual config for sha256 (actually I did write in the first
version), but for simplicity, the common config is used as of writing
this.

Many lines still refer "sha1" although they may point to both SHA1 and
SHA256.  They are left untouched for making the changes simpler.

This patch is based on the early work by Rostislav Krasny:
  https://patchwork.kernel.org/project/git/patch/pull.979.git.1623687519832.gitgitgadget@gmail.com
I refreshed, revised and extended to the latest state.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
gitk provides scrolling of several windows, uses hard-coded values for
the amount of scrolling, and these values differ across platforms and
widgets. The nominal value used is either 1 text line per mouse /
touchpad / button event, or 5 lines. Furthermore, Tk does not scroll
text widgets by 1 line when told to, this usually gets 2-3 lines of
motion. The upper canvas objects holding the commit graph do scroll as
defined. But, clearly no value is universally preferred, so let's give
the user some control over this. Provide a single multiplier to be
applied for all scroll bindings, with a value of 3 to mean the default
nominal value of 3 line. This is selected both as a compromise between
the various defaults across platforms, and because it is the smallest
value honored by the two text widgets on the bottom of the screen.

Later commits will connect this variable for actual scrolling events.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk supports scrolling of 5 windows, but does this differently on the
aqua, x11, and win32 platforms as Tk provides different events on each.
TIP 171 removes some differences on win32 while altering the required
bindings on x11. TIP 474, which is in Tk 8.7 and later, finally unifies
all platforms on using common MouseWheel bindings. Importantly for now,
TIP 171 causes delivery of MouseWheel events to the widget under the
mouse cursor on win32, eliminating the need for completely different
bindings on win32.

Let's make some common functions to unify as much as we can in Tk 8.6.
Examining the platforms shows that the default platform scrolling is
overridden differently on the 3 platforms, and the nominal amount of
motion achieved per mouse wheel "click" is different. win32 nominally
makes everything move 5 lines per click, aqua 1 line per click, and x11
is a mixture. Part of this is due to win32 overriding all scroll events,
while x11 and aqua override smaller sets. Also, note that the text
widgets (the lower two panes) always scroll by 2-3 lines when given a
smaller scroll amount, while the upper three canvas objects follow the
requested scrolling value more accurately.

First, let's have a common routine to calculate the scroll value to give
to a widget in an event. This accounts for the user preference, the
scale of the %D (delta) value given by the event (120 on win32, 1 on
aqua, assumed 1 on x11), and must always be integer. Include negation as
by convention the screen moves opposite to the MouseWheel delta. Allow
setting an offset value to account for the larger minimum scrolling of
text widgets.

Second, let's have a common declaration of MouseWheel event bindings, as
those are shared by all in Tcl9, and by aqua/win32 earlier. Bind all
five display windows here. Note that the Patch/Tree widget (cflist)
cannot scroll horizontally.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk on win32 binds windows_mousewheel_redirector to all MouseWheel
events in the main window. This proc determines the widget under the
cursor, then determines what scroll command to give, possibly none, and
issues scroll commands to the widget. The top panes get only vertical
scroll events, as does the lower right Patch/Tree pane. All others get
both vertical and horizontal events. These are all hard coded at +/-
five lines.

We now have common MouseWheel event bindings that follow user
preferences for the scrolling amount, bind for only the five main
display widgets, and leave the other gui elements untouched. Let's use
this instead. With the scrolling preference set at 5, the users should
not notice much, if any, difference.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk has x11 mouse bindings that receive button presses, not MouseWheel
events, as this is the Tk implementation through Tk 8.6. On x11, gitk
translates each button event to a scrolling value of +/- 5 for the upper
three panes that scroll vertically as one unit. gitk applies similar
scaling for horizontal scaling of the lower-left commit details pane
(ctext), but not for vertical scrolling of either of the bottom panes.
Rather, the Tk default scrolling actions are used for vertical
scrolling.

Let's make X11 behave similarly to the just modified win32 platform. Do
so by connecting vertical and horizontal scrolling events for the same
items bound in 'proc bind_mousewheel' and using the same user preference
values.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Tk provides MouseWheel events to aqua, similar to win32. But, these
events on aqua have a nominal motion value (%D) of 1, not 120 as on
win32. gitk on aqua provides specific bindings only for the top 3 panes,
giving a nominal scrolling amount of +/- 1 for all events. gitk includes
a hidden feature providing horizontal scrolling of the commit graph,
added in 5fdcbb1 ("gitk: Fixes for Mac OS X TkAqua", 2009-03-23).
This horizontal scrolling is triggered by mouse events in any of the top
3 panes, and thus violates normal gui design where the object under the
mouse cursor scrolls.

Let's update this using the common bindings in 'proc bind_mousewheel',
allowing user preferences on motion scaling to apply to all windows.
The commit graph scrolling feature is removed by this, and will be added
back for all platforms in a later commit.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk commit 5fdcbb1 ("gitk: Fixes for Mac OS X TkAqua", 2009-03-23),
adds horizontal scrolling of the commit graph pane on aqua, but not on
x11 or win32. Also, the horizontal scrolling is triggered by MouseWheel
events attached to any of the three panes, not just the commit graph
that is the only one that scrolls. It is unusual to scroll a widget that
is not under the mouse, many would consider this a bug. No horizontal
scrollbar is provided for this, so there is no real cue for the user
that horizontal scrolling is available. We removed this aqua only
feature by transitioning aqua to use the common MouseWheel bindings set.

Let's add this as a feature on all platforms, and use the same approach
for scaling scroll motion as we do elsewhere.  For horizontal scrolling,
honor only events received by the commit graph in conformance with
normal GUI design.  Vertical scrolling is unchanged, and events received
by any of the 3 panes continue to scroll all 3 in unison.

Per the ancient and long ignored CUA standards, we should add a
horizontal scrollbar to the commit-graph, but gitk's interface is
already very cluttered: adding a scrollbar to only one of these three
panes is difficult while maintaining common pane vertical size,
especially so considering the movable sash separating panes 1 & 2, and
will consume yet more space. So, leave this as a hidden feature, now
available on all platforms.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
TclTk 8.7 (still in alpha), and 9.0 (released), implement TIP 474 that
delivers uniform handling of mouse and touchpad scrolling events on all
platforms, and by default bound to most widgets. TIP 474 also implements
use of the Option- modifier key (Alt- key on PC, Option- key on Macs) to
indicate desire for more motion per scroll wheel event, the
amplification is not defined but seems to be 5x to 10x.

So, for TclTk >= 8.7 we can use identical MouseWheel bindings on all
platforms, and should enable use of the Option- modifier to enable
larger motion. Let's do all of this, and use a 5x multiplier for the
Option- modifier.

This largely follows the prior win32 model, except that Tk 8.6 does not
reliably use the Option- modifier because the Alt- key conflicts with
builtin behavior to activate the main menubar. Presumably this conflict
is addressed in the win32 Tcl9.x package.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk uses '-encoding binary' in several places to handle non-text data.
Per TIP 699, this is not recommended as there has been too much
confusion and misconfiguration of binary channels, and this option is
removed in Tcl 9.

Tcl defines a binary channel as one that reproduces the input data
exactly. As Tcl stores all data internally in unicode format, a binary
channel requires 3 things:
-  -encoding iso8859-1 : this causes each byte of input to be translated
   to its unicode equivalent (may be multi-byte).
-  -translation lf : this avoids any translation of line endings, which
   by default are translated to \n on input.
-  -eofchar {} : this avoids any use of an end of file character, which
   is ctrl-z by default on Windows.

The recommended '-translation binary' makes all three settings, but this
is not done in gitk now. Rather, gitk uses '-encoding binary', which is
an alias to '-encoding iso8859-1' removed by TIP 699, in multiple places,
and -eofchar {} in one place but not all. All other files, configured in
non-binary fashion, have -eofchar {}.

Unix and Windows differ on line ending conventions, Tcl by default
converts line endings to \n on input, and to those common on the
platform on output. git emits only \n on Unix or Windows. Also, Tcl's
proc gets recognizes and removes \n, \r, or \r\n as line endings, and
this is used by gitk except in procs selectline and parsecommit. But,
those two procs recognize any combination of \n and \r as terminating a
line. So, there is no need to translate line endings on input, and using
-translation binary avoids any such translation.

Tcl sets eofchar to ctrl-z (ascii \0x1a) only on Windows, otherwise
eofchar is {}. This provides compatibility to old DOS based codes and
files originating when file systems recorded only sectors allocated, and
not bytes used. git does not use ctrl-z to terminate data anywhere. Only
two channels in gitk leave eofchar at the default value, both use
-encoding binary now. A third one was converted in commit 681c329
("gitk: Handle blobs containing a DOS end-of-file marker", 2009-03-16),
fixing such a problem of early data termination. Using eofchar {} is
correct, even if not always necessary.

Tcl 9 forces change, using -translation binary per TIP 699 does what
gitk needs and is backwards compatible to Tcl 8.x. Do it.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk looks for configuration files under $(HOME)/.., and uses the
typical shortcut formats to find this, e.g., ~/.config/. This relies
upon Tcl expanding such constructs to replace ~ with $(HOME). But, Tcl 9
has stopped doing that for various reasons, and now supplies [file
tildeexpand ...] to perform this expansion.

There are a very few places that need this expansion, and all must be
modified regardless of approach taken.

POSIX specifies that $HOME be defined at the time of login, and both
Cygwin and MSYS (underlying git for windows) set this variable. Tcl8
uses the POSIX defined pwnam to look up the underlying database record
on Unix, but will get the same result as using $HOME on any POSIX
compliant system. On Windows, Tcl just accesses $HOME, falling back to
other environment variables if $HOME is not set.  Git for Windows has
$HOME defined by MSYS, so this works just as on the others.

As $env(HOME) works in Tcl 8 and 9, while anything using [file
tildeexpand ... ] will not, let's use the simpler approach as doing so
adds no lines of code.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk invokes many git commands expecting output in utf-8 encoding, but
git accepts extended ascii (code page unknown) as utf-8 without
validating, so cannot guarantee valid utf-8 on output.  In particular,
using any extended ascii code page, of which there are many, has long
been acceptable given that everyone on a project is aware of and uses
that same code page to view all data. utf-8 accepts only 7-bit ascii
characters in single bytes, and any characters outside of that base set
require at least two bytes.

Tcl is a string based language, and transcodes all input data to an
internal unicode format, and to whatever format is requested on output:
"pure" binary is recoded using iso8859-1.  Tcl8.x silently recodes
invalid utf-8 as binary data, so extended ascii characters maintain
their binary value on output but may not display correctly.

Tcl 8.7 added three profiles to control this behaviour: strict (raises
exceptions), replace (replaces each invalid byte with ?), and the
default tcl8 maintaining the old behavior.  Tcl 9 changes the default
profile to strict, meaning any invalid utf-8 raises an exception that
gitk does not handle.

An example of this in the git repository is commit 7eb93c8965 ("[PATCH]
Simplify git script", 2005-09-07). This includes extended ascii
characters in the author name and commit message. As a result, gitk +
Tcl 9 cannot view the git repository at any point beyond that commit.
Note: Tcl 9.0 has a bug, to be fixed in 9.1, where this particular
condition results in a memory error causing Tcl to crash [1].

The tcl8 profile used so far has acceptable behavior given gitk's
acceptance: this allows gitk to accept extended ascii though it may
display incorrectly.  Let's continue that behavior by overriding open to
use the tcl8 profile on Tcl9 and later: Tcl 8.6 does not understand
fconfigure -profile, and Tcl 8.7 maintains the tcl8 profile.

[1] Per https://core.tcl-lang.org/tcl/tktview/73bb42fb3f35cd613af6fcea465e35bbfd352216

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk in the prior commit learned to apply -profile tcl8 to all input
data streams, avoiding errors on non-binary data streams whose encoding
is not utf-8. But, gitk also consumes binary data streams (generally blobs
from commits), and internally decodes this to support various displays.

With Tcl9, errors occur in this decoding for the same reasons described
in the previous commit: basically, the underlying data was not validated
to conform to the given encoding, and this source encoding may not be
utf-8. gitk performs this decoding using Tcl's '[encoding convert from'
operator.

For example, the 7th commit in gitk's history has the extended ascii
value 0xA9, so

	gitk 9a40c50

in gitk's repository raises an exception. The error log has:

unexpected byte sequence starting at index 11: '\xA9'
    while executing
"encoding convertfrom $diffencoding $line"
    (procedure "parseblobdiffline" line 135)
    invoked from within
"parseblobdiffline $ids $line"
    (procedure "getblobdiffline" line 16)
    invoked from within
"getblobdiffline file6 9a40c50"
    ("eval" body line 1)
    invoked from within
"eval $script"
    (procedure "dorunq" line 11)
    invoked from within
"dorunq"
    ("after" script)

This problem has a similar fix to the prior issue: we must use the tlc8
profile when converting this data. Do so, again only on Tcl9 as Tcl8.6
does not recognize -profile, and only Tcl 9.0 makes strict the default.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
Tcl/Tk 9.0 has been released, and has shipped in Fedora 42. Prior
patches in this sequence have addressed known incompatibilities, so gitk
is now operating with Tcl9. So, let's allow Tcl9.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk tests for having Tk being at least 8.5 or 8.6, using this
to enable code that will not work on earlier versions. But, gitk
now requires Tcl+Tk >= 8.6, so remove code for earlier versions.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
If a file is renamed between commits and an external diff is started
through gitk on the original or the renamed file name,
gitk is unable to open the renamed file in the external diff editor.
It fails to fetch the renamed file from git, because it fetches it
using its original path in contrast to using the renamed path of the
file.
Detect the rename and open the external diff with the original and
the renamed file instead of no file (fetch the renamed file path and
name from git) no matter if the original or the renamed file is
selected in gitk.
Since moved or renamed file are handled the same way do this also
for moved files.

Signed-off-by: Tobias Boesch <tobias.boesch@miele.com>
Signed-off-by: Johannes Sixt <j6t@kdbg.org>
External tools such as Jujutsu may add many references that are of no
interest to the user. This preference allows hiding them.

Signed-off-by: Ori Avtalion <ori@avtalion.name>
* js/more-merge-heads:
  gitk: enable --merge after conflicted cherry-picks and reverts
* js/offset-label-lines:
  Offset label lines to not hide history lines.
* js/do-restore-position:
  Revert "gitk: Only restore window size from ~/.gitk, not position"
* tb/external-diff-renamed:
  gitk: add external diff file rename detection
* ti/support-sha256:
  gitk: Add support of SHA256 repo
* ml/tcltk-9:
  gitk - remove implementations for Tcl/Tk < 8.6
  gitk: allow Tcl/Tk 9.0+
  gitk: use -profile tcl8 on encoding conversions
  gitk: use -profile tcl8 for file input with Tcl 9
  gitk: Tcl9 doesn't expand ~, use $env(HOME)
  gitk: switch to -translation binary
  gitk: update scrolling for TclTk 8.7+ / TIP 474
  gitk: allow horizontal commit-graph scrolling
  gitk: update aqua scrolling for TclTk 8.6 / TIP171
  gitk: update x11 scrolling for TclTk 8.6 / TIP 171
  gitk: update win32 scrolling for Tk 8.6 / TIP 171
  gitk: mousewheel scrolling functions for Tk 8.6
  gitk: wheel scrolling multiplier preference
  gitk: separate x11 / win32 / aqua Mouse bindings
  gitk: Make TclTk 8.6 the minimum, allow 8.7

# Conflicts:
#	gitk
…6t-testing

* 'hide_custom_refs' of github.com:salty-horse/gitk:
  gitk: Add user preference to hide specific references

# Conflicts:
#	gitk
gitk has alternate code paths for early git up to 1.72, and has no
defined minimum version. Setting any version > 1.72 as minimum will
allow removing those code paths.

The recent set of advisories published for git, gitk, and git-gui add
updates for v2.43 and later, but Debian has buster withgit 2.20 still
available.  While Debian would be responsible for backporting any fixes
to such an early version, we have no good reason preclude it.
So, make 2.20 the minimum required git version.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk has a few code fragments that are used only for git versions <=
1.7.2 that do not support submodules, notes, word differences, or
texconv filters. We just set the minimum git version higher than 1.7.2
so these code fragments have no effect. Delete them.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
mark987 added 3 commits July 9, 2025 12:25
gitk added the option to used themed Tk (ttk) in 0cc08ff ("gitk: Add
a user preference to enable/disable use of themed widgets", 2009-09-05).
Using ttk had to be optional as Tk 8.4, then in common use, did not have
ttk. However, the above commit made ttk the default when available, so
the ttk code paths are by now very well tested. However, this means gitk
has many code paths to support both widget sets, increasing the
maintenance burden.

All ttk features used by gitk are available from the first Tk 8.6
release, and gitk now requires Tk >= 8.6. Let's make ttk non-optional,
allowing code simplification in subsequent commits.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk uses ${NS} to select between the original Tk widgets, and the newer
themed widgets, the former are in the anonymous global namespace, while
the themed ones are in the ttk namespace.  As gitk uses only themed
widgets, this indirection now serves no purpose. Let's switch to
explicit use of ttk:: via global search/replace. More simplification,
including removal of the NS variable, is kept for a later patch to keep
this one smaller.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
gitk has code paths and variables to use the earlier non-themed widget
set, but this code is made irrelevant by prior commits to use only the
ttk widgets. Clean this up.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
@j6t
Copy link
Owner

j6t commented Jul 10, 2025

Thanks, this is certainly the way to go!

But please do not build on top of j6t-testing. I guess the potential conflict arises from the removal of ${NS}. In this case, I suggest that we remove all uses that are in master, but do not remove the variable so that it is still available for the topic branches.

@mark987
Copy link
Contributor Author

mark987 commented Jul 11, 2025

Removing pre-ttk support depends upon the updates for Tcl/Tk 8.6, basically the last commit in what you carry as 'ml/tcltk-9', a3a7e5e. There are three major topics convolved:

  1. eliminate support for early git
  2. updates for Tcl/Tk 8.6
  3. updates for Tcl/Tk 8.7+, including 9.0

Unfortunately, these lead to merge conflicts, regardless of order. Any other topic adding / removing a global variable is likely to conflict, so keeping all of the current in-flight topics open and independent is problematic.

I can rearrange ml/tcltk-9 into early git support removal, Tcl 8.6 updates, including ttk removal, then Tcl 8.7/9.0 support if you desire. Or, just let ml/tcltk-9 get integrated to master and I'll return with ttk, etc. later. Let me know.

BTW - I have a similar but larger series for git-gui to get to the same goals (remove early git support, Tcl 8.6, then 8.6/9+). Conflicts abound again there, so I'll follow whatever order we settle on with gitk.

@j6t
Copy link
Owner

j6t commented Jul 13, 2025

Would it make sense that you pick the commits from #20 that are necessary for this feature here, and then rebuild the remaining patches of #20 on top of this branch?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants