better-git-of-theseus 0.5.1__tar.gz → 0.6.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.
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/PKG-INFO +1 -1
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/better_git_of_theseus.egg-info/PKG-INFO +1 -1
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/analyze.py +12 -3
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/app.py +37 -10
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/cmd.py +10 -6
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/plotly_plots.py +6 -6
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/setup.py +1 -1
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/LICENSE +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/README.md +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/better_git_of_theseus.egg-info/SOURCES.txt +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/better_git_of_theseus.egg-info/dependency_links.txt +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/better_git_of_theseus.egg-info/entry_points.txt +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/better_git_of_theseus.egg-info/requires.txt +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/better_git_of_theseus.egg-info/top_level.txt +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/__init__.py +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/line_plot.py +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/stack_plot.py +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/survival_plot.py +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/git_of_theseus/utils.py +0 -0
- {better_git_of_theseus-0.5.1 → better_git_of_theseus-0.6.0}/setup.cfg +0 -0
|
@@ -256,6 +256,7 @@ def analyze(
|
|
|
256
256
|
procs=2,
|
|
257
257
|
quiet=False,
|
|
258
258
|
opt=False,
|
|
259
|
+
progress_callback=None,
|
|
259
260
|
):
|
|
260
261
|
use_mailmap = (Path(repo_dir) / ".mailmap").exists()
|
|
261
262
|
repo = git.Repo(repo_dir)
|
|
@@ -304,9 +305,11 @@ def analyze(
|
|
|
304
305
|
) # repo.git.commit_graph('write --changed-paths') doesn't work for some reason
|
|
305
306
|
|
|
306
307
|
desc = "{:<55s}".format("Listing all commits")
|
|
307
|
-
for commit in tqdm(
|
|
308
|
+
for i, commit in enumerate(tqdm(
|
|
308
309
|
repo.iter_commits(branch), desc=desc, unit=" Commits", **tqdm_args
|
|
309
|
-
):
|
|
310
|
+
)):
|
|
311
|
+
if progress_callback:
|
|
312
|
+
progress_callback(0, f"Listing commits: {i}")
|
|
310
313
|
cohort = datetime.datetime.utcfromtimestamp(commit.committed_date).strftime(
|
|
311
314
|
cohortfm
|
|
312
315
|
)
|
|
@@ -330,6 +333,8 @@ def analyze(
|
|
|
330
333
|
master_commits.append(commit)
|
|
331
334
|
last_date = commit.committed_date
|
|
332
335
|
bar.update()
|
|
336
|
+
if progress_callback:
|
|
337
|
+
progress_callback(0, f"Backtracking branch: {len(master_commits)} commits found")
|
|
333
338
|
if not commit.parents:
|
|
334
339
|
break
|
|
335
340
|
commit = commit.parents[0]
|
|
@@ -388,6 +393,8 @@ def analyze(
|
|
|
388
393
|
curve_key_tuples.add(("ext", ext))
|
|
389
394
|
curve_key_tuples.add(("dir", get_top_dir(entry.path)))
|
|
390
395
|
bar.update()
|
|
396
|
+
if progress_callback:
|
|
397
|
+
progress_callback(0, f"Discovering entries: {entries_total}")
|
|
391
398
|
master_commits[i] = MiniCommit(
|
|
392
399
|
commit
|
|
393
400
|
) # Might have cached the entries, we don't want that
|
|
@@ -465,7 +472,9 @@ def analyze(
|
|
|
465
472
|
**tqdm_args,
|
|
466
473
|
) as bar:
|
|
467
474
|
cbar = tqdm(master_commits, desc=desc, unit=" Commits", position=0, **tqdm_args)
|
|
468
|
-
for commit in cbar:
|
|
475
|
+
for i, commit in enumerate(cbar):
|
|
476
|
+
if progress_callback:
|
|
477
|
+
progress_callback(i / len(master_commits), f"Analyzing commit {i+1}/{len(master_commits)}")
|
|
469
478
|
t = datetime.datetime.utcfromtimestamp(commit.committed_date)
|
|
470
479
|
ts.append(t) # x axis
|
|
471
480
|
|
|
@@ -51,7 +51,8 @@ if len(sys.argv) > 1:
|
|
|
51
51
|
default_repo = sys.argv[1]
|
|
52
52
|
|
|
53
53
|
repo_path = default_repo
|
|
54
|
-
|
|
54
|
+
repo_name = os.path.basename(os.path.abspath(repo_path))
|
|
55
|
+
st.sidebar.markdown(f"**Repo:** {repo_name}")
|
|
55
56
|
|
|
56
57
|
# Fetch branches for the selectbox
|
|
57
58
|
try:
|
|
@@ -106,6 +107,9 @@ with st.sidebar.expander("Analysis Parameters"):
|
|
|
106
107
|
|
|
107
108
|
@st.cache_data(show_spinner=False)
|
|
108
109
|
def run_analysis(repo_path, branch, cohortfm, interval, procs, ignore):
|
|
110
|
+
# This is a dummy wrapper for the cached function
|
|
111
|
+
# Because we need the callback to update the UI, we can't easily cache the callback-enabled version
|
|
112
|
+
# However, we can cache the final result.
|
|
109
113
|
return analyze(
|
|
110
114
|
repo_path,
|
|
111
115
|
cohortfm=cohortfm,
|
|
@@ -117,20 +121,43 @@ def run_analysis(repo_path, branch, cohortfm, interval, procs, ignore):
|
|
|
117
121
|
quiet=True
|
|
118
122
|
)
|
|
119
123
|
|
|
124
|
+
def run_analysis_with_progress(repo_path, branch, cohortfm, interval, procs, ignore):
|
|
125
|
+
progress_bar = st.progress(0)
|
|
126
|
+
status_text = st.empty()
|
|
127
|
+
|
|
128
|
+
def progress_callback(progress, text):
|
|
129
|
+
progress_bar.progress(progress)
|
|
130
|
+
status_text.text(text)
|
|
131
|
+
|
|
132
|
+
results = analyze(
|
|
133
|
+
repo_path,
|
|
134
|
+
cohortfm=cohortfm,
|
|
135
|
+
interval=interval,
|
|
136
|
+
ignore=ignore,
|
|
137
|
+
outdir=None,
|
|
138
|
+
branch=branch,
|
|
139
|
+
procs=procs,
|
|
140
|
+
quiet=True,
|
|
141
|
+
progress_callback=progress_callback
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
progress_bar.empty()
|
|
145
|
+
status_text.empty()
|
|
146
|
+
return results
|
|
147
|
+
|
|
120
148
|
# State management for analysis results
|
|
121
149
|
if 'analysis_results' not in st.session_state:
|
|
122
150
|
st.session_state.analysis_results = None
|
|
123
151
|
|
|
124
152
|
if st.sidebar.button("🚀 Run Analysis") or (len(sys.argv) > 1 and st.session_state.analysis_results is None):
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
st.session_state.analysis_results = None
|
|
153
|
+
try:
|
|
154
|
+
st.session_state.analysis_results = run_analysis_with_progress(
|
|
155
|
+
repo_path, branch, cohortfm, interval, procs, ignore
|
|
156
|
+
)
|
|
157
|
+
st.success("Analysis completed!")
|
|
158
|
+
except Exception as e:
|
|
159
|
+
st.error(f"Analysis failed: {e}")
|
|
160
|
+
st.session_state.analysis_results = None
|
|
134
161
|
|
|
135
162
|
# Main View
|
|
136
163
|
if st.session_state.analysis_results:
|
|
@@ -12,12 +12,16 @@ def main():
|
|
|
12
12
|
|
|
13
13
|
# Run streamlit
|
|
14
14
|
# We pass the repo_path as an argument to the streamlit script
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
try:
|
|
16
|
+
subprocess.run([
|
|
17
|
+
sys.executable, "-m", "streamlit", "run",
|
|
18
|
+
app_path,
|
|
19
|
+
"--browser.gatherUsageStats", "false",
|
|
20
|
+
"--", repo_path
|
|
21
|
+
])
|
|
22
|
+
except KeyboardInterrupt:
|
|
23
|
+
# Exit gracefully on Ctrl+C
|
|
24
|
+
sys.exit(0)
|
|
21
25
|
|
|
22
26
|
if __name__ == "__main__":
|
|
23
27
|
main()
|
|
@@ -68,8 +68,8 @@ def plotly_stack_plot(data, max_n=20, normalize=False, title=None):
|
|
|
68
68
|
),
|
|
69
69
|
xaxis=dict(title="Date", gridcolor='rgba(128,128,128,0.2)'),
|
|
70
70
|
hovermode="x unified",
|
|
71
|
-
margin=dict(l=20, r=20, t=60, b=
|
|
72
|
-
legend=dict(orientation="h", yanchor="top", y=-0.
|
|
71
|
+
margin=dict(l=20, r=20, t=60, b=120),
|
|
72
|
+
legend=dict(orientation="h", yanchor="top", y=-0.25, xanchor="center", x=0.5),
|
|
73
73
|
plot_bgcolor='rgba(0,0,0,0)',
|
|
74
74
|
paper_bgcolor='rgba(0,0,0,0)'
|
|
75
75
|
)
|
|
@@ -97,8 +97,8 @@ def plotly_line_plot(data, max_n=20, normalize=False, title=None):
|
|
|
97
97
|
),
|
|
98
98
|
xaxis=dict(title="Date", gridcolor='rgba(128,128,128,0.2)'),
|
|
99
99
|
hovermode="x unified",
|
|
100
|
-
margin=dict(l=20, r=20, t=60, b=
|
|
101
|
-
legend=dict(orientation="h", yanchor="top", y=-0.
|
|
100
|
+
margin=dict(l=20, r=20, t=60, b=120),
|
|
101
|
+
legend=dict(orientation="h", yanchor="top", y=-0.25, xanchor="center", x=0.5),
|
|
102
102
|
plot_bgcolor='rgba(0,0,0,0)',
|
|
103
103
|
paper_bgcolor='rgba(0,0,0,0)'
|
|
104
104
|
)
|
|
@@ -169,8 +169,8 @@ def plotly_survival_plot(commit_history, exp_fit=False, years=5, title=None):
|
|
|
169
169
|
yaxis=dict(title="Lines still present (%)", range=[0, 105], gridcolor='rgba(128,128,128,0.2)'),
|
|
170
170
|
xaxis=dict(title="Years", range=[0, years], gridcolor='rgba(128,128,128,0.2)'),
|
|
171
171
|
hovermode="x unified",
|
|
172
|
-
margin=dict(l=20, r=20, t=50, b=
|
|
173
|
-
legend=dict(orientation="h", yanchor="top", y=-0.
|
|
172
|
+
margin=dict(l=20, r=20, t=50, b=120),
|
|
173
|
+
legend=dict(orientation="h", yanchor="top", y=-0.25, xanchor="center", x=0.5),
|
|
174
174
|
plot_bgcolor='rgba(0,0,0,0)',
|
|
175
175
|
paper_bgcolor='rgba(0,0,0,0)'
|
|
176
176
|
)
|
|
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
5
5
|
|
|
6
6
|
setup(
|
|
7
7
|
name="better-git-of-theseus",
|
|
8
|
-
version="0.
|
|
8
|
+
version="0.6.0",
|
|
9
9
|
description="Plot stats on Git repositories with interactive Plotly charts",
|
|
10
10
|
long_description=long_description,
|
|
11
11
|
long_description_content_type="text/markdown",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|