Compare commits

...

51 Commits
2.0.7 ... 2.1.0

Author SHA1 Message Date
Lukáš Mešťan
228e67f879 Merge pull request #99 from tomice/master
Fix issue with env vars not respecting spaces
2020-05-07 10:29:58 +02:00
Tom Ice
891e2277ad Add info on how to use experimental JSON feature
* The JSON output feature was not originally explained well and needed
  some additional information on how it worked. Extra info on how to use
  this feature, as well as reminding people that this is a beta feature,
  was added to help the users when trying out this option

Fixes #96
2020-05-01 17:57:19 -04:00
Tom Ice
cc87b3046f Fix issue with env vars not respecting spaces
* If a space existed within _GIT_SINCE, _GIT_UNTIL, or _GIT_PATHSPEC,
  the shell would split the variable at the first space it saw because
  the variables were not quoted.

  If you were to simply quote the variables, then a null variable would
  get inserted into git's log, and it would cause an error.

  This change adds default values to these variables at all times so
  the variables are always assigned to something that git understands.

Fixes #95
2020-05-01 15:29:33 -04:00
Lukáš Mešťan
7aea224e21 Merge pull request #98 from novadiscovery/97-new-lines-as-percent
add percentage for new lines as well
2020-05-01 11:37:49 +02:00
frederic.cogny
c37492bb4c chore(git-quick-stats): add tab instead of space for nicer alignment between percentage counts 2020-05-01 01:03:21 +02:00
frederic.cogny
c258e34afe feat(git-quick-stats): add percentage for new lines as well 2020-05-01 00:36:10 +02:00
Lukáš Mešťan
9e18cf35d4 Merge pull request #94 from arzzen/patch-issue-91
Update commitsByWeekday sorting
2020-02-18 11:31:35 +01:00
Lukáš Mešťan
24ae67ae57 update commitsByWeekday sorting
Fix inconsistent sum sorting in by-weekday, #91
2020-02-14 09:34:46 +01:00
Lukáš Mešťan
ed0e3cbb6b Merge pull request #93 from tomice/master
Fixing OS X compatibility with merge feature
2020-02-13 09:42:06 +01:00
Tom Ice
46a771138e Fixing OS X compatibility with merge feature
* OS X utilizes an older version of GNU Bash. As such, certain features
  such as lowercase expansion can fail. This commit removes the Bash 4.0
  syntax in favor of a POSIX syntax with awk.
2020-02-11 08:25:44 -05:00
Lukáš Mešťan
9f54b87ed5 Update FUNDING.yml 2020-02-05 09:33:07 +00:00
Lukáš Mešťan
246076f5f6 Bump year 2020-01-20 08:00:06 +00:00
Lukáš Mešťan
c0a1795c1a Merge pull request #89 from arzzen/feature/issue-88
refs #88
2020-01-20 08:57:48 +01:00
Lukáš Mešťan
63b9b42034 Merge pull request #90 from tomice/feature/issue-88
Add view strategy to allow merge commits in stats
2020-01-20 08:53:12 +01:00
Tom Ice
90f9e359c3 Add view strategy to allow merge commits in stats
* Users can now switch between allowing merge commits in their stats,
  showing only merges in the stats, or ignoring merge commits in
  the stats all together.

  Showing merges might be good for people who wish to see the entire
  history as git shows it by default. For this, setting the new variable
  _GIT_MERGE_VIEW to enable will show merge commits in the stats together
  with normal commits.

  Showing only merges might be useful for people who wish to see how
  much of their git history is taken up by merges alone. It can be useful
  for re-evaluating a particular workflow. For this, setting the new var
  _GIT_MERGE_VIEW to exclusive will show only merge commits in the stats.

  The default action is to not display merge commits.

Resolves #88
2020-01-17 10:53:51 -05:00
Lukas Mestan
82ba58e01d refs #88 2020-01-11 14:09:04 +01:00
Lukas Mestan
5b64a8de17 fix path 2019-12-16 14:05:28 +01:00
Lukas Mestan
b77021c545 update .github dir 2019-12-16 14:04:23 +01:00
Lukáš Mešťan
62458b6fd1 Merge pull request #87 from arzzen/arzzen-patch-1
Update issue templates
2019-12-16 14:01:55 +01:00
Lukáš Mešťan
ad5b503eea Update issue templates 2019-12-16 14:01:31 +01:00
Lukas Mestan
96b5dab53f remove docs 2019-12-16 13:58:01 +01:00
Lukáš Mešťan
85b7fb1cdf Create CNAME 2019-12-16 13:11:25 +01:00
Lukáš Mešťan
151b260be1 Update README.md 2019-12-16 11:04:15 +01:00
Lukáš Mešťan
f06b7f4833 Update README.md 2019-12-16 11:01:04 +01:00
Lukáš Mešťan
bf7533afa7 Merge pull request #86 from frxyt/develop
Add Dockerfile
2019-12-16 10:52:26 +01:00
Jérémy WALTHER
27edcf0f7a Add Dockerfile 2019-12-12 19:09:56 +01:00
Lukáš Mešťan
dc72babb20 Merge pull request #82 from 4ndrej/patch-1
refactor checkUtils: remove repeating commands
2019-10-27 10:12:00 +01:00
Andrej
c8ad2fba84 array of util names are read only now 2019-10-25 14:23:15 +02:00
Andrej
5cf8feee53 refactor checkUtils: remove repeating commands
putting checked utils into array and running through the array in for loop cleans the code
2019-10-25 10:41:05 +02:00
Lukáš Mešťan
17fc8f326c Merge pull request #81 from lightopenid/gh-68
update travis yml
2019-10-13 17:49:01 +02:00
Lukas Mestan
d5c17e43c0 update travis yml 2019-10-13 17:44:51 +02:00
Lukáš Mešťan
75c8bdc0de Merge pull request #80 from ProcrastinatorCp/gh-70
Support commits by co-authors
2019-10-13 17:41:05 +02:00
Lukáš Mešťan
1a9be34f4c Update .travis.yml 2019-10-13 17:30:01 +02:00
Chandra Prakash
4979eaa69f Support commits by co-authors
https://github.com/arzzen/git-quick-stats/issues/70

Commits by multiple authors (co-authored-by) were only counted towards main author.
Modified commitsPerAuthor() to include co-author's commits.
2019-10-13 02:16:54 +08:00
Lukáš Mešťan
1ed838f532 Merge pull request #79 from tomice/master
Updating README.md
2019-10-10 14:26:04 +02:00
Tom Ice
0fd9171e11 Adding info on how to exclude files in the docs
* Added information in the README.md to show how to exclude files
  from the stats by utilizing git pathspec
* Updated the built-in help, manpage, and tests to reflect how git
  pathspec can be utilized on files and folders
* Removed the \r tokens that were put in README.md from Windows

Fixes #61
2019-10-10 08:15:42 -04:00
Lukáš Mešťan
b14f364b6a Update FUNDING.yml 2019-10-10 08:08:18 +00:00
Tom Ice
10ad00bcbb Updating README.md
* Added info that demonstrates this utility has the ability to
  choose between running this as "git-quick-stats" or
  "git quick-stats" as requested in Issue #77
* Adjusted Table of Contents to show all sections and subsections
  of the README.md
* Cleaned up some grammar and added some extra info in various
  places
* Ran through VS Code's markdownlint extension and adjusted some
  syntax accordingly
2019-10-09 13:44:52 -04:00
Lukáš Mešťan
539f49bb68 Merge pull request #74 from jorgesumle/master
Update text errors from README.md
2019-09-18 12:21:07 +02:00
Jorge Maldonado Ventura
10bc3106f6 Update text errors from README.md
Hyphens are necessary for compound adjectives
2019-09-18 11:21:05 +02:00
Lukáš Mešťan
7160e3c39d Update README.md 2019-09-17 18:10:16 +02:00
Lukáš Mešťan
f17cbd0ff7 Merge pull request #72 from keur/makefile_destdir
make: Use DESTDIR
2019-08-12 09:42:07 +02:00
Kevin Kuehler
a3cd429850 make: Use DESTDIR
This is more standard than forcing the user to specify the destination
directory as part of PREFIX.
2019-08-11 13:59:33 -07:00
Lukáš Mešťan
e069deaf8a Update FUNDING.yml 2019-06-07 19:01:29 +02:00
Lukáš Mešťan
b1285b828e Create FUNDING.yml 2019-05-28 08:47:17 +00:00
Tom Ice
c11bce17bd Merge pull request #71 from tomice/master
Added ability to save log as a JSON formatted file
2019-05-26 10:27:58 -04:00
Tom Ice
5f0bc1c7cf Removed GPG info from JSON and updated README pics
* The GPG settings don't play well with OS X if you don't have
  certain tools installed, so they were removed from the git log
  format settings for the JSON output.

* Pictures have been updated to reflect the new menu option.
2019-05-24 23:35:11 -04:00
Tom Ice
5f71b785ac Added ability to save log as a JSON formatted file
* The main feature of this commit is addressing the feature request
  of adding the ability to save the output as a file to use in other
  tools. I decided to use the JSON format as it's relatively straight
  forward and easy to create thanks to a few Google searches.

  The original feature request was to add the ability to output any of
  the options as a JSON/XML/YAML format. That said, because this entire project
  is relying only on built-in shell utilities, we kind of have to format stuff
  ourselves in relatively primitive tools such as awk, sed, and bash in order
  to adhere to the "spirit" of this codebase.

  It is possible to use Perl and/or Python, but that would defeat the purpose
  of this, in my opinion. The downside of not using these tools is that it
  might not be as robust and battle hardened as the others.

  AS SUCH, THIS FEATURE IS CURRENTLY EXPERIMENTAL.

  As people provide feedback, we can adjust this and possibly extend it to
  more options. For now, it respects _GIT_SINCE and _GIT_UNTIL. It does not
  respect variable expansion in paths, though, so saving it to a location such
  as "${my_save_location}" will fail.

* Made some of the variables a bit more robust by utilizing the -r flag to
  make the variables readonly. It should be noted that "local readonly" does
  not work, nor does "readonly local". The best way to do this is either via
  "local -r foo=bar" or "local foo=bar && readonly bar".

* Fixed a few comments describing how functions work.

* Added a .gitignore.

* Changed all functions to adhere to camelCase style for no real reason
  other than consistency and a few other minor things.

* Closes #31
2019-05-24 21:15:19 -04:00
Tom Ice
cdb3f20790 Fixing failed test that occurred after merging PR
* This is just a small change to make it so that the build passes
  tests. It is minor and does not affect the release functionality
2019-05-17 17:28:02 -04:00
Tom Ice
dd69477293 Merge pull request #69 from mhickman/master
Change format of _GIT_SINCE in help
2019-05-17 13:00:16 -04:00
Matt Hickman
4aef465e6b Change format of _GIT_SINCE in help
The format _GIT_SINCE is what `git --since` takes in
which is YYYY-MM-DD.

Ref: https://git-scm.com/book/en/v2/Git-Basics-Viewing-the-Commit-History
2019-05-17 09:54:27 -07:00
22 changed files with 512 additions and 873 deletions

5
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
# These are supported funding model platforms
github: [arzzen]
open_collective: git-quick-stats
custom: ['https://lukasmestan.com/thanks/']

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

10
.gitignore vendored Normal file
View File

@@ -0,0 +1,10 @@
*.json
*.db
.DS_Store*
._*
.*.swp
.*.swo
.Spotlight*
.Trash*
**/*~
nbproject/*

View File

@@ -11,8 +11,6 @@ addons:
- cmake
install:
- git checkout ${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}
- git branch --set-upstream-to origin/$TRAVIS_BRANCH
- git rev-parse HEAD
script: make test

27
Dockerfile Normal file
View File

@@ -0,0 +1,27 @@
FROM alpine
# Copy sources
COPY . /app
# Install required packages & build git-quick-stats
RUN apk add --no-cache bash git make ncurses util-linux \
&& cd /app \
&& make install \
&& rm -rf /app \
&& apk del --no-cache make \
&& mkdir -p /usr/local/bin \
&& echo -en "#!/bin/bash\nset -e\n[[ \"\${1::1}\" == '-' ]] && set -- /usr/bin/git quick-stats \"\$@\"\nexec \"\$@\"" \
> /usr/local/bin/docker-entrypoint \
&& chmod +x /usr/local/bin/docker-entrypoint
# Declare all variables usables by git-quick-stats
ENV _GIT_SINCE= \
_GIT_UNTIL= \
_GIT_LIMIT= \
_GIT_PATHSPEC= \
_MENU_THEME=default \
TERM=xterm-256color
WORKDIR /git
ENTRYPOINT [ "/usr/local/bin/docker-entrypoint" ]
CMD [ "/usr/bin/git", "quick-stats" ]

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2019 Lukáš Mešťan
Copyright (c) 2020 Lukáš Mešťan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -1,4 +1,7 @@
PREFIX ?= /usr/local
_INSTDIR ?= $(DESTDIR)$(PREFIX)
BINDIR ?= $(_INSTDIR)/bin
MANDIR ?= $(_INSTDIR)/share/man
TASK_DONE = echo -e "\n✓ $@ done\n"
.PHONY: test
@@ -15,14 +18,14 @@ help:
@$(TASK_DONE)
install:
install -d -m 0755 $(PREFIX)/bin
install -m 0755 git-quick-stats $(PREFIX)/bin/git-quick-stats
install -d -m 0755 $(BINDIR)
install -m 0755 git-quick-stats $(BINDIR)/git-quick-stats
$(MAKE) man
@$(TASK_DONE)
uninstall:
rm -f $(PREFIX)/bin/git-quick-stats
rm -f $(PREFIX)/share/man/man1/git-quick-stats.1
rm -f $(BINDIR)/git-quick-stats
rm -f $(MANDIR)/man1/git-quick-stats.1
@$(TASK_DONE)
reinstall:
@@ -32,8 +35,8 @@ reinstall:
@$(TASK_DONE)
man:
install -d -m 0755 $(PREFIX)/share/man/man1/
install -m 0644 git-quick-stats.1 $(PREFIX)/share/man/man1/
install -d -m 0755 $(MANDIR)/man1/
install -m 0644 git-quick-stats.1 $(MANDIR)/man1/
test:
tests/commands_test.sh

180
README.md
View File

@@ -1,58 +1,96 @@
## GIT quick statistics [![Backers on Open Collective](https://opencollective.com/git-quick-stats/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/git-quick-stats/sponsors/badge.svg)](#sponsors) [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Simple%20and%20efficient%20way%20to%20access%20various%20statistics%20in%20git%20repository&url=https://github.com/arzzen/git-quick-stat&via=arzzen&hashtags=git,stats,tool,statistics,developers) [![Travis](https://api.travis-ci.org/arzzen/git-quick-stats.svg?branch=master)](https://travis-ci.org/arzzen/git-quick-stats) [![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/git-quick-stats.svg)](http://braumeister.org/formula/git-quick-stats) [![Linuxbrew package](https://repology.org/badge/version-for-repo/linuxbrew/git-quick-stats.svg)](https://repology.org/metapackage/git-quick-stats/packages)
# GIT quick statistics [![Backers on Open Collective](https://opencollective.com/git-quick-stats/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/git-quick-stats/sponsors/badge.svg)](#sponsors) [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Simple%20and%20efficient%20way%20to%20access%20various%20statistics%20in%20git%20repository&url=https://github.com/arzzen/git-quick-stat&via=arzzen&hashtags=git,stats,tool,statistics,developers) [![Travis](https://api.travis-ci.org/arzzen/git-quick-stats.svg?branch=master)](https://travis-ci.org/arzzen/git-quick-stats) [![Homebrew package](https://repology.org/badge/version-for-repo/homebrew/git-quick-stats.svg)](http://braumeister.org/formula/git-quick-stats) [![Linuxbrew package](https://repology.org/badge/version-for-repo/linuxbrew/git-quick-stats.svg)](https://repology.org/metapackage/git-quick-stats/packages)
> `git-quick-stats` is a simple and efficient way to access various statistics in git repository.
> Any git repository contains tons of information about commits, contributors, and files. Extracting this information is not always trivial, mostly because of a gadzillion options to a gadzillion git commands I dont think there is a single person alive who knows them all. Probably not even [Linus Torvalds](https://github.com/torvalds) himself :).
![mainMenuScreenshot](https://user-images.githubusercontent.com/8818630/57629726-4704f080-756a-11e9-89cc-f8bdeea3c982.png)
> `git-quick-stats` is a simple and efficient way to access various statistics in a git repository.
>
> Any git repository may contain tons of information about commits, contributors, and files. Extracting this information is not always trivial, mostly because there are a gadzillion options to a gadzillion git commands I dont think there is a single person alive who knows them all. Probably not even [Linus Torvalds](https://github.com/torvalds) himself :).
![mainMenuScreenshot](https://user-images.githubusercontent.com/8818630/58364013-61e53800-7e7b-11e9-87f9-790d6744fbd5.png)
## Table of Contents
[**Screenshots**](#screenshots)
[**Installation**](#installation)
* [**Unix OS**](#unix-like-os)
* [**OS X**](#os-x-homebrew)
* [**Windows**](#windows-cygwin)
[**Usage**](#usage)
* [**Git log since/until**](#git-log-since-until)
* [**Interactive**](#interactive)
* [**Non-interactive**](#non-interactive)
* [**Command-line arguments**](#command-line-arguments)
* [**Git log since and until**](#git-log-since-and-until)
* [**Git log limit**](#git-log-limit)
* [**Git pathspec**](#git-pathspec)
* [**Tests**](#tests)
* [**Git merge view strategy**](#git-merge-view-strategy)
* [**Color themes**](#color-themes)
[**Installation**](#installation)
* [**UNIX and Linux**](#unix-and-linux)
* [**macOS**](#macos-homebrew)
* [**Windows**](#windows)
* [**Docker**](#docker)
[**System requirements**](#system-requirements)
* [**Dependences**](#dependences)
[**Contribution**](#contribution)
* [**Dependencies**](#dependencies)
[**FAQ**](#faq)
[**License**](#licensing)
[**Contribution**](#contribution)
* [**Code reviews**](#code-reviews)
* [**Some tips for good pull requests**](#some-tips-for-good-pull-requests)
* [**Formatting**](#formatting)
[**Tests**](#tests)
[**Licensing**](#licensing)
[**Contributors**](#contributors)
* [**Backers**](#backers)
* [**Sponsors**](#sponsors)
## Screenshots
![commitsByWeekdayScreenshot](https://user-images.githubusercontent.com/8818630/57629719-42d8d300-756a-11e9-8031-8132e14aa10f.png)
![commitsByHourScreenshot](https://user-images.githubusercontent.com/8818630/57629717-40767900-756a-11e9-97d4-301ffe7535c7.png)
![commitsByWeekdayScreenshot](https://user-images.githubusercontent.com/8818630/58364011-61e53800-7e7b-11e9-9417-16cbb241ac2e.png)
![commitsByHourScreenshot](https://user-images.githubusercontent.com/8818630/58364010-61e53800-7e7b-11e9-8711-a40b50aebf52.png)
## Usage
### Interactive
git-quick-stats has a built-in interactive menu that can be executed as such:
```bash
git-quick-stats
```
Or you can use (non-interactive) direct execution:
Or
`git-quick-stats <optional-command-to-execute-directly>`
```bash
git quick-stats
```
### Non-interactive
For those who prefer to utilize command-line options, `git-quick-stats` also has a non-interactive mode supporting both short and long options:
```bash
git-quick-stats <optional-command-to-execute-directly>
```
Or
```bash
git quick-stats <optional-command-to-execute-directly>
```
### Command-line arguments
Possible arguments in short and long form:
```
```bash
-r, --suggest-reviewers
show the best people to contact to review code
-T, --detailed-git-stats
@@ -83,50 +121,67 @@ Possible arguments in short and long form:
see changelogs
-L, --changelogs-by-author
see changelogs by author
-j, --json-output
save git log as a JSON formatted file to a specified area
-h, -?, --help
display this help text in the terminal
```
#### Git log since / until
### Git log since and until
You can set variable `_GIT_SINCE`, `_GIT_UNTIL` and limit the git log
You can set the variables `_GIT_SINCE` and/or `_GIT_UNTIL` before running `git-quick-stats` to limit the git log. These work similar to git's built-in `--since` and `--until` log options.
```bash
export _GIT_SINCE="2017-20-01"
export _GIT_UNTIL="2017-22-01"
export _GIT_SINCE="2017-01-20"
export _GIT_UNTIL="2017-01-22"
```
then run `git quick-stats` (affect all stats, except "My daily status" and "Git changelogs" )
Once set, run `git quick-stats` as normal. Note that this affects all stats that parse the git log history until unset.
### Git log limit
#### Git log limit
You can set variable `_GIT_LIMIT` for limited output (it will affect: "Git changelogs" and "Branch tree view" )
You can set variable `_GIT_LIMIT` for limited output. It will affect the "changelogs" and "branch tree" options.
```bash
export _GIT_LIMIT=20
```
#### Git pathspec
### Git pathspec
You can exclude directory from the stats by using [pathspec](https://git-scm.com/docs/gitglossary#gitglossary-aiddefpathspecapathspec)
You can exclude a directory from the stats by using [pathspec](https://git-scm.com/docs/gitglossary#gitglossary-aiddefpathspecapathspec)
```bash
export _GIT_PATHSPEC=':!directory'
```
#### Color themes
You can also exclude files from the stats. Note that it works with any alphanumeric, glob, or regex that git respects.
```bash
export _GIT_PATHSPEC=':!package-lock.json'
```
### Git merge view strategy
You can set the variable `_GIT_MERGE_VIEW` to enable merge commits to be part of the stats by setting `_GIT_MERGE_VIEW` to `enable`. You can also choose to only show merge commits by setting `_GIT_MERGE_VIEW` to `exclusive`. Default is to not show merge commits. These work similar to git's built-in `--merges` and `--no-merges` log options.
```bash
export _GIT_MERGE_VIEW="enable"
export _GIT_MERGE_VIEW="exclusive"
```
### Color themes
You can change to the legacy color scheme by toggling the variable `_MENU_THEME` between `default` and `legacy`
```bash
export _MENU_THEME=legacy
```
![legacyThemeScreenshot](https://user-images.githubusercontent.com/8818630/57629724-453b2d00-756a-11e9-9ffc-6a7f53c5fc49.png)
![legacyThemeScreenshot](https://user-images.githubusercontent.com/8818630/58364012-61e53800-7e7b-11e9-910a-aaff836260eb.png)
## Installation
#### Unix like OS
### UNIX and Linux
```bash
git clone https://github.com/arzzen/git-quick-stats.git && cd git-quick-stats
@@ -145,24 +200,37 @@ For update/reinstall
sudo make reinstall
```
#### OS X (homebrew)
### macOS (homebrew)
```bash
brew install git-quick-stats
```
#### Windows (cygwin)
Or you can follow the UNIX and Linux instructions if you wish.
### Windows
If you are installing with Cygwin, use these scripts:
* [installer](https://gist.github.com/arzzen/35e09866dfdadf2108b2420045739245)
* [uninstaller](https://gist.github.com/arzzen/21c660014d0663b6c5710014714779d6)
If you are wishing to use this with WSL, follow the UNIX and Linux instructions.
### Docker
You can use the Docker image provided:
* Build: `docker build -t arzzen/git-quick-stats .`
* Run interactive menu: `docker run --rm -it -v $(pwd):/git arzzen/git-quick-stats`
* Docker pull command: `docker pull arzzen/git-quick-stats` [docker repository](https://hub.docker.com/r/arzzen/git-quick-stats)
## System requirements
* Unix like OS with a proper shell
* Tools we use: awk ; cat ; column ; echo ; git ; grep ; head ; seq ; sort ; tput ; tr ; uniq ; wc
* An OS with a Bash shell
* Tools we use: awk ; basename ; cat ; column ; echo ; git ; grep ; head ; seq ; sort ; tput ; tr ; uniq ; wc
#### Dependences
### Dependencies
* [`bsdmainutils`](https://packages.debian.org/sid/bsdmainutils) `apt install bsdmainutils`
@@ -170,17 +238,19 @@ brew install git-quick-stats
*Q:* I get some errors after run git-quick-stats in cygwin like `/usr/local/bin/git-quick-stats: line 2: $'\r': command not found`
*A:* You can run dos2unix app in cygwin `/bin/dos2unix.exe /usr/local/bin/git-quick-stats`. This will convert it to Unix format and you then should be able to run it.
*A:* You can run the dos2unix app in cygwin as follows: `/bin/dos2unix.exe /usr/local/bin/git-quick-stats`. This will convert the script from the CR-LF convention that Microsoft uses to the LF convention that UNIX, OS X, and Linux use. You should then should be able to run it as normal.
## Contribution
Want to contribute? Great! First, read this page.
#### Code reviews
All submissions, including submissions by project members, require review.</br>
We use Github pull requests for this purpose.
### Code reviews
All submissions, including submissions by project members, require review.</br>
We use GitHub pull requests for this purpose.
### Some tips for good pull requests
#### Some tips for good pull requests:
* Use our code </br>
When in doubt, try to stay true to the existing code of the project.
* Write a descriptive commit message. What problem are you solving and what
@@ -193,11 +263,11 @@ We use Github pull requests for this purpose.
HEAD. This make reviewing the code so much easier, and our history more
readable.
#### Formatting
### Formatting
This documentation is written using standard [markdown syntax](https://help.github.com/articles/markdown-basics/). Please submit your changes using the same syntax.
#### Tests
## Tests
[![codecov](https://codecov.io/gh/arzzen/git-quick-stats/branch/master/graph/badge.svg)](https://codecov.io/gh/arzzen/git-quick-stats)
@@ -206,31 +276,29 @@ make test
```
## Licensing
MIT see [LICENSE][] for the full license text.
[read this page]: http://github.com/arzzen/git-quick-stats/blob/master/docs/CONTRIBUTING.md
[read this page]: http://github.com/arzzen/git-quick-stats/blob/master/.github/CONTRIBUTING.md
[landing page]: http://arzzen.github.io/git-quick-stats
[LICENSE]: https://github.com/arzzen/git-quick-stats/blob/master/LICENSE
## Contributors
This project exists thanks to all the people who contribute.
This project exists thanks to all the people who contribute.
<a href="https://github.com/arzzen/git-quick-stats/graphs/contributors"><img src="https://opencollective.com/git-quick-stats/contributors.svg?width=890&button=false" /></a>
## Backers
### Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/git-quick-stats#backer)]
<a href="https://opencollective.com/git-quick-stats#backers" target="_blank"><img src="https://opencollective.com/git-quick-stats/backers.svg?width=890"></a>
## Sponsors
### Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/git-quick-stats#sponsor)]
<a href="https://opencollective.com/git-quick-stats/sponsor/0/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/git-quick-stats/sponsor/0/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/0/avatar.svg?v=1"></a>
<a href="https://opencollective.com/git-quick-stats/sponsor/1/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/git-quick-stats/sponsor/2/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/git-quick-stats/sponsor/3/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/3/avatar.svg"></a>
@@ -240,5 +308,3 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
<a href="https://opencollective.com/git-quick-stats/sponsor/7/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/git-quick-stats/sponsor/8/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/git-quick-stats/sponsor/9/website" target="_blank"><img src="https://opencollective.com/git-quick-stats/sponsor/9/avatar.svg"></a>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,509 +0,0 @@
/*!
* Start Bootstrap - Creative Bootstrap Theme (http://startbootstrap.com)
* Code licensed under the Apache License v2.0.
* For details, see http://www.apache.org/licenses/LICENSE-2.0.
*/
html,
body {
width: 100%;
height: 100%;
}
body {
font-family: Merriweather,'Helvetica Neue',Arial,sans-serif;
}
hr {
max-width: 50px;
border-color: #f05f40;
border-width: 3px;
}
hr.light {
border-color: #fff;
}
a {
color: #f05f40;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
a:hover,
a:focus {
color: #eb3812;
}
#about a {
color: rgba(52, 52, 52, .7);
}
#about a:hover,
#about a:focus {
color: rgb(52, 52, 52);
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
}
p {
margin-bottom: 20px;
font-size: 16px;
line-height: 1.5;
}
.bg-primary {
background-color: #f05f40;
}
.bg-dark {
color: #fff;
background-color: #222;
}
.text-faded {
color: rgba(255,255,255,.7);
}
section {
padding: 100px 0;
}
aside {
padding: 50px 0;
}
.no-padding {
padding: 0;
}
.navbar-default {
border-color: rgba(34,34,34,.05);
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
background-color: #fff;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.navbar-default .navbar-header .navbar-brand {
text-transform: uppercase;
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
font-weight: 700;
color: #2d8888;
}
.navbar-default .navbar-header .navbar-brand:hover,
.navbar-default .navbar-header .navbar-brand:focus {
color: #eb3812;
}
.navbar-default .nav > li>a,
.navbar-default .nav>li>a:focus {
text-transform: uppercase;
font-size: 13px;
font-weight: 700;
color: #222;
}
.navbar-default .nav > li>a:hover,
.navbar-default .nav>li>a:focus:hover {
color: #f05f40;
}
.navbar-default .nav > li.active>a,
.navbar-default .nav>li.active>a:focus {
color: #f05f40!important;
background-color: transparent;
}
.navbar-default .nav > li.active>a:hover,
.navbar-default .nav>li.active>a:focus:hover {
background-color: transparent;
}
@media(min-width:768px) {
.navbar-default {
border-color: rgba(255,255,255,.3);
background-color: transparent;
}
.navbar-default .navbar-header .navbar-brand {
color: rgba(255,255,255,.7);
}
.navbar-default .navbar-header .navbar-brand:hover,
.navbar-default .navbar-header .navbar-brand:focus {
color: #fff;
}
.navbar-default .nav > li>a,
.navbar-default .nav>li>a:focus {
color: rgba(255,255,255,.7);
}
.navbar-default .nav > li>a:hover,
.navbar-default .nav>li>a:focus:hover {
color: #fff;
}
.navbar-default.affix {
border-color: rgba(34,34,34,.05);
background-color: #fff;
}
.navbar-default.affix .navbar-header .navbar-brand {
font-size: 14px;
color: #f05f40;
}
.navbar-default.affix .navbar-header .navbar-brand:hover,
.navbar-default.affix .navbar-header .navbar-brand:focus {
color: #eb3812;
}
.navbar-default.affix .nav > li>a,
.navbar-default.affix .nav>li>a:focus {
color: #222;
}
.navbar-default.affix .nav > li>a:hover,
.navbar-default.affix .nav>li>a:focus:hover {
color: #f05f40;
}
}
header {
position: relative;
width: 100%;
min-height: auto;
text-align: center;
color: #fff;
background-color: #2f2d2f;
/*background-color: #2c3333;*/
/*background-image: url(../img/header.jpg);*/
/*background-position: center;*/
/*-webkit-background-size: cover;*/
/*-moz-background-size: cover;*/
/*background-size: cover;*/
/*-o-background-size: cover;*/
}
header .header-content {
position: relative;
width: 100%;
padding: 100px 15px;
text-align: center;
}
header .header-content .header-content-inner h1 {
margin-top: 0;
margin-bottom: 0;
/* text-transform: uppercase; */
font-weight: 700;
font-size: 120px;
}
header .header-content .header-content-inner hr {
margin: 30px auto;
}
header .header-content .header-content-inner p {
margin-bottom: 50px;
font-size: 16px;
font-weight: 300;
color: rgba(255,255,255,.7);
}
@media(min-width:768px) {
header {
min-height: 100%;
}
header .header-content {
position: absolute;
top: 50%;
padding: 0 50px;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
}
header .header-content .header-content-inner {
margin-right: auto;
margin-left: auto;
max-width: 1000px;
}
header .header-content .header-content-inner p {
margin-right: auto;
margin-left: auto;
max-width: 80%;
font-size: 18px;
}
}
.section-heading {
margin-top: 0;
}
.service-box {
margin: 50px auto 0;
max-width: 400px;
}
@media(min-width:992px) {
.service-box {
margin: 20px auto 0;
}
}
.service-box p {
margin-bottom: 0;
}
.portfolio-box {
display: block;
position: relative;
margin: 0 auto;
max-width: 650px;
}
.portfolio-box .portfolio-box-caption {
display: block;
position: absolute;
bottom: 0;
width: 100%;
height: 100%;
text-align: center;
color: #fff;
opacity: 0;
background: rgba(240,95,64,.9);
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content {
position: absolute;
top: 50%;
width: 100%;
text-align: center;
transform: translateY(-50%);
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category,
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
padding: 0 15px;
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
text-transform: uppercase;
font-size: 14px;
font-weight: 600;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
font-size: 18px;
}
.portfolio-box:hover .portfolio-box-caption {
opacity: 1;
}
@media(min-width:768px) {
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-category {
font-size: 16px;
}
.portfolio-box .portfolio-box-caption .portfolio-box-caption-content .project-name {
font-size: 22px;
}
}
.call-to-action h2 {
margin: 0 auto 20px;
}
.text-primary {
color: #f05f40;
}
.no-gutter > [class*=col-] {
padding-right: 0;
padding-left: 0;
}
.btn-default {
border-color: #fff;
color: #222;
background-color: #fff;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.btn-default:hover,
.btn-default:focus,
.btn-default.focus,
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
border-color: #ededed;
color: #222;
background-color: #f2f2f2;
}
.btn-default:active,
.btn-default.active,
.open > .dropdown-toggle.btn-default {
background-image: none;
}
.btn-default.disabled,
.btn-default[disabled],
fieldset[disabled] .btn-default,
.btn-default.disabled:hover,
.btn-default[disabled]:hover,
fieldset[disabled] .btn-default:hover,
.btn-default.disabled:focus,
.btn-default[disabled]:focus,
fieldset[disabled] .btn-default:focus,
.btn-default.disabled.focus,
.btn-default[disabled].focus,
fieldset[disabled] .btn-default.focus,
.btn-default.disabled:active,
.btn-default[disabled]:active,
fieldset[disabled] .btn-default:active,
.btn-default.disabled.active,
.btn-default[disabled].active,
fieldset[disabled] .btn-default.active {
border-color: #fff;
background-color: #fff;
}
.btn-default .badge {
color: #fff;
background-color: #222;
}
.btn-primary {
border-color: #f05f40;
color: #fff;
background-color: #2d8888;
-webkit-transition: all .35s;
-moz-transition: all .35s;
transition: all .35s;
}
.btn-primary:hover,
.btn-primary:focus,
.btn-primary.focus,
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
color: #fff;
background-color: #68a9a9;
}
.btn-primary:active,
.btn-primary.active,
.open > .dropdown-toggle.btn-primary {
background-image: none;
}
.btn-primary.disabled,
.btn-primary[disabled],
fieldset[disabled] .btn-primary,
.btn-primary.disabled:hover,
.btn-primary[disabled]:hover,
fieldset[disabled] .btn-primary:hover,
.btn-primary.disabled:focus,
.btn-primary[disabled]:focus,
fieldset[disabled] .btn-primary:focus,
.btn-primary.disabled.focus,
.btn-primary[disabled].focus,
fieldset[disabled] .btn-primary.focus,
.btn-primary.disabled:active,
.btn-primary[disabled]:active,
fieldset[disabled] .btn-primary:active,
.btn-primary.disabled.active,
.btn-primary[disabled].active,
fieldset[disabled] .btn-primary.active {
border-color: #f05f40;
background-color: #f05f40;
}
.btn-primary .badge {
color: #f05f40;
background-color: #fff;
}
.btn {
border: 0;
border-radius: 300px;
text-transform: uppercase;
font-family: 'Open Sans','Helvetica Neue',Arial,sans-serif;
font-weight: 700;
font-size: 1.4em;
}
.btn-xl {
padding: 15px 30px;
}
::-moz-selection {
text-shadow: none;
color: #fff;
background: #222;
}
::selection {
text-shadow: none;
color: #fff;
background: #222;
}
img::selection {
color: #fff;
background: 0 0;
}
img::-moz-selection {
color: #fff;
background: 0 0;
}
body {
webkit-tap-highlight-color: #222;
}
#map {
height: 300px;
overflow: visible;
position: relative;
}
.subtitle {
color: #b1b1b1;
}
.logo {
width: 50%;
padding-bottom: 5px;
}
.screencap {
width: 80%;
padding-top: 20px;
padding-bottom: 30px;
}

View File

@@ -1,81 +0,0 @@
/*!
* The code below adds the modal functionality of the Freelancer Bootstrap Theme
* and was originally part of this theme.
*
*
* Start Bootstrap - Freelancer Bootstrap Theme (http://startbootstrap.com)
* Code licensed under the Apache License v2.0.
* For details, see http://www.apache.org/licenses/LICENSE-2.0.
*/
body {
overflow-x: hidden;
}
.img-centered {
margin: 0 auto;
}
.portfolio-modal .modal-content {
padding: 100px 0;
min-height: 100%;
border: 0;
border-radius: 0;
text-align: center;
background-clip: border-box;
-webkit-box-shadow: none;
box-shadow: none;
}
.portfolio-modal .modal-content h2 {
margin: 0;
font-size: 3em;
}
.portfolio-modal .modal-content img {
margin-bottom: 30px;
}
.portfolio-modal .modal-content .item-details {
margin: 30px 0;
}
.portfolio-modal .close-modal {
position: absolute;
top: 25px;
right: 25px;
width: 75px;
height: 75px;
background-color: transparent;
cursor: pointer;
}
.portfolio-modal .close-modal:hover {
opacity: .3;
}
.portfolio-modal .close-modal .lr {
z-index: 1051;
width: 1px;
height: 75px;
margin-left: 35px;
background-color: #2c3e50;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.portfolio-modal .close-modal .lr .rl {
z-index: 1052;
width: 1px;
height: 75px;
background-color: #2c3e50;
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
.portfolio-modal .modal-backdrop {
display: none;
opacity: 0;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Lukas Mestan">
<meta name="description" content="Commandline GIT statistics">
<title>git quick stats</title>
<link rel="shortcut icon" href="favicon.ico?v=1" type="image/x-icon">
<link rel="stylesheet" href="css/bootstrap.min.css" type="text/css">
<link href="https://fonts.googleapis.com/css?family=Montserrat" rel="stylesheet">
<link rel="stylesheet" href="css/animate.min.css" type="text/css">
<link rel="stylesheet" href="css/creative.css" type="text/css">
<link rel="stylesheet" href="css/modals.css" type="text/css">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
<meta http-equiv="refresh" content="0;url=https://lukasmestan.com/git-quick-stats/">
</head>
<body id="page-top">
<header>
<div class="header-content">
<div class="header-content-inner">
<h1>git quick stats</h1>
<h3 class="subtitle"> simple and efficient way to access various statistics in git repository</h3>
<img class="screencap" src="bg.png" \>
<br>
<a href="https://github.com/arzzen/git-quick-stats" class="btn btn-primary btn-xl page-scroll">download</a>
</div>
</div>
</header>
</body>
</html>

View File

@@ -7,19 +7,52 @@
set -o nounset
set -o errexit
# Beginning git log date. Respects all git datetime formats
# If $_GIT_SINCE is never set, choose epoch time as that is
# as far back as git will allow you to go
_since=${_GIT_SINCE:-}
[[ -n "${_since}" ]] && _since="--since=$_since"
if [[ -n "${_since}" ]]; then
_since="--since=$_since"
else
_since="--since=1970-01-01"
fi
# End of git log date. Respects all git datetime formats
# If $_GIT_UNTIL is never set, choose the latest system
# time from the user's current environment
_until=${_GIT_UNTIL:-}
[[ -n "${_until}" ]] && _until="--until=$_until"
if [[ -n "${_until}" ]]; then
_until="--until=$_until"
else
_until="--until=$(date)"
fi
# Set files or directories to be excluded in stats
# If $_GIT_PATHSPEC is not set, shift over the option completely
_pathspec=${_GIT_PATHSPEC:-}
[[ -n "${_pathspec}" ]] && _pathspec="-- $_pathspec"
if [[ -n "${_pathspec}" ]]; then
_pathspec="-- $_pathspec"
else
_pathspec="--"
fi
# Set merge commit view strategy. Default is to show no merge commits
# Exclusive shows only merge commits
# Enable shows regular commits together with normal commits
_merges=${_GIT_MERGE_VIEW:-}
_merges=$(echo "$_merges" | awk '{print tolower($0)}')
if [[ "${_merges}" == "exclusive" ]]; then
_merges="--merges"
elif [[ "${_merges}" == "enable" ]]; then
_merges=""
else
_merges="--no-merges"
fi
# Limit git log output
_limit=${_GIT_LIMIT:-}
if [[ -n "${_limit}" ]];
then _limit=$_limit
if [[ -n "${_limit}" ]]; then
_limit=$_limit
else
_limit=10
fi
@@ -33,23 +66,15 @@ _theme="${_MENU_THEME:=default}"
# ARGS: None
# OUTS: None
################################################################################
function check_utils() {
local msg="not found. Please make sure this is installed and in PATH."
function checkUtils() {
local -r msg="not found. Please make sure this is installed and in PATH."
declare -ar utils=("awk" "basename" "cat" "column" "echo" "git" "grep" "head"
"seq" "sort" "tput" "tr" "uniq" "wc")
command -v awk >/dev/null 2>&1 || { echo >&2 "awk ${msg}"; exit 1; }
command -v basename >/dev/null 2>&1 || { echo >&2 "basename ${msg}"; exit 1; }
command -v cat >/dev/null 2>&1 || { echo >&2 "cat ${msg}"; exit 1; }
command -v column >/dev/null 2>&1 || { echo >&2 "column ${msg}"; exit 1; }
command -v echo >/dev/null 2>&1 || { echo >&2 "echo ${msg}"; exit 1; }
command -v git >/dev/null 2>&1 || { echo >&2 "git ${msg}"; exit 1; }
command -v grep >/dev/null 2>&1 || { echo >&2 "grep ${msg}"; exit 1; }
command -v head >/dev/null 2>&1 || { echo >&2 "head ${msg}"; exit 1; }
command -v seq >/dev/null 2>&1 || { echo >&2 "seq ${msg}"; exit 1; }
command -v sort >/dev/null 2>&1 || { echo >&2 "sort ${msg}"; exit 1; }
command -v tput >/dev/null 2>&1 || { echo >&2 "tput ${msg}"; exit 1; }
command -v tr >/dev/null 2>&1 || { echo >&2 "tr ${msg}"; exit 1; }
command -v uniq >/dev/null 2>&1 || { echo >&2 "uniq ${msg}"; exit 1; }
command -v wc >/dev/null 2>&1 || { echo >&2 "wc ${msg}"; exit 1; }
for u in "${utils[@]}"
do
command -v "$u" >/dev/null 2>&1 || { echo >&2 "$u ${msg}"; exit 1; }
done
}
################################################################################
@@ -57,8 +82,8 @@ function check_utils() {
# ARGS: None
# OUTS: None
################################################################################
function usage() {
local program=$(basename "$0")
function usage() {
local -r program=$(basename "$0")
echo "
NAME
@@ -106,16 +131,22 @@ OPTIONS
see changelogs
-L, --changelogs-by-author
see changelogs by author
-j, --json-output
save git log as a JSON formatted file to a specified area
-h, -?, --help
display this help text in the terminal
ADDITIONAL USAGE
You can set _GIT_SINCE and _GIT_UNTIL to limit the git time log
ex: export _GIT_SINCE=\"2017-20-01\"
ex: export _GIT_SINCE=\"2017-01-20\"
You can set _GIT_LIMIT for limited output log
ex: export _GIT_LIMIT=20
You can exclude a directory from the stats by using pathspec
ex: export _GIT_PATHSPEC=':!directory'
You can exclude directories or files from the stats by using pathspec
ex: export _GIT_PATHSPEC=':!pattern'
You can set _GIT_MERGE_VIEW to view merge commits with normal commits
ex: export _GIT_MERGE_VIEW=enable
You can also set _GIT_MERGE_VIEW to only show merge commits
ex: export _GIT_MERGE_VIEW=exclusive
You can set _MENU_THEME to display the legacy color scheme
ex: export _MENU_THEME=legacy"
}
@@ -125,13 +156,13 @@ ADDITIONAL USAGE
# ARGS: None
# OUTS: $opt: Option selected by the user based on menu choice
################################################################################
function show_menu() {
local normal=$(tput sgr0)
local cyan=$(tput setaf 6)
local bold=$(tput bold)
local red=$(tput setaf 1)
local yellow=$(tput setaf 3)
local white=$(tput setaf 7)
function showMenu() {
local -r normal=$(tput sgr0)
local -r cyan=$(tput setaf 6)
local -r bold=$(tput bold)
local -r red=$(tput setaf 1)
local -r yellow=$(tput setaf 3)
local -r white=$(tput setaf 7)
local titles=""
local text=""
local nums=""
@@ -140,17 +171,17 @@ function show_menu() {
# Adjustable color menu option
if [[ "${_theme}" == "legacy" ]]; then
titles="${bold}${red}"
text="${normal}${cyan}"
nums="${bold}${yellow}"
help_txt="${normal}${yellow}"
exit_txt="${bold}${red}"
titles="${bold}${red}" && readonly titles
text="${normal}${cyan}" && readonly text
nums="${bold}${yellow}" && readonly nums
help_txt="${normal}${yellow}" && readonly help_txt
exit_txt="${bold}${red}" && readonly exit_txt
else
titles="${bold}${cyan}"
text="${normal}${white}"
nums="${normal}${bold}${white}"
help_txt="${normal}${cyan}"
exit_txt="${bold}${cyan}"
titles="${bold}${cyan}" && readonly titles
text="${normal}${white}" && readonly text
nums="${normal}${bold}${white}" && readonly nums
help_txt="${normal}${cyan}" && readonly help_txt
exit_txt="${bold}${cyan}" && readonly exit_txt
fi
echo -e "\n${titles} Generate:${normal}"
@@ -159,18 +190,19 @@ function show_menu() {
echo -e "${nums} 3)${text} Git changelogs (last $_limit days)"
echo -e "${nums} 4)${text} Git changelogs by author"
echo -e "${nums} 5)${text} My daily status"
echo -e "${nums} 6)${text} Save git log output in JSON format"
echo -e "\n${titles} List:"
echo -e "${nums} 6)${text} Branch tree view (last $_limit)"
echo -e "${nums} 7)${text} All branches (sorted by most recent commit)"
echo -e "${nums} 8)${text} All contributors (sorted by name)"
echo -e "${nums} 9)${text} Git commits per author"
echo -e "${nums} 10)${text} Git commits per date"
echo -e "${nums} 11)${text} Git commits per month"
echo -e "${nums} 12)${text} Git commits per weekday"
echo -e "${nums} 13)${text} Git commits per hour"
echo -e "${nums} 14)${text} Git commits by author per hour"
echo -e "${nums} 7)${text} Branch tree view (last $_limit)"
echo -e "${nums} 8)${text} All branches (sorted by most recent commit)"
echo -e "${nums} 9)${text} All contributors (sorted by name)"
echo -e "${nums} 10)${text} Git commits per author"
echo -e "${nums} 11)${text} Git commits per date"
echo -e "${nums} 12)${text} Git commits per month"
echo -e "${nums} 13)${text} Git commits per weekday"
echo -e "${nums} 14)${text} Git commits per hour"
echo -e "${nums} 15)${text} Git commits by author per hour"
echo -e "\n${titles} Suggest:"
echo -e "${nums} 15)${text} Code reviewers (based on git history)"
echo -e "${nums} 16)${text} Code reviewers (based on git history)"
echo -e "\n${help_txt}Please enter a menu option or ${exit_txt}press Enter to exit."
echo -n "${text}> ${normal}"
read -r opt
@@ -181,26 +213,27 @@ function show_menu() {
# ARGS: $* (required): String to print (usually provided by other functions)
# OUTS: None
################################################################################
function option_picked() {
local bold=$(tput bold)
local red=$(tput setaf 1)
local reset=$(tput sgr0)
function optionPicked() {
local -r bold=$(tput bold)
local -r red=$(tput setaf 1)
local -r reset=$(tput sgr0)
local msg=${*:-"${reset}Error: No message passed"}
echo -e "${bold}${red}${msg}${reset}\n"
}
################################################################################
# DESC: Shows detailed contribution stats per author by parsing every commit in
# the repo and outputting their contribution stats
# ARGS: None
# ARGS: $branch (optional): Users can specify an alternative branch instead of
# the current default one
# OUTS: None
################################################################################
function detailedGitStats() {
local is_branch_existing=false
local branch="${1:-}"
local _branch=""
# Check if requesting for a specific branch
if [[ -n "${branch}" ]]; then
# Check if branch exist
@@ -214,42 +247,42 @@ function detailedGitStats() {
fi
# Prompt message
if [[ $is_branch_existing && -n "${_branch}" ]]; then
option_picked "Contribution stats (by author) on ${_branch} branch:"
if [[ "${is_branch_existing}" && -n "${_branch}" ]]; then
optionPicked "Contribution stats (by author) on ${_branch} branch:"
elif [[ -n "${branch}" && -z "${_branch}" ]]; then
option_picked "Branch \"${branch}\" does not exist.\nContribution stats (by author) on the current branch:"
optionPicked "Branch ${branch} does not exist.\nContribution stats (by author) on the current branch:"
else
option_picked "Contribution stats (by author) on the current branch:"
optionPicked "Contribution stats (by author) on the current branch:"
fi
git -c log.showSignature=false log ${_branch} --use-mailmap --no-merges --numstat \
git -c log.showSignature=false log ${_branch} --use-mailmap $_merges --numstat \
--pretty="format:commit %H%nAuthor: %aN <%aE>%nDate: %ad%n%n%w(0,4,4)%B%n" \
$_since $_until $_pathspec | LC_ALL=C awk '
"$_since" "$_until" "$_pathspec" | LC_ALL=C awk '
function printStats(author) {
printf "\t%s:\n", author
if(more["total"] > 0) {
printf "\t insertions: %d (%.0f%%)\n", more[author], \
printf "\t insertions: %d\t(%.0f%%)\n", more[author], \
(more[author] / more["total"] * 100)
}
if(less["total"] > 0) {
printf "\t deletions: %d (%.0f%%)\n", less[author], \
printf "\t deletions: %d\t(%.0f%%)\n", less[author], \
(less[author] / less["total"] * 100)
}
if(file["total"] > 0) {
printf "\t files: %d (%.0f%%)\n", file[author], \
printf "\t files: %d\t(%.0f%%)\n", file[author], \
(file[author] / file["total"] * 100)
}
if(commits["total"] > 0) {
printf "\t commits: %d (%.0f%%)\n", commits[author], \
printf "\t commits: %d\t(%.0f%%)\n", commits[author], \
(commits[author] / commits["total"] * 100)
}
if (first[author] != "") {
printf "\t lines changed: %s\n", more[author] + less[author]
printf "\t lines changed: %d\t(%.0f%%)\n", more[author] + less[author], ((more[author] + less[author])/ (more["total"]+ less["total"]) * 100 )
printf "\t first commit: %s\n", first[author]
printf "\t last commit: %s\n", last[author]
}
@@ -273,8 +306,8 @@ function detailedGitStats() {
/^[0-9]/ {
more[author] += $1
less[author] += $2
file[author] += 1
file[author] += 1
more["total"] += $1
less["total"] += $2
file["total"] += 1
@@ -296,9 +329,9 @@ function detailedGitStats() {
# OUTS: None
################################################################################
function suggestReviewers() {
option_picked "Suggested code reviewers (based on git history):"
git -c log.showSignature=false log --use-mailmap --no-merges $_since $_until \
--pretty=%aN $_pathspec | head -n 100 | sort | uniq -c | sort -nr | LC_ALL=C awk '
optionPicked "Suggested code reviewers (based on git history):"
git -c log.showSignature=false log --use-mailmap $_merges "$_since" "$_until" \
--pretty=%aN "$_pathspec" | head -n 100 | sort | uniq -c | sort -nr | LC_ALL=C awk '
{ args[NR] = $0; }
END {
for (i = 1; i <= NR; ++i) {
@@ -307,24 +340,39 @@ function suggestReviewers() {
}' | column -t -s,
}
################################################################################
# DESC: Saves the git log output in a JSON format
# ARGS: $json_path (required): Path to where the file is saved
# OUTS: A JSON formatted file
################################################################################
function jsonOutput() {
optionPicked "Output log saved to file at: ${json_path}/output.json"
git -c log.showSignature=false log --use-mailmap $_merges "$_since" "$_until" \
--pretty=format:'{%n "commit": "%H",%n "abbreviated_commit": "%h",%n "tree": "%T",%n "abbreviated_tree": "%t",%n "parent": "%P",%n "abbreviated_parent": "%p",%n "refs": "%D",%n "encoding": "%e",%n "subject": "%s",%n "sanitized_subject_line": "%f",%n "body": "%b",%n "commit_notes": "%N",%n "author": {%n "name": "%aN",%n "email": "%aE",%n "date": "%aD"%n },%n "commiter": {%n "name": "%cN",%n "email": "%cE",%n "date": "%cD"%n }%n},' \
| sed "$ s/,$//" \
| sed ':a;N;$!ba;s/\r\n\([^{]\)/\\n\1/g' \
| awk 'BEGIN { print("[") } { print($0) } END { print("]") }' \
> "${json_path}/output.json"
}
################################################################################
# DESC: Displays a horizontal bar graph based on total commits per month
# ARGS: None
# OUTS: None
################################################################################
function commitsByMonth() {
option_picked "Git commits by month:"
optionPicked "Git commits by month:"
echo -e "\tmonth\tsum"
for i in Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
do
echo -en "\t$i\t"
git -c log.showSignature=false shortlog -n --no-merges --format='%ad %s' \
$_since $_until | grep " $i " | wc -l
done | awk '{
count[$1] = $2
total += $2
}
END{
git -c log.showSignature=false shortlog -n $_merges --format='%ad %s' \
"$_since" "$_until" | grep " $i " | wc -l
done | awk '{
count[$1] = $2
total += $2
}
END{
for (month in count) {
s="|";
if (total > 0) {
@@ -344,23 +392,23 @@ function commitsByMonth() {
# OUTS: None
################################################################################
function commitsByWeekday() {
option_picked "Git commits by weekday:"
optionPicked "Git commits by weekday:"
echo -e "\tday\tsum"
local counter=1
for i in Mon Tue Wed Thu Fri Sat Sun
do
echo -en "\t$i\t"
git -c log.showSignature=false shortlog -n --no-merges --format='%ad %s' \
$_since $_until | grep "$i " | wc -l
echo -en "\t$counter\t$i\t"
git -c log.showSignature=false shortlog -n $_merges --format='%ad %s' \
"$_since" "$_until" | grep "$i " | wc -l
counter=$((counter+1))
done | awk '{
}
NR == FNR {
count[$1] = $2;
total += $2;
next
NR == FNR {
count[$1" "$2] = $3;
total += $3;
next
}
END{
END{
for (day in count) {
s="|";
if (total > 0) {
@@ -368,10 +416,10 @@ function commitsByWeekday() {
for (i = 1; i <= percent; ++i) {
s=s"█"
}
printf( "\t%s\t%-0s\t%s\n", day, count[day], s );
printf("\t%s\t%s\t%-0s\t%s\n", substr(day,0,1), substr(day,3,5), count[day], s);
}
}
}' | sort -k 2 -n -r
}' | sort -k 1 -n | awk '{$1=""}1' | awk '{$1=$1}1' | awk '{printf("\t%s\t%s\t%s\n", $1, $2, $3)}'
}
################################################################################
@@ -384,23 +432,23 @@ function commitsByHour() {
local _author=""
if [[ -z "${author}" ]]; then
option_picked "Git commits by hour:"
optionPicked "Git commits by hour:"
_author="--author=**"
else
option_picked "Git commits by hour for author '${author}':"
optionPicked "Git commits by hour for author '${author}':"
_author="--author=${author}"
fi
echo -e "\thour\tsum"
for i in $(seq -w 0 23)
do
echo -ne "\t$i\t"
git -c log.showSignature=false shortlog -n --no-merges --format='%ad %s' \
"${_author}" $_since $_until | grep ' '$i: | wc -l
done | awk '{
count[$1] = $2
total += $2
}
END{
git -c log.showSignature=false shortlog -n $_merges --format='%ad %s' \
"${_author}" "$_since" "$_until" | grep ' '$i: | wc -l
done | awk '{
count[$1] = $2
total += $2
}
END{
for (hour in count) {
s="|";
if (total > 0) {
@@ -421,9 +469,9 @@ function commitsByHour() {
# OUTS: None
################################################################################
function commitsPerDay() {
option_picked "Git commits per date:";
git -c log.showSignature=false log --use-mailmap --no-merges $_since $_until \
--date=short --format='%ad' $_pathspec | sort | uniq -c
optionPicked "Git commits per date:";
git -c log.showSignature=false log --use-mailmap $_merges "$_since" "$_until" \
--date=short --format='%ad' "$_pathspec" | sort | uniq -c
}
################################################################################
@@ -433,15 +481,29 @@ function commitsPerDay() {
# OUTS: None
################################################################################
function commitsPerAuthor() {
option_picked "Git commits per author:"
git -c log.showSignature=false shortlog $_since $_until --no-merges -n -s \
| sort -nr | LC_ALL=C awk '
{ args[NR] = $0; sum += $0 }
END {
for (i = 1; i <= NR; ++i) {
printf "%s,%2.1f%%\n", args[i], 100 * args[i] / sum
}
}' | column -t -s,
optionPicked "Git commits per author:"
local authorCommits=$(git -c log.showSignature=false log --use-mailmap $_merges \
"$_since" "$_until" | grep -i Author: | cut -c9-)
local coAuthorCommits=$(git -c log.showSignature=false log --use-mailmap $_merges \
"$_since" "$_until" | grep -i Co-Authored-by: | cut -c21-)
if [[ -z "${coAuthorCommits}" ]]
then
allCommits="${authorCommits}"
else
allCommits="${authorCommits}\n${coAuthorCommits}"
fi
echo -e "${allCommits}" | awk '
{ $NF=""; author[NR] = $0 }
END {
for(i in author) {
sum[author[i]]++; name[author[i]] = author[i]; total++;
}
for(i in sum) {
printf "\t%d,%s,%2.1f%%\n", sum[i], name[i], (100 * sum[i] / total)
}
}' | sort -n -r | column -t -s,
}
################################################################################
@@ -450,7 +512,7 @@ function commitsPerAuthor() {
# OUTS: None
################################################################################
function myDailyStats() {
option_picked "My daily status:"
optionPicked "My daily status:"
git diff --shortstat '@{0 day ago}' | sort -nr | tr ',' '\n' | LC_ALL=C awk '
{ args[NR] = $0; }
END {
@@ -460,7 +522,7 @@ function myDailyStats() {
}'
echo -e "\t" $(git -c log.showSignature=false log --use-mailmap \
--author="$(git config user.name)" --no-merges \
--author="$(git config user.name)" $_merges \
--since=$(date "+%Y-%m-%dT00:00:00") \
--until=$(date "+%Y-%m-%dT23:59:59") --reverse \
| grep commit | wc -l) "commits"
@@ -472,9 +534,9 @@ function myDailyStats() {
# OUTS: None
################################################################################
function contributors() {
option_picked "All contributors (sorted by name):"
git -c log.showSignature=false log --use-mailmap --no-merges $_since $_until \
--format='%aN' $_pathspec | sort -u | cat -n
optionPicked "All contributors (sorted by name):"
git -c log.showSignature=false log --use-mailmap $_merges "$_since" "$_until" \
--format='%aN' "$_pathspec" | sort -u | cat -n
}
################################################################################
@@ -483,9 +545,9 @@ function contributors() {
# OUTS: None
################################################################################
function branchTree() {
option_picked "Branching tree view:"
optionPicked "Branching tree view:"
git -c log.showSignature=false log --use-mailmap --graph --abbrev-commit \
$_since $_until --decorate \
"$_since" "$_until" --decorate \
--format=format:'--+ Commit: %h %n | Date: %aD (%ar) %n'' | Message: %s %d %n'' + Author: %aN %n' \
--all | head -n $((_limit*5))
}
@@ -496,7 +558,7 @@ function branchTree() {
# OUTS: None
################################################################################
function branchesByDate() {
option_picked "All branches (sorted by most recent commit):"
optionPicked "All branches (sorted by most recent commit):"
git for-each-ref --sort=committerdate refs/heads/ \
--format='[%(authordate:relative)] %(authorname) %(refname:short)' | cat -n
}
@@ -509,36 +571,37 @@ function branchesByDate() {
function changelogs() {
local author="${1:-}"
local _author=""
local next=$(date +%F)
if [[ -z "${author}" ]]; then
option_picked "Git changelogs:"
optionPicked "Git changelogs:"
_author="--author=**"
else
option_picked "Git changelogs for author '${author}':"
optionPicked "Git changelogs for author '${author}':"
_author="--author=${author}"
fi
NEXT=$(date +%F)
git -c log.showSignature=false log \
--use-mailmap \
--no-merges \
$_merges \
--format="%cd" \
--date=short "${_author}" $_since $_until $_pathspec \
| sort -u -r | head -n $_limit | while read DATE; do
echo -e "\n[$DATE]"
GIT_PAGER=cat git -c log.showSignature=false log \
--use-mailmap --no-merges \
--format=" * %s (%aN)" "${_author}" \
--since=$DATE --until=$NEXT
NEXT=$DATE
done
--date=short "${_author}" "$_since" "$_until" "$_pathspec" \
| sort -u -r | head -n $_limit \
| while read DATE; do
echo -e "\n[$DATE]"
GIT_PAGER=cat git -c log.showSignature=false log \
--use-mailmap $_merges \
--format=" * %s (%aN)" "${_author}" \
--since=$DATE --until=$next
next=$DATE
done
}
################################################################################
# MAIN
# Check to make sure all utilities required for this script are installed
check_utils
checkUtils
# Check if we are currently in a git repo.
git rev-parse --is-inside-work-tree > /dev/null
@@ -550,7 +613,7 @@ if [[ "$#" -eq 1 ]]; then
-T|--detailed-git-stats) detailedGitStats;;
-R|--git-stats-by-branch)
branch=""
while [[ -z "${branch}" ]]; do
while [[ -z "${branch}" ]]; do
read -r -p "Which branch? " branch
done
detailedGitStats "${branch}";;
@@ -563,7 +626,7 @@ if [[ "$#" -eq 1 ]]; then
-c|--changelogs) changelogs;;
-L|--changelogs-by-author)
author="${_GIT_AUTHOR:-}"
while [[ -z "${author}" ]]; do
while [[ -z "${author}" ]]; do
read -r -p "Which author? " author
done
changelogs "${author}";;
@@ -571,11 +634,29 @@ if [[ "$#" -eq 1 ]]; then
-o|--commits-by-hour) commitsByHour;;
-A|--commits-by-author-by-hour)
author="${_GIT_AUTHOR:-}"
while [[ -z "${author}" ]]; do
while [[ -z "${author}" ]]; do
read -r -p "Which author? " author
done
commitsByHour "${author}";;
-m|--commits-by-month) commitsByMonth;;
-j|--json-output)
json_path=""
while [[ -z "${json_path}" ]]; do
echo "NOTE: This feature is in beta!"
echo "The file name will be saved as \"output.json\"."
echo "The full path must be provided."
echo "Variables or shorthands such as ~ are not valid."
echo "You do not need the final slash at the end of a directory path."
echo "You must have write permission to the folder you are trying to save this to."
echo "This feature only works interactively and cannot be combined with other options."
echo -e "Example of a valid path: /home/$(whoami)\n"
read -r -p "Please provide the full path to directory to save JSON file: " json_path
if [[ ! -w "${json_path}" ]]; then
echo "Invalid path or permission denied to write to given area."
json_path=""
fi
done
jsonOutput "${json_path}";;
-h|-\?|--help) usage;;
*) echo "Invalid argument"; usage; exit 1;;
esac
@@ -585,39 +666,56 @@ fi
# Parse interactive commands
clear
show_menu
showMenu
while [[ "${opt}" != "" ]]; do
clear
case "${opt}" in
1) detailedGitStats; show_menu;;
1) detailedGitStats; showMenu;;
2) branch=""
while [[ -z "${branch}" ]]; do
while [[ -z "${branch}" ]]; do
read -r -p "Which branch? " branch
done
detailedGitStats "${branch}"; show_menu;;
3) changelogs; show_menu;;
detailedGitStats "${branch}"; showMenu;;
3) changelogs; showMenu;;
4) author=""
while [[ -z "${author}" ]]; do
while [[ -z "${author}" ]]; do
read -r -p "Which author? " author
done
changelogs "${author}"; show_menu;;
5) myDailyStats; show_menu;;
6) branchTree; show_menu;;
7) branchesByDate; show_menu;;
8) contributors; show_menu;;
9) commitsPerAuthor; show_menu;;
10) commitsPerDay; show_menu;;
11) commitsByMonth; show_menu;;
12) commitsByWeekday; show_menu;;
13) commitsByHour; show_menu;;
14) author=""
while [[ -z "${author}" ]]; do
changelogs "${author}"; showMenu;;
5) myDailyStats; showMenu;;
6) json_path=""
while [[ -z "${json_path}" ]]; do
echo "NOTE: This feature is in beta!"
echo "The file name will be saved as \"output.json\"."
echo "The full path must be provided."
echo "Variables, subshell commands, or shorthands such as ~ may not be valid."
echo "You do not need the final slash at the end of a directory path."
echo "You must have write permission to the folder you are trying to save this to."
echo "This feature only works interactively and cannot be combined with other options."
echo -e "Example of a valid path: /home/$(whoami)\n"
read -r -p "Please provide the full path to directory to save JSON file: " json_path
if [[ ! -w "${json_path}" ]]; then
echo "Invalid path or permission denied to write to given area."
json_path=""
fi
done
jsonOutput "${json_path}"; showMenu;;
7) branchTree; showMenu;;
8) branchesByDate; showMenu;;
9) contributors; showMenu;;
10) commitsPerAuthor; showMenu;;
11) commitsPerDay; showMenu;;
12) commitsByMonth; showMenu;;
13) commitsByWeekday; showMenu;;
14) commitsByHour; showMenu;;
15) author=""
while [[ -z "${author}" ]]; do
read -r -p "Which author? " author
done
commitsByHour "${author}"; show_menu;;
15) suggestReviewers; show_menu;;
commitsByHour "${author}"; showMenu;;
16) suggestReviewers; showMenu;;
q|"\n") exit;;
*) clear; option_picked "Pick an option from the menu"; show_menu;;
*) clear; optionPicked "Pick an option from the menu"; showMenu;;
esac
done

View File

@@ -1,4 +1,4 @@
.TH git-quick-stats "1" "January 2019" "git-quick-stats" "User Commands"
.TH git-quick-stats "1" "January 2020" "git-quick-stats" "User Commands"
.SH NAME
.B git\-quick\-stats
\- Simple and efficient way to access various stats in a git repository.
@@ -94,24 +94,35 @@ see changelogs
see changelogs by author
.HP
.PP
\fB\-j\fR, \fB\-\-json\-output\fR
.IP
save git log as a JSON formatted file to a specified area
.HP
.PP
\fB\-h\fR, \-?, \fB\-\-help\fR
.IP
display this help text in the terminal
.PP
.SH ADDITIONAL USAGE
You can set _GIT_SINCE and _GIT_UNTIL to limit the git time log, example:
.IP
.PP
.B export _GIT_SINCE="2017\-20\-01"
.IP
.B export _GIT_SINCE="2017\-01\-20"
.PP
You can set _GIT_LIMIT for limited output log, example:
.PP
.B export _GIT_LIMIT=20
.PP
You can exclude a directory from the stats by using pathspec, example:
You can exclude directories or files from the stats by using pathspec, example:
.PP
.B export _GIT_PATHSPEC=':!directory'
.B export _GIT_PATHSPEC=':!pattern'
.PP
You can set _GIT_MERGE_VIEW to show merge commits with normal commits, example:
.PP
.B export _GIT_MERGE_VIEW="enable"
.PP
You can also set _GIT_MERGE_VIEW to only show merge commits, example:
.PP
.B export _GIT_MERGE_VIEW="exclusive"
.PP
You can switch to the legacy color scheme, example:
.PP

View File

@@ -3,8 +3,7 @@
. tests/assert.sh -v
src="./git-quick-stats"
#assert "$src fail" "Invalid argument\n\nNAME\n git-quick-stats - Simple and efficient way to access various stats in a git repo\n\nSYNOPSIS\n For non-interactive mode: git-quick-stats [OPTIONS]\n For interactive mode: git-quick-stats\n\nDESCRIPTION\n Any git repository contains tons of information about commits, contributors,\n and files. Extracting this information is not always trivial, mostly because\n of a gadzillion options to a gadzillion git commands.\n\n This program allows you to see detailed information about a git repository.\n\nOPTIONS\n suggestReviewers - see best people to contact to review code\n detailedGitStats - displays a detailed list of git status\n commitsPerDay - displays a list of commits per day\n commitsByMonth - displays a list of commits per month\n commitsByWeekday - displays a list of commits per weekday\n commitsByHour - displays a list of commits per hour\n commitsByAuthorByHour - see a list of commits per hour by author\n commitsPerAuthor - displays a list of commits per author\n myDailyStats - see your current daily stats\n contributors - see a list of all contributors\n branchTree - see an ASCII graph of the git repo\n branchesByDate - show branches by date\n changelogs - see changelogs\n changelogsByAuthor - see changelogs by author\n\nADDITIONAL USAGE\n You can set _GIT_SINCE and _GIT_UNTIL to limit the git time log\n ex: export _GIT_SINCE=2017-20-01\n You can set _GIT_LIMIT for limited output log\n ex: export _GIT_LIMIT=20\n You can exclude a directory from the stats by using pathspec\n ex: export _GIT_PATHSPEC=':!directory'\n \nCONTRIBUTION\n For details regarding contribution, please see the contribution.md document\n\nLICENSE\n This is under the MIT license. See LICENSE in the repo for more info"
assert "$src fail" "Invalid argument\n\nNAME\n git-quick-stats - Simple and efficient way to access various stats in a git repo\n\nSYNOPSIS\n For non-interactive mode: git-quick-stats [OPTIONS]\n For interactive mode: git-quick-stats\n\nDESCRIPTION\n Any git repository contains tons of information about commits, contributors,\n and files. Extracting this information is not always trivial, mostly because\n of a gadzillion options to a gadzillion git commands.\n\n This program allows you to see detailed information about a git repository.\n\nOPTIONS\n -r, --suggest-reviewers\n show the best people to contact to review code\n -T, --detailed-git-stats\n give a detailed list of git stats\n -R, --git-stats-by-branch\n see detailed list of git stats by branch\n -d, --commits-per-day\n displays a list of commits per day\n -m, --commits-by-month\n displays a list of commits per month\n -w, --commits-by-weekday\n displays a list of commits per weekday\n -o, --commits-by-hour\n displays a list of commits per hour\n -A, --commits-by-author-by-hour\n displays a list of commits per hour by author\n -a, --commits-per-author\n displays a list of commits per author\n -S, --my-daily-stats\n see your current daily stats\n -C, --contributors\n see a list of everyone who contributed to the repo\n -b, --branch-tree\n show an ASCII graph of the git repo branch history\n -D, --branches-by-date\n show branches by date\n -c, --changelogs\n see changelogs\n -L, --changelogs-by-author\n see changelogs by author\n -h, -?, --help\n display this help text in the terminal\n\nADDITIONAL USAGE\n You can set _GIT_SINCE and _GIT_UNTIL to limit the git time log\n ex: export _GIT_SINCE=\"2017-20-01\"\n You can set _GIT_LIMIT for limited output log\n ex: export _GIT_LIMIT=20\n You can exclude a directory from the stats by using pathspec\n ex: export _GIT_PATHSPEC=':!directory'\n You can set _MENU_THEME to display the legacy color scheme\n ex: export _MENU_THEME=legacy"
assert "$src fail" "Invalid argument\n\nNAME\n git-quick-stats - Simple and efficient way to access various stats in a git repo\n\nSYNOPSIS\n For non-interactive mode: git-quick-stats [OPTIONS]\n For interactive mode: git-quick-stats\n\nDESCRIPTION\n Any git repository contains tons of information about commits, contributors,\n and files. Extracting this information is not always trivial, mostly because\n of a gadzillion options to a gadzillion git commands.\n\n This program allows you to see detailed information about a git repository.\n\nOPTIONS\n -r, --suggest-reviewers\n show the best people to contact to review code\n -T, --detailed-git-stats\n give a detailed list of git stats\n -R, --git-stats-by-branch\n see detailed list of git stats by branch\n -d, --commits-per-day\n displays a list of commits per day\n -m, --commits-by-month\n displays a list of commits per month\n -w, --commits-by-weekday\n displays a list of commits per weekday\n -o, --commits-by-hour\n displays a list of commits per hour\n -A, --commits-by-author-by-hour\n displays a list of commits per hour by author\n -a, --commits-per-author\n displays a list of commits per author\n -S, --my-daily-stats\n see your current daily stats\n -C, --contributors\n see a list of everyone who contributed to the repo\n -b, --branch-tree\n show an ASCII graph of the git repo branch history\n -D, --branches-by-date\n show branches by date\n -c, --changelogs\n see changelogs\n -L, --changelogs-by-author\n see changelogs by author\n -j, --json-output\n save git log as a JSON formatted file to a specified area\n -h, -?, --help\n display this help text in the terminal\n\nADDITIONAL USAGE\n You can set _GIT_SINCE and _GIT_UNTIL to limit the git time log\n ex: export _GIT_SINCE=\"2017-01-20\"\n You can set _GIT_LIMIT for limited output log\n ex: export _GIT_LIMIT=20\n You can exclude directories or files from the stats by using pathspec\n ex: export _GIT_PATHSPEC=':!pattern'\n You can set _GIT_MERGE_VIEW to view merge commits with normal commits\n ex: export _GIT_MERGE_VIEW=enable\n You can also set _GIT_MERGE_VIEW to only show merge commits\n ex: export _GIT_MERGE_VIEW=exclusive\n You can set _MENU_THEME to display the legacy color scheme\n ex: export _MENU_THEME=legacy"
assert_raises "$src fail" 1
assert_contains "$src --suggest-reviewers" "Suggested code reviewers (based on git history)" 127