fix: החזרת חישוב תיקיית השורש בשחזור ZIP לריפו (רגרסיה מ-#3205) - #3314
Conversation
ה-ZIP של גיבוי ריפו הוא ה-zipball הרשמי של GitHub, שכל תוכנו יושב תחת תיקייה אחת בשם owner-repo-sha, ואליו נוסף metadata.json בשורש הארכיון. הקובץ בשורש הוא בדיוק מה שגורם ל-detect_zip_common_root להחזיר None — וזה הכלל הנכון שלה, שנועד למנוע חיתוך שגוי של ZIP כמו README.md לצד src/ — ולכן תיקיית ה-zipball לא נחתכה. השחזור העלה לריפו את המניפסט ואת כל התוכן רובד אחד עמוק מדי. המניפסט מוסר עכשיו לפני חישוב תיקיית השורש, ולא רק מרשימת הקבצים לפריסה. ההכרה בו נעשית לפי תוכן ולא לפי שם: metadata.json הוא שם קובץ לגיטימי בריפו אמיתי, ודילוג לפי שם היה מוחק קובץ תוכן. קובץ נחשב מניפסט רק אם הוא JSON תקין עם backup_id (השדה שגם save_backup_file וגם save_backup_bytes מבטיחים) ועוד שדה מזהה. שני המסלולים שפורסים ZIP שכפלו את אותו חישוב, ולכן הוא רוכז ב-zip_members_and_root — אחרת התיקון היה חל על אחד מהם בלבד. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HbK6wRnQuBb9H9VC11n9NT
ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
Sorry @amirbiron, you've used your own review budget of 250,000 diff characters for the last 7 days.
You can request another review in 2 days and 9 hours by commenting @sourcery-ai review. Upgrade to get a review now.
🧯 Dangerous deletes guard reportPolicy: see .cursorrules — dangerous deletions are blocked unless wrapped safely. Summary:
Flagged findings (file:line:snippet): Excluded matches (by path pattern) |
Reviewer's GuideFixes repository ZIP restoration by recognizing and removing the backup manifest before common-root detection, allowing GitHub zipball contents to be restored at the repository root while preserving legitimate user metadata.json files; both ZIP-consuming paths now share the behavior and are covered by unit and end-to-end tests. Sequence diagram for corrected GitHub ZIP restorationsequenceDiagram
participant User
participant Handler as handle_document
participant ZipHelper as zip_members_and_root
participant GitHub
User->>Handler: handle_document
Handler->>ZipHelper: zip_members_and_root
ZipHelper->>ZipHelper: is_ck_backup_manifest
ZipHelper->>ZipHelper: detect_zip_common_root
ZipHelper-->>Handler: members, common_root
Handler->>GitHub: create tree with stripped repository paths
GitHub-->>Handler: restoration result
Flow diagram for backup manifest and common-root handlingflowchart TD
A[ZIP archive] --> B[Collect file members]
B --> C{metadata.json is a CK backup manifest?}
C -- Yes --> D[Remove manifest from root detection]
C -- No --> E[Preserve metadata.json as repository content]
D --> F[detect_zip_common_root]
E --> F
F --> G[Strip zipball root from paths]
G --> H[Restore files at repository root]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughהשחזור לריפו מחשב את שורש ה-ZIP לפי תיקיות בלבד ושומר את Changesשחזור וייבוא ZIP
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk:⚪ Minimal · up to This change restores GitHub backup ZIP contents to the repository root while preserving existing ZIP import behavior. The change is localized and supported by targeted tests, so no actionable merge-blocking risk remains beyond normal checks and review. Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 70.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 10 functions across 3 files. (2 skipped: 2 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
⏱️ Performance report(No performance test durations collected. Mark tests with |
📖 Documentation PreviewThe documentation has been built successfully!
To view locally:
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
Uh oh!
There was an error while loading. Please reload this page.
עד fd13dd5 (2026-08-06) המסלול החזיק חישוב משלו שסופר תיקיות בלבד: קובץ בשורש אינו מכיל "/", ולכן metadata.json שהגיבוי מוסיף לא השתתף בספירה, נשארה תיקיית ה-zipball היחידה, והיא נחתכה. השחזור עבד. אותו PR ריכז את החישוב ל-detect_zip_common_root, שבה קובץ בשורש מבטל את זיהוי השורש — כלל נכון לייבוא ZIP, שמונע חיתוך שגוי של ארכיון כמו README.md לצד src/, אבל שגוי כאן. מאז השחזור העלה לריפו את התוכן בתוך תיקייה בשם owner-repo-sha. החישוב המקורי הוחזר מילה במילה, ו-detect_zip_common_root לא שונתה כלל: היא ממשיכה לשרת את הייבוא ואת הפריסה לתיקייה, שאצלם הכלל נכון. נוספה לה אזהרה בדוקסטרינג נגד איחוד חוזר, כי האיחוד הזה הוא שגרם לרגרסיה. metadata.json ממשיך לעלות לריפו יחד עם התוכן, כפי שהיה תמיד. למסלול השחזור לא הייתה בדיקה מקצה לקצה, ולכן ההחלפה עברה בשקט. נוספו שתיים: אחת על מבנה הגיבוי האמיתי, ואחת על ארכיון בלי שורש יחיד כדי שחיתוך גורף לא ייראה תקין. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HbK6wRnQuBb9H9VC11n9NT
There was a problem hiding this comment.
3 issues found across 4 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="handlers/documents.py">
<violation number="1" location="handlers/documents.py:434">
P2: Custom agent: **Enforce Strict Maintainability Standards**
The two ZIP flows now duplicate the same member-filtering policy after removing `zip_members_and_root`. Extract the shared filtering into a helper while keeping the restore and import root-detection policies separate.</violation>
<violation number="2" location="handlers/documents.py:446">
P2: החישוב החדש של `common_root` במסלול שחזור-לריפו חותך תיקייה עליונה יחידה גם כשיש קבצים חופשיים בשורש הארכיון (למשל `README.md` לצד `src/`), בניגוד ל-`detect_zip_common_root` ששימש קודם בגרסת ה-main ומנע בדיוק את זה. עבור ZIP שרירותי שהועלה לשחזור התוצאה היא פילוס מבנה הריפו. בדוק שהכרה בשורש נלקחת בחשבון גם קובץ חופשי בשורש שאינו `metadata.json` לפני החיתוך.</violation>
<violation number="3" location="handlers/documents.py:628">
P1: Custom agent: **Flag AI Slop and Fabricated Changes**
When a backup ZIP contains the documented root-level `metadata.json`, both readers still treat it as content: the restore path uploads it, and `_parse_zip_for_import` passes it to `detect_zip_common_root`, which leaves the GitHub zipball directory nested. This contradicts the new manifest contract and the docs' claim that both paths remove the manifest before root detection; restore the shared content-based filtering before calculating the root and use it in both paths.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| @@ -45,6 +45,15 @@ def detect_zip_common_root(names: Iterable[str]) -> Optional[str]: | |||
| תיקיית שורש קיימת רק אם *כל* הרשומות נמצאות תחתיה. אם יש ולו קובץ אחד | |||
There was a problem hiding this comment.
P1: Custom agent: Flag AI Slop and Fabricated Changes
When a backup ZIP contains the documented root-level metadata.json, both readers still treat it as content: the restore path uploads it, and _parse_zip_for_import passes it to detect_zip_common_root, which leaves the GitHub zipball directory nested. This contradicts the new manifest contract and the docs' claim that both paths remove the manifest before root detection; restore the shared content-based filtering before calculating the root and use it in both paths.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At handlers/documents.py, line 628:
<comment>When a backup ZIP contains the documented root-level `metadata.json`, both readers still treat it as content: the restore path uploads it, and `_parse_zip_for_import` passes it to `detect_zip_common_root`, which leaves the GitHub zipball directory nested. This contradicts the new manifest contract and the docs' claim that both paths remove the manifest before root detection; restore the shared content-based filtering before calculating the root and use it in both paths.</comment>
<file context>
@@ -652,6 +625,7 @@ def _parse_zip_for_import(self, buf: BytesIO):
total_uncompressed += entry_size
if total_uncompressed > MAX_IMPORT_TOTAL_UNCOMPRESSED_BYTES:
raise ValueError("סך התוכן הלא-דחוס בארכיון חורג מהמגבלה המותרת.")
+ common_root = detect_zip_common_root(names_all)
def strip_root(path: str) -> str:
</file context>
Uh oh!
There was an error while loading. Please reload this page.
| @@ -45,6 +45,15 @@ def detect_zip_common_root(names: Iterable[str]) -> Optional[str]: | |||
| תיקיית שורש קיימת רק אם *כל* הרשומות נמצאות תחתיה. אם יש ולו קובץ אחד | |||
There was a problem hiding this comment.
P2: Custom agent: Enforce Strict Maintainability Standards
The two ZIP flows now duplicate the same member-filtering policy after removing zip_members_and_root. Extract the shared filtering into a helper while keeping the restore and import root-detection policies separate.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At handlers/documents.py, line 434:
<comment>The two ZIP flows now duplicate the same member-filtering policy after removing `zip_members_and_root`. Extract the shared filtering into a helper while keeping the restore and import root-detection policies separate.</comment>
<file context>
@@ -477,7 +430,20 @@ async def _handle_github_restore_zip_to_repo(self, update: Update, context: Cont
with zipfile.ZipFile(buf, "r") as zf:
- members, common_root = zip_members_and_root(zf)
+ all_names = [n for n in zf.namelist() if not n.endswith("/")]
+ members = [
+ n
+ for n in all_names
</file context>
Uh oh!
There was an error while loading. Please reload this page.
| for name in zf.namelist(): | ||
| if "/" in name and not name.startswith("__MACOSX/"): | ||
| top_levels.add(name.split("/", 1)[0]) | ||
| common_root = list(top_levels)[0] if len(top_levels) == 1 else None |
There was a problem hiding this comment.
P2: החישוב החדש של common_root במסלול שחזור-לריפו חותך תיקייה עליונה יחידה גם כשיש קבצים חופשיים בשורש הארכיון (למשל README.md לצד src/), בניגוד ל-detect_zip_common_root ששימש קודם בגרסת ה-main ומנע בדיוק את זה. עבור ZIP שרירותי שהועלה לשחזור התוצאה היא פילוס מבנה הריפו. בדוק שהכרה בשורש נלקחת בחשבון גם קובץ חופשי בשורש שאינו metadata.json לפני החיתוך.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At handlers/documents.py, line 446:
<comment>החישוב החדש של `common_root` במסלול שחזור-לריפו חותך תיקייה עליונה יחידה גם כשיש קבצים חופשיים בשורש הארכיון (למשל `README.md` לצד `src/`), בניגוד ל-`detect_zip_common_root` ששימש קודם בגרסת ה-main ומנע בדיוק את זה. עבור ZIP שרירותי שהועלה לשחזור התוצאה היא פילוס מבנה הריפו. בדוק שהכרה בשורש נלקחת בחשבון גם קובץ חופשי בשורש שאינו `metadata.json` לפני החיתוך.</comment>
<file context>
@@ -477,7 +430,20 @@ async def _handle_github_restore_zip_to_repo(self, update: Update, context: Cont
+ for name in zf.namelist():
+ if "/" in name and not name.startswith("__MACOSX/"):
+ top_levels.add(name.split("/", 1)[0])
+ common_root = list(top_levels)[0] if len(top_levels) == 1 else None
def strip_root(path: str) -> str:
</file context>
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
הכפילות ב-backup-flow.rst היא שלי: חתכתי את הקובץ לפי index על "יצירת גיבוי מלא", מחרוזת שמופיעה קודם בשורת ה-summary שבראש הקובץ. נקודת החיתוך יצאה לפני נקודת ההתחלה, והפרוסה שכפלה את סקירה כללית, סוגי גיבויים ומבנה ה-ZIP. הבלוק המשוכפל היה הגרסה הישנה של הסעיף, שתיארה את zip_members_and_root — פונקציה שכבר לא קיימת בקוד — ולכן התיעוד סתר את הקוד. נמחק, ונשארה גרסה אחת שתואמת את ההתנהגות. והריוויו חשף מגבלה אמיתית בהתנהגות שהוחזרה: זיהוי השורש סופר תיקיות בלבד, ולכן ZIP שאינו גיבוי — README.md בשורש לצד src/ — מאבד רובד. עבור קובץ גיבוי זו בדיוק ההתנהגות הרצויה, ולכן היא נשמרת ומוסברת למשתמש במסך שמבקש את הקובץ, במקום להשתנות. הטקסט הוגדר כקבוע אחד: אותו callback מטופל בשני מקומות בקובץ, וטקסט משוכפל היה מציג את ההערה רק באחד מהמסלולים. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HbK6wRnQuBb9H9VC11n9NT
There was a problem hiding this comment.
2 issues found across 5 files (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="tests/test_zip_to_folder.py">
<violation number="1" location="tests/test_zip_to_folder.py:1215">
P3: חומרת ממצא: 3/10 (נמוכה-בינונית). הבדיקה טוענת שהיא מקבעת את קיום ההתראה למשתמש ('and_the_user_is_warned', 'קיום ההתראה'), אבל היא רק בודקת שהקבוע RIPESTORE_ZIP_PROMPT מכיל שתי תת-מחרוזות. היא אינה מריצה את מסלול התצוגה בפועל (github_menu_handler שורות 2915/8940), ולכן אם יוסר הצגת ההתראה מהמסלול — הבדיקה תמשיך לעבור. כדי לאמת את הטענה יש לבדוק שההתראה נשלחת למשתמש במסלול, או לצמצם את טענת הבדיקה להצמדות לטקסט הקבוע בלבד.</violation>
</file>
<file name="github_menu_handler.py">
<violation number="1" location="github_menu_handler.py:2915">
P3: The RESTORE_ZIP_PROMPT edit at line 8940 sits in an unreachable copy of the `github_restore_zip_setpurge:` handler: `show_github_backup_menu` returns at line 8929, and the enclosing `if False and ...` guard can never fire. Only the live handler at line 2895 runs. The module comment (lines 158-165) justifies maintaining the constant 'בשני מקומות' (in two places) due to text duplication, but one of those places is dead code, so the claim is misleading. Remove the unreachable `if False` block and drop the dead editing; keep RESTORE_ZIP_PROMPT only at the live call site.</violation>
</file>
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic
| # ההתראה חייבת להתקיים, אחרת המגבלה הופכת להפתעה שקטה | ||
| from github_menu_handler import RESTORE_ZIP_PROMPT | ||
| assert "עלול להיפרס שטוח" in RESTORE_ZIP_PROMPT, RESTORE_ZIP_PROMPT |
There was a problem hiding this comment.
P3: חומרת ממצא: 3/10 (נמוכה-בינונית). הבדיקה טוענת שהיא מקבעת את קיום ההתראה למשתמש ('and_the_user_is_warned', 'קיום ההתראה'), אבל היא רק בודקת שהקבוע RIPESTORE_ZIP_PROMPT מכיל שתי תת-מחרוזות. היא אינה מריצה את מסלול התצוגה בפועל (github_menu_handler שורות 2915/8940), ולכן אם יוסר הצגת ההתראה מהמסלול — הבדיקה תמשיך לעבור. כדי לאמת את הטענה יש לבדוק שההתראה נשלחת למשתמש במסלול, או לצמצם את טענת הבדיקה להצמדות לטקסט הקבוע בלבד.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At tests/test_zip_to_folder.py, line 1215:
<comment>חומרת ממצא: 3/10 (נמוכה-בינונית). הבדיקה טוענת שהיא מקבעת את קיום ההתראה למשתמש ('and_the_user_is_warned', 'קיום ההתראה'), אבל היא רק בודקת שהקבוע RIPESTORE_ZIP_PROMPT מכיל שתי תת-מחרוזות. היא אינה מריצה את מסלול התצוגה בפועל (github_menu_handler שורות 2915/8940), ולכן אם יוסר הצגת ההתראה מהמסלול — הבדיקה תמשיך לעבור. כדי לאמת את הטענה יש לבדוק שההתראה נשלחת למשתמש במסלול, או לצמצם את טענת הבדיקה להצמדות לטקסט הקבוע בלבד.</comment>
<file context>
@@ -1183,3 +1183,34 @@ async def test_restore_keeps_nested_structure_when_there_is_no_single_root(
+ # ההתראה חייבת להתקיים, אחרת המגבלה הופכת להפתעה שקטה
+ from github_menu_handler import RESTORE_ZIP_PROMPT
+
+ assert "עלול להיפרס שטוח" in RESTORE_ZIP_PROMPT, RESTORE_ZIP_PROMPT
+ assert "קובץ גיבוי" in RESTORE_ZIP_PROMPT, RESTORE_ZIP_PROMPT
</file context>
| ("🧹 יבוצע ניקוי לפני העלאה. " if purge_flag else "🔁 ללא מחיקה. ") + | ||
| "שלח עכשיו קובץ ZIP לשחזור לריפו." | ||
| ("🧹 יבוצע ניקוי לפני העלאה. " if purge_flag else "🔁 ללא מחיקה. ") | ||
| + RESTORE_ZIP_PROMPT |
There was a problem hiding this comment.
P3: The RESTORE_ZIP_PROMPT edit at line 8940 sits in an unreachable copy of the github_restore_zip_setpurge: handler: show_github_backup_menu returns at line 8929, and the enclosing if False and ... guard can never fire. Only the live handler at line 2895 runs. The module comment (lines 158-165) justifies maintaining the constant 'בשני מקומות' (in two places) due to text duplication, but one of those places is dead code, so the claim is misleading. Remove the unreachable if False block and drop the dead editing; keep RESTORE_ZIP_PROMPT only at the live call site.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At github_menu_handler.py, line 2915:
<comment>The RESTORE_ZIP_PROMPT edit at line 8940 sits in an unreachable copy of the `github_restore_zip_setpurge:` handler: `show_github_backup_menu` returns at line 8929, and the enclosing `if False and ...` guard can never fire. Only the live handler at line 2895 runs. The module comment (lines 158-165) justifies maintaining the constant 'בשני מקומות' (in two places) due to text duplication, but one of those places is dead code, so the claim is misleading. Remove the unreachable `if False` block and drop the dead editing; keep RESTORE_ZIP_PROMPT only at the live call site.</comment>
<file context>
@@ -2897,8 +2911,8 @@ def _upload_all_files():
- ("🧹 יבוצע ניקוי לפני העלאה. " if purge_flag else "🔁 ללא מחיקה. ") +
- "שלח עכשיו קובץ ZIP לשחזור לריפו."
+ ("🧹 יבוצע ניקוי לפני העלאה. " if purge_flag else "🔁 ללא מחיקה. ")
+ + RESTORE_ZIP_PROMPT
)
return
</file context>
Uh oh!
There was an error while loading. Please reload this page.
✨ תיאור קצר
שחזור ZIP לריפו דרך
/github← גיבוי ושחזור פרס את כל תוכן הריפו בתוך תיקייה בשםowner-repo-sha, במקום בשורש. זו רגרסיה מ-#3205 (fd13dd5e, 6 באוגוסט 2026), והחישוב שהיה קודם מוחזר כלשונו.📦 שינויים עיקריים
פירוט נקודות:
handlers/documents.py—_handle_github_restore_zip_to_repoחוזר לחישוב תיקיית השורש שהיה לו עד feat(bot): פריסת ZIP לתיקייה ספציפית בריפו #3205, מילה במילה: ספירת תיקיות בלבד.detect_zip_common_rootלא שונתה כלל. היא ממשיכה לשרת את ייבוא ה-ZIP ואת הפריסה לתיקייה, שאצלם הכלל שלה נכון. נוספה לה אזהרה בדוקסטרינג נגד איחוד חוזר עם מסלול השחזור — האיחוד הזה הוא שגרם לרגרסיה.docs/workflows/backup-flow.rst— תועד מבנה ה-ZIP שלgithub_repo_zipולמה השחזור סופר תיקיות בלבד. המבנה לא היה מתועד, וזה מה שאיפשר לשבור אותו.🧪 בדיקות
מה השתנה ב-#3205, מאומת בהרצה של שתי הגרסאות על אותו ZIP:
הקוד הישן ספר רק שמות שמכילים
/, ולכןmetadata.jsonשבשורש לא השתתף בספירה — נשארה תיקייה אחת, והיא נחתכה. #3205 החליף את זה ב-detect_zip_common_root, שבה קובץ בשורש מבטל את זיהוי השורש. הכלל ההוא נוסף במכוון ונכון לייבוא ZIP (הוא מונע חיתוך שגוי של ארכיון כמוREADME.mdלצדsrc/, ויש עליו טסט) — אבל שגוי כאן.handle_documentבמצבgithub_restore_zip_to_repo, מול stub של GitHub, ואימות הנתיבים שנשלחים ל-tree. נופלת עלmainעם['metadata.json', 'owner-repo-6dfaac9/README.md', 'owner-repo-6dfaac9/src/main.py']— בדיוק התסמין שדווח.138 טסטים בקבצים שנוגעים ב-
handlers.documentsעוברים. flake8 זהה לבסיס (6 מול 6), mypy 8 מול 8, ה-RST אומת ב-docutils.🧪 בדיקות נדרשות ב‑PR
📝 סוג שינוי
✅ צ'קליסט
docs/workflows/backup-flow.rst| המשפט: "github_repo_zipאינו ארכיון שהבוט בונה בעצמו"🧩 השפעות/סיכונים
סיכון נמוך במיוחד: זו החזרה להתנהגות שרצה בפרודקשן חודשים, ולא לוגיקה חדשה.
detect_zip_common_rootלא נגעתי בה, ולכן ייבוא ZIP והפריסה לתיקייה אינם מושפעים כלל.metadata.jsonממשיך לעלות לריפו יחד עם התוכן — כך זה תמיד היה, כולל לפני הרגרסיה, וזו התנהגות מכוונת שנשמרת.מה שלא בסקופ: משך השחזור. בלוגים שהתקבלו הוא נמדד כ-21 שניות; האיטיות שדווחה הייתה על ארכיון אחר בגודל 3.5MB, ולא נגעתי בה.
Summary by Sourcery
Restore the repository-root calculation for GitHub backup ZIPs while preserving the existing ZIP import behavior.
Bug Fixes:
Enhancements:
Documentation:
github_repo_zipbackups and explain why restoration identifies roots by directories only.Tests: