การสร้าง Git ใน Elixir — ตอนที่ 1

ฉันเพิ่งได้รับหนังสือBuilding Git เล่มนี้ เขียนโดย James Coglan มันเป็นหนังสือที่ค่อนข้างหนา อย่างที่ชื่อเรื่องว่าไว้ การสร้างระบบควบคุมเวอร์ชัน Git โดยใช้ภาษาการเขียนโปรแกรม Ruby ฉันคิดว่ามันจะเป็นแบบฝึกหัดที่สนุกที่จะใช้ Git โดยใช้ Elixir ขณะที่ฉันอ่านหนังสือ บทความนี้เป็นบทความแนะนำชุดแรกในชุดบทความที่เน้นการเดินทางของฉันในการใช้ Git ในภาษาโปรแกรม Elixir

นี่ไม่ใช่บทเรียนการเขียนโปรแกรม Elixir เบื้องต้น ดังนั้น ฉันจะไม่เน้นที่แนวคิดหรือไลบรารีของ Elixir โปรดดูที่ [1] และ [2] นอกจากนี้ สำหรับการรวบรวมความรู้โดยละเอียดเกี่ยวกับ Git internals ฉันแนะนำให้คุณอ่านหนังสือด้านบนและ/หรืออ่านเอกสาร [3]

เนื่องจากนี่เป็นเพียงส่วนที่ 1 ของบทความชุดนี้ ฉันจะอธิบายทฤษฎีเล็กน้อยเกี่ยวกับสิ่งที่เราพยายามสร้างในบทความนี้ และจะแนะนำการใช้งาน Elixir อย่างละเอียด

ทฤษฎีเล็กน้อย

Git เก็บข้อมูลที่เก็บในไดเร็กทอรี .git ในโครงการวานิลลา ขณะที่เราพิมพ์ git init ไดเร็กทอรี . git จะมีลักษณะดังนี้ —

โครงสร้างที่เก็บ git

เพื่อให้ภาพรวมโดยย่อ —

  • HEAD — มีการอ้างอิงถึงการคอมมิทปัจจุบันไม่ว่าจะใช้ commit ID หรือการอ้างอิงเชิงสัญลักษณ์ไปยังสาขาปัจจุบัน
  • config — มีการตั้งค่าคอนฟิกสำหรับที่เก็บนี้
  • คำอธิบาย — มีชื่อของที่เก็บ
  • hooks — มีสคริปต์ต่างๆ ที่ทำงานโดยคำสั่ง git ต่างๆ
  • info — มีข้อมูลเมตาดาต้าต่างๆ เกี่ยวกับ repository
  • อ อบเจ็ กต์ —นี่คือฐานข้อมูลของ git และมีเนื้อหาทั้งหมดที่ติดตาม ในบทความนี้เราจะเน้นไปที่การสร้างและเติมข้อมูลไดเรกทอรีนี้เป็นหลัก
  • refs — เก็บพอยน์เตอร์ต่างๆ ไว้ในฐานข้อมูล.git/objects สิ่งสำคัญที่สุดคือ.git/refs/headsเก็บคอมมิตล่าสุดในแต่ละสาขาในพื้นที่ และ.git/refs/tagsเก็บแท็ก

โครงสร้างที่เก็บมีลักษณะดังนี้ด้านล่างด้วยไดเร็กทอรีและไฟล์ใหม่บางส่วน —

โครงสร้างที่เก็บหลังจากคอมมิชชันเริ่มต้น

ที่นี่ -

  • COMMIT_EDITMSG — มีข้อความยืนยันที่ให้ไว้
  • ดัชนี — มีข้อมูลไบนารีที่ใช้ในการสร้างคอมมิตครั้งต่อไป
  • บันทึก — มีบันทึก ต่าง ๆ ที่ใช้โดยคำสั่งreflog
  • new object/<sub-directories> — บางไดเร็กทอรีย่อยใหม่ถูกสร้างขึ้นด้วยแฮชที่คลุมเครือเป็นชื่อไฟล์ หากเราตรวจสอบหนึ่งในสิ่งเหล่านี้ด้วย ID ที่พิมพ์โดยคำสั่งgit log —

เราสามารถใช้git cat-file -pเพื่อแสดงข้อมูลเกี่ยวกับวัตถุนี้จากฐานข้อมูล git —

ข้อมูลเกี่ยวกับวัตถุ

เอาต์พุตด้านบนอ้างถึงทรีที่มีรหัสการคอมมิต aaa96ced2d9a1c8e72c56b253a0e2fe78393feb7

เราสามารถตรวจสอบวัตถุนี้โดยใช้คำสั่งที่คล้ายกัน —

ตัวแทนต้นไม้

จากผลลัพธ์ เราจะเห็นต้นไม้นี้อ้างถึงรหัสการคอมมิทอื่นce013625030ba8dba906f756967f9e9ca394464aซึ่งแสดงถึงไฟล์hello.txt

การตรวจสอบการกระทำนี้ด้วยคำสั่งเดียวกันแสดงให้เห็นว่า —

ตอนนี้เพื่อตรวจสอบว่า git เก็บวัตถุในระบบไฟล์ได้อย่างไร -

เอาต์พุตแสดงเนื้อหาบีบอัดของอ็อบเจ็กต์ blob บนระบบไฟล์

หนังสือเล่มนี้มีคำสั่งที่สะดวกสำหรับการขยายเนื้อหาที่บีบอัด —

alias inflate='ruby -r zlib -e "STDOUT.write Zlib::Inflate.inflate(STDIN.read)"'

คำสั่ง hexdump ใช้กับ blob . ที่พอง

อย่างที่เราเห็น git เก็บ blobs โดยการเติมคำว่า blob, ช่องว่าง, ความยาวของ blob, null byte ตามด้วยเนื้อหาที่บีบอัดโดยใช้ zlib

จุดเน้นของบทความนี้

ในบทความนี้ เป้าหมายของฉันคือการเริ่มต้นโดยไม่มีอะไรเกิดขึ้น และสร้างสองคำสั่ง —

  • git init — ซึ่งจะเริ่มต้น .git ด้วยอ็อบเจ กต์ และ ไดเรกทอรี อ้างอิงเท่านั้น
  • git commit — ซึ่งจะสร้างฐานข้อมูลอ็อบเจ็กต์พร้อมไฟล์ใดๆ ในไดเร็กทอรีการทำงานปัจจุบัน

ต่อจากนี้ไป ฉันจะอ้างถึงเวอร์ชันน้ำอมฤตนี้โดยใช้ชื่อที่เรียกใช้งานได้ — egit

เกมส์รหัสน้ำอมฤต

ซอร์สโค้ดสำหรับบทความนี้มีให้จาก —https://github.com/imeraj/elixir_git

มันมีไฟล์ READMEเกี่ยวกับวิธีสร้างไฟล์ปฏิบัติการและใช้คำสั่งgit initและcommit

การแยกวิเคราะห์อาร์กิวเมนต์บรรทัดคำสั่ง

cli.exทำการแยกวิเคราะห์อาร์กิวเมนต์บรรทัดคำสั่ง —

ที่นี่,

  • parse_args (บรรทัดที่ 12 -17) — แยกวิเคราะห์อาร์กิวเมนต์บรรทัดคำสั่งและสร้างทูเพิลสำหรับการประมวลผลคำสั่งภายใน —

{:commit, dir} → สำหรับ egit commit

คำสั่ง egit initสามารถใช้ไดเร็กทอรีทางเลือกเป็นอาร์กิวเมนต์ได้ หากไม่มีการส่งผ่านใด ๆ มันจะสร้างไดเร็กทอรี .git ในไดเร็กทอรีการทำงานปัจจุบัน

  • กระบวนการ (บรรทัด 51–57) — ประมวลผลอาร์กิวเมนต์บรรทัดคำสั่งแยกวิเคราะห์และเรียกใช้โมดูลที่จำเป็นสำหรับ init และ commit

helpers.exมีฟังก์ชันตัวช่วยบางอย่าง —

ที่นี่ -

  • git_path (บรรทัดที่ 6–9) — สร้างพาธสำหรับไดเร็กทอรี .git
  • db_path (บรรทัดที่ 11–14) — สร้างเส้นทาง db สำหรับอ็อบเจ กต์
  • ls_r (บรรทัดที่ 16–30) — แสดงรายการไฟล์ทั้งหมดภายใต้ไดเร็กทอรีการทำงานปัจจุบันรวมถึงไดเร็กทอรีย่อยใดๆ
  • create_random_string (บรรทัดที่ 33–38) — สร้างสตริงตัวอักษรและตัวเลขแบบสุ่มตามความยาวที่กำหนด

init.exใช้คำสั่ง init —

ที่นี่ -

  • init (บรรทัดที่ 8–12) — ถูกเรียกด้วยพาธที่ควรสร้างไดเร็กทอรี .git
  • make_dirs (บรรทัดที่ 14- 28) — สร้างไดเร็กทอรีภายใต้ .git สำหรับตอนนี้มันก็แค่สร้าง.git/objectsและ . git/refsถ้า .git ยังไม่มีอยู่
  • บรรทัดที่ 26 — พิมพ์ข้อความหากไดเร็กทอรี .git เริ่มต้นอย่างถูกต้อง

commit.exใช้คำสั่ง commit —

ที่นี่,

  • คอมมิต (บรรทัดที่ 8–20) — ใช้คำสั่งcommit ตอนนี้มันคอมมิตไฟล์ทั้งหมดในไดเร็กทอรีปัจจุบันและไดเร็กทอรีย่อยใดๆ
  • บรรทัดที่ 9 — แสดงรายการไฟล์ทั้งหมดในไดเร็กทอรีปัจจุบันรวมถึงไดเร็กทอรีย่อย
  • บรรทัดที่ 10–14 —สำหรับไฟล์ใดๆ ที่ได้รับในขั้นตอนข้างต้น จะสร้างโครงสร้าง BLOB ที่มีเนื้อหาไฟล์และเขียนในฐานข้อมูลอ็อบเจ็กต์

โครงสร้างนี้มีสองฟิลด์ — dataและoid (ฉันจะพูดถึงoidในไม่ช้า)

database.exจัดเตรียมโมดูลฐานข้อมูลและทำการยกส่วนใหญ่ของไดเร็กทอรีอ็อบเจ็กต์ -

ที่นี่ -

  • บรรทัดที่ 10 — สร้างเนื้อหาด้วยโครงสร้าง — blob word, ช่องว่าง, ความยาวของ blob และ null byte ตามด้วยเนื้อหาไฟล์ข้อความธรรมดาเป็นสตริง
  • บรรทัดที่ 11 — สร้างแฮช ID วัตถุโดยใช้ SHA-1 บนเนื้อหา
  • บรรทัดที่ 12 — ทำหน้าที่เขียน blobs จริง ๆ
  • บรรทัดที่ 19 — สร้าง object_path จาก db_path โดยการรวมอักขระสองตัวแรกของ oid และอักขระที่เหลือ ดังนั้นเราจึงได้เส้นทางเช่น — db_path/<2 chars>/<rest chars>ซึ่งแสดงด้านล่างในฐานข้อมูลวัตถุ —
  • บรรทัดที่ 21 — สร้างเส้นทางไฟล์ชั่วคราวโดยใช้ ฟังก์ชัน generate_temp_name () ซึ่งสร้างชื่อไฟล์ในรูปแบบเดียวกับที่ Git ทำจริง โค้ดแรกเขียน blob ในเส้นทางชั่วคราวนี้และเปลี่ยนชื่อเป็น object_path จริง ( line 41 ) ในภายหลัง
  • บรรทัดที่ 23–35:สร้างไฟล์ชั่วคราวในโหมดอ่าน เขียน และเอกสิทธิ์ ดังนั้นหากไฟล์นั้นมีอยู่แล้ว ไฟล์จะเกิดข้อผิดพลาด (ในกรณีที่ชื่อไฟล์ชั่วคราวของเรามีการชนกัน)
  • บรรทัดที่ 37 : บีบอัดเนื้อหา
  • บรรทัดที่ 38–39 : เขียนเนื้อหาบีบอัดและปิดไฟล์

ตอนนี้ egit init และ commit ถูกนำไปใช้แล้ว เรามาลอง egit หมุน และตรวจสอบฐานข้อมูลเปรียบเทียบกับฐานข้อมูลของ Git จริงกัน

ตัวอย่างเซสชันที่เริ่มต้น repo และส่งไฟล์hello.txtที่มีเนื้อหาhelloแสดงอยู่ด้านล่าง -

เซสชันกับ egit

ที่นี่ -

  • ฉันเริ่มต้น .git ที่ตำแหน่งไดเร็กทอรี egit
  • tree .gitแสดงสิ่งที่อยู่ภายใต้ .git ทันทีหลังจากegit init
  • ฉันสร้าง hello.txt โดยมีคำว่า “hello” เป็นเนื้อหา
  • tree .gitแสดงสิ่งที่อยู่ภายใต้ .git หลังจากegit commit
  • ในที่สุด cat with inflate และ hexdump แสดงเนื้อหาของ blob ฐานข้อมูลอ็อบเจ็กต์ในข้อความธรรมดาซึ่งแสดงข้อมูลถูกจัดเก็บในรูปแบบที่คล้ายคลึงกันกับ Git จริง

ในส่วนที่ 1 ของชุดบทความเหล่านี้ ฉันได้ใช้ คำสั่ง egit initและegit commit (พื้นฐานมาก) ตั้งแต่เริ่มต้น และแสดงผลลัพธ์เมื่อเปรียบเทียบกับระบบควบคุมเวอร์ชัน Git จริง บทความต่อไปในชุดนี้จะเพิ่มและปรับปรุงคำสั่งใน Elixir ต่อไปในขณะที่ฉันดำเนินการผ่านหนังสือ - Building Git

สำหรับโพสต์ทางเทคนิคที่ละเอียดและลึกซึ้งยิ่งขึ้นในอนาคต โปรดติดตามฉันที่นี่ หรือบนทวิต เตอร์

อ้างอิง

  1. https://elixir-lang.org/getting-started/introduction.html
  2. https://elixir-lang.org/docs.html
  3. https://git-scm.com/docs
  4. https://github.com/imeraj/elixir_git

Suggested posts

ทรัพยากรการเข้ารหัสที่ฉันใช้มากที่สุด

ทรัพยากรการเข้ารหัสที่ฉันใช้มากที่สุด

สัปดาห์นี้ ฉันได้รับอีเมลจากสมาชิกรายการอีเมลรายวัน พวกเขาต้องการทราบ: คุณเข้าชมแหล่งข้อมูลใดรายวัน รายสัปดาห์ และรายเดือน คำถามที่ดี! ฉันยินดีที่จะพยายามแบ่งปันข้อมูลเชิงลึกเกี่ยวกับเวิร์กโฟลว์และทรัพยากรยอดนิยมที่ฉันใช้

กล่องเครื่องมือเทอร์มินัลที่ทันสมัย

กล่องเครื่องมือเทอร์มินัลที่ทันสมัย

เครื่องมือเทอร์มินัล เชลล์ และบรรทัดคำสั่งกำหนดมาตรฐานในปี 2566 นักพัฒนาทั้งหมดใช้เทอร์มินัล สำหรับบางคน เวิร์กโฟลว์ทั้งหมดของพวกเขาคือเทอร์มินัล โพสต์นี้จะแนะนำกล่องเครื่องมือเทอร์มินัล Hypermodern — เครื่องมือเทอร์มินัล เชลล์ และบรรทัดคำสั่งที่กำหนดมาตรฐานในปี 2023 คิตตี้เป็นเทอร์มินัลอีมูเลเตอร์ คิตตี้เป็นเทอร์มินัลอีมูเลเตอร์ — เป็นทางเลือกแทนเทอร์มินัล GNOME , Alacritty หรือ Windows Terminal

Related posts

การฆาตกรรมของจอร์แดน นีลี และปัญหาการเหยียดเชื้อชาติ "ผู้รักชาติ"

สหรัฐฯ สามารถดำเนินขั้นตอนสำคัญในการไม่ถือเอาพฤติกรรมเหยียดเชื้อชาติกับการเป็นชาวอเมริกันที่ดีได้หรือไม่?

การฆาตกรรมของจอร์แดน นีลี และปัญหาการเหยียดเชื้อชาติ "ผู้รักชาติ"

[ทริกเกอร์การแจ้งเตือน: บทความนี้รวมถึงภาพหน้าจอของผู้คนที่ยกย่องฆาตกรจอร์แดน นีลี] ในที่สุดเจ้าหน้าที่บังคับใช้กฎหมายก็ได้ตั้งข้อหาแดเนียล เพนนี ชายผู้บีบคอจอร์แดน นีลีจนเสียชีวิตในข้อหาฆาตกรรมครั้งนั้น และอาจไม่เต็มใจนัก

สองปีในการออกแบบ - ดี ไม่ดี และน่าเกลียด...

สองปีในการออกแบบ - ดี ไม่ดี และน่าเกลียด...

“หวัดดี Siri เล่น Me Dive โดย Olivia Dean” ในเดือนพฤษภาคม 2021 ฉันเริ่มฝึกงานที่ Future Academy Africa ในเมือง Akure ประเทศไนจีเรีย

ศิลปะเคยไม่ฝักใฝ่ฝ่ายใดหรือไม่?

ศิลปะเคยไม่ฝักใฝ่ฝ่ายใดหรือไม่?

เมื่อวานนี้ เราปิดการแข่งขัน Eurovision Song Contest ปีนี้ด้วยตอนจบที่สดใสและวุ่นวาย โดย Loreen นักร้องชาวสวีเดนคว้าถ้วยรางวัลกลับบ้าน กลายเป็นผู้หญิงคนแรกที่ชนะสองครั้งและนำมงกุฎกลับมายังสวีเดน 50 ปีหลังจาก ABBA ชนะการแข่งขัน กับ “วอเตอร์ลู” พวกเขากลายเป็นหนึ่งในการแสดงที่ยิ่งใหญ่ที่สุดในวงการเพลงป๊อป

เงินทุนกำจัดคาร์บอนในปีงบประมาณ 24

รายละเอียดคำขอจัดสรรของ Carbon180 ข้ามเส้นทาง

เงินทุนกำจัดคาร์บอนในปีงบประมาณ 24

โดย Alyson Lee ที่ปรึกษาด้านการจัดการภาครัฐ กระบวนการจัดสรรประจำปีของรัฐบาลกลางเป็นหัวใจสำคัญของความพยายามของเราในการให้ทุนสนับสนุนการกำจัดก๊าซคาร์บอนไดออกไซด์ (CDR) ในแต่ละปี Carbon180 จะส่งคำขอไปยังสำนักงานรัฐสภาหลายแห่งเพื่อช่วยชี้แนะว่าเงินดอลลาร์ในปีหน้าจะไหลไปที่ใด