שבוע 10 – יום 2: commit, status, checkout

היום נדאג לממש 3 פקודות נוספות לתוכנת ה־wit שאנחנו כותבים: commit, status ו־checkout.
בכל תרגיל, הגישו למערכת התרגילים את כל העבודה שלכם עד עכשיו (כולל סעיפים קודמים).

תרגיל 1: הפקודה commit

ממשו את הפונקציה commit, שתופעל בעזרת הרצת הפקודה python path/to/wit.py commit MESSAGE.
הפונקציה תרוץ אך ורק אם אחת מתיקיות האב של תיקיית העבודה העכשווית מכילה את התיקייה .wit.

פקודה זו למעשה יוצרת “נקודת שמירה” של ממש, שאליה נוכל לשחזר את הפרויקט כשנרצה.
כשנעשה commit, ניצור “תמונה” מתוך הקבצים שאספנו לתוך staging_area בעזרת הפקודה add.

חלק ראשון: יצירת תיקייה

בעת הפעלת הפונקציה, תיווצר תיקייה חדשה בתוך תיקיית images שיצרתם ביום 1 בעזרת הפונקציה init.
שמה של התיקייה החדשה יורכב מ־40 תווים אקראיים בטווח 0-9a-f (התווים: 1234567890abcdef). שם התיקייה הזה יקרא מעכשיו “commit id”.

חלק שני: יצירת קובץ metadata על ה־commit

ליד אותה תיקייה ששמה הוא ה־commit id, יווצר קובץ באותו שם, עם הסיומת .txt, ובו יהיה התוכן הבא:

parent=None
date=Sat Aug 26 19:00:20 2020 +0300
message=The message

החליפו את The message בהודעה שנכתבה אחרי המילה commit בפקודה שהוקלדה בשורת הפקודה.
בינתיים, השאירו את השורה parent: None כפי שהיא.

חלק שלישי: יצירת השמירה

הפונקציה תעתיק את תוכן התיקייה staging_area לתוך התיקייה החדשה שנוצרה.
התוכן בתיקייה staging_area יישאר כמו שהוא ולא ישונה.

חלק רביעי: ארגון המידע לגישה עתידית

  1. בקובץ בשם references.txt שנמצא ישרות תחת תיקיית .wit, הוסיפו את השורה HEAD=commit_id, כאשר במקום commit_id יכתב שם התיקייה שנוצרה בעקבות פקודת ה־commit. אם הקובץ לא קיים, צרו אותו.
  2. בשורה אחרת באותו קובץ, כתבו master=commit_id. גם פה במקום commit_id יכתב שם התיקייה שנוצרה בעקבות פקודת ה־commit.

חלק חמישי: מה קורה בקומיט הבא?

נניח שנוספו בעזרת הפקודה add עוד כמה קבצים ל־staging_area, והמשתמש מבקש לעשות שוב commit.

כל התיקייה של staging_area תועתק לתיקייה חדשה בתוך images, שעבורה יוגרל commit_id חדש.
הפעם, השורה בה כתוב parent צריכה להצביע על ה־commit_id הקודם (תוכלו לקחת אותו מ־HEAD).
השורות HEAD ו־master ב־references.txt צריכות להתעדכן בהתאם ל־commit_id החדש שנוצר.

בונוס: אם אין שינוי מפעם שעברה, אל תאפשרו לעשות commit נוסף.

תרגיל 2: הפקודה status

ממשו את הפונקציה status שתופעל בעזרת הרצת הפקודה python path/to/wit.py status.
הפונקציה תרוץ אך ורק אם אחת מתיקיות האב של תיקיית העבודה העכשווית מכילה את התיקייה .wit.

הפקודה תדפיס הודעה למשתמש, בה יהיו הפרטים הבאים:

  1. ה־commit id שבו אנחנו נמצאים כרגע (ה־HEAD)
  2. תחת הכותרת Changes to be committed:, יהיו קבצים שעשינו להם add מאז ה־commit האחרון, והם יתווספו לתיקייה שתיווצר ב־images בפקודת ה־commit הבאה.
  3. תחת הכותרת Changes not staged for commit: יופיעו קבצים שנמצאים ב־staging_area כרגע, אבל התוכן שלהם ב"תיקייה האמיתית" לא תואם את התוכן שלהם בתיקיית staging_area.
    במילים אחרות: קבצים שעשו להם פעם add, נמצאים ב־staging_area באותו נתיב, אבל התוכן שלהם שֻׁנָּה מאז ה־commit האחרון ומאז שהתוכן שלהם שֻׁנָּה לא עשו להם add.
    באופן מעט משונה, קבצים שמופיעים ב־Changes to be committed: (סעיף 2) יכולים להופיע גם פה, אם ערכנו אותם, עשינו להם add ואז ערכנו אותם שוב.
  4. תחת הכותרת Untracked files: יופיעו קבצים שאין להם קובץ תואם ב־staging_area.

בונוס: ממשו פקודת wit rm שתאפשר למחוק קבצים מ־staging_area.
אם אתם לא מתייחסים לבונוס: אין צורך לתמוך במקרים של מחיקת קבצים מהתיקייה הראשית.

הבהרה: קבצים יכולים להופיע תחת הכותרת Changes to be commited גם אם עשינו להם commit בעבר. אם, לדוגמה, עשינו commit לקובץ שנקרא “targil.py”, אבל מייד שינינו אותו ועשינו לו wit add מחדש, בפקודת ה־status אנחנו נראה את הקובץ תחת הכותרת “Changes to be commited”.

תרגיל 3: הפקודה checkout

ממשו את הפונקציה checkout שתופעל בעזרת הרצת הפקודה python path/to/wit.py checkout commit_id.
הפונקציה תרוץ אך ורק אם אחת מתיקיות האב של תיקיית העבודה העכשווית מכילה את התיקייה .wit.

פעולה בסיסית

הפונקציה checkout תחליף את כל הקבצים שנמצאים תחת “התיקייה המקורית” (זו שבתוכה יש את התיקייה .wit).
הפונקציה תעתיק אל התיקייה המקורית את כל הקבצים שנמצאים בתיקייה images/commit_id, כאשר commit_id הוא הפרמטר שהוכנס לפקודת ה־checkout.

התחשבו בנקודות הבאות:

  1. כדי לא לאבד מידע, הפקודה תכשל ולא תתחיל לרוץ אם יש קבצים שמופיעים ב־wit status תחת הכותרת Changes to be committed:, או תחת הכותרת Changes not staged for commit:.
  2. קבצים שמופיעים תחת הכותרת Untracked files: לא ישונו – הם ישארו כמו שהם, והקבצים שלצידם יוחלפו או יווצרו.

עדכנו את ה־HEAD ל־commit_id שבו אתם נמצאים אחרי הרצת הפקודה.
כמו כן, החליפו את התוכן של staging_area כך שתוכנה החדש יהיה תוכן התיקייה images/commit_id.

הרחבה

אם במקום הפרמטר commit_id יכתב master, הפקודה תקח את ה־commit id המקושר אליו ותעשה checkout אל ה־commit_id הרלוונטי.

עדכון ה־master בעת פקודת commit

אם התבצע commit וה־commit id שאליו מצביע HEAD הוא אותו commit id שאליו מצביע master (לפי references.txt), יש לעדכן את שניהם ל־commit_id החדש.
אם התבצע checkout שהעביר את ה־HEAD כך שהוא לא מצביע לאותו commit id שאליו מצביע ה־master, ה־commit id שאליו מצביע master לא ישתנה.

2 לייקים

אחד הפוסטים פוצל לנושא חדש: לא לאפשר commit אם היה שינוי?