Commit Graph

78494 Commits (master)

Author SHA1 Message Date
Junio C Hamano 45547b60ac Merge branch 'master' of https://github.com/j6t/gitk
* 'master' of https://github.com/j6t/gitk:
  gitk: set minimum size on configuration dialog
  gitk: separate code blocks for configuration dialog
  gitk: make configuration dialog resizing useful
  gitk: add theme selection to color configuration page
  gitk: add proc run_themeloader
  gitk: eliminate unused ui color variables
  gitk: eliminate Interface color option from gui
  gitk: use text labels for next/prev search buttons
  gitk: use text labels for commit ID buttons
  gitk: do not invoke tk_setPalette
  gitk: use config variables to define and load a theme
  gitk: make sha1but a ttk::button
  gitk: use themed spinboxes
  gitk: fix MacOS 10.14 "Mojave" crash on launch
  gitk: fix error when remote tracking branch is deleted
2025-10-05 13:32:47 -07:00
Johannes Sixt c435c515da Merge branch 'ml/themes'
* ml/themes:
  gitk: set minimum size on configuration dialog
  gitk: separate code blocks for configuration dialog
  gitk: make configuration dialog resizing useful
  gitk: add theme selection to color configuration page
  gitk: add proc run_themeloader
  gitk: eliminate unused ui color variables
  gitk: eliminate Interface color option from gui
  gitk: use text labels for next/prev search buttons
  gitk: use text labels for commit ID buttons
  gitk: do not invoke tk_setPalette
  gitk: use config variables to define and load a theme
  gitk: make sha1but a ttk::button
  gitk: use themed spinboxes

Signed-off-by: Johannes Sixt <j6t@kdbg.org>
2025-10-05 13:09:49 +02:00
Mark Levedahl 6565ca8220 gitk: set minimum size on configuration dialog
gitk sets no size limit on its configuration dialog, allowing the user
to collapse the window so almost nothing is visible. The geometry
manager sets an initial size so all the widgets are visible, though
ignores the potentially very long text in the entry widgets in doing so.
Let's use this initial size as the minimum. The size information is
computed in Tk's idle processing queue, so a wait is required.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-10-04 10:37:18 -04:00
Mark Levedahl 8e65d38064 gitk: separate code blocks for configuration dialog
gitk's configuration dialog uses a large number of widgets, and this
code is hard to read as there is no easily recognizable grouping or
breaks. Help this by adding space between items that occupy a single row
in the dialog.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-10-04 10:37:18 -04:00
Mark Levedahl b9f6b8237d gitk: make configuration dialog resizing useful
gitk's configuration dialog can be resized, but this does not expand the
space allocated to any widgets. Some items may have long lines of text
that would be visible if the widgets expanded, but this does not happen.

The top-level container uses a two column grid and allocates any space
change equally to both columns.  However, the configuration pages are
contained in one cell so half the additional space is wasted if
expanding. Also, the individual configuration pages do not mark any
column or widgets to expand, so any additional space given is just used
as padding.

Collapse the top-level page to have one column, placing the "OK" and
"Cancel" buttons in a non-resizing frame in column 1 (this keeps the
buttons in constant geometry as the dialog is expanded). This makes all
additional space go to the configuration page.

Mark column 3 of the individual pages to get all additional space, and
mark the text widgets in that column so they will expand to use the
space. While we're at it, eliminate or simplify use of frames to contain
column 2 content, and harmonize the indents of that content.

prefspage_general adds a special "spacer" label in row 2, column 1, that
causes all of the subsequent rows with no column 1 content to indent,
and this carries over to the next notebook tab (prefspage_color) through
some undocumented feature. The fonts page has a different indent, again
for unknown reason. The documented approach would be to use -padx
explicitly on all the rows to set the indents.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-10-04 10:31:40 -04:00
Johannes Sixt ead1687a3e Merge branch 'es/ignore-osascript-failure'
* es/ignore-osascript-failure:
  gitk: fix MacOS 10.14 "Mojave" crash on launch
2025-10-04 15:36:42 +02:00
Johannes Sixt d7cedce063 Merge branch 'mr/sort-refs-by-type'
* mr/sort-refs-by-type:
  gitk: fix error when remote tracking branch is deleted
2025-10-04 15:36:12 +02:00
Junio C Hamano 5099f64a82 The fourteenth batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-10-02 12:26:13 -07:00
Junio C Hamano 7ae9eaf806 Merge branch 'kh/you-still-use-whatchanged-fix'
The "do you still use it?" message given by a command that is
deeply deprecated and allow us to suggest alternatives has been
updated.

* kh/you-still-use-whatchanged-fix:
  BreakingChanges: remove claim about whatchanged reports
  whatchanged: remove not-even-shorter clause
  whatchanged: hint about git-log(1) and aliasing
  you-still-use-that??: help the user help themselves
  t0014: test shadowing of aliases for a sample of builtins
  git: allow alias-shadowing deprecated builtins
  git: move seen-alias bookkeeping into handle_alias(...)
  git: add `deprecated` category to --list-cmds
  Makefile: don’t add whatchanged after it has been removed
2025-10-02 12:26:12 -07:00
Junio C Hamano 2f49ec7991 Merge branch 'ps/meson-build-docs'
The build procedure based on meson learned a target to only build
documentation, similar to "make doc".

* ps/meson-build-docs:
  ci: don't compile whole project when testing docs with Meson
  meson: print docs backend as part of the summary
  meson: introduce a "docs" alias to compile documentation only
2025-10-02 12:26:12 -07:00
Junio C Hamano 2ddbf1431d Merge branch 'ps/config-get-color-fixes'
The use of "git config get" command to learn how ANSI color
sequence is for a particular type, e.g., "git config get
--type=color --default=reset no.such.thing", isn't very ergonomic.

* ps/config-get-color-fixes:
  builtin/config: do not spawn pager when printing color codes
  builtin/config: special-case retrieving colors without a key
  builtin/config: do not die in `get_color()`
  t1300: small style fixups
  t1300: write test expectations in the test's body
2025-10-02 12:26:12 -07:00
Junio C Hamano f2d464b9f5 Merge branch 'cc/fast-import-strip-signed-commits'
"git fast-import" learned that "--signed-commits=<how>" option that
corresponds to that of "git fast-export".

* cc/fast-import-strip-signed-commits:
  fast-import: add '--signed-commits=<mode>' option
  gpg-interface: refactor 'enum sign_mode' parsing
2025-10-02 12:26:12 -07:00
Junio C Hamano db0babf9b2 Merge branch 'ms/refs-optimize'
"git refs optimize" is added for not very well explained reason
despite it does the same thing as "git pack-refs"...

* ms/refs-optimize:
  t: add test for git refs optimize subcommand
  t0601: refactor tests to be shareable
  builtin/refs: add optimize subcommand
  doc: pack-refs: factor out common options
  builtin/pack-refs: factor out core logic into a shared library
  builtin/pack-refs: convert to use the generic refs_optimize() API
  reftable-backend: implement 'optimize' action
  files-backend: implement 'optimize' action
  refs: add a generic 'optimize' API
2025-10-02 12:26:12 -07:00
Junio C Hamano fd13909eb6 Merge branch 'jt/odb-transaction'
The work to build on the bulk-checkin infrastructure to create many
objects at once in a transaction and to abstract it into the
generic object layer continues.

* jt/odb-transaction:
  odb: add transaction interface
  object-file: update naming from bulk-checkin
  object-file: relocate ODB transaction code
  bulk-checkin: drop flush_odb_transaction()
  builtin/update-index: end ODB transaction when --verbose is specified
  bulk-checkin: remove ODB transaction nesting
2025-10-02 12:26:11 -07:00
Mark Levedahl c0932eda80 gitk: add theme selection to color configuration page
gitk allows configuring a particular theme in its configuration file
(default on linux: ~/.config/git/gitk), but offers no ability to modify
this from gitk's configuration editor. Let's add this to the color
configuration page.

Present the offered themes in a list, and allow choosing / modifying a
theme definition file ($themeloader). Update the list of themes if the
theme file is modified, and update the theme if specifically requested
(by default, just change the value for use after gitk is restarted).

Any theme definition file can change the global options database,
affecting potentially any theme. So, the ultimate configuration should
have either
- no theme definition file (themeloader = {}), and a native Tk, theme,
or
- themeloader naming a valid file, and $theme naming a theme defined by
  that file.

But, there is no trivial way to enforce the above. Shrug.

Helped-by: Johannes Sixt <j6t@kdbg.org>
Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-10-01 13:54:31 -04:00
Mark Levedahl 830c4578cd gitk: add proc run_themeloader
gitk currently accepts a single themeloader file via the config file,
and will source this with errors reported to the console. This is fine
for simple configuration, but will not support interactive theme
exploration from the gui. In particular, a themeloader file must be
sourced only once as the themes defined cannot be re-defined. Also,
errors must be handled rather than just aborting while printing to the
console.  So, add a proc to handle the above, supporting expansion of
the gui config pages.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:54:09 -04:00
Mark Levedahl 83a2de9ca6 gitk: eliminate unused ui color variables
gitk has a number of variables used in setting up colors for the classic
(non-themed) widget set. These variables are unused with ttk, so let's
eliminate them. But, leave the variables in the config file for now -
those can be eliminated after this change is merged.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:53:59 -04:00
Mark Levedahl 1eadf0f3e0 gitk: eliminate Interface color option from gui
gitk offers to change the ui color on the colors prefs page, but the
variable set has no effect because gitk is using themes. Let's eliminate
the "Interface" color selection option from that page.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:53:55 -04:00
Mark Levedahl 9950eff841 gitk: use text labels for next/prev search buttons
gitk allows searching for commits with various criteria, and provides
up/down search buttons to facilitate this search. These buttons are
labelled with bitmaps, and those bitmaps are not always recolored
correctly for the ui scheme as the theme colors are not known. Let's
just use text labels on these, allowing the styles to handle any
coloring needed. Use utf codepoints for the arrows, presuming that these
code points are available in the selected font.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:53:46 -04:00
Mark Levedahl 61c0cfe08c gitk: use text labels for commit ID buttons
gitk maintains a stack of commit ids visited, and allows navigating
these using a pair of buttons shown with arrows using bitmaps. An attempt
is made to recolor these bitmaps to handle different color schemes, but
this is unreliable across multiple themes as the required colors are not
universally known. Let's just use text labels for these buttons,
allowing the themes to recolor the text along with everything else. Use
utf code points for the text, presuming that these arrow glyphs are
available in the selected font.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:53:40 -04:00
Mark Levedahl 7754656a4c gitk: do not invoke tk_setPalette
gitk uses themed widgets with a user selected theme, but also invokes
tk_setPalette to configure colors for the non-themed widgets including
the menubar. However, themes in general are expected to configure
those colors already. The builtin themes (default, alt, clam, classic on
unix/X11) all have compatible colors, and need no such reconfiguration,
and (most, if not all) available themes set the options database for this
purpose as well. Furthermore, gitk in the past avoided invoking
tk_setPalette on Windows to avoid some issues.

So, let's stop calling tk_setPalette everywhere, and just rely upon the
selected theme (possibly user installed) to have set all needed colors.

Note: if a user installs more than one theme using $themeloader, the last
one installed will have defined the colors to be used. Those colors will
probably be incorrect for any other set, including Tk's builtin set.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:53:29 -04:00
Mark Levedahl 8ccb2d4a76 gitk: use config variables to define and load a theme
gitk uses themed tk, but has no capability to alter the theme defined
by Tk. While there are documented ways to install other themes, and
to make one the default, these methods are obscure at best. Instead,
let's offer two config variables:

- theme  this is the name of the theme to use, and must be available.
- themeloader - this is the full pathname of a tcl script that
  will load one or more themes into the Tk namespace.

By default, theme is set to the theme active when Tk is started, and
themeloader = {}.  These variables must be defined to something else to
have any user visible effect.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-29 20:53:21 -04:00
Junio C Hamano 821f583da6 The thirteenth batcn
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-29 11:40:36 -07:00
Junio C Hamano d5518d52b2 Merge branch 'tc/last-modified-recursive-fix'
"git last-modified" operating in non-recursive mode used to trigger
a BUG(), which has been corrected.

* tc/last-modified-recursive-fix:
  last-modified: fix bug when some paths remain unhandled
2025-09-29 11:40:35 -07:00
Junio C Hamano 96ed0a8906 Merge branch 'kn/refs-files-case-insensitive'
Deal more gracefully with directory / file conflicts when the files
backend is used for ref storage, by failing only the ones that are
involved in the conflict while allowing others.

* kn/refs-files-case-insensitive:
  refs/files: handle D/F conflicts during locking
  refs/files: handle F/D conflicts in case-insensitive FS
  refs/files: use correct error type when lock exists
  refs/files: catch conflicts on case-insensitive file-systems
2025-09-29 11:40:35 -07:00
Junio C Hamano a89fa2fff2 Merge branch 'jk/color-variable-fixes'
Some places in the code confused a variable that is *not* a boolean
to enable color but is an enum that records what the user requested
to do about color.  A couple of bugs of this sort have been fixed,
while the code has been cleaned up to prevent similar bugs in the
future.

* jk/color-variable-fixes:
  config: store want_color() result in a separate bool
  add-interactive: retain colorbool values longer
  color: return bool from want_color()
  color: use git_colorbool enum type to store colorbools
  pretty: use format_commit_context.auto_color as colorbool
  diff: stop passing ecbdata->use_color as boolean
  diff: pass o->use_color directly to fill_metainfo()
  diff: don't use diff_options.use_color as a strict bool
  diff: simplify color_moved check when flushing
  grep: don't treat grep_opt.color as a strict bool
  color: return enum from git_config_colorbool()
  color: use GIT_COLOR_* instead of numeric constants
2025-09-29 11:40:35 -07:00
Junio C Hamano a5d4779e6e Merge branch 'dk/stash-apply-index'
The stash.index configuration variable can be set to make "git stash
pop/apply" pretend that it was invoked with "--index".

* dk/stash-apply-index:
  stash: honor stash.index in apply, pop modes
  stash: refactor private config globals
  t3905: remove unneeded blank line
  t3903: reduce dependencies on previous tests
2025-09-29 11:40:35 -07:00
Junio C Hamano cff1e3c870 Merge branch 'je/doc-checkout'
Doc updates.

* je/doc-checkout:
  doc: git-checkout: clarify restoring files section
  doc: git-checkout: split up restoring files section
  doc: git-checkout: deduplicate --detach explanation
  doc: git-checkout: clarify `-b` and `-B`
  doc: git-checkout: clarify `git checkout <branch>`
  doc: git-checkout: clarify ARGUMENT DISAMBIGUATION
  doc: git-checkout: clarify intro sentence
2025-09-29 11:40:34 -07:00
Junio C Hamano 4bac57bc67 Merge branch 'jk/setup-revisions-freefix'
There are double frees and leaks around setup_revisions() API used
in "git stash show", which has been fixed, and setup_revisions()
API gained a wrapper to make it more ergonomic when using it with
strvec-manged argc/argv pairs.

* jk/setup-revisions-freefix:
  revision: retain argv NULL invariant in setup_revisions()
  treewide: pass strvecs around for setup_revisions_from_strvec()
  treewide: use setup_revisions_from_strvec() when we have a strvec
  revision: add wrapper to setup_revisions() from a strvec
  revision: manage memory ownership of argv in setup_revisions()
  stash: tell setup_revisions() to free our allocated strings
2025-09-29 11:40:34 -07:00
Junio C Hamano 84edf99568 Merge branch 'pw/rebase-i-cleanup-fix'
"git rebase -i" failed to clean-up the commit log message when the
command commits the final one in a chain of "fixup" commands, which
has been corrected.

* pw/rebase-i-cleanup-fix:
  sequencer: remove VERBATIM_MSG flag
  rebase -i: respect commit.cleanup when picking fixups
2025-09-29 11:40:34 -07:00
Junio C Hamano d960d6a6fb Merge branch 'jc/3.0-default-initial-branch-to-main-addendum'
Keep giving hint about the default initial branch name for users
who may be surprised after Git 3.0 switch-over.

* jc/3.0-default-initial-branch-to-main-addendum:
  initial branch: give hints after switching the default name
2025-09-29 11:40:34 -07:00
Junio C Hamano e50c3ca095 Merge branch 'pw/3.0-default-initial-branch-to-main'
Declare that "git init" that is not otherwise configured uses
'main' as the initial branch, not 'master', starting Git 3.0.

* pw/3.0-default-initial-branch-to-main:
  t0613: stop setting default initial branch
  t9902: switch default branch name to main
  t4013: switch default branch name to main
  breaking-changes: switch default branch to main
2025-09-29 11:40:34 -07:00
Junio C Hamano d235f69ae8 Merge branch 'nb/send-email-no-dup-reply-to'
"git send-email --compose --reply-to=<address>" used to add
duplicated Reply-To: header, which made mailservers unhappy.  This
has been corrected.

* nb/send-email-no-dup-reply-to:
  send-email: don't duplicate Reply-to: in intro message
2025-09-29 11:40:33 -07:00
Junio C Hamano 347af012db Merge branch 'ps/clar-updates'
Import a newer version of the clar unit testing framework.

* ps/clar-updates:
  t/unit-tests: update to 10e96bc
  t/unit-tests: update clar to fcbed04
2025-09-29 11:40:33 -07:00
Mark Levedahl fe2005e723 gitk: make sha1but a ttk::button
gitk's 'Commit ID' button uses a classic widget, not a themed one,
leading to inconsistent style. Commit 51a7e8b654 (d93f1713b0 ("gitk: Use
themed tk widgets", 2009-04-17) that added themed widgets did not touch
this particular widget, but does not say why. Regardless, let's use a
themed button to be consistent with the rest of the interface.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-25 15:55:57 -04:00
Mark Levedahl 811b8a34b9 gitk: use themed spinboxes
gitk uses classic (non-themed) spinboxes rather than the ttk variants.
Commit d93f1713b0 ("gitk: Use themed tk widgets", 2009-04-17) that added
ttk makes no mention of why ttk:spinboxes were omitted, but this leads
to an inconsistent interface. Let's use the ttk version.

Signed-off-by: Mark Levedahl <mlevedahl@gmail.com>
2025-09-25 12:04:02 -04:00
Junio C Hamano bb69721404 The twelfth batch
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-23 11:53:40 -07:00
Junio C Hamano 3e0e2e3a5c Merge branch 'cs/subtree-squash-split-fix'
"git subtree" (in contrib/) did not work correctly when splitting
squashed subtrees, which has been improved.

* cs/subtree-squash-split-fix:
  contrib/subtree: fix split with squashed subtrees
2025-09-23 11:53:40 -07:00
Junio C Hamano 7c15d990cc Merge branch 'rs/get-oid-with-flags-cleanup'
Code clean-up.

* rs/get-oid-with-flags-cleanup:
  use repo_get_oid_with_flags()
2025-09-23 11:53:40 -07:00
Junio C Hamano 2e8d7569ea Merge branch 'jk/add-i-color'
Some among "git add -p" and friends ignored color.diff and/or
color.ui configuration variables, which is an old regression, which
has been corrected.

* jk/add-i-color:
  contrib/diff-highlight: mention interactive.diffFilter
  add-interactive: manually fall back color config to color.ui
  add-interactive: respect color.diff for diff coloring
  stash: pass --no-color to diff plumbing child processes
2025-09-23 11:53:40 -07:00
Junio C Hamano 2be606a3bd Merge branch 'cc/promisor-remote-capability'
The "promisor-remote" capability mechanism has been updated to
allow the "partialCloneFilter" settings and the "token" value to be
communicated from the server side.

* cc/promisor-remote-capability:
  promisor-remote: use string_list_split() in mark_remotes_as_accepted()
  promisor-remote: allow a client to check fields
  promisor-remote: use string_list_split() in filter_promisor_remote()
  promisor-remote: refactor how we parse advertised fields
  promisor-remote: use string constants for 'name' and 'url' too
  promisor-remote: allow a server to advertise more fields
  promisor-remote: refactor to get rid of 'struct strvec'
2025-09-23 11:53:40 -07:00
Jeff King a04bc71725 revision: retain argv NULL invariant in setup_revisions()
In an argc/argv pair, the entry for argv[argc] is generally NULL. You
can iterate by counting up to argc, or by looking for the NULL entry in
argv.

When we pass such a pair to setup_revisions(), it shrinks argc to
account for the options we consumed and returns the result to the
caller. But it doesn't touch the entries after the reduced argc. So
argv[argc] will be left pointing at some arbitrary entry rather than
NULL.

This isn't the source of any known bugs, since all callers are aware of
the limitation and act accordingly. But it's a possible gotcha that may
be easy to miss.

Let's set the new argv[argc] to NULL, taking care to free it if the
caller asked us to do so.

It is tempting to do likewise for all of the entries afterwards, too, as
some of them may also need to be freed (e.g., if coming from a strvec).
But doing so isn't entirely trivial, as we munge argc in the function
(e.g., when we find "--" and move all of the entries after it into the
prune_data list). It would be possible with some light refactoring, but
it's probably not worth it. Nobody should ever look at them (they are
beyond the revised argc and past the NULL argv entry) outside of strvec
cleanup, and setup_revisions_from_strvec() already handles this case.

There's one other interesting gotcha: many callers which do not want to
provide arguments just pass 0/NULL for argc/argv. We need to check for
this case before assigning the final NULL.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 14:27:03 -07:00
Jeff King 18068139f2 treewide: pass strvecs around for setup_revisions_from_strvec()
The previous commit converted callers of setup_revisions() with a strvec
to use the safer and easier _from_strvec() variant.

Let's now convert spots that don't directly have a strvec, but receive
an argc/argv pair that eventually comes from one. We'll instead pass the
strvec down to the point where we call setup_revisions().

That makes these functions slightly less flexible if they were to grow
other callers that don't use strvecs, but this rigidity is buying us
some safety. It is only safe to pass the free_removed_argv_elements
option to setup_revisions() if we know the elements of argv/argc are
allocated on the heap. That isn't communicated in the type system when
we are passed the bare elements. But if we get a strvec, we know that
the elements are allocated strings.

And at any rate, each of these modified functions has only a single
caller (that has a strvec), so the loss of flexibility is unlikely to
ever matter.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 14:27:03 -07:00
Jeff King b553332f82 treewide: use setup_revisions_from_strvec() when we have a strvec
The previous commit introduced a wrapper to make using setup_revisions()
with a strvec easier and safer. It converted spots that were already
doing most of what the wrapper did.

Let's now convert spots where we were not setting up the
free_removed_argv_elements flag. As discussed in the previous commit,
this probably isn't fixing any bugs or leaks (since these sites wouldn't
trigger the re-shuffling of argv that causes them). This is mostly
future-proofing us against setup_revisions() becoming more aggressive
about its re-shuffling.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 14:27:03 -07:00
Jeff King f93c1d86cc revision: add wrapper to setup_revisions() from a strvec
The setup_revisions() function was designed to take the argc/argv pair
from the operating system. But we sometimes construct our own argv using
a strvec and pass that in. There are a few gotchas that callers need to
deal with here:

  1. You should always pass the free_removed_argv_elements option via
     setup_revision_opt. Otherwise, entries may be leaked if
     setup_revisions() re-shuffles options.

  2. After setup_revisions() returns, the strvec state is odd. We get a
     reduced argc from setup_revisions() telling us how many unknown
     options were left in place. Entries after that in argv may be
     retained, or may be NULL (depending on how the reshuffling
     happened). But the strvec's "nr" field still represents the
     original value, and some of the entries it thinks it is still
     storing may be NULL. Callers must be careful with how they access
     it.

Some callers deal with (1), but not all. In practice they are OK because
they do not pass any options that would cause setup_revisions() to
re-shuffle (namely unknown options which may be relayed from the user,
and the use of the "--" separator). But it's probably a good idea to
consistently pass this option anyway to future-proof ourselves against
the details of setup_revisions() changing.

No callers address (2), though I don't think there any visible bugs.
Most of them simply call strvec_clear() and never otherwise look at the
result. And in fact, if they naively set foo.nr to the argc returned by
setup_revisions(), that would cause leaks!  Because setup_revisions()
does not free consumed options[1], we have to leave the "nr" field of
the strvec at its original value to find and free them during
strvec_clear().

So I don't think there are any bugs to fix here, but we can make things
safer and simpler for callers. Let's introduce a helper function that
sets the free_removed_argv_elements automatically and shrinks the strvec
to represent the retained options afterwards (taking care to free the
now-obsolete entries).

We'll start by converting all of the call-sites which use the
free_removed_argv_elements option. There should be no behavior change
for them, except that their "shrunken" entries are cleaned up
immediately, rather than waiting for a strvec_clear() call.

[1] Arguably setup_revisions() should be doing this step for us if we
    told it to free removed options, but there are many existing callers
    which will be broken if it did. Introducing this helper is a
    possible first step towards that.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 14:27:03 -07:00
Jeff King cd43948798 revision: manage memory ownership of argv in setup_revisions()
The setup_revisions() function takes an argc/argv pair and consumes
arguments from it, returning a reduced argc count to the caller. But it
may also overwrite entries within the argv array, as it shifts unknown
options to the front of argv (so they can be found in the range of
0..argc-1 after we return).

For a normal argc/argv coming from the operating system, this is OK.
We don't need to worry about memory ownership of the strings in those
entries. But some callers pass in allocated strings from a strvec, and
we do need to care about those.

We faced a similar issue in f92dbdbc6a (revisions API: don't leak memory
on argv elements that need free()-ing, 2022-08-02), which added an
option for callers to tell us that elements need to be freed. But the
implementation within setup_revisions() was incomplete.  It only covered
the case of dropping "--", but not the movement of unknown options.

When we shift argv entries around, we should free the elements we are
about to overwrite, so they are not leaked. For example, in:

  git stash show -p --invalid

we will pass this to setup_revisions():

  argc = 3, argv[] = { "show", "-p", "--invalid", NULL }

which will then return:

   argc = 2, argv[] = { "show", "--invalid", "--invalid", NULL }

overwriting the "-p" entry, which is leaked unless we free it at that
moment.

You can see in the output above another potential problem. We now have
two copies of the "--invalid" string. If the caller does not respect the
new argc when free-ing the strings via strvec_clear(), we'll get a
double-free. And git-stash suffers from this, and will crash with the
above command.

So it seems at first glance that the solution is to just assign the
reduced argc to the strvec.nr field in the caller. Then it would stop
after freeing only any copied entries. But that's not always right
either!

Remember that we are reducing "argc" to account for elements we've
consumed. So if there isn't an invalid option, we'd turn:

  argc = 2, argv[] = { "show", "-p", NULL }

into:

  argc = 1, argv[] = { "show", "-p", NULL }

In that case strvec_clear() must keep looking past the shortened argc we
return to find the original "-p" to free. It needs to use the original
argc to do that.

We can solve this by turning our argv writes into strict moves, not
copies. When we shuffle an unknown option to the front, we'll overwrite
its old position with NULL. That leaves an argv array that may have NULL
"holes" in it.

So in the "--invalid" example above we get:

   argc = 2, argv[] = { "show", "--invalid", NULL, NULL }

but something like "git stash -p --invalid -p" would yield:

  argc = 3, argv[] = { "show", "--invalid", NULL, "-p", NULL }

because we move "--invalid" to overwrite the first "-p", but the second
one is quietly consumed. But strvec_clear() can handle that fine (it
iterates over the "nr" field, and passing NULL to free() is OK).

To ease the implementation, I've introduced a helper function. It's a
little hacky because it must take a double-pointer to set the old
position to NULL. Which in turn means we cannot pass "&arg", our local
alias for the current entry we're parsing, but instead "&argv[i]", the
pointer in the original array. And to make it even more confusing, we
delegate some of this work to handle_revision_opt(), which is passed a
subset of the argv array, so is always working on "&argv[0]".

Likewise, because handle_revision_opt() only receives the part of argv
left to parse, it receives the array to accumulate unknown options as a
separate unkc/unkv pair. But we're always working on the same argv
array, so our strategy works fine. I suspect this would be a bit more
obvious (and avoid some pointer cleverness) if all functions saw the
full argv array and worked with positions within it (and our new helper
would take two positions, a src and dst). But that would involve
refactoring handle_revision_opt().  I punted on that, as what's here is
not too ugly and is all contained within revision.c itself.

The new test demonstrates that "git stash show -p --invalid" no longer
crashes with a double-free (because we move instead of copy). And it
passes with SANITIZE=leak because we free "-p" before overwriting.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 14:27:03 -07:00
Jeff King 3ea35c64b0 stash: tell setup_revisions() to free our allocated strings
In "git stash show", we do a first pass of parsing our command line
options by splitting them into revision args and stash args. These are
stored in strvecs, and we pass the revision args to setup_revisions().

But setup_revisions() may modify the argv we pass it, causing us to leak
some of the entries. In particular, if it sees a "--" string, that will
be dropped from argv. This is the same as other cases addressed by
f92dbdbc6a (revisions API: don't leak memory on argv elements that need
free()-ing, 2022-08-02), and we should fix it the same way: by passing
the free_removed_argv_elements option to setup_revisions().

The added test here is run only with SANITIZE=leak, without checking its
output, because the behavior of stash with "--" is a little odd:

  1. Running "git stash show" will show --stat output. But running "git
     stash show --" will show --patch.

  2. I'd expect a non-option after "--" to be treated as a pathspec, so:

       git stash show -p 1 -- foo

     would look treat "1" as a stash (a synonym for stash@{1}) and
     restrict the resulting diff to "foo". But it doesn't. We split the
     revision/stash args without any regard to "--". So in the example
     above both "1" and "foo" are stashes. Which is an error, but also:

       git stash show -- foo

     treats "foo" as a stash, not a pathspec.

These are both oddities that we may want to address (or may not, if we
want to retain historical quirks). But they are well outside the scope
of this patch. So for now we'll just let the tests confirm we aren't
leaking without otherwise expecting any behavior. If we later address
either of those points and end up with another test that covers "stash
show --", we can drop this leak-only test.

Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 14:24:52 -07:00
Patrick Steinhardt 93dbb6b3c5 t/unit-tests: update to 10e96bc
Update to 10e96bc (Merge pull request #127 from
pks-gitlab/pks-ci-improvements, 2025-09-22). This commit includes a
couple of changes:

  - The GitHub CI has been updated to include a 32 bit CI job.
    Furthermore, the jobs now compile with "-Werror" and more warnings
    enabled.

  - An issue was addressed where `uintptr_t` is not available on
    NonStop [1].

  - The clar selftests have been restructured so that it is now possible
    to add small test suites more readily. This was done to add tests
    for the above addressed issue, where we now use "%p" to print
    pointers in a platform dependent way.

  - An issue was addressed where the test output had a trailing
    whitespace with certain output formats, which caused whitespace
    issues in the test expectation files.

[1]: <01c101dc2842$38903640$a9b0a2c0$@nexbridge.com>

Reported-by: Randall S. Becker <rsbecker@nexbridge.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 10:09:03 -07:00
Patrick Steinhardt e4dabf4fd6 builtin/config: do not spawn pager when printing color codes
With `git config get --type=color` the user asks us to parse a specific
configuration key and turn the value into an ANSI color escape sequence.
The printed string can then for example be used as part of shell scripts
to reuse the same colors as Git.

Right now though we set up the auto-pager, which means that the string
may be written to the pager instead of directly to the terminal. This
behaviour is problematic for two reasons:

  - Color codes are meant for direct terminal output; writing them into
    a pager does not seem like a sensible thing to do without additional
    text.

  - It is inconsistent with `git config --get-color`, which never uses a
    pager, despite the fact that we claim `git config get --type=color`
    to be a drop-in replacement in git-config(1).

Fix this by disabling the pager when outputting color sequences.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 09:32:57 -07:00
Patrick Steinhardt 54b24b1080 builtin/config: special-case retrieving colors without a key
Our documentation for git-config(1) has a section where it explains how
to parse and use colors as Git would configure them. In order to get the
ANSI color escape sequence to reset the colors to normal we recommend
the following command:

    $ git config get --type=color --default="reset" ""

This command is not supposed to parse any configuration keys. Instead,
it is expected to parse the "reset" default value and turn it into a
proper ANSI color escape sequence.

It was reported though [1] that this command doesn't work:

    $ git config get --type=color --default="reset" ""
    error: key does not contain a section:

This error was introduced in 4e51389000 (builtin/config: introduce "get"
subcommand, 2024-05-06), where we introduced the "get" subcommand to
retrieve configuration values. The preimage of that commit used `git
config --get-color "" "reset"` instead, which still works.

This use case is really quite specific to parsing colors, as it wouldn't
make sense to give git-config(1) a default value and an empty config key
only to return that default value unmodified. But with `--type=color` we
don't return the value directly; we instead parse the value into an ANSI
escape sequence.

As such, we can easily special-case this one use case:

    - If the provided config key is empty;

    - the user is asking for a color code; and

    - the user has provided a default value,

then we call `get_color()` directly. Do so to make the documented
command work as expected.

[1]: <aI+oQvQgnNtC6DVw@szeder.dev>

Reported-by: SZEDER Gábor <szeder.dev@gmail.com>
Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2025-09-22 09:32:57 -07:00