gitlogstats 1.5.2__tar.gz → 1.7.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/PKG-INFO +29 -2
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/README.md +28 -1
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/docs/SPEC.md +18 -0
- gitlogstats-1.7.0/docs/examples/project-1-stats.csv +126 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/pyproject.toml +1 -1
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/scripts/board/manifest.yaml +32 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/__main__.py +38 -12
- gitlogstats-1.7.0/src/gitlogstats/aggregate.py +195 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/git_logs_parser.py +73 -17
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/github.py +45 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/github_stats.py +143 -30
- gitlogstats-1.7.0/tests/test_aggregate.py +455 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/test_github.py +38 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/test_integration.py +445 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/CLAUDE.md +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/agents/developer-agent.md +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/agents/spec-reviewer.md +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/hooks/format-edited.sh +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/hooks/guard-paths.sh +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/hooks/guard-paths.test.mjs +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/hooks/verify.sh +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/settings.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/skills/phase-handoff/SKILL.md +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.claude/skills/stale-check/SKILL.md +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.github/workflows/build.yaml +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.gitignore +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/.prettierrc.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/LICENSE +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/Pipfile +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/Pipfile.lock +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/docs/examples/README.md +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/docs/examples/assignment-stats.sh +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/package-lock.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/package.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/repos.txt +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/requirements.txt +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/scripts/board/config.mjs +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/scripts/board/derive.mjs +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/scripts/board/derive.test.mjs +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/scripts/board/sync.mjs +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/__init__.py +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/clones.py +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/src/gitlogstats/identity.py +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fake_gh.py +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/commit_linked.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/commit_unlinked.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/contributors.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/contributors_page2.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/pulls_page1.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/pulls_page2.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/user_full.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/fixtures/github/user_private.json +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/test_clobber.py +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/test_git_logs_parser.py +0 -0
- {gitlogstats-1.5.2 → gitlogstats-1.7.0}/tests/test_identity.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: gitlogstats
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.0
|
|
4
4
|
Summary: Track developers' contributions to one or more git repositories within a particular time range.
|
|
5
5
|
Project-URL: Homepage, https://github.com/bloombar/gitlogstats
|
|
6
6
|
Project-URL: Repository, https://github.com/bloombar/gitlogstats.git
|
|
@@ -726,7 +726,8 @@ The command `gitlogstats --help` shows the usage instructions:
|
|
|
726
726
|
```
|
|
727
727
|
usage: gitlogstats [-h] (-r REPOSITORY | -rf REPOFILE) [-u USER] [-s START]
|
|
728
728
|
[-e END] [-x EXCLUSIONS] [-f {csv,json,markdown}]
|
|
729
|
-
[-b BRANCH] [-v] [-c] [
|
|
729
|
+
[-b BRANCH] [-v] [-c] [-a {developer,repository,day}]
|
|
730
|
+
[--github] [--clobber]
|
|
730
731
|
|
|
731
732
|
options:
|
|
732
733
|
-h, --help show this help message and exit
|
|
@@ -751,6 +752,11 @@ options:
|
|
|
751
752
|
The branch to parse, if not the default branch
|
|
752
753
|
-v, --verbose Whether to output debugging info
|
|
753
754
|
-c, --clean Remove contributors without any contribuition
|
|
755
|
+
-a {developer,repository,day}, --aggregate {developer,repository,day}
|
|
756
|
+
Combine the results into one row per developer, summed
|
|
757
|
+
over all repositories, one row per repository, summed
|
|
758
|
+
over its contributors, or one row per day with
|
|
759
|
+
activity, summed over everyone
|
|
754
760
|
--github Also report GitHub pull requests opened, merged,
|
|
755
761
|
closed and self-merged per contributor, with their git
|
|
756
762
|
and GitHub emails, their pushes to the analyzed branch
|
|
@@ -840,6 +846,27 @@ By default, every contributor in a repository's history is listed, with zeros fo
|
|
|
840
846
|
gitlogstats -rf repos.txt -c
|
|
841
847
|
```
|
|
842
848
|
|
|
849
|
+
### Totals per developer or per repository
|
|
850
|
+
|
|
851
|
+
By default there is one row per contributor per repository. Add `-a developer` to get one row per developer with their statistics summed over every repository, or `-a repository` to get one row per repository summed over its contributors.
|
|
852
|
+
|
|
853
|
+
```
|
|
854
|
+
gitlogstats -rf repos.txt -a developer
|
|
855
|
+
gitlogstats -rf repos.txt -a repository
|
|
856
|
+
```
|
|
857
|
+
|
|
858
|
+
Developer rows have no `repository` column; instead a `repositories` column counts the repositories the developer was active in during the date range. Repository rows have no username or email columns; a `contributors` column counts the contributors who were active in the repository during the date range. `-u` and `-c` are applied first, so `-u alice -a repository` shows Alice's share of each repository. With `--github`, a developer's rows are combined by GitHub username, so different git names linked to one GitHub account become one row, and their email addresses are listed together. A developer matched to a GitHub account in one repository but not in another (for example a repository not on GitHub) keeps a separate row for each.
|
|
859
|
+
|
|
860
|
+
### Activity per day
|
|
861
|
+
|
|
862
|
+
Add `-a day` to get one row per day on which anything happened, summed over every contributor and repository, in date order:
|
|
863
|
+
|
|
864
|
+
```
|
|
865
|
+
gitlogstats -rf repos.txt -a day
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
The columns are `date`, the usual counts, `repositories` (how many repositories had activity that day) and `contributors` (how many developers were active that day; someone active in several repositories counts once, but, as with `-a developer`, someone matched to a GitHub account in one repository and not in another counts twice). Every event is counted on its own day in local time: commits and merges on their commit date and, with `--github`, pull requests on the day they were opened, merged or closed and pushes on the day they were pushed. The days therefore add up to the totals printed without `-a`. Days without activity are left out. Combine with `-u` to see one contributor's days.
|
|
869
|
+
|
|
843
870
|
### Cloned repositories
|
|
844
871
|
|
|
845
872
|
Each repository is cloned into a `repos/` directory under the directory you run the command from, and later runs update (`git pull`) the existing clone instead of cloning again, which makes them much faster. Add `--clobber` to delete the clones the run used, once the results have been printed; `repos/` itself is removed too if nothing else is left in it. Clones from other runs are kept, and nothing is deleted if the run fails before printing, so you can inspect it. With `-v`, each deleted path is listed on standard error.
|
|
@@ -29,7 +29,8 @@ The command `gitlogstats --help` shows the usage instructions:
|
|
|
29
29
|
```
|
|
30
30
|
usage: gitlogstats [-h] (-r REPOSITORY | -rf REPOFILE) [-u USER] [-s START]
|
|
31
31
|
[-e END] [-x EXCLUSIONS] [-f {csv,json,markdown}]
|
|
32
|
-
[-b BRANCH] [-v] [-c] [
|
|
32
|
+
[-b BRANCH] [-v] [-c] [-a {developer,repository,day}]
|
|
33
|
+
[--github] [--clobber]
|
|
33
34
|
|
|
34
35
|
options:
|
|
35
36
|
-h, --help show this help message and exit
|
|
@@ -54,6 +55,11 @@ options:
|
|
|
54
55
|
The branch to parse, if not the default branch
|
|
55
56
|
-v, --verbose Whether to output debugging info
|
|
56
57
|
-c, --clean Remove contributors without any contribuition
|
|
58
|
+
-a {developer,repository,day}, --aggregate {developer,repository,day}
|
|
59
|
+
Combine the results into one row per developer, summed
|
|
60
|
+
over all repositories, one row per repository, summed
|
|
61
|
+
over its contributors, or one row per day with
|
|
62
|
+
activity, summed over everyone
|
|
57
63
|
--github Also report GitHub pull requests opened, merged,
|
|
58
64
|
closed and self-merged per contributor, with their git
|
|
59
65
|
and GitHub emails, their pushes to the analyzed branch
|
|
@@ -143,6 +149,27 @@ By default, every contributor in a repository's history is listed, with zeros fo
|
|
|
143
149
|
gitlogstats -rf repos.txt -c
|
|
144
150
|
```
|
|
145
151
|
|
|
152
|
+
### Totals per developer or per repository
|
|
153
|
+
|
|
154
|
+
By default there is one row per contributor per repository. Add `-a developer` to get one row per developer with their statistics summed over every repository, or `-a repository` to get one row per repository summed over its contributors.
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
gitlogstats -rf repos.txt -a developer
|
|
158
|
+
gitlogstats -rf repos.txt -a repository
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Developer rows have no `repository` column; instead a `repositories` column counts the repositories the developer was active in during the date range. Repository rows have no username or email columns; a `contributors` column counts the contributors who were active in the repository during the date range. `-u` and `-c` are applied first, so `-u alice -a repository` shows Alice's share of each repository. With `--github`, a developer's rows are combined by GitHub username, so different git names linked to one GitHub account become one row, and their email addresses are listed together. A developer matched to a GitHub account in one repository but not in another (for example a repository not on GitHub) keeps a separate row for each.
|
|
162
|
+
|
|
163
|
+
### Activity per day
|
|
164
|
+
|
|
165
|
+
Add `-a day` to get one row per day on which anything happened, summed over every contributor and repository, in date order:
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
gitlogstats -rf repos.txt -a day
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The columns are `date`, the usual counts, `repositories` (how many repositories had activity that day) and `contributors` (how many developers were active that day; someone active in several repositories counts once, but, as with `-a developer`, someone matched to a GitHub account in one repository and not in another counts twice). Every event is counted on its own day in local time: commits and merges on their commit date and, with `--github`, pull requests on the day they were opened, merged or closed and pushes on the day they were pushed. The days therefore add up to the totals printed without `-a`. Days without activity are left out. Combine with `-u` to see one contributor's days.
|
|
172
|
+
|
|
146
173
|
### Cloned repositories
|
|
147
174
|
|
|
148
175
|
Each repository is cloned into a `repos/` directory under the directory you run the command from, and later runs update (`git pull`) the existing clone instead of cloning again, which makes them much faster. Add `--clobber` to delete the clones the run used, once the results have been printed; `repos/` itself is removed too if nothing else is left in it. Clones from other runs are kept, and nothing is deleted if the run fails before printing, so you can inspect it. With `-v`, each deleted path is listed on standard error.
|
|
@@ -202,6 +202,24 @@ When several repositories are analyzed, the results are printed once, after all
|
|
|
202
202
|
|
|
203
203
|
**Status:** Done
|
|
204
204
|
|
|
205
|
+
#### OUT-6 Aggregated results
|
|
206
|
+
|
|
207
|
+
`-a/--aggregate developer` prints one row per developer, summed over every repository analyzed, instead of one row per contributor per repository. Its columns are `username, start_date, end_date, commits, insertions, deletions, files, merges, repositories`, where `repositories` is the number of repositories in which the developer has any activity in the date range (a non-zero count, git or GitHub, as for `-c`); there is no `repository` column. With `--github`, the columns `github_username, prs_opened, prs_merged, prs_closed_unmerged, prs_self_merged, git_email, github_email, pushes_to_default, web_commits` follow. Rows are combined when they share a GitHub username (ignoring case), or, for rows without one, the same git `username` exactly; a developer matched to a GitHub user in one repository but not in another is reported as two rows. `username` is the git username of the developer's row with the most commits (ties alphabetical, as in STAT-11), `github_username` the first non-empty one among the developer's rows, and `git_email` and `github_email` list every distinct email of the combined rows, sorted alphabetically (ignoring case) and separated by `; `.
|
|
208
|
+
|
|
209
|
+
`-a/--aggregate repository` prints one row per repository, summed over its contributors. Its columns are `repository, start_date, end_date, commits, insertions, deletions, files, merges, contributors`, where `contributors` is the number of its contributors with any activity in the date range; with `--github`, `prs_opened, prs_merged, prs_closed_unmerged, prs_self_merged, pushes_to_default, web_commits` follow. There are no `username`, `github_username`, `git_email` or `github_email` columns.
|
|
210
|
+
|
|
211
|
+
In both modes every count is the sum of the combined rows, so each total equals the sum of the rows printed without `--aggregate`. A GitHub count is empty (`null` in JSON) only when it is empty in every combined row (CLI-3). Aggregation is applied after `-u` and `-c`, so it combines only the rows those options keep. Rows are sorted by `username` (or `github_username`, for a developer with no git username) or by `repository`, ignoring case. The aggregated columns are printed in every output format, and in the CSV header even when there are no rows. Without `-a`, the output is unchanged.
|
|
212
|
+
|
|
213
|
+
**Status:** Done
|
|
214
|
+
|
|
215
|
+
#### OUT-7 Results by day
|
|
216
|
+
|
|
217
|
+
`-a/--aggregate day` prints one row per day on which anything was counted, summed over every contributor and repository analyzed, in date order. Its columns are `date, commits, insertions, deletions, files, merges, repositories, contributors`, where `date` is the day in `mm/dd/yyyy` format, `repositories` is the number of repositories with any activity that day and `contributors` the number of developers with any activity that day (a developer is identified as in OUT-6, so one person active in several repositories counts once, while one matched to a GitHub user in one repository but not in another counts twice). With `--github`, the columns `prs_opened, prs_merged, prs_closed_unmerged, prs_self_merged, pushes_to_default, web_commits` follow. There are no `username`, `repository`, `start_date`, `end_date`, `github_username`, `git_email` or `github_email` columns.
|
|
218
|
+
|
|
219
|
+
Each event is counted on the day it happened, in local time, the same way FILT-1 limits the date range: a commit, merge or website commit on its commit date; a pull request as opened on the day it was created, as merged (and self-merged) on the day it was merged, and as closed without merging on the day it was closed; a push on the day it was pushed. So the day totals add up to the totals printed without `-a`. Days without any activity are left out. `-u` limits the counts to that contributor (as in CLI-3 with `--github`); `-c` changes nothing, since inactive contributors add nothing to a day. A GitHub count is empty (`null` in JSON) only when no repository with activity that day could be asked about (CLI-3). The columns are printed in the CSV header even when there are no rows.
|
|
220
|
+
|
|
221
|
+
**Status:** Done
|
|
222
|
+
|
|
205
223
|
### 5. Command-Line Interface
|
|
206
224
|
|
|
207
225
|
#### CLI-1 Help and usage
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
username,repository,start_date,end_date,commits,insertions,deletions,files,merges,github_username,prs_opened,prs_merged,prs_closed_unmerged,prs_self_merged,git_email,github_email,pushes_to_default,web_commits
|
|
2
|
+
Jade Leong,specification-phase-exercise-sakjp,09/01/2026,10/16/2026,4,124,45,4,0,Jade-Leong,1,1,0,0,jyl9618@nyu.edu,,2,0
|
|
3
|
+
Khidir Ahmed,specification-phase-exercise-sakjp,09/01/2026,10/16/2026,4,9,6,4,0,khidirahmed,2,2,0,1,kka6822@nyu.edu,kka6822@nyu.edu,2,1
|
|
4
|
+
Pope,specification-phase-exercise-sakjp,09/01/2026,10/16/2026,6,31,5,6,3,pope-cruz,4,4,0,3,168572503+pope-cruz@users.noreply.github.com; popecruz822@gmail.com,,1,0
|
|
5
|
+
sethderusha,specification-phase-exercise-sakjp,09/01/2026,10/16/2026,10,55,34,10,7,sethderusha,2,2,0,2,165086066+sethderusha@users.noreply.github.com; srd6665@nyu.edu,,8,0
|
|
6
|
+
alissawu,specification-phase-exercise-sakjp,09/01/2026,10/16/2026,1,1,0,1,0,alissawu,1,1,0,0,alissawu77@gmail.com,alissawu77@gmail.com,0,0
|
|
7
|
+
bloombar,specification-phase-exercise-sakjp,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
8
|
+
Dialloni,specification-phase-exercise-leodiajulce,09/01/2026,10/16/2026,5,130,6,6,3,Dialloni,0,0,0,0,119769795+Dialloni@users.noreply.github.com; dialoabo@gmail.com,,0,0
|
|
9
|
+
Jrleitersdorf,specification-phase-exercise-leodiajulce,09/01/2026,10/16/2026,4,437,13,5,2,Jrleitersdorf,0,0,0,0,jrleitersdorf@gmail.com,,0,0
|
|
10
|
+
Leonid2004,specification-phase-exercise-leodiajulce,09/01/2026,10/16/2026,3,189,6,3,3,Leonid2004,0,0,0,0,72578139+Leonid2004@users.noreply.github.com; leophilo7@gmail.com,,0,0
|
|
11
|
+
bloombar,specification-phase-exercise-leodiajulce,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
12
|
+
carinutza,specification-phase-exercise-leodiajulce,09/01/2026,10/16/2026,13,146,33,18,4,carinutza,0,0,0,0,ilie.carina@gmail.com,,1,0
|
|
13
|
+
YusefMoustafa,specification-phase-exercise-waterfall,09/01/2026,10/16/2026,6,119,7,6,0,YusefMoustafa,0,0,0,0,158067706+YusefMoustafa@users.noreply.github.com,,6,6
|
|
14
|
+
bloombar,specification-phase-exercise-waterfall,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
15
|
+
krishivseth,specification-phase-exercise-waterfall,09/01/2026,10/16/2026,7,555,23,10,1,krishivseth,2,2,0,2,93362198+krishivseth@users.noreply.github.com,,1,7
|
|
16
|
+
monica9482,specification-phase-exercise-waterfall,09/01/2026,10/16/2026,15,77,97,15,1,monica9482,0,0,0,0,ml9482@nyu.edu,,16,0
|
|
17
|
+
sing1179,specification-phase-exercise-waterfall,09/01/2026,10/16/2026,5,91,19,5,0,sing1179,0,0,0,0,143670921+sing1179@users.noreply.github.com,,5,5
|
|
18
|
+
Sarah Toussaint,specification-phase-exercise-tigers,09/01/2026,10/16/2026,3,50,2,3,0,sarahtoussaint,1,0,1,0,sat10002@nyu.edu,,3,3
|
|
19
|
+
bloombar,specification-phase-exercise-tigers,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
20
|
+
izz04,specification-phase-exercise-tigers,09/01/2026,10/16/2026,14,175,70,14,4,izz04,6,6,0,2,73780798+izz04@users.noreply.github.com,,9,14
|
|
21
|
+
jk8308-jpg,specification-phase-exercise-tigers,09/01/2026,10/16/2026,2,48,1,2,3,jk8308-jpg,2,2,0,0,jk8308@nyu.edu,,0,0
|
|
22
|
+
nonyembaezue,specification-phase-exercise-tigers,09/01/2026,10/16/2026,7,32,6,7,1,nonyembaezue,0,0,0,0,cam9137@nyu.edu,,7,7
|
|
23
|
+
bloombar,specification-exercise-project-1,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
24
|
+
sallyhegab,specification-exercise-project-1,09/01/2026,10/16/2026,5,109,14,5,1,sallyhegab,0,0,0,0,158313024+sallyhegab@users.noreply.github.com; sh6568@nyu.edu,,5,0
|
|
25
|
+
sar9249,specification-exercise-project-1,09/01/2026,10/16/2026,1,1,1,1,0,sar9249,1,1,0,0,sar9249@nyu.edu,,0,1
|
|
26
|
+
Ryan Lin,specification-phase-exercise-codekitchen,09/01/2026,10/16/2026,2,3,1,2,0,ryanwlin,0,0,0,0,ryanandlin@gmail.com,,2,2
|
|
27
|
+
berrizy,specification-phase-exercise-codekitchen,09/01/2026,10/16/2026,2,2,3,2,0,berrizy,0,0,0,0,nahasselma@gmail.com,,2,0
|
|
28
|
+
bloombar,specification-phase-exercise-codekitchen,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
29
|
+
rishachada,specification-phase-exercise-codekitchen,09/01/2026,10/16/2026,6,114,37,6,0,rishachada,0,0,0,0,rc5294@nyu.edu,,6,2
|
|
30
|
+
schauhans,specification-phase-exercise-codekitchen,09/01/2026,10/16/2026,2,24,3,2,0,schauhans,0,0,0,0,139730145+schauhans@users.noreply.github.com; sc10486@nyu.edu,,2,1
|
|
31
|
+
yufeiihuang,specification-phase-exercise-codekitchen,09/01/2026,10/16/2026,9,65,13,9,0,yufeiihuang,0,0,0,0,yufeixyhuang@gmail.com,,9,9
|
|
32
|
+
AmitavNarayan,specification-phase-exercise-no-ai-team,09/01/2026,10/16/2026,26,489,443,26,7,AmitavNarayan,6,6,0,6,amitavnarayan2@gmail.com,,21,8
|
|
33
|
+
Trisolis,specification-phase-exercise-no-ai-team,09/01/2026,10/16/2026,8,221,109,8,3,Trisolis,3,3,0,2,papijackwaiter@gmail.com,papijackwaiter@gmail.com,5,0
|
|
34
|
+
bloombar,specification-phase-exercise-no-ai-team,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
35
|
+
rfang1224,specification-phase-exercise-no-ai-team,09/01/2026,10/16/2026,3,9,5,3,0,rfang1224,1,1,0,0,rf2789@nyu.edu,,2,2
|
|
36
|
+
Abel200595,specification-phase-exercise-smart_monkeys-,09/01/2026,10/16/2026,1,507,1,4,0,Abel200595,0,0,0,0,ym3057@nyu.edu,,0,0
|
|
37
|
+
Jialiang Cao,specification-phase-exercise-smart_monkeys-,09/01/2026,10/16/2026,4,9,19,4,0,jialiangcao,0,0,0,0,jcao2080@gmail.com,,3,0
|
|
38
|
+
RayyanAhmed21,specification-phase-exercise-smart_monkeys-,09/01/2026,10/16/2026,7,252,111,7,5,RayyanAhmed21,5,5,0,5,ra4073@nyu.edu,,0,3
|
|
39
|
+
bloombar,specification-phase-exercise-smart_monkeys-,09/01/2026,10/16/2026,1,15,0,1,1,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
40
|
+
rz3007,specification-phase-exercise-smart_monkeys-,09/01/2026,10/16/2026,2,54,4,2,0,rz3007,0,0,0,0,rz3007@nyu.edu,,0,2
|
|
41
|
+
Asritha Pannem,specification-phase-exercise-controller,09/01/2026,10/16/2026,1,42,0,1,0,,0,0,0,0,asp9404@nyu.edu,,0,0
|
|
42
|
+
NISUN05,specification-phase-exercise-controller,09/01/2026,10/16/2026,6,106,7,6,0,NISUN05,0,0,0,0,na3755@nyu.edu,,6,0
|
|
43
|
+
Nishika Gorla,specification-phase-exercise-controller,09/01/2026,10/16/2026,3,32,4,3,0,nishikagorla,2,2,0,0,nishika.gorla@gmail.com,nishika.gorla@gmail.com,3,0
|
|
44
|
+
Pranay Engineer,specification-phase-exercise-controller,09/01/2026,10/16/2026,6,70,11,6,5,PranayEng,3,3,0,3,88552049+PranayEng@users.noreply.github.com; Pme7634@nyu.edu,,1,1
|
|
45
|
+
ai2652-png,specification-phase-exercise-controller,09/01/2026,10/16/2026,8,317,213,8,5,ai2652-png,5,5,0,5,ai2652@nyu.edu,,6,8
|
|
46
|
+
bloombar,specification-phase-exercise-controller,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
47
|
+
,specification-phase-exercise-controller,09/01/2026,10/16/2026,0,0,0,0,0,scanfasri,0,0,0,0,,,1,0
|
|
48
|
+
ShuoWu6529,specification-phase-exercise-forked,09/01/2026,10/16/2026,7,24,6,7,11,ShuoWu6529,6,6,0,4,sw6529@nyu.edu,sw6529@nyu.edu,1,0
|
|
49
|
+
bloombar,specification-phase-exercise-forked,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
50
|
+
ew2725,specification-phase-exercise-forked,09/01/2026,10/16/2026,6,24,14,6,6,ew2725,5,5,0,1,ew2725@nyu.edu,,0,0
|
|
51
|
+
jack-k-jiang,specification-phase-exercise-forked,09/01/2026,10/16/2026,8,37,14,8,6,jack-k-jiang,8,8,0,6,82908596+jack-k-jiang@users.noreply.github.com; jackj12358@gmail.com,,0,0
|
|
52
|
+
ronaldszeto,specification-phase-exercise-forked,09/01/2026,10/16/2026,7,24,3,7,1,ronaldszeto,5,5,0,1,rs9316@nyu.edu,,1,2
|
|
53
|
+
xuruikun,specification-phase-exercise-forked,09/01/2026,10/16/2026,23,93,61,23,3,xuruikun,7,7,0,7,88195416+xuruikun@users.noreply.github.com,,8,23
|
|
54
|
+
MarcoHGulino,specification-phase-exercise-team2,09/01/2026,10/16/2026,5,81,36,5,0,MarcoHGulino,0,0,0,0,mg6378@nyu.edu,,3,5
|
|
55
|
+
Sai Shettar,specification-phase-exercise-team2,09/01/2026,10/16/2026,12,46,14,12,0,saishettar,0,0,0,0,sai.r.shettar@gmail.com,saishettar@nyu.edu,4,12
|
|
56
|
+
SiennaSSM,specification-phase-exercise-team2,09/01/2026,10/16/2026,14,122,48,14,0,SiennaSSM,0,0,0,0,sm12131@nyu.edu,,4,14
|
|
57
|
+
bloombar,specification-phase-exercise-team2,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
58
|
+
elbow74,specification-phase-exercise-team2,09/01/2026,10/16/2026,5,86,48,5,0,elbow74,0,0,0,0,92692888+elbow74@users.noreply.github.com,,5,5
|
|
59
|
+
Abyssjac,specification-phase-exercise-sth,09/01/2026,10/16/2026,7,229,183,8,1,Abyssjac,0,0,0,0,131870078+Abyssjac@users.noreply.github.com; zuzhou.abyss@gmail.com,,7,0
|
|
60
|
+
Jessie Zhang,specification-phase-exercise-sth,09/01/2026,10/16/2026,7,24,10,7,0,jessiezhang218,1,1,0,1,jessiezhang0218@gmail.com; jz6102@nyu.edu,jessiezhang0218@gmail.com,1,7
|
|
61
|
+
Shiqi Wang,specification-phase-exercise-sth,09/01/2026,10/16/2026,5,132,66,5,4,ShiqiWang1115,4,4,0,4,sw6423@nyu.edu,,0,0
|
|
62
|
+
Sinu112,specification-phase-exercise-sth,09/01/2026,10/16/2026,2,74,2,2,0,Sinu112,2,2,0,2,xs2471@nyu.edu,,0,2
|
|
63
|
+
bloombar,specification-phase-exercise-sth,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
64
|
+
TracyWang0904,specification-phase-exercise-byteme,09/01/2026,10/16/2026,8,226,43,21,0,TracyWang0904,0,0,0,0,yw8252@nyu.edu,,8,0
|
|
65
|
+
bloombar,specification-phase-exercise-byteme,09/01/2026,10/16/2026,0,0,0,0,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
66
|
+
AliG643,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,4,90,9,4,4,AliG643,1,1,0,0,sg7920@nyu.edu,sg7920@nyu.edu,0,0
|
|
67
|
+
S1rius-Yang,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,1,3,1,1,0,S1rius-Yang,0,0,0,0,hy2743@nyu.edu,,0,1
|
|
68
|
+
Sirius,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,3,6,4,3,0,,0,0,0,0,s1rius@SiriusdeMacBook-Pro.local,,0,0
|
|
69
|
+
Yuyang-Ding1102,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,4,425,63,4,7,Yuyang-Ding1102,2,1,1,1,yd2734@nyu.edu,,0,4
|
|
70
|
+
Yvonne,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,2,80,27,2,0,Lyvoj,0,0,0,0,261538801+Lyvoj@users.noreply.github.com,,0,0
|
|
71
|
+
Zihan Chen,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,6,148,88,6,0,Vent1Zzz,0,0,0,0,203582969+Vent1Zzz@users.noreply.github.com,,1,0
|
|
72
|
+
bloombar,specification-phase-exercise-purple-sasquatch,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
73
|
+
Dizay-53,specification-exercise-hibiscus,09/01/2026,10/16/2026,3,46,3,3,0,Dizay-53,2,2,0,1,Ya2522@nyu.edu,,0,3
|
|
74
|
+
LefeiKe,specification-exercise-hibiscus,09/01/2026,10/16/2026,4,54,6,4,3,LefeiKe,4,4,0,1,87459566+LefeiKe@users.noreply.github.com; lk3104@nyu.edu,,0,0
|
|
75
|
+
ange285,specification-exercise-hibiscus,09/01/2026,10/16/2026,1,2,1,1,1,ange285,1,1,0,0,enjelia126@gmail.com,,0,1
|
|
76
|
+
bloombar,specification-exercise-hibiscus,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
77
|
+
sofia-matari,specification-exercise-hibiscus,09/01/2026,10/16/2026,2,46,11,2,6,sofia-matari,2,2,0,0,sbm9838@nyu.edu,,0,0
|
|
78
|
+
yasminek27,specification-exercise-hibiscus,09/01/2026,10/16/2026,9,118,28,9,5,yasminek27,9,9,0,0,yk2154@nyu.edu,,0,0
|
|
79
|
+
aw4580,specification-phase-exercise-search,09/01/2026,10/16/2026,6,57,30,6,0,aw4580,0,0,0,0,134334340+aw4580@users.noreply.github.com; aw4580@nyu.edu,,7,5
|
|
80
|
+
benzaslavsky,specification-phase-exercise-search,09/01/2026,10/16/2026,1,17,2,1,2,benzaslavsky,1,1,0,1,62486098+benzaslavsky@users.noreply.github.com; benzy.venue@gmail.com,,0,0
|
|
81
|
+
bloombar,specification-phase-exercise-search,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
82
|
+
iindes,specification-phase-exercise-search,09/01/2026,10/16/2026,1,1,1,1,1,iindes,1,1,0,1,59502115+iindes@users.noreply.github.com,,0,1
|
|
83
|
+
lkykathy,specification-phase-exercise-search,09/01/2026,10/16/2026,7,338,61,7,6,lkykathy,7,7,0,6,67247076+lkykathy@users.noreply.github.com; linkeying0425@gmail.com,,0,0
|
|
84
|
+
saramhersch,specification-phase-exercise-search,09/01/2026,10/16/2026,1,4,0,1,0,saramhersch,0,0,0,0,smh9864@nyu.edu,,1,1
|
|
85
|
+
SparkFan-ui,specification-phase-exercise-sttke,09/01/2026,10/16/2026,4,271,28,5,0,SparkFan-ui,0,0,0,0,jf4832@nyu.edu,,6,4
|
|
86
|
+
bloombar,specification-phase-exercise-sttke,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
87
|
+
kevinhan923,specification-phase-exercise-sttke,09/01/2026,10/16/2026,3,116,185,3,0,kevinhan923,0,0,0,0,69257524+kevinhan923@users.noreply.github.com,,4,0
|
|
88
|
+
23matthewc,specification-phase-exercise-nocturnal,09/01/2026,10/16/2026,0,0,0,0,2,23matthewc,0,0,0,0,76405126+23matthewc@users.noreply.github.com,,0,0
|
|
89
|
+
ajoykumarrishi,specification-phase-exercise-nocturnal,09/01/2026,10/16/2026,14,310,24,14,0,ajoykumarrishi,1,1,0,0,151567609+ajoykumarrishi@users.noreply.github.com; rishi.ajoykumar9@gmail.com,,0,14
|
|
90
|
+
bloombar,specification-phase-exercise-nocturnal,09/01/2026,10/16/2026,0,0,0,0,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
91
|
+
christinalin06,specification-phase-exercise-nocturnal,09/01/2026,10/16/2026,7,119,31,7,1,christinalin06,2,2,0,0,Christinalin006@gmail.com,,3,1
|
|
92
|
+
DyingRavioli,specification-phase-exercise-goodTeam,09/01/2026,10/16/2026,5,147,87,5,3,DyingRavioli,5,5,0,5,109256424+DyingRavioli@users.noreply.github.com,,1,5
|
|
93
|
+
RayyanAhmed21,specification-phase-exercise-goodTeam,09/01/2026,10/16/2026,4,121,17,4,0,RayyanAhmed21,0,0,0,0,ra4073@nyu.edu,,0,0
|
|
94
|
+
UIYrj,specification-phase-exercise-goodTeam,09/01/2026,10/16/2026,3,38,4,3,2,UIYrj,2,2,0,2,158982316+UIYrj@users.noreply.github.com,,0,3
|
|
95
|
+
bloombar,specification-phase-exercise-goodTeam,09/01/2026,10/16/2026,1,15,0,1,1,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
96
|
+
rz3007,specification-phase-exercise-goodTeam,09/01/2026,10/16/2026,2,54,4,2,0,rz3007,0,0,0,0,rz3007@nyu.edu,,0,2
|
|
97
|
+
sanay-d-nyu,specification-phase-exercise-goodTeam,09/01/2026,10/16/2026,6,77,9,6,1,sanay-d-nyu,1,1,0,1,sd5113@nyu.edu,sd5113@nyu.edu,1,0
|
|
98
|
+
DaniyalMl,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,1,1,0,1,0,DaniyalMlk,0,0,0,0,103329154+DaniyalMlk@users.noreply.github.com,,1,1
|
|
99
|
+
Jayyu2005,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,1,6,1,1,0,Jayyu2005,0,0,0,0,jy4886@nyu.edu,,1,1
|
|
100
|
+
LefeiKe,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,2,2,2,2,0,LefeiKe,0,0,0,0,lk3104@nyu.edu,,2,0
|
|
101
|
+
bloombar,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,1,1,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
102
|
+
catw1thtea,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,3,5,3,3,0,catw1thtea,0,0,0,0,ds7746@nyu.edu,danialsagymbayev@gmail.com,3,3
|
|
103
|
+
denisekos,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,1,129,5,1,0,denisekos,0,0,0,0,denise.koswara28@gmail.com,,1,1
|
|
104
|
+
manzim7,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,3,9,3,3,5,manzim7,0,0,0,0,mm13507@nyu.edu,,3,0
|
|
105
|
+
,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,0,0,0,0,0,mosada2515,1,0,1,0,,,0,0
|
|
106
|
+
,specification-phase-exercise-ddjz,09/01/2026,10/16/2026,0,0,0,0,0,Yded21,1,0,0,0,,,0,0
|
|
107
|
+
LefeiKe,specification-phase-exercise-team1,09/01/2026,10/16/2026,2,2,2,2,0,LefeiKe,0,0,0,0,lk3104@nyu.edu,,0,0
|
|
108
|
+
Yded21,specification-phase-exercise-team1,09/01/2026,10/16/2026,1,187,14,1,0,Yded21,1,1,0,0,eddyzzy@outlook.com,,0,1
|
|
109
|
+
ac11238,specification-phase-exercise-team1,09/01/2026,10/16/2026,9,29,12,9,0,ac11238,0,0,0,0,ac11348@nyu.edu,,12,9
|
|
110
|
+
bloombar,specification-phase-exercise-team1,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
111
|
+
manzim7,specification-phase-exercise-team1,09/01/2026,10/16/2026,1,5,1,1,0,manzim7,0,0,0,0,mm13507@nyu.edu,,0,0
|
|
112
|
+
uwtz,specification-phase-exercise-team1,09/01/2026,10/16/2026,8,189,37,8,1,uwtz,0,0,0,0,86273231+uwtz@users.noreply.github.com,,8,8
|
|
113
|
+
SeanA12,specification-phase-exercise-GitLost,09/01/2026,10/16/2026,2,36,2,2,2,SeanA12,2,2,0,0,106447402+SeanA12@users.noreply.github.com; seanalliman112@gmai.com,,0,0
|
|
114
|
+
bloombar,specification-phase-exercise-GitLost,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
115
|
+
layan-al,specification-phase-exercise-GitLost,09/01/2026,10/16/2026,4,161,5,4,0,layan-al,5,4,1,0,103759519+layan-al@users.noreply.github.com,,0,0
|
|
116
|
+
ogngnaoh,specification-phase-exercise-GitLost,09/01/2026,10/16/2026,0,0,0,0,4,ogngnaoh,0,0,0,0,ngoviethoang9@gmail.com,,0,0
|
|
117
|
+
rayyang262,specification-phase-exercise-GitLost,09/01/2026,10/16/2026,1,2,2,1,0,rayyang262,0,0,0,0,rayyang2026@gmail.com,,1,1
|
|
118
|
+
BrianDai22,specification-phase-exercise-mihir-brian-yash-linh-theo,09/01/2026,10/16/2026,3,158,157,4,0,BrianDai22,0,0,0,0,mooprules@gmail.com,,0,0
|
|
119
|
+
Mihir Ganesan,specification-phase-exercise-mihir-brian-yash-linh-theo,09/01/2026,10/16/2026,6,243,35,6,0,,0,0,0,0,mihirganesan@10-17-27-151.dynapool.wireless.nyu.edu; mihirganesan@10-17-58-124.dynapool.wireless.nyu.edu,,0,0
|
|
120
|
+
bloombar,specification-phase-exercise-mihir-brian-yash-linh-theo,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
121
|
+
theoegoldstine,specification-phase-exercise-mihir-brian-yash-linh-theo,09/01/2026,10/16/2026,4,6,4,4,0,theoegoldstine,0,0,0,0,63026703+theoegoldstine@users.noreply.github.com,,0,4
|
|
122
|
+
yash-pandya9798,specification-phase-exercise-mihir-brian-yash-linh-theo,09/01/2026,10/16/2026,1,8,2,1,0,yash-pandya9798,0,0,0,0,yash.pandya9798@gmail.com,,0,1
|
|
123
|
+
RayyanAhmed21,specification-phase-exercise,09/01/2026,10/16/2026,5,175,18,5,4,RayyanAhmed21,4,4,0,4,ra4073@nyu.edu,,0,1
|
|
124
|
+
bloombar,specification-phase-exercise,09/01/2026,10/16/2026,1,15,0,1,1,bloombar,1,1,0,1,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
125
|
+
rz3007,specification-phase-exercise,09/01/2026,10/16/2026,3,55,5,3,1,rz3007,1,1,0,1,rz3007@nyu.edu,,1,3
|
|
126
|
+
bloombar,specification-phase-exercise-helloworld,09/01/2026,10/16/2026,1,15,0,1,0,bloombar,0,0,0,0,2209098+bloombar@users.noreply.github.com; amos@cs.nyu.edu,,0,0
|
|
@@ -5,7 +5,7 @@ build-backend = "hatchling.build"
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "gitlogstats"
|
|
7
7
|
description = "Track developers' contributions to one or more git repositories within a particular time range."
|
|
8
|
-
version = "1.
|
|
8
|
+
version = "1.7.0"
|
|
9
9
|
authors = [
|
|
10
10
|
{ name="Tobody Tothing", email="nobody.nothing@nowhere.com" },
|
|
11
11
|
]
|
|
@@ -132,6 +132,38 @@
|
|
|
132
132
|
family: OUT
|
|
133
133
|
phase: 1
|
|
134
134
|
status: Done
|
|
135
|
+
- id: OUT-6
|
|
136
|
+
title: Aggregated results
|
|
137
|
+
full: -a/--aggregate developer prints one row per developer, summed over every
|
|
138
|
+
repository analyzed, instead of one row per contributor per repository. Its
|
|
139
|
+
columns are username, start_date, end_date, commits, insertions, deletions,
|
|
140
|
+
files, merges, repositories, where repositories is the number of
|
|
141
|
+
repositories in which the developer has any activity in the date range (a
|
|
142
|
+
non-zero count, git or GitHub, as for -c); there is no repository column.
|
|
143
|
+
With --github, the columns github_username, prs_opened, prs_merged,
|
|
144
|
+
prs_closed_unmerged, prs_self_merged, git_email, github_email,
|
|
145
|
+
pushes_to_default, web_commits follow. Rows are combined when they share a
|
|
146
|
+
GitHub username (ignoring case), or, for rows without…
|
|
147
|
+
section: §4 Output
|
|
148
|
+
family: OUT
|
|
149
|
+
phase: 1
|
|
150
|
+
status: Done
|
|
151
|
+
- id: OUT-7
|
|
152
|
+
title: Results by day
|
|
153
|
+
full: -a/--aggregate day prints one row per day on which anything was counted,
|
|
154
|
+
summed over every contributor and repository analyzed, in date order. Its
|
|
155
|
+
columns are date, commits, insertions, deletions, files, merges,
|
|
156
|
+
repositories, contributors, where date is the day in mm/dd/yyyy format,
|
|
157
|
+
repositories is the number of repositories with any activity that day and
|
|
158
|
+
contributors the number of developers with any activity that day (a
|
|
159
|
+
developer is identified as in OUT-6, so one person active in several
|
|
160
|
+
repositories counts once, while one matched to a GitHub user in one
|
|
161
|
+
repository but not in another counts twice). With --github, the columns
|
|
162
|
+
prs_opened, prs_merged, prs_closed_unmerged, prs_self_merged…
|
|
163
|
+
section: §4 Output
|
|
164
|
+
family: OUT
|
|
165
|
+
phase: 1
|
|
166
|
+
status: Done
|
|
135
167
|
- id: PKG-1
|
|
136
168
|
title: Installable package
|
|
137
169
|
full: The tool installs with pip install gitlogstats, which provides a
|
|
@@ -5,6 +5,7 @@ import datetime
|
|
|
5
5
|
import re
|
|
6
6
|
import sys
|
|
7
7
|
from . import GitLogsParser
|
|
8
|
+
from . import aggregate
|
|
8
9
|
from .clones import remove_clones
|
|
9
10
|
from .git_logs_parser import FIELDNAMES
|
|
10
11
|
from .github import (
|
|
@@ -14,7 +15,7 @@ from .github import (
|
|
|
14
15
|
GitHubUnavailable,
|
|
15
16
|
check_gh,
|
|
16
17
|
)
|
|
17
|
-
from .github_stats import github_rows
|
|
18
|
+
from .github_stats import github_day_rows, github_rows
|
|
18
19
|
|
|
19
20
|
|
|
20
21
|
def valid_date(value):
|
|
@@ -146,6 +147,15 @@ def main():
|
|
|
146
147
|
default=False,
|
|
147
148
|
action="store_true",
|
|
148
149
|
)
|
|
150
|
+
parser.add_argument(
|
|
151
|
+
"-a",
|
|
152
|
+
"--aggregate",
|
|
153
|
+
help="Combine the results into one row per developer, summed over all "
|
|
154
|
+
"repositories, one row per repository, summed over its contributors, "
|
|
155
|
+
"or one row per day with activity, summed over everyone",
|
|
156
|
+
default=None,
|
|
157
|
+
choices=aggregate.MODES,
|
|
158
|
+
)
|
|
149
159
|
parser.add_argument(
|
|
150
160
|
"--github",
|
|
151
161
|
help="Also report GitHub pull requests opened, merged, closed and "
|
|
@@ -244,21 +254,37 @@ def main():
|
|
|
244
254
|
verbose=args.verbose,
|
|
245
255
|
clean=False if args.github else args.clean,
|
|
246
256
|
)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
257
|
+
if args.aggregate == aggregate.DAY:
|
|
258
|
+
# OUT-7: rows for single days, each with its date
|
|
259
|
+
if args.github:
|
|
260
|
+
rows = github_day_rows(
|
|
261
|
+
last_parser, repo_url, last_parser.get_identities(), args
|
|
262
|
+
)
|
|
263
|
+
else:
|
|
264
|
+
rows = last_parser.day_rows()
|
|
265
|
+
# an idle contributor adds nothing to a day; keep memory small
|
|
266
|
+
rows = [row for row in rows if aggregate.is_active(row)]
|
|
267
|
+
else:
|
|
268
|
+
rows = last_parser.parse()
|
|
269
|
+
if args.github:
|
|
270
|
+
rows = github_rows(
|
|
271
|
+
last_parser, rows, repo_url, last_parser.get_identities(), args
|
|
272
|
+
)
|
|
252
273
|
all_results.extend(rows) # collect across repos
|
|
253
274
|
|
|
254
275
|
# emit a single table (or JSON array) covering all repositories
|
|
255
276
|
if last_parser is not None:
|
|
256
|
-
# an empty CSV table still gets the
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
277
|
+
# an empty CSV table still gets the columns it would have had
|
|
278
|
+
if args.aggregate:
|
|
279
|
+
# OUT-6, OUT-7: one row per developer, repository or day
|
|
280
|
+
all_results = aggregate.aggregate(all_results, args.aggregate, args.github)
|
|
281
|
+
fieldnames = aggregate.fieldnames(args.aggregate, args.github)
|
|
282
|
+
elif args.github:
|
|
283
|
+
fieldnames = (
|
|
284
|
+
FIELDNAMES + GITHUB_FIELDNAMES + EMAIL_FIELDNAMES + ACTIVITY_FIELDNAMES
|
|
285
|
+
)
|
|
286
|
+
else:
|
|
287
|
+
fieldnames = None
|
|
262
288
|
output = last_parser.format_results(all_results, args.format, fieldnames)
|
|
263
289
|
# end with exactly one newline: CSV and Markdown output already has one
|
|
264
290
|
print(output, end="" if output.endswith("\n") else "\n")
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"""Combine result rows by developer or by repository (OUT-6), or by day (OUT-7).
|
|
2
|
+
|
|
3
|
+
Everything here is pure logic over the rows the rest of the tool produces: no
|
|
4
|
+
git, no network. Each aggregated row sums the counts of the rows it combines.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import datetime
|
|
8
|
+
|
|
9
|
+
from gitlogstats.git_logs_parser import FIELDNAMES
|
|
10
|
+
from gitlogstats.github import (
|
|
11
|
+
ACTIVITY_FIELDNAMES,
|
|
12
|
+
EMAIL_FIELDNAMES,
|
|
13
|
+
GITHUB_FIELDNAMES,
|
|
14
|
+
)
|
|
15
|
+
from gitlogstats.identity import join_emails
|
|
16
|
+
|
|
17
|
+
DEVELOPER = "developer"
|
|
18
|
+
REPOSITORY = "repository"
|
|
19
|
+
DAY = "day"
|
|
20
|
+
MODES = [DEVELOPER, REPOSITORY, DAY]
|
|
21
|
+
|
|
22
|
+
# the git counts (commits to merges), summed in every mode
|
|
23
|
+
GIT_COUNTS = FIELDNAMES[4:]
|
|
24
|
+
|
|
25
|
+
# the GitHub pull-request counts (CLI-3), summed in every mode
|
|
26
|
+
PR_COUNTS = GITHUB_FIELDNAMES[1:]
|
|
27
|
+
|
|
28
|
+
# every count; a row with any of them non-zero is active, as for -c (FILT-4)
|
|
29
|
+
ALL_COUNTS = GIT_COUNTS + PR_COUNTS + ACTIVITY_FIELDNAMES
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def fieldnames(mode, github):
|
|
33
|
+
"""
|
|
34
|
+
The output columns of an aggregated table, in order.
|
|
35
|
+
@param mode: DEVELOPER, REPOSITORY or DAY
|
|
36
|
+
@param github: whether the GitHub columns are reported (--github)
|
|
37
|
+
@returns: a list of column names
|
|
38
|
+
"""
|
|
39
|
+
dates = ["start_date", "end_date"]
|
|
40
|
+
if mode == DEVELOPER:
|
|
41
|
+
columns = ["username"] + dates + GIT_COUNTS + ["repositories"]
|
|
42
|
+
if github:
|
|
43
|
+
columns += ["github_username"] + PR_COUNTS + EMAIL_FIELDNAMES
|
|
44
|
+
columns += ACTIVITY_FIELDNAMES
|
|
45
|
+
elif mode == DAY:
|
|
46
|
+
columns = ["date"] + GIT_COUNTS + ["repositories", "contributors"]
|
|
47
|
+
if github:
|
|
48
|
+
columns += PR_COUNTS + ACTIVITY_FIELDNAMES
|
|
49
|
+
else:
|
|
50
|
+
columns = ["repository"] + dates + GIT_COUNTS + ["contributors"]
|
|
51
|
+
if github:
|
|
52
|
+
columns += PR_COUNTS + ACTIVITY_FIELDNAMES
|
|
53
|
+
return columns
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def developer_key(row):
|
|
57
|
+
"""
|
|
58
|
+
The developer a row belongs to: its GitHub user, ignoring case, when it
|
|
59
|
+
has one, otherwise its exact git username.
|
|
60
|
+
@param row: a result row
|
|
61
|
+
@returns: a hashable key
|
|
62
|
+
"""
|
|
63
|
+
login = row.get("github_username")
|
|
64
|
+
if login:
|
|
65
|
+
return ("github", login.casefold())
|
|
66
|
+
return ("git", row["username"])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def is_active(row):
|
|
70
|
+
"""
|
|
71
|
+
Whether a row has any activity: a non-zero count, git or GitHub.
|
|
72
|
+
@param row: a result row
|
|
73
|
+
@returns: a bool
|
|
74
|
+
"""
|
|
75
|
+
return any(row.get(field) for field in ALL_COUNTS)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def main_username(rows):
|
|
79
|
+
"""
|
|
80
|
+
The git username of a developer's rows: the one with the most commits,
|
|
81
|
+
ties alphabetical, as when combining identities in one repository (STAT-11).
|
|
82
|
+
@param rows: the rows of one developer
|
|
83
|
+
@returns: a username, or "" if every row is GitHub-only
|
|
84
|
+
"""
|
|
85
|
+
named = [row for row in rows if row["username"]]
|
|
86
|
+
if not named:
|
|
87
|
+
return ""
|
|
88
|
+
return min(named, key=lambda row: (-(row["commits"] or 0), row["username"]))[
|
|
89
|
+
"username"
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def sum_values(values):
|
|
94
|
+
"""
|
|
95
|
+
Add up counts. An unavailable count (None, CLI-3) is skipped, so the total
|
|
96
|
+
is None only when every count is unavailable.
|
|
97
|
+
@param values: numbers or None
|
|
98
|
+
@returns: their sum, or None
|
|
99
|
+
"""
|
|
100
|
+
present = [value for value in values if value is not None]
|
|
101
|
+
return sum(present) if present else None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def first_text(values):
|
|
105
|
+
"""
|
|
106
|
+
The first non-empty text. When there is none, "" if any value is
|
|
107
|
+
available, or None if every value is unavailable.
|
|
108
|
+
@param values: strings or None
|
|
109
|
+
@returns: a string, or None
|
|
110
|
+
"""
|
|
111
|
+
values = list(values)
|
|
112
|
+
for value in values:
|
|
113
|
+
if value:
|
|
114
|
+
return value
|
|
115
|
+
return None if all(value is None for value in values) else ""
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def merge_emails(values):
|
|
119
|
+
"""
|
|
120
|
+
Join '; '-separated email lists into one sorted list without repeats
|
|
121
|
+
(STAT-13), or None if every list is unavailable.
|
|
122
|
+
@param values: '; '-separated strings, "" or None
|
|
123
|
+
@returns: a '; '-separated string, or None
|
|
124
|
+
"""
|
|
125
|
+
values = list(values)
|
|
126
|
+
if all(value is None for value in values):
|
|
127
|
+
return None
|
|
128
|
+
return join_emails(
|
|
129
|
+
email for value in values if value for email in value.split("; ")
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def combine(rows, columns):
|
|
134
|
+
"""
|
|
135
|
+
Build the aggregated row of one group.
|
|
136
|
+
@param rows: the rows of one developer, repository or day
|
|
137
|
+
@param columns: the output columns, from fieldnames()
|
|
138
|
+
@returns: one row with those columns
|
|
139
|
+
"""
|
|
140
|
+
active = [row for row in rows if is_active(row)]
|
|
141
|
+
out = {}
|
|
142
|
+
for field in columns:
|
|
143
|
+
if field == "username":
|
|
144
|
+
out[field] = main_username(rows)
|
|
145
|
+
elif field in ("repository", "start_date", "end_date", "date"):
|
|
146
|
+
out[field] = rows[0][field]
|
|
147
|
+
elif field == "repositories":
|
|
148
|
+
out[field] = len({row["repository"] for row in active})
|
|
149
|
+
elif field == "contributors":
|
|
150
|
+
out[field] = len({developer_key(row) for row in active})
|
|
151
|
+
elif field == "github_username":
|
|
152
|
+
out[field] = first_text(row[field] for row in rows)
|
|
153
|
+
elif field in EMAIL_FIELDNAMES:
|
|
154
|
+
out[field] = merge_emails(row[field] for row in rows)
|
|
155
|
+
else:
|
|
156
|
+
out[field] = sum_values(row[field] for row in rows)
|
|
157
|
+
return out
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def aggregate(rows, mode, github):
|
|
161
|
+
"""
|
|
162
|
+
Combine result rows into one row per developer, repository or day. Rows
|
|
163
|
+
are sorted by username (or GitHub username, for a developer with no git
|
|
164
|
+
username) or by repository, ignoring case, or by date. Days only count
|
|
165
|
+
active rows, so a day without activity is left out (OUT-7).
|
|
166
|
+
@param rows: result rows of every repository, after -u and -c; in DAY
|
|
167
|
+
mode, rows for single days, each with a "date" key
|
|
168
|
+
@param mode: DEVELOPER, REPOSITORY or DAY
|
|
169
|
+
@param github: whether the rows carry the GitHub columns (--github)
|
|
170
|
+
@returns: the aggregated rows, sorted
|
|
171
|
+
"""
|
|
172
|
+
groups = {}
|
|
173
|
+
for row in rows:
|
|
174
|
+
if mode == DEVELOPER:
|
|
175
|
+
key = developer_key(row)
|
|
176
|
+
elif mode == REPOSITORY:
|
|
177
|
+
key = row["repository"]
|
|
178
|
+
elif is_active(row):
|
|
179
|
+
key = row["date"]
|
|
180
|
+
else:
|
|
181
|
+
continue
|
|
182
|
+
groups.setdefault(key, []).append(row)
|
|
183
|
+
columns = fieldnames(mode, github)
|
|
184
|
+
combined = [combine(group, columns) for group in groups.values()]
|
|
185
|
+
|
|
186
|
+
def sort_key(row):
|
|
187
|
+
if mode == DAY:
|
|
188
|
+
return (datetime.datetime.strptime(row["date"], "%m/%d/%Y"), "")
|
|
189
|
+
if mode == DEVELOPER:
|
|
190
|
+
name = row["username"] or row.get("github_username") or ""
|
|
191
|
+
else:
|
|
192
|
+
name = row["repository"]
|
|
193
|
+
return (name.casefold(), name)
|
|
194
|
+
|
|
195
|
+
return sorted(combined, key=sort_key)
|