一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

Linux|Centos|Ubuntu|系統(tǒng)進(jìn)程|Fedora|注冊(cè)表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服務(wù)器之家 - 服務(wù)器系統(tǒng) - Linux - 使用 NFS 將 Git 提交記錄顯示成文件目錄

使用 NFS 將 Git 提交記錄顯示成文件目錄

2024-01-09 17:03未知服務(wù)器之家 Linux

大家好!某天,我突發(fā)奇想 —— 是否能把 Git 存儲(chǔ)庫制作成一個(gè) FUSE 文件系統(tǒng),然后把所有的提交記錄做成文件夾呢?答案是肯定的!有g(shù)iblefs、GitMounter和用于 Plan 9 號(hào)的git9。 但在 Mac 上使用 FUSE 實(shí)在很煩人 —— 你需要安裝一個(gè)

使用 NFS 將 Git 提交記錄顯示成文件目錄

大家好!某天,我突發(fā)奇想 —— 是否能把 Git 存儲(chǔ)庫制作成一個(gè) FUSE 文件系統(tǒng),然后把所有的提交記錄做成文件夾呢?答案是肯定的!有g(shù)iblefs、GitMounter和用于 Plan 9 號(hào)的git9。

但在 Mac 上使用 FUSE 實(shí)在很煩人 —— 你需要安裝一個(gè)內(nèi)核擴(kuò)展,但由于安全的原因,Mac OS 上安裝內(nèi)核擴(kuò)展看起來越來越難了。此外,我還有一些想法,希望能用與這些項(xiàng)目不同的方式來組織文件系統(tǒng)。

因此,我想在 Mac OS 上嘗試 FUSE 以外的掛載文件系統(tǒng)的方法會(huì)很有趣,因此我創(chuàng)建了一個(gè)名為git-commit-folders的項(xiàng)目來做這個(gè)事。它可以同時(shí)使用 FUSE 和 NFS(至少在我的電腦上),WebDav 的實(shí)現(xiàn)起來還有點(diǎn)問題。

這個(gè)項(xiàng)目很有實(shí)驗(yàn)性(我不確定這究竟是一個(gè)有用的軟件,還是一個(gè)思考 Git 如何工作的有趣玩具),但寫起來很有趣,我自己也很喜歡在小型存儲(chǔ)庫中使用它,下面是我在寫這個(gè)項(xiàng)目時(shí)遇到的一些問題。

目標(biāo):像文件夾一樣顯示提交記錄

我做這個(gè)事的主要目的是給大家一些啟發(fā):Git 核心是如何運(yùn)行的。總結(jié)來說,Git 提交記錄實(shí)際上和文件夾非常類似 —— 每個(gè) Git 提交都包含一個(gè)目錄,其中列出了文件,這個(gè)目錄也可以有子目錄,依此類推。

只是為了節(jié)省磁盤空間,Git 提交實(shí)際上并不是以文件夾的形式實(shí)現(xiàn)的。

而在git-commit-folders,所有的提交記錄實(shí)際上看起來就是一個(gè)文件夾,如果你想瀏覽歷史提交記錄,你可以像瀏覽文件系統(tǒng)一樣瀏覽它們!例如如果你像查看我的博客的初始提交記錄,你可以如下操作:

$ ls commits/8d/8dc0/8dc0cb0b4b0de3c6f40674198cb2bd44aeee9b86/
README

其他之后的提交記錄,如下:

$ ls /tmp/git-homepage/commits/c9/c94e/c94e6f531d02e658d96a3b6255bbf424367765e9/
_config.yml  config.rb  Rakefile  rubypants.rb  source

分支是符號(hào)鏈接

通過git-commit-folders掛載的文件系統(tǒng)中,提交是唯一真正的文件夾 —— 其他一切(分支、標(biāo)簽等)都是提交記錄的符號(hào)鏈接。這反映了 Git 底層的工作方式。

$ ls -l branches/
lr-xr-xr-x 59 bork bazil-fuse -> ../commits/ff/ff56/ff563b089f9d952cd21ac4d68d8f13c94183dcd8
lr-xr-xr-x 59 bork follow-symlink -> ../commits/7f/7f73/7f73779a8ff79a2a1e21553c6c9cd5d195f33030
lr-xr-xr-x 59 bork go-mod-branch -> ../commits/91/912d/912da3150d9cfa74523b42fae028bbb320b6804f
lr-xr-xr-x 59 bork mac-version -> ../commits/30/3008/30082dcd702b59435f71969cf453828f60753e67
lr-xr-xr-x 59 bork mac-version-debugging -> ../commits/18/18c0/18c0db074ec9b70cb7a28ad9d3f9850082129ce0
lr-xr-xr-x 59 bork main -> ../commits/04/043e/043e90debbeb0fc6b4e28cf8776e874aa5b6e673
$ ls -l tags/
lr-xr-xr-x - bork 31 Dec  1969 test-tag -> ../commits/16/16a3/16a3d776dc163aa8286fb89fde51183ed90c71d0

這個(gè)并不能完全呈現(xiàn) Git 的所有工作機(jī)理(相比簡(jiǎn)單的類似文件夾的提交,還有很多復(fù)雜的細(xì)節(jié)),但是我希望大家對(duì)“每個(gè)提交如同一個(gè)文件夾,里面有你的舊版本代碼”有一個(gè)直觀的認(rèn)識(shí)。

這么做有什么好處呢?

在我深入介紹它的實(shí)現(xiàn)之前,我想說下為什么把 Git 提交記錄變成擁有文件夾的文件系統(tǒng)很有用。我的很多項(xiàng)目最終都沒有真正使用過(比如dnspeep),但我發(fā)現(xiàn)自己在做這個(gè)項(xiàng)目的時(shí)候確實(shí)使用到了一些。

目前為止我發(fā)現(xiàn)主要用處是:

  • 查找已經(jīng)刪除的函數(shù) - 可以用grep someFunction branch_histories/main/*/commit.go查找它的舊版本
  • 快速查看其他分支的一個(gè)文件并從其拷貝一行,如vim branches/other-branch/go.mod
  • 在每個(gè)分支中搜索某個(gè)函數(shù),如grep someFunction branches/*/commit.go

所有這些操作都通過提交記錄的符號(hào)鏈接,來替代提交記錄的直接引用。

這些都不是最有效的方法(你可以用git showgit log -S或者git grep來完成類似操作),但是對(duì)我個(gè)人來說,我經(jīng)常忘記 Git 語法,而瀏覽文件系統(tǒng)對(duì)我來說更簡(jiǎn)單。git worktree還允許你同時(shí)簽出多個(gè)分支,但對(duì)我來說,為了看一個(gè)文件而設(shè)置整個(gè)工作樹感覺很奇怪。

接下來我想談?wù)勎矣龅降囊恍﹩栴}。

問題 1: 用 WebDav 還是 NFS?

Mac OS 原生支持的兩個(gè)文件系統(tǒng)是 WebDav 和 NFS。我說不出那個(gè)更新容易實(shí)現(xiàn),所以我就索性嘗試兩個(gè)都支持。

起初,WebDav 的實(shí)現(xiàn)看起來更容易一些,在golang.org/x/net上有一個(gè)WebDav 實(shí)現(xiàn),這個(gè)很好配置。

但這個(gè)實(shí)現(xiàn)不支持符號(hào)鏈接,我想可能原因是它用的是io/fs接口,而io/fs還不支持符號(hào)鏈接。不過看起來正在進(jìn)行中。所以我放棄了 WebDav,而決定重點(diǎn)放在 NFS 實(shí)現(xiàn)上了,用go-nfsNFSv3 的庫文件來實(shí)現(xiàn)。

有人也提到了 Mac 上的FileProvider,我還沒有深入了解這個(gè)。

問題 2: 如何確保所有的實(shí)現(xiàn)保持一致?

我已經(jīng)實(shí)現(xiàn)了三個(gè)不同的文件系統(tǒng)(FUSE、NFS 和 WebDav),但對(duì)我來說還是沒搞清楚如何避免大量的重復(fù)代碼。

我的朋友 Dave 建議寫一個(gè)核心實(shí)現(xiàn),然后寫一個(gè)適配器(如fuse2nfsfuse2dav)來轉(zhuǎn)換成 NFS 和 WebDav 版本。這個(gè)看起來需要我著手實(shí)現(xiàn)三個(gè)文件系統(tǒng)的接口:

  • 對(duì)應(yīng) FUSE 的fs.FS
  • 對(duì)應(yīng) NFS 的billy.Filesystem
  • 對(duì)應(yīng) WebDav 的webdav.Filesystem

因此我把所有的核心邏輯放到fs.FS接口上,然后寫兩個(gè)函數(shù):

  • func Fuse2Dav(fs fs.FS) webdav.FileSystem
  • func Fuse2NFS(fs fs.FS) billy.Filesystem

所有的文件系統(tǒng)都比較類似,因此轉(zhuǎn)換起來不是很難,但就是有大量的煩人的問題需要修復(fù)。

問題 3: 我不想羅列所有的提交記錄怎么辦

一些 Git 存儲(chǔ)庫有成千上萬的提交記錄。我的第一個(gè)想法是如何讓commits/看起來是空的,這樣就可以如下展示:

$ ls commits/
$ ls commits/80210c25a86f75440110e4bc280e388b2c098fbd/
fuse  fuse2nfs  go.mod  go.sum  main.go  README.md

因此所有的提交記錄可以直接查看,但是又不能羅列它們。這個(gè)對(duì)文件系統(tǒng)是一個(gè)奇怪的事情,實(shí)際上 FUSE 可以做到。但我在 NFS 上無法實(shí)現(xiàn)。我認(rèn)為這里的原因是,如果你告訴 NFS 某個(gè)目錄是空的,它就會(huì)認(rèn)為該目錄實(shí)際上是空的,這是合理的。

我們最終是這樣處理的:

  • 按照.git/objects的方式,以前兩個(gè)字符組織管理提交記錄(因此ls commits會(huì)顯示0b 03 05 06 07 09 1b 1e 3e 4a),但這樣做會(huì)分為兩層,這樣18d46e76d7c2eedd8577fae67e3f1d4db25018b0則為commits/18/18df/18d46e76d7c2eedd8577fae67e3f1d4db25018b0
  • 開始只羅列一次所有的已經(jīng)打包的提交哈希,將它們緩存在內(nèi)存中,然后后面僅更新稀疏對(duì)象。主要思路是版本庫中幾乎所有的提交都應(yīng)該打包,而且 Git 不會(huì)經(jīng)常重新打包提交

這個(gè)看起來在擁有百萬提交記錄的 Linux 內(nèi)核的 Git 存儲(chǔ)庫上似乎效果不錯(cuò)。在我的機(jī)器上實(shí)測(cè)它初始化大概需要一分鐘,之后只需快速增量更新即可。

每個(gè)提交哈希只有 20 個(gè)字節(jié),因此緩存 1 百萬個(gè)提交哈希也不是很大,大約 20MB。

我認(rèn)為更聰明的做法是延遲加載提交列表 —— Git 會(huì)按提交 ID 對(duì)其打包文件進(jìn)行排序,所以你可以很容易地進(jìn)行二叉樹搜索,找到所有以1b1b8c開始的提交。我用的Git 庫對(duì)此并不支持,因?yàn)榱_列出來 Git 存儲(chǔ)庫所有的提交記錄確實(shí)一個(gè)奇怪的事情。我花了幾天時(shí)間嘗試實(shí)現(xiàn)它,但沒有達(dá)到我想要的性能,所以就放棄了。

問題 4: 不是目錄

我常遇到下面這個(gè)錯(cuò)誤:

"/tmp/mnt2/commits/59/59167d7d09fd7a1d64aa1d5be73bc484f6621894/": Not a directory (os error 20)

這起初真的把我嚇了一跳,但事實(shí)證明,這只是表示在列出目錄時(shí)出現(xiàn)了錯(cuò)誤,而 NFS 庫處理該錯(cuò)誤的方式就是顯示 “Not a directory”(不是目錄)。這個(gè)錯(cuò)誤遇到了很多次,我需要每次跟蹤這個(gè)錯(cuò)誤的根源。

有很多類似錯(cuò)誤。我也遇到cd: system call interrupted,令人沮喪的是,但最終也只是程序中的其他錯(cuò)誤。

我意識(shí)到終極大法是用 Wireshark 查看 NFS 發(fā)送和接受的數(shù)據(jù)包,很多問題便可迎刃而解。

問題 5: inode 編號(hào)

在開始的時(shí)候我不小心將所有的文件夾的 inode 設(shè)為 0。這很糟糕,因?yàn)槿绻诿總€(gè)目錄的 inode 都為 0 的目錄上運(yùn)行查找,它就會(huì)抱怨文件系統(tǒng)循環(huán)并放棄,這個(gè)也是符合邏輯的。

我通過定義一個(gè)inode(string)來修復(fù)這個(gè)問題,通過散列字符串來獲取 inode 編號(hào),并使用樹 ID / blob ID 作為散列字符串。

問題 6: 過期文件句柄

我一直遇到這個(gè)“Stale NFS file handle”(過期文件句柄)錯(cuò)誤。問題是,我需要獲取未知的 64 字節(jié) NFS “文件句柄”,并將其映射到正確的目錄。

我使用的 NFS 庫的工作方式是為每個(gè)文件生成一個(gè)文件句柄,并通過固定大小的緩存來緩存這些引用。這對(duì)小型存儲(chǔ)庫來說沒問題,但是如果對(duì)于擁有海量的文件的存儲(chǔ)庫來說,由于緩存就會(huì)溢出,就會(huì)導(dǎo)致“stale file handle” 錯(cuò)誤。

這仍然是個(gè)問題,我不知道如何解決。我不明白真正的 NFS 服務(wù)器是如何做到這一點(diǎn)的,也許它們只是有一個(gè)非常大的緩存?

NFS 文件句柄占用 64 個(gè)字節(jié)(不是比特),確實(shí)很大,所以很多時(shí)候似乎可以將整個(gè)文件路徑編碼到句柄中,根本不需要緩存。也許我會(huì)在某個(gè)時(shí)候嘗試實(shí)現(xiàn)這一點(diǎn)。

問題 7: 分支歷史

branch_histories/目錄目前僅羅列對(duì)應(yīng)分支的最近 100 個(gè)提交記錄。我不知道該怎么做,如果能以某種方式列出分支的全部歷史就更好了。也許我可以使用commits/目錄中類似的子文件夾技巧。

問題 8: 子模塊

Git 存儲(chǔ)庫有時(shí)包含了子模塊。由于目前我對(duì)子模塊的理解還不深入,我先忽略它吧。因此這個(gè)算是一個(gè)問題。

問題 9: NFSv4 是否更好?

我構(gòu)建這個(gè)項(xiàng)目使用的是 NFSv3 庫,因?yàn)槲耶?dāng)時(shí)只能找到一個(gè) NFSv3 的 Go 庫文件。可當(dāng)我搞完的時(shí)候才發(fā)現(xiàn)了一個(gè)名叫 buildbarn 的項(xiàng)目里有NFSv4 服務(wù)器。有沒有可能用它會(huì)更好一些?

我不知道這樣做有什么問題,或者用 NFSv4 有哪些優(yōu)點(diǎn)?我還有點(diǎn)不確定是否要使用 buildbarn NFS 庫,因?yàn)椴磺宄麄兪欠裣M渌耸褂盟?/p>

就這些吧

之前已經(jīng)解決了很多問題我都忘記了,這是我目前能回想起來的。我未來有可能解決或根本解決不了 NFS 的“過期文件句柄” 錯(cuò)誤,或者“在 Linux 內(nèi)核的存儲(chǔ)庫上啟動(dòng)需要 1 分鐘”的問題,就這樣吧。

感謝我的朋友vasi,他給我了很多文件系統(tǒng)方面的幫助。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 久久99re2在线视频精品 | 国内自拍网红在线自拍综合 | 国产免费视频 | 色噜噜狠狠色综合 | 丝袜老师好湿好紧我要进去了 | 国产在线观看色 | 视频高h | a级黄色网| 色播开心网 | 亚洲天堂男人网 | 男人的天堂久久 | 免费老外的毛片清高 | 国产精品麻豆 | 精新精新国产自在现 | 天天欲色成人综合网站 | 深夜影院a | 国产精品色爱综合网 | 日本一卡二卡3卡四卡网站精品 | 成人精品mv视频在线观看 | 色综合亚洲精品激情狠狠 | 美国一级大黄大色毛片 | 久久久久青草大香线综合精品 | 午夜爱爱片 | 天天色天天综合 | 亚洲精品免费在线观看 | 亚洲国产自 | 亚洲精品91香蕉综合区 | 日本高清va不卡视频在线观看 | 91看片淫黄大片.在线天堂 | 亚瑟天堂久久一区二区影院 | 大学生宿舍飞机china free | 小舞丝袜调教喷水沦为肉奴 | 菠萝视频在线完整版 | 久久精品WWW人人爽人人 | 91人人 | 男男playh片在线观看 | 精品日韩欧美一区二区三区 | 亚洲精品一区二区久久久久 | 色婷婷六月天 | 好爽好深好猛好舒服视频上 | 456亚洲人成高清在线 |