שלום אורח התחבר

יצירת רשימת שינויים אוטומטית מתוך גיט

הבלוג מתעדכן בכל שבוע ביום ראשון. הזינו כתובת מייל וקבלו את הפוסטים החדשים לתיבה.

סקריפט awk קצר יכול לעזור לנו להציג רשימות שינויים מתוך גיט בצורה יותר ידידותית, ובדרך גם ללמד אותנו משהו על סקריפטים ושינויי פורמט של טקסטים.

1המשימה

הפקודה הבאה מציגה רשימת שינויים מקוצרת במאגר גיט:

git log --tags --pretty="%h%x09%d%x09%s" --decorate=full

פלט לדוגמא נראה כך:

33d34b4  (HEAD -> refs/heads/master, tag: refs/tags/v2) FIXED bash header
06a8ab7         ADD csh header
adc73ff         ADD postgres support
c5769c8  (tag: refs/tags/v1)    FIXED linux related deadlock
56bfafe         ADD Mysql support
a53848a         ADD new control panel
779e4fe         FIXED ui bugs
99066b1         initial file

נרצה לייצר מהפלט רשימת שינויים שתכלול כותרת לכל תג ותחתיה את השינויים הרלוונטים. פלט לדוגמא:

*** v2
 -   ADD csh header
 -   ADD postgres support

*** v1
 -   ADD Mysql support
 -   ADD new control panel
 -   FIXED ui bugs
 -   initial file

2פתרון באמצעות awk

הכלי awk מציע יכולות עיבוד טקסט מתקדמות בקוד מאוד ממוקד. התוכנית הבאה מבצעת את ההמרה:

#!/usr/local/bin/gawk -F\t -f

length($2)>0 {
# start new version block
  match($2, "tag: refs/tags/(\\w+)", tags)
  current_tag = tags[1]
  if (block++ >0) print ""

  print "*** " current_tag
  $1 = ""
  $2 = ""
  print " - " $0

  next
}

{
  $1 = ""
  print " - " $0
}

כמה נקודות ששווה לשים לב אליהן:

  1. השדות בטקסט מופרדים בטאבים, ולכן בשורת הפתיח הגדרתי את טאב כתו הפרדה.

  2. הפקודה match מתאימה את השדה השני לביטוי רגולארי. הפרמטר השלישי הוא מערך עבור הערכים שנלכדו בסוגריים. פרמטר זה הוא הרחבה של gnu awk ובאופן כללי מומלץ להשתמש בגירסא זו.

  3. הפקודה next עוצרת את הטיפול בשורת הקלט הנוכחית וממשיכה לאיטרציה הבאה של הלולאה בשורת קלט חדשה.

3הרחבה: שימוש במערכים ופונקציות

אפשרות נוספת היא לסדר את השינויים לפי קטגוריות, למשל קודם להציג את כל התוספות ורק אחר כך להציג את כל תיקוני הבאגים. ב awk ארגון מחדש כזה אפשרי באמצעות מערכים: נגדיר מערך לשינויים ומערך לתוספות, בכל פעם שניתקל בערך נוסיף אותו למערך הרלוונטי ובסוף כל בלוק נדפיס את שני המערכים ונרוקן אותם. כך נראה הקוד:

#!/usr/local/bin/gawk -F\t -f
function init() {
  delete fix
  delete add
  added = 0
  fixed = 0
}

function handleAdd(line) {
  add[added++] = line
}

function handleFixed(line) {
  fix[fixed++] = line
}

function printAll() {
  if (added > 0) {
    print "New Features:"
    for (i=0; i < added; i++) {
      print " - " add[i]
    }
    print ""
  }

  if (fixed > 0) {
    print "Bug Fixes:"
    for (i=0; i < fixed; i++) {
      print " - " fix[i]
    }
  }

  init()

}

BEGIN { init() }
END { printAll() }

length($2)>0 {
# start new version block
  printAll()
  match($2, "tag: refs/tags/(\\w+)", tags)
  current_tag = tags[1]
  if (block++ >0) print ""

  print "*** " current_tag
  next
}

/ADD/ {
  handleAdd($3)
}

/FIXED/ {
  handleFixed($3)
}

והפלט:

*** v2
New Features:
 - ADD csh header
 - ADD postgres support


*** v1
New Features:
 - ADD Mysql support
 - ADD new control panel

Bug Fixes:
 - FIXED ui bugs

4איך ללמוד עוד

הכלי awk הוא כלי עם הרבה מאוד יכולות הקשורות לעיבוד טקסט, ושווה מאוד להכיר אותו ולהוסיף לארגז הכלים שלכם. ספר ההדרכה החינמי GNU Awk User's Guide הוא קצת ארוך אבל מלא בדוגמאות שימושיות שיעזרו לכם להפיק את המירב מכלי זה.


נהניתם מהפוסט? מוזמנים לשתף ולהגיב