gitcast 1.0.6__tar.gz → 1.0.9__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.
- {gitcast-1.0.6/gitcast.egg-info → gitcast-1.0.9}/PKG-INFO +1 -1
- {gitcast-1.0.6 → gitcast-1.0.9}/cli/gitcast.py +4 -9
- gitcast-1.0.9/core/trigger.py +115 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/pypi-errors.md +15 -0
- {gitcast-1.0.6 → gitcast-1.0.9/gitcast.egg-info}/PKG-INFO +1 -1
- {gitcast-1.0.6 → gitcast-1.0.9}/gitcast.egg-info/SOURCES.txt +3 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/setup.py +1 -1
- gitcast-1.0.9/ui/popup.py +12 -0
- gitcast-1.0.9/ui/review.py +25 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/web/index.html +15 -8
- {gitcast-1.0.6 → gitcast-1.0.9}/.env.example +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/LICENSE +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/MANIFEST.in +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/README.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/ai/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/ai/formatter.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/ai/generator.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/ai/prompts.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/ai/viral_patterns.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/analytics.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/auth.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/auth_middleware.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/auth_routes.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/monitoring.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/payload.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/ratelimit.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/routes.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/server.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/api/validators.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/assets/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/assets/favicon-16x16.png +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/assets/favicon-32x32.png +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/assets/favicon-64x64.png +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/assets/favicon.ico +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/assets/icon.png +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/cli/.env.example +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/cli/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/config/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/config/settings.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/capture.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/codebase_reader.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/framing.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/hotkey.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/log_stream.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/ocr.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/screenshot_session.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/security.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/core/tray.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/api-keys.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/article-generator.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/capture-flow.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/changelog.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/contributing.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/dashboard.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/insights.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/introduction.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/post-formats.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/providers.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/quickstart.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/docs/sprint-mode.md +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/gitcast.egg-info/dependency_links.txt +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/gitcast.egg-info/entry_points.txt +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/gitcast.egg-info/requires.txt +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/gitcast.egg-info/top_level.txt +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/publisher/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/publisher/clipboard.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/publisher/twitter.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/pyproject.toml +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/requirements.txt +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/setup.cfg +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/cleanup.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/engagement.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/insights.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/key_manager.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/logger.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/metrics.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/sprint.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/streak.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/supabase_client.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/storage/tone_memory.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/tests/test_keys.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/tests/test_ocr_fix.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/ui/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/web/__init__.py +0 -0
- {gitcast-1.0.6 → gitcast-1.0.9}/web/landing.html +0 -0
|
@@ -67,16 +67,11 @@ def main():
|
|
|
67
67
|
# open browser
|
|
68
68
|
webbrowser.open("http://localhost:8000")
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
print("[OK] server running at http://localhost:8000")
|
|
71
|
+
print("[OK] browser opened")
|
|
72
|
+
|
|
71
73
|
from core.tray import run_tray
|
|
72
|
-
|
|
73
|
-
import os as _os
|
|
74
|
-
_parent = _os.path.dirname(_os.path.dirname(_os.path.abspath(__file__)))
|
|
75
|
-
if _os.path.exists(_os.path.join(_parent, "main.py")):
|
|
76
|
-
_sys.path.insert(0, _parent)
|
|
77
|
-
elif _os.path.exists(_os.path.join(_os.getcwd(), "main.py")):
|
|
78
|
-
_sys.path.insert(0, _os.getcwd())
|
|
79
|
-
from main import on_trigger
|
|
74
|
+
from core.trigger import on_trigger
|
|
80
75
|
run_tray(trigger_callback=on_trigger)
|
|
81
76
|
return
|
|
82
77
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import threading
|
|
2
|
+
from core.capture import run_capture
|
|
3
|
+
from core.ocr import run_ocr
|
|
4
|
+
from api.payload import build_payload
|
|
5
|
+
from ui.popup import show_popup
|
|
6
|
+
from config.settings import is_sprint_mode
|
|
7
|
+
from storage.sprint import log_sprint_capture
|
|
8
|
+
from ai.generator import generate_posts
|
|
9
|
+
from ui.review import show_review
|
|
10
|
+
from publisher.twitter import publish_post
|
|
11
|
+
from storage.logger import log_post
|
|
12
|
+
import asyncio
|
|
13
|
+
import webbrowser
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def on_trigger():
|
|
17
|
+
"""
|
|
18
|
+
Called every time the hotkey fires.
|
|
19
|
+
Full capture → generate → review flow.
|
|
20
|
+
"""
|
|
21
|
+
print("[Trigger] on_trigger fired successfully")
|
|
22
|
+
print("[Gitcast] Hotkey fired — starting capture...")
|
|
23
|
+
|
|
24
|
+
capture = run_capture()
|
|
25
|
+
print("[Trigger] capture complete")
|
|
26
|
+
ocr = run_ocr(capture["screenshot"]["path"])
|
|
27
|
+
print("[Trigger] OCR complete")
|
|
28
|
+
|
|
29
|
+
if is_sprint_mode():
|
|
30
|
+
log_sprint_capture(
|
|
31
|
+
git_diff=capture["git_diff"].get("diff", ""),
|
|
32
|
+
ocr_text=ocr.get("text", ""),
|
|
33
|
+
raw_thought="",
|
|
34
|
+
timestamp=capture["screenshot"]["timestamp"],
|
|
35
|
+
)
|
|
36
|
+
print("[Gitcast] Sprint Mode — capture logged silently.")
|
|
37
|
+
return
|
|
38
|
+
|
|
39
|
+
def on_submit(raw_thought):
|
|
40
|
+
print("[Trigger] raw thought received")
|
|
41
|
+
print(f"[Gitcast] Raw thought: '{raw_thought}'")
|
|
42
|
+
payload = build_payload(
|
|
43
|
+
raw_thought=raw_thought,
|
|
44
|
+
ocr_result=ocr,
|
|
45
|
+
capture_result=capture,
|
|
46
|
+
)
|
|
47
|
+
payload["use_vision_fallback"] = False
|
|
48
|
+
payload["screenshot_b64"] = None
|
|
49
|
+
|
|
50
|
+
def generate_and_show():
|
|
51
|
+
try:
|
|
52
|
+
print('[Trigger] calling generate_posts...')
|
|
53
|
+
print("[Trigger] generating posts...")
|
|
54
|
+
variations = asyncio.run(generate_posts(payload))
|
|
55
|
+
print(f'[Trigger] got {len(variations)} variations')
|
|
56
|
+
print(f'[Trigger] keys: {list(variations.keys())}')
|
|
57
|
+
for k, v in variations.items():
|
|
58
|
+
print(f'[Trigger] {k}: {v[:50]}...')
|
|
59
|
+
|
|
60
|
+
print("[Trigger] opening review window")
|
|
61
|
+
webbrowser.open("http://localhost:8000")
|
|
62
|
+
|
|
63
|
+
def on_publish(post_text, format_key,
|
|
64
|
+
screenshot_path):
|
|
65
|
+
print(f"[Gitcast] Publishing: {format_key}")
|
|
66
|
+
result = publish_post(
|
|
67
|
+
post_text, screenshot_path)
|
|
68
|
+
if result.get("success"):
|
|
69
|
+
if result.get("fallback"):
|
|
70
|
+
print("[Gitcast] Copied to clipboard")
|
|
71
|
+
else:
|
|
72
|
+
print(f"[Gitcast] Published: "
|
|
73
|
+
f"{result.get('tweet_url')}")
|
|
74
|
+
log_post(
|
|
75
|
+
post_text=post_text,
|
|
76
|
+
format_key=format_key,
|
|
77
|
+
screenshot_path=screenshot_path,
|
|
78
|
+
tweet_url=result.get(
|
|
79
|
+
"tweet_url", ""),
|
|
80
|
+
tweet_id=result.get(
|
|
81
|
+
"tweet_id", ""),
|
|
82
|
+
fallback=result.get(
|
|
83
|
+
"fallback", False),
|
|
84
|
+
)
|
|
85
|
+
else:
|
|
86
|
+
print(f"[Gitcast] Error: "
|
|
87
|
+
f"{result.get('error')}")
|
|
88
|
+
|
|
89
|
+
def on_close():
|
|
90
|
+
print("[Gitcast] Review closed.")
|
|
91
|
+
|
|
92
|
+
show_review(
|
|
93
|
+
payload=payload,
|
|
94
|
+
variations=variations,
|
|
95
|
+
on_publish=on_publish,
|
|
96
|
+
on_close=on_close,
|
|
97
|
+
)
|
|
98
|
+
except Exception as e:
|
|
99
|
+
print(f'[Trigger] generation error: {e}')
|
|
100
|
+
import traceback
|
|
101
|
+
traceback.print_exc()
|
|
102
|
+
|
|
103
|
+
threading.Thread(
|
|
104
|
+
target=generate_and_show,
|
|
105
|
+
daemon=True
|
|
106
|
+
).start()
|
|
107
|
+
|
|
108
|
+
def on_dismiss():
|
|
109
|
+
print("[Gitcast] Capture dismissed.")
|
|
110
|
+
|
|
111
|
+
print("[Trigger] popup showing")
|
|
112
|
+
show_popup(
|
|
113
|
+
on_submit=on_submit,
|
|
114
|
+
on_dismiss=on_dismiss
|
|
115
|
+
)
|
|
@@ -6,6 +6,20 @@ This document records the issues faced during the testing, packaging, and execut
|
|
|
6
6
|
|
|
7
7
|
## 1. Resolved Issues
|
|
8
8
|
|
|
9
|
+
### Fixed in `gitcast==1.0.8`
|
|
10
|
+
|
|
11
|
+
#### Issue 2.3: Unauthorized (401) API Errors on localhost
|
|
12
|
+
* **Symptom**: Browser console logs API call failures: `api/keys/status:1 Failed to load resource: the server responded with a status of 401 (Unauthorized)`.
|
|
13
|
+
* **Root Cause**: On page load, the frontend checked if a token existed in `localStorage` and immediately verified it by querying `/api/keys/status`. When the server has restarted or the session has expired, the old token was no longer valid, causing the FastAPI backend to reject it with a `401 Unauthorized` response before the frontend could retrieve a fresh token.
|
|
14
|
+
* **Resolution**: Optimized `authGate` in `web/index.html` to check if the app is accessed on `localhost` (using `window.location.hostname`). If so, it auto-fetches the fresh session token directly from the server's `/api/token` endpoint *first* before verifying or falling back to `localStorage`. This avoids sending any request to `/api/keys/status` with an invalid/expired session token on startup, eliminating the console error.
|
|
15
|
+
|
|
16
|
+
### Fixed in `gitcast==1.0.7`
|
|
17
|
+
|
|
18
|
+
#### Issue 2.2: ImportError and Pygame conflicts when running gitcast CLI from project directories containing `main.py`
|
|
19
|
+
* **Symptom**: Running `gitcast` from any project directory containing its own `main.py` (e.g., `snakegame/main.py`) causes the application to crash on startup after initializing the user's local modules (e.g., importing `pygame` and running game startup logic).
|
|
20
|
+
* **Root Cause**: In `cli/gitcast.py`, the script checked if `main.py` existed in the current working directory (`os.getcwd()`), and if so, prepended `os.getcwd()` to `sys.path` and attempted to run `from main import on_trigger`. This executed the user's local `main.py` and crashed when `on_trigger` was not defined.
|
|
21
|
+
* **Resolution**: Moved `on_trigger` to `core/trigger.py` and removed all local directory `sys.path` injection.
|
|
22
|
+
|
|
9
23
|
### Fixed in `gitcast==1.0.6`
|
|
10
24
|
|
|
11
25
|
#### Issue 1.4: FastAPI Server Rate Limiting on Localhost
|
|
@@ -66,3 +80,4 @@ This document records the issues faced during the testing, packaging, and execut
|
|
|
66
80
|
```
|
|
67
81
|
* **Status**: Logged and waiting for future triage. The application starts, but key bindings or endpoints triggers are failing to generate the actual post output.
|
|
68
82
|
|
|
83
|
+
|
|
@@ -42,6 +42,7 @@ core/ocr.py
|
|
|
42
42
|
core/screenshot_session.py
|
|
43
43
|
core/security.py
|
|
44
44
|
core/tray.py
|
|
45
|
+
core/trigger.py
|
|
45
46
|
docs/api-keys.md
|
|
46
47
|
docs/article-generator.md
|
|
47
48
|
docs/capture-flow.md
|
|
@@ -78,6 +79,8 @@ storage/tone_memory.py
|
|
|
78
79
|
tests/test_keys.py
|
|
79
80
|
tests/test_ocr_fix.py
|
|
80
81
|
ui/__init__.py
|
|
82
|
+
ui/popup.py
|
|
83
|
+
ui/review.py
|
|
81
84
|
web/__init__.py
|
|
82
85
|
web/index.html
|
|
83
86
|
web/landing.html
|
|
@@ -51,7 +51,7 @@ if os.path.exists(requirements_path):
|
|
|
51
51
|
|
|
52
52
|
setup(
|
|
53
53
|
name="gitcast",
|
|
54
|
-
version="1.0.
|
|
54
|
+
version="1.0.9",
|
|
55
55
|
description="git diff → published post. under 60 seconds.",
|
|
56
56
|
long_description=long_description,
|
|
57
57
|
long_description_content_type="text/markdown",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
def show_popup(on_submit, on_dismiss):
|
|
2
|
+
"""
|
|
3
|
+
Tkinter popup fallback/mock.
|
|
4
|
+
Immediately submits a default thought to run the pipeline.
|
|
5
|
+
"""
|
|
6
|
+
import threading
|
|
7
|
+
|
|
8
|
+
def run():
|
|
9
|
+
print("[Gitcast] Mock popup triggered.")
|
|
10
|
+
on_submit("Captured via hotkey trigger")
|
|
11
|
+
|
|
12
|
+
threading.Thread(target=run, daemon=True).start()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import webbrowser
|
|
3
|
+
from config.settings import CURRENT_DRAFT
|
|
4
|
+
|
|
5
|
+
def show_review(payload, variations, on_publish, on_close):
|
|
6
|
+
"""
|
|
7
|
+
Tkinter review window fallback/mock.
|
|
8
|
+
Saves the generated variations to current draft and opens the web dashboard.
|
|
9
|
+
"""
|
|
10
|
+
print("[Gitcast] Mock review window triggered - saving draft and opening browser.")
|
|
11
|
+
draft_data = {
|
|
12
|
+
"payload": payload,
|
|
13
|
+
"variations": variations,
|
|
14
|
+
"timestamp": payload.get("timestamp", ""),
|
|
15
|
+
"status": "ready"
|
|
16
|
+
}
|
|
17
|
+
try:
|
|
18
|
+
with open(CURRENT_DRAFT, "w", encoding="utf-8") as f:
|
|
19
|
+
json.dump(draft_data, f, indent=4)
|
|
20
|
+
print("[Gitcast] Draft saved successfully.")
|
|
21
|
+
except Exception as e:
|
|
22
|
+
print(f"[Gitcast] Failed to save draft: {e}")
|
|
23
|
+
|
|
24
|
+
webbrowser.open("http://localhost:8000")
|
|
25
|
+
on_close()
|
|
@@ -2361,16 +2361,14 @@
|
|
|
2361
2361
|
return;
|
|
2362
2362
|
}
|
|
2363
2363
|
|
|
2364
|
-
let token =
|
|
2364
|
+
let token = '';
|
|
2365
2365
|
let valid = false;
|
|
2366
2366
|
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
if (!valid) {
|
|
2373
|
-
// Auto-fetch localhost token if stored token is missing or invalid
|
|
2367
|
+
// 1. If on localhost, try to get the active session token directly from the server first
|
|
2368
|
+
const isLocalhost = window.location.hostname === 'localhost' ||
|
|
2369
|
+
window.location.hostname === '127.0.0.1' ||
|
|
2370
|
+
window.location.hostname === '[::1]';
|
|
2371
|
+
if (isLocalhost) {
|
|
2374
2372
|
try {
|
|
2375
2373
|
const tokenRes = await fetch('/api/token');
|
|
2376
2374
|
if (tokenRes.status === 200) {
|
|
@@ -2386,6 +2384,15 @@
|
|
|
2386
2384
|
}
|
|
2387
2385
|
}
|
|
2388
2386
|
|
|
2387
|
+
// 2. Fallback to localStorage token if we couldn't get a valid token from localhost auto-fetch
|
|
2388
|
+
if (!valid) {
|
|
2389
|
+
token = localStorage.getItem('sl_token') || '';
|
|
2390
|
+
if (token) {
|
|
2391
|
+
setAuthToken(token, localStorage.getItem('sl_user') || 'local_user');
|
|
2392
|
+
valid = await verifyStoredToken(token);
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2389
2396
|
if (valid) {
|
|
2390
2397
|
await showDashboard(false);
|
|
2391
2398
|
} else {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|