%% %% Copyright (C) 2014 by Julien Cretel %% %% This work may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either version 1.3 %% of this license or (at your option) any later version. %% The latest version of this license is in %% %% http://www.latex-project.org/lppl.txt %% %% and version 1.3 or later is part of all distributions of LaTeX %% version 2005/12/01 or later. %% %% This work has the LPPL maintenance status `maintained'. %% %% The Current Maintainer of this work is Julien Cretel. %% %% This work currently consists of the file gitdags.sty. %% \NeedsTeXFormat{LaTeX2e}[2011/06/27] \ProvidesClass{gitdags} [2014/08/28 v0.1 A package for drawing educational Git history graphs] \DeclareOption*{\PassOptionsToPackage{\CurrentOption}{tikz}} \ProcessOptions\relax \RequirePackage{xcolor-solarized} \RequirePackage{tikz} \usetikzlibrary{ arrows.meta, graphs, positioning, shadows, shapes, } % conflict color \colorlet{conflictcolor}{red} % custom shape, adapted from 102.5.3 in the TikZ 3.0 manual \pgfdeclareshape{dogeared}{ \inheritsavedanchors[from=rectangle] \inheritanchorborder[from=rectangle] \inheritanchor[from=rectangle]{center} \inheritanchor[from=rectangle]{north} \inheritanchor[from=rectangle]{south} \inheritanchor[from=rectangle]{west} \inheritanchor[from=rectangle]{east} \backgroundpath{% \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y \pgf@xc=\pgf@xb \advance\pgf@xc by-5pt \pgf@yc=\pgf@yb \advance\pgf@yc by-5pt \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}} \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yb}} \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yc}} \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}} \pgfpathclose \pgfpathmoveto{\pgfpoint{\pgf@xc}{\pgf@yb}} \pgfpathlineto{\pgfpoint{\pgf@xc}{\pgf@yc}} \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yc}} \pgfpathclose } } % To cancel a shadow (see http://tex.stackexchange.com/a/198298/21891) \tikzset{reset preaction/.code={\def\tikz@preactions{}}} % --- repository history graphs --- % style definitions \tikzset{ gitdags node/.style={ draw, node distance = 1.4em, drop shadow = {opacity=0.15}, font = \fontfamily{lmtt}\selectfont\small, }, DAGref/.style={ gitdags node, shape = rectangle, minimum height = 1.4em, draw = solarized-base01, thick, font = \fontfamily{lmtt}\selectfont\scriptsize, }, DAGedge/.style={ semithick, Latex-, draw = gray, }, DAGrefedge/.style={ DAGedge, thick, densely dotted, }, DAGcommit/.style={ gitdags node, shape = rounded rectangle, rounded rectangle arc length = 90, minimum height = 1.6em, minimum width = 2em, draw = solarized-base01, fill = solarized-green!20, very thick, }, graphs/DAG/.style={ nodes = DAGcommit, edges = DAGedge, branch down = 3em, grow right sep = 1.5em, }, gitareas/.style={ gitdags node, shape = rectangle, rounded corners = .5em, minimum width = 7em, minimum height = 3em, text opacity = 0.75, semithick, }, gitSA/.style={ gitareas, anchor = north west, xshift = 1em, yshift = -1em, draw = solarized-orange, fill = solarized-orange!5, text = solarized-orange, }, gitWT/.style={ gitareas, node distance = .6em, draw = solarized-violet, fill = solarized-violet!5, text = solarized-violet, }, resetarrows/.style={ -Stealth, dashed, thick, draw = solarized-base02, draw opacity = .75, }, highlighted commit/.style={ DAGcommit, reset preaction, fill opacity = 0, draw = solarized-base02, }, problematic commits/.style={ reset preaction, draw opacity = .25, fill opacity = .25, }, graphs/unreachable/.style={ problematic commits, target edge style = problematic commits, }, graphs/conflict/.style={ empty nodes, problematic commits, target edge style = problematic commits, draw = conflictcolor, fill = conflictcolor!25, }, placeholder commits/.style={ reset preaction, draw opacity = 0, fill opacity = 0, }, graphs/placeholder/.style={ placeholder commits, target edge style = placeholder commits, }, blob/.style={ shape = dogeared, minimum width = 2em, minimum height = 2.82em, node distance = .75em, line join = bevel, draw = black, fill = white, align = left, font = \ttfamily\tiny, }, } % directed acyclic graph \newcommand\gitDAG[1][]{\graph[DAG,#1]} % helper macro (let's check the name's availability) \newcommand\nodename@gitdags{} % local-branch reference \newcommand\gitbranch[4][]{% \renewcommand\nodename@gitdags{#1}% \if\relax\detokenize{#1}\relax% check for empty optional argument \renewcommand\nodename@gitdags{#2}% \fi \node[ DAGref, fill = yellow!30, ] (\nodename@gitdags) [#3] {#2}; \draw[DAGrefedge] (#4) -- (\nodename@gitdags); } % remote-branch reference \newcommand\gitremotebranch[4][]{% \renewcommand\nodename@gitdags{#1}% \if\relax\detokenize{#1}\relax% check for empty optional argument \renewcommand\nodename@gitdags{#2}% \fi \node[ DAGref, fill = solarized-blue!20, ] (\nodename@gitdags) [#3] {#2}; \draw[DAGrefedge] (#4) -- (\nodename@gitdags); } % tag reference \newcommand\gittag[4][]{% \renewcommand\nodename@gitdags{#1}% \if\relax\detokenize{#1}\relax% check for empty optional argument \renewcommand\nodename@gitdags{#2}% \fi \node[ DAGref, fill = solarized-magenta!20, ] (\nodename@gitdags) [#3] {#2}; \draw[DAGrefedge] (#4) -- (\nodename@gitdags); } % HEAD symbolic reference \newcommand\gitHEAD[2]{% \node[ DAGref, fill = solarized-red!20, node distance = 1em, ] (gitHEAD) [#1] {HEAD}; \draw[DAGrefedge] (#2) -- (gitHEAD); } % the following macro is useful for explaining how merge conflicts arise \newcommand\gitblob[2][] {\node[blob,#1] {#2};} % to highlight a merge conflict arising in a given file \newcommand\gitblobmc[1]{% \node[ blob, draw = conflictcolor, text = conflictcolor, font = \scriptsize, #1] {???}; } % staging area and worktree \newcommand\SAandWT{% \node[ gitSA, ] (stagingarea) at (current bounding box.south east) {staging area}; \node[ gitWT, below=of stagingarea, ] (workingtree) {working tree}; } % arrows pointing from a commit to the staging area or working tree \newcommand\toSAorWT[2]{% \node[highlighted commit] at (#1) {\phantom{#1}}; \draw[resetarrows] (#1.south) to[out=290, in=170] ([xshift=1em,yshift=-1em]#2.north west); } \newcommand\toSAfrom[1]{\toSAorWT{#1}{stagingarea}} \newcommand\toWTfrom[1]{\toSAorWT{#1}{workingtree}} \endinput