\IfTargetDateBefore doesn’t use dates from \DeclareRelease and \DeclareCurrentRelease

latex-basepackage-writing

I am a little confused with the rollback mechanism in LaTeX. I want to let users test the future breaking changes of my package and also I want to keep the future changes in the same package file. So I tried the following demo file:

\begin{filecontents*}[force]{demo.sty}
\NeedsTeXFormat{LaTeX2e}[2018-04-01]
\DeclareRelease{v2026}{2026-01-01}{demo.sty}
\DeclareCurrentRelease{}{2022-01-01}
\IfTargetDateBefore{2026-01-01}{\newcommand\test{old}}{\newcommand\test{new}}
\end{filecontents*}

\documentclass{article}

%\usepackage{demo}[=v2026] % the result is "new" even if I write \IfTargetDateBefore{2027-01-01}

%\usepackage{demo}[=2026-01-01] % the result is "new"

%\usepackage{demo} % the result is "new" but I expect it would be "old"

%\usepackage{demo}[=2022-01-01] % ! LaTeX Error: Suspicious rollback date given.

\begin{document}

\test

\end{document}

The questions are:

(1) Is it correct to make \DeclareRelease use the same package file as \DeclareCurrentRelease?

(2) Why \IfTargetDateBefore doesn't use the dates in \DeclareRelease and \DeclareCurrentRelease as target dates?

(3) For \DeclareRelease, I have given both name and date in declaring a release, but it is strange that \usepackage{demo}[=<name>] and \usepackage{demo}[=<date>] still behave differently.

[Update] Based on the answer of Frank Mittelbach, I have another question:

(4) Is it a good idea to provide \DeclareFutureRelease{<name>}{<date>} command after \DeclareCurrentRelease for this use case? This command doesn't include a <file> argument, and it only maps the <name> to <date> so that \IfTargetDateBefore can use it. In general, <name> such as beta is much easier to remember than <date> such as 2026-01-01.

Best Answer

The rollback mechanism in LaTeX is a lightweight "roll back" mechanism, not a roll forward one, even though it does support rolling forward in a limited restricted way.

In particular it only applies if there is an explicit request for a dated roll back, but it does not do anything if not, and if you have a request for a named version then it just jumps to that version and again doesn't look at dates.

Furthermore all release dates have to be (as documented) in increasing order, e.g., you can't have a current release of 2022 and a previous of 2026. See https://www.latex-project.org/publications/2018-FMi-TUB-tb122mitt-version-rollback.pdf.

I have augmented your example a bit and commented on the cases, hope that helps.

The only form the mechanism supports "future releases" is to give them just a name but not a date, and then tell your users to try out "v2023-beta" and inside such a file \IfTargetDateBefore has no effect.


\begin{filecontents}[force]{demo.sty}
\NeedsTeXFormat{LaTeX2e}[2018-04-01]
\DeclareRelease{v2025}{2025-01-01}{demo0.sty}
\DeclareRelease{v2026}{2026-01-01}{demo.sty}
\DeclareRelease{v2027}{2027-01-01}{demo2.sty}
\DeclareCurrentRelease{}{2022-01-01}

\typeout{testing for \pkgcls@innerdate}

\IfTargetDateBefore{2025-12-31}{\renewcommand\testa{\typeout{testa=old}}}{\renewcommand\testa{\typeout{testa=new}}}
\IfTargetDateBefore{2026-01-01}{\renewcommand\testb{\typeout{testb=old}}}{\renewcommand\testb{\typeout{testb=new}}}
\IfTargetDateBefore{2027-01-01}{\renewcommand\testc{\typeout{testc=old}}}{\renewcommand\testc{\typeout{testc=new}}}
\end{filecontents}


\documentclass{article}

\providecommand\testa{\typeout{testa=unset}}
\providecommand\testb{\typeout{testb=unset}}
\providecommand\testc{\typeout{testc=unset}}

\makeatletter
\let\pkgcls@debug\typeout
\makeatother

\usepackage{demo}[=v2026] % the result is "new" even if I write \IfTargetDateBefore{2027-01-01}
%
% no release date give so \IfTargetDateBefore is always new because the assumption is that the named release contains the current code for that name 

%\usepackage{demo}[=2026-01-01] % the result is "new"
%
% this is correct because the new code was at 2026-01-01 and not before


\usepackage{demo} % the result is "new" but I expect it would be "old"
%
% no request for rollback so current file is used with the assumption that everything is "new" any \IfTargetDateBefore contains old code in its first argument.

%\usepackage{demo}[=2022-01-01] % ! LaTeX Error: Suspicious rollback date given.
%
% first dated release is for 2025 so LaTeX complains (because release dates have to be ordered by date).

\begin{document}

\testa \testb \testc

\end{document}

With the internal debugging turned on, so you get something like

LaTeX Warning: Writing or overwriting file `./demo.sty'.


(/usr/local/texlive/2022/texmf-dist/tex/latex/base/article.cls
Document Class: article 2021/10/04 v1.4n Standard LaTeX document class
(/usr/local/texlive/2022/texmf-dist/tex/latex/base/size10.clo))
--- File loaded request (\usepackage or ...)
    1: demo
    2: 
    3: =v2026
    4: sty
(./demo.sty
---\DeclareRelease:
    1: v2025
    2: 2025-01-01
    3: demo0.sty
Label doesn't match
---\DeclareRelease:
    1: v2026
    2: 2026-01-01
    3: demo.sty
Result: use demo.sty
(./demo.sty
testing for \maxdimen 
Include code introduced on 2025-12-31
Include code introduced on 2026-01-01
Include code introduced on 2027-01-01
))
--- File loaded request (\usepackage or ...)
    1: l3backend-pdftex
    2: 
    3: 
    4: def
(/usr/local/texlive/2022/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def)
(./rollback.aux)
testa=new
testb=new
testc=new

from the above.

To answer your questions from the end of your post:

(1) it works as long as you don't confuse the algorithm by putting the dates in random order, but it is a bit pointless as you achieve the same effect by not using that \DeclareRelease line at all as it will then fall through to current release and uses \IfTargetReleaseBefore if a dated release is asked for.

(2) because that would require more testing and thus making each and every package processing slower (and quite frankly, because your idea was not considered as a use case).

(3) named and dated release selection behave differently because the "named" one has the assumption that the file it points to contains the "current" code for the named release so any \IfTarget... selected the new code branch.