TeX - LaTeX Asked by CL. on April 1, 2021
I use Git to track changes on my TEX files. When producing a PDF, it would be nice to include the current branch and commit ID somewhere in the document (e.g. on the title page or in a footer).
I know that the package gitinfo2 exists but I’d rather avoid adding any hooks to Git. Besides, I am aware of this question but I would prefer a solution that does not require enabling write18
.
Given that the name of the current branch can be found in .git/HEAD
and the current commit ID is stored in .git/refs/heads/[name of branch]
, is it possible to embed this information in the final document?
As stated in the question, the branch name can be extracted from .git/HEAD
and given [branch name]
, the commit ID can be found in .git/refs/heads/[branch name]
.
The package catchfile
provides the command CatchFileDef
, which allows us to read .git/HEAD
into a macro. As HEAD
has no file extension, MiKTeX users have to add a trailing dot to the file name:
CatchFileDef{headfull}{.git/HEAD.}{}
This assigns something like ref: refs/heads/master
to headfull
. As this string has a trailing whitespace character, we use StrGobbleRight
from the xstring package to trim it:1
StrGobbleRight{headfull}{1}[head]
In order to extract only the branch name (master
in the example) from this string, we can use StrBehind
:
StrBehind[2]{head}{/}[branch]
This saves the branch name in branch
. Finally, we can use CatchFileDef
again, to save the commit ID in commit
:
CatchFileDef{commit}{.git/refs/heads/branch.}{}
There are some edge cases where .git/refs/heads/branch.
does not exist: After running git pack-refs
(which is a side effect of git gc --aggressive
, for example), the heads are packed into the file .git/packed-refs
instead of individual branchname
files. As a workaround, check if the file exists before trying to read it:
IfFileExists{.git/refs/heads/branch.}{%
CatchFileDef{commit}{.git/refs/heads/branch.}{}}{%
newcommand{commit}{dots~(in emph{packed-refs})}}
As a fallback, this creates the (not-so-useful) output "... (in packed-refs)" instead of a commit ID – but this only lasts until the next commit, when the file heads/branchname
is recreated for the affected branch.
(A more ambitious workaround could parse packed-refs
, of course.)
documentclass{article}
usepackage{xstring}
usepackage{catchfile}
CatchFileDef{headfull}{.git/HEAD.}{}
StrGobbleRight{headfull}{1}[head]
StrBehind[2]{head}{/}[branch]
IfFileExists{.git/refs/heads/branch.}{%
CatchFileDef{commit}{.git/refs/heads/branch.}{}}{%
newcommand{commit}{dots~(in emph{packed-refs})}}
begin{document}
This revision: texttt{commit} on branch texttt{branch}.
end{document}
This revision:
d92dc1386e48e04ceecb85461ed3b232146e6a32
on branchmaster
.
1 Using the last optional argument of StrGobbleRight
(name
) to assign the trimmed string to a macro (head
) is necessary to allow further manipulation of the string using the xstring
functions – see here for a discussion.
Correct answer by CL. on April 1, 2021
A no-package approach (tested on mac os, modify it for Windows regarding extra needed dot perhaps) based on @CL.'s answer.
documentclass{article}
newcommanddotGitHEAD{}
newcommandbranch{}
newcommandcommit{}
makeatletterletmyfilehandle@inputcheckmakeatother
openinmyfilehandle=.git/HEADrelax
begingroupendlinechar-1
globalreadmyfilehandle to dotGitHEAD
endgroup
closeinmyfilehandle
newcommandGetBranch{}
defGetBranch ref: refs/heads/#1relax{renewcommand{branch}{#1}}
expandafterGetBranchdotGitHEADrelax
openinmyfilehandle=.git/refs/heads/branchrelax
begingroupendlinechar-1
globalreadmyfilehandle to commit
endgroup
closeinmyfilehandle
begin{document}
branch+++
commit+++
This revision: texttt{commit} on branch texttt{branch}.
end{document}
Package getcommit
:
ProvidesPackage{getcommit}[2018/10/16 get current commit and branch (JFB)]
@ifundefined{branch}{}
{PackageWarning{getcommit}{ATTENTION!^^J
@spaces@spacesstringbranchspace macro was already
defined. Overwritten.}}
@ifundefined{commit}{}
{PackageWarning{getcommit}{ATTENTION!^^J
@spaces@spacesstringcommitspace macro was already
defined. Overwritten.}}
openin@inputcheck=.git/HEADrelax
begingroupendlinechar-1
globalread@inputcheck to getcommit@HEAD
endgroup
closein@inputcheck
defgetcommit@GetBranch ref: refs/heads/#1relax{defbranch{#1}}
expandaftergetcommit@GetBranchgetcommit@HEADrelax
openin@inputcheck=.git/refs/heads/branchrelax
begingroupendlinechar-1
globalread@inputcheck to commit
endgroup
closein@inputcheck
endinput
Example of use:
documentclass{article}
usepackage{getcommit}
begin{document}
+++branch+++
+++commit+++
%frenchspacing
This revision: texttt{commit} on branch texttt{branch}.
end{document}
Answered by user4686 on April 1, 2021
We can use input
instead read
primitive:
defgitdir{.git/}
defreadgitcommitA #1 {defgitcommit{#1}}
defreadgitbranchA #1 #2 {defgitbranch{#2}}
defreadgitcommit{expandafterreadgitbranchA input gitdir HEAD
expandafterreadgitcommitA input gitdirgitbranchrelax}
readgitcommit
Now, the commit ID is in "gitcommit" macro.
Answered by wipet on April 1, 2021
If you are using latexmk
,
you can use an alternative approach to intialize gitinfo2
,
that does not require git hooks (https://github.com/rbarazzutti/gitinfo2-latexmk).
Setup:
$ git submodule add https://github.com/rbarazzutti/gitinfo2-latexmk gitinfo2-latexmk
$ echo "do './gitinfo2-latexmk/gitinfo2.pm';" >> latexmkrc
Usage:
usepackage[mark]{gitinfo2}
Answered by canochordo on April 1, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP