|
3 | 3 | """
|
4 | 4 |
|
5 | 5 | import collections
|
6 |
| -import datetime |
| 6 | +from datetime import datetime, timezone |
7 | 7 | from typing import Dict, Optional
|
8 | 8 |
|
9 | 9 | from git_py_stats.git_operations import run_git_command
|
10 | 10 |
|
11 | 11 |
|
12 |
| -def branch_tree_view() -> None: |
| 12 | +def branch_tree() -> None: |
13 | 13 | """
|
14 | 14 | Displays a visual graph of recent commits across all branches.
|
15 | 15 | """
|
| 16 | + |
| 17 | + # Since can be hardcoded for now. It'll be based on the earliest commit |
| 18 | + # in the repo |
| 19 | + earliest_commit_date = run_git_command(['git', 'log', '--reverse', '--format=%ad']) |
| 20 | + if earliest_commit_date: |
| 21 | + # Take the first line as the earliest commit date |
| 22 | + first_commit_date = earliest_commit_date.split('\n')[0] |
| 23 | + since = f"--since='{first_commit_date}'" |
| 24 | + else: |
| 25 | + # If no commits, set since to an empty string |
| 26 | + since = '' |
| 27 | + |
| 28 | + # Until will be current system's date and time |
| 29 | + now = datetime.now(timezone.utc).astimezone() |
| 30 | + until_formatted = now.strftime('%a, %d %b %Y %H:%M:%S %Z') |
| 31 | + until = f"--until='{until_formatted}'" |
16 | 32 |
|
17 |
| - cmd = ['git', 'log', '--graph', '--oneline', '--all', '-n', '10'] |
| 33 | + # Empty log options for now |
| 34 | + log_options = '' |
| 35 | + |
| 36 | + # Hardcoded limit |
| 37 | + limit=10 |
| 38 | + |
| 39 | + # Format string for git --format so it gets interpreted correctly |
| 40 | + format_str = "--format=--+ Commit: %h%n | Date: %aD (%ar)%n | Message: %s %d%n + Author: %aN %n" |
| 41 | + |
| 42 | + # Perform final git command |
| 43 | + cmd = [ |
| 44 | + 'git', '-c', 'log.showSignature=false', 'log', |
| 45 | + '--use-mailmap', |
| 46 | + '--graph', |
| 47 | + '--abbrev-commit', |
| 48 | + since, |
| 49 | + until, |
| 50 | + '--decorate', |
| 51 | + format_str, |
| 52 | + '--all' |
| 53 | + ] |
| 54 | + |
18 | 55 | output = run_git_command(cmd)
|
| 56 | + |
| 57 | + # handle the head -n $((_limit*5)) portion |
19 | 58 | if output:
|
20 |
| - print("Branch tree view (last 10 commits):") |
21 |
| - print(output) |
| 59 | + print('Branching tree view:\n') |
| 60 | + lines = output.split('\n') |
| 61 | + total_lines = limit * 5 |
| 62 | + limited_lines = lines[:total_lines] |
| 63 | + |
| 64 | + for line in limited_lines: |
| 65 | + print(f"{line}") |
| 66 | + |
| 67 | + commit_count = sum(1 for line in limited_lines if line.strip().startswith('--+ Commit:')) |
22 | 68 | else:
|
23 | 69 | print('No data available.')
|
24 | 70 |
|
25 | 71 |
|
26 |
| -def all_branches_sorted() -> None: |
| 72 | +def branches_by_date() -> None: |
27 | 73 | """
|
28 | 74 | Lists branches sorted by the latest commit date.
|
29 | 75 | """
|
30 |
| - |
31 |
| - cmd = [ |
32 |
| - 'git', 'for-each-ref', '--sort=-committerdate', '--format', '%(refname:short)', |
33 |
| - 'refs/heads/' |
34 |
| - ] |
| 76 | + |
| 77 | + # Original command: |
| 78 | + # git for-each-ref --sort=committerdate refs/heads/ \ |
| 79 | + # --format='[%(authordate:relative)] %(authorname) %(refname:short)' | cat -n |
| 80 | + # TODO: Wouldn't git log --pretty=format:'%ad' --date=short be better here? |
| 81 | + # Then we could pipe it through sort, uniq -c, sort -nr, etc. |
| 82 | + # Possibly feed back into the parent project |
| 83 | + format_str = "[%(authordate:relative)] %(authorname) %(refname:short)" |
| 84 | + cmd = ['git', 'for-each-ref', '--sort=committerdate', 'refs/heads/', f'--format={format_str}'] |
| 85 | + |
35 | 86 | output = run_git_command(cmd)
|
36 | 87 | if output:
|
37 |
| - print("All branches sorted by most recent commits:") |
38 |
| - print(output) |
| 88 | + # Split the output into lines |
| 89 | + lines = output.split('\n') |
| 90 | + |
| 91 | + # Number the lines similar to 'cat -n' |
| 92 | + numbered_lines = [f"{idx + 1} {line}" for idx, line in enumerate(lines)] |
| 93 | + |
| 94 | + # Output numbered lines |
| 95 | + print('All branches (sorted by most recent commit):\n') |
| 96 | + for line in numbered_lines: |
| 97 | + print(f'\t{line}') |
39 | 98 | else:
|
40 |
| - print('No branches available.') |
| 99 | + print('No commits found.') |
41 | 100 |
|
42 | 101 |
|
43 |
| -def all_contributors() -> None: |
| 102 | +def contributors() -> None: |
44 | 103 | """
|
45 | 104 | Lists all contributors alphabetically.
|
46 | 105 | """
|
47 |
| - |
48 |
| - cmd = ['git', 'shortlog', '-sn', '--all'] |
| 106 | + |
| 107 | + # Hardcode variables |
| 108 | + # TODO: Make these configurable by the user |
| 109 | + earliest_commit_date = run_git_command(['git', 'log', '--reverse', '--format=%ad']) |
| 110 | + if earliest_commit_date: |
| 111 | + # Take the first line as the earliest commit date |
| 112 | + first_commit_date = earliest_commit_date.split('\n')[0] |
| 113 | + since = f"--since='{first_commit_date}'" |
| 114 | + else: |
| 115 | + # If no commits, set since to an empty string |
| 116 | + since = '' |
| 117 | + |
| 118 | + |
| 119 | + now = datetime.now(timezone.utc).astimezone() |
| 120 | + until_formatted = now.strftime('%a, %d %b %Y %H:%M:%S %Z') |
| 121 | + until = f"--until={until_formatted}" |
| 122 | + |
| 123 | + pathspec = "" # No pathspec filtering |
| 124 | + |
| 125 | + merges = "--no-merges" |
| 126 | + limit = 50 |
| 127 | + log_options = "" |
| 128 | + |
| 129 | + # Original command |
| 130 | + # git -c log.showSignature=false log --use-mailmap $_merges "$_since" "$_until" \ |
| 131 | + # --format='%aN' $_log_options $_pathspec | sort -u | cat -n |
| 132 | + cmd = [ |
| 133 | + 'git', |
| 134 | + '-c', 'log.showSignature=false', |
| 135 | + 'log', |
| 136 | + '--use-mailmap', |
| 137 | + merges, |
| 138 | + since, |
| 139 | + until, |
| 140 | + '--format=%aN', |
| 141 | + log_options |
| 142 | + ] |
| 143 | + |
| 144 | + # Append pathspec only if it's not empty. Currently hardcoded |
| 145 | + if pathspec: |
| 146 | + cmd.append(pathspec) |
| 147 | + |
| 148 | + # Remove any empty strings from the command to prevent Git misinterpretation |
| 149 | + # Breaks without this |
| 150 | + cmd = [arg for arg in cmd if arg] |
| 151 | + |
| 152 | + # Execute the Git command |
49 | 153 | output = run_git_command(cmd)
|
50 | 154 | if output:
|
51 |
| - print("All contributors:") |
52 |
| - contributors = [line.strip() for line in output.split('\n')] |
53 |
| - contributors.sort(key=lambda x: x.split('\t')[1]) |
54 |
| - for contributor in contributors: |
55 |
| - print(contributor) |
| 155 | + print('All contributors (sorted by name):\n') |
| 156 | + # Split the output into individual author names |
| 157 | + authors = [line.strip() for line in output.split('\n') if line.strip()] |
| 158 | + |
| 159 | + # Remove duplicates by converting the list to a set |
| 160 | + unique_authors = set(authors) |
| 161 | + |
| 162 | + # Sort the unique authors alphabetically |
| 163 | + sorted_authors = sorted(unique_authors) |
| 164 | + |
| 165 | + # Apply the limit |
| 166 | + limited_authors = sorted_authors[:limit] |
| 167 | + |
| 168 | + # Number the authors similar to 'cat -n' and print |
| 169 | + numbered_authors = [f"{idx + 1} {author}" for idx, author in enumerate(limited_authors)] |
| 170 | + for author in numbered_authors: |
| 171 | + print(f'\t{author}') |
56 | 172 | else:
|
57 | 173 | print('No contributors found.')
|
58 | 174 |
|
59 |
| - |
60 | 175 | def new_contributors() -> None:
|
61 | 176 | """
|
62 | 177 | Lists contributors sorted by email.
|
|
0 commit comments