Sitelet https://github.com/git-quick-stats/git-quick-stats/commit/d407af3aba10d1eb099b7ec3824ef6fec151bfdf
Skip to content

Commit d407af3

Browse files
committed
GNU date requirements for macOS and FreeBSD
1 parent 125eec7 commit d407af3

3 files changed

Lines changed: 65 additions & 29 deletions

File tree

‎README.md‎

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -280,15 +280,16 @@ sudo make reinstall
280280

281281
### macOS (homebrew)
282282

283-
macOS requires GNU coreutils to be installed and for the non "g" aliased
284-
versions to be exported to your path. The following is an example of how to
285-
perform this if you are using Homebrew as your package manager.
283+
`git-quick-stats` requires GNU `date`. On macOS, install GNU coreutils:
286284

287285
```bash
288286
brew install coreutils
289287
export PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH"
290288
```
291289

290+
The script auto-detects GNU date as either `date` or `gdate`, so exporting
291+
`gnubin` is optional for this project.
292+
292293
From there, you can install via Homebrew as follows:
293294

294295
```bash
@@ -297,10 +298,20 @@ brew install git-quick-stats
297298

298299
Or you can follow the UNIX and Linux instructions if you wish.
299300

300-
If you would like to default to using the GNU coreutils (recommended), then you
301-
can add `export PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH"` to
302-
your applicable `~/.bash_profile`, `~/.zprofile`, or other relevant profile
303-
based on the shell of your choice.
301+
If you would like to default to using GNU coreutils system-wide, add
302+
`export PATH="$HOMEBREW_PREFIX/opt/coreutils/libexec/gnubin:$PATH"` to your
303+
applicable `~/.bash_profile`, `~/.zprofile`, or other relevant profile based
304+
on the shell of your choice.
305+
306+
### FreeBSD
307+
308+
`git-quick-stats` requires GNU `date`. On FreeBSD, install GNU coreutils:
309+
310+
```bash
311+
pkg install coreutils
312+
```
313+
314+
FreeBSD provides GNU date as `gdate`, and the script auto-detects it.
304315

305316
### Windows
306317

@@ -322,6 +333,7 @@ You can use the Docker image provided:
322333
## System requirements
323334

324335
- An OS with a Bash shell
336+
- GNU `date` available as either `date` or `gdate`
325337
- Tools we use:
326338

327339
```bash

‎git-quick-stats‎

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,15 @@ COLOR_DARKEST_RED=$(tput setaf 52)
2828
COLOR_GRAY=$(tput setaf 240)
2929
COLOR_RESET=$(tput sgr0)
3030

31+
# Detect GNU date command (may be 'gdate' on FreeBSD/macOS with coreutils)
32+
if date --version >/dev/null 2>&1; then
33+
_DATE_CMD="date"
34+
elif gdate --version >/dev/null 2>&1; then
35+
_DATE_CMD="gdate"
36+
else
37+
_DATE_CMD="date"
38+
fi
39+
3140
# Beginning git log date. Respects all git datetime formats
3241
# If $_GIT_SINCE is never set, look at the repository to find the first date.
3342
# NOTE: previously this put the date at the fixed GIT epoch (May 2005)
@@ -45,7 +54,7 @@ _until=${_GIT_UNTIL:-}
4554
if [[ -n "${_until}" ]]; then
4655
_until="--until=$_until"
4756
else
48-
_until="--until=$(LC_TIME=C date '+%a, %d %b %Y %H:%M:%S %Z')"
57+
_until="--until=$(LC_TIME=C $_DATE_CMD '+%a, %d %b %Y %H:%M:%S %Z')"
4958
fi
5059

5160
# Set files or directories to be excluded in stats
@@ -128,13 +137,13 @@ function commitsCalendarByAuthor() {
128137
# Gather commit counts
129138
git -c log.showSignature=false log --use-mailmap $_merges \
130139
--date=iso --author="$author" "$_since" "$_until" $_log_options \
131-
--pretty='%ad' $_pathspec | awk '
140+
--pretty='%ad' $_pathspec | awk -v date_cmd="$_DATE_CMD" '
132141
{
133142
split($0, a, " ");
134143
# a[1] = YYYY-MM-DD
135144
split(a[1], date_fields, "-");
136145
mon = date_fields[2] + 0;
137-
cmd = "date -d \"" a[1] "\" +%u";
146+
cmd = date_cmd " -d \"" a[1] "\" +%u";
138147
cmd | getline weekday;
139148
close(cmd);
140149
# weekday: 1=Mon, ..., 7=Sun
@@ -204,14 +213,14 @@ function commitsHeatmap() {
204213

205214
local i
206215
for i in $(seq $((_commit_days-1)) -1 0); do
207-
local day=$(date -d "-$i days" +"%Y-%m-%d")
208-
if [[ $(date -d "$day" +%u) -gt 5 ]]; then
216+
local day=$($_DATE_CMD -d "-$i days" +"%Y-%m-%d")
217+
if [[ $($_DATE_CMD -d "$day" +%u) -gt 5 ]]; then
209218
echo -en "${COLOR_GRAY}"
210219
else
211220
echo -en "${COLOR_RESET}"
212221
fi
213222

214-
local dayName=$(date -d "$day" +%a)
223+
local dayName=$($_DATE_CMD -d "$day" +%a)
215224
printf "%s | %s |" "$dayName" "$day"
216225

217226
declare -a commits_per_hour
@@ -264,7 +273,7 @@ function commitsHeatmap() {
264273
################################################################################
265274
function checkUtils() {
266275
readonly MSG="not found. Please make sure this is installed and in PATH."
267-
readonly UTILS="awk basename cat column date echo git grep head printf seq \
276+
readonly UTILS="awk basename cat column echo git grep head printf seq \
268277
sort tput tr uniq"
269278

270279
for u in $UTILS
@@ -274,16 +283,13 @@ function checkUtils() {
274283

275284
# NOTE: The --version flag is only available in GNU date which is required
276285
# for how the current date/time strings are used in this shell script.
277-
# To fully support the legacy BSD date found in a default install within
278-
# macOS and older distributions of Linux and Unix, a handful of helper
279-
# functions can probably be created to handle every case of incompatibility
280-
# between the two. Until that's implemented, it is probably best to warn
281-
# the user that this will not work rather than having it silently bomb out
282-
# during runtime.
283-
if ! date --version >/dev/null 2>&1; then
286+
# On FreeBSD and macOS the system date is BSD date; GNU date may be
287+
# installed as 'gdate' via coreutils. _DATE_CMD is auto-detected above.
288+
if ! "$_DATE_CMD" --version >/dev/null 2>&1; then
284289
echo "ERROR: GNU date is required."
285-
echo "If you're on macOS, please install it using 'brew install coreutils'."
286-
echo "Ensure that your PATH is configured to use GNU date as well."
290+
echo "On macOS, install it with: brew install coreutils"
291+
echo "On FreeBSD, install it with: pkg install coreutils (provides gdate)"
292+
echo "Ensure that GNU date (or gdate) is in your PATH."
287293
echo "See the README.md for further details."
288294
exit 1
289295
fi
@@ -680,7 +686,7 @@ function changelogs() {
680686
local _author=""
681687
local commits=""
682688
local author="${1:-}"
683-
local next=$(date +%F)
689+
local next=$($_DATE_CMD +%F)
684690

685691
if [[ -z "${author}" ]]; then
686692
optionPicked "Git changelogs:"
@@ -979,7 +985,7 @@ function newContributors() {
979985
local firstCommit=$(git -c log.showSignature=false log --author="$c" \
980986
--reverse --use-mailmap $_merges "$_since" "$_until" \
981987
--format='%at' $_log_options $_pathspec | filter_ignored_authors | head -n 1)
982-
if [[ $firstCommit -ge $(date -d "$newDate" +%s) ]]; then
988+
if [[ $firstCommit -ge $($_DATE_CMD -d "$newDate" +%s) ]]; then
983989
echo "$c"
984990
fi
985991
done
@@ -1044,7 +1050,7 @@ function parse_year() {
10441050
# Handle the raw UNIX timestamp format i.e. 1697375696 +0000
10451051
if [[ "$date_str" =~ ^[0-9]+(\ [+-][0-9]{4})?$ ]]; then
10461052
timestamp=$(echo "$date_str" | awk '{print $1}')
1047-
year=$(date -d "@$timestamp" '+%Y' 2>/dev/null)
1053+
year=$($_DATE_CMD -d "@$timestamp" '+%Y' 2>/dev/null)
10481054
else
10491055
# Default case can get funky. We need to create a clever regex to
10501056
# handle the default case which is like Mon Oct 15 12:34:56 2023 +0000
@@ -1065,7 +1071,7 @@ function parse_year() {
10651071
date_str=$(echo "$date_str" | awk -F'/' '{print $2"/"$1"/"$3}')
10661072
fi
10671073
# Extract the final date
1068-
year=$(date -d "$date_str" '+%Y' 2>/dev/null)
1074+
year=$($_DATE_CMD -d "$date_str" '+%Y' 2>/dev/null)
10691075
fi
10701076

10711077
echo "$year"
@@ -1361,7 +1367,7 @@ if [[ "$#" -eq 1 ]]; then
13611367
# what people may try. This script doesn't provide any additional
13621368
# output for a bad date since `date`'s STDERR already contains
13631369
# useful information.
1364-
if ! date -d "${newDate}" +%s > /dev/null 2>&1; then
1370+
if ! $_DATE_CMD -d "${newDate}" +%s > /dev/null 2>&1; then
13651371
newDate=""
13661372
fi
13671373
done
@@ -1458,7 +1464,7 @@ if [[ "$#" -eq 0 ]]; then
14581464
11) newDate=""
14591465
while [[ -z "${newDate}" ]]; do
14601466
read -r -p "Since what date? (e.g. '2023-04-13', '13 April 2023', 'last Thursday') " newDate
1461-
if ! date -d "${newDate}" +%s > /dev/null 2>&1; then
1467+
if ! $_DATE_CMD -d "${newDate}" +%s > /dev/null 2>&1; then
14621468
newDate=""
14631469
fi
14641470
done

‎git-quick-stats.1‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ and files. Extracting this information is not always trivial, mostly because
1717
of a gadzillion options to a gadzillion git commands.
1818
This program allows you to see detailed information about a git repository.
1919
.PP
20+
.SH PLATFORM NOTES
21+
.PP
22+
git-quick-stats requires GNU date support for date parsing options.
23+
.PP
24+
On macOS, install GNU coreutils with:
25+
.PP
26+
.B brew install coreutils
27+
.PP
28+
On FreeBSD, install GNU coreutils with:
29+
.PP
30+
.B pkg install coreutils
31+
.PP
32+
GNU date may be available as either
33+
.B date
34+
or
35+
.B gdate
36+
and git-quick-stats auto-detects both.
37+
.PP
2038
.SH GENERATE OPTIONS
2139
.PP
2240
\fB\-h\fR, \-?, \fB\-\-help\fR

0 commit comments

Comments
 (0)