歡迎來到我的YOLO系列,我將在其中展示我構建的簡單工具和項目——有時是為了好玩,有時是為了解決特定問題,有時只是出於純粹的好奇心。這裡的目標不僅是展示一個工具;而是展示一個工具。我還將深入探討與過程相關的一些有趣的內容,無論是技術見解還是在製作這些小實驗時學到的教訓。
沒有人要求它,也沒有人想要它——但無論如何它就在這裡。來認識 rrm,這個工具似乎只能解決我遇到的問題(但是,嘿,這可能是第 8 層問題,或者更可能是技能問題!)。
rrm 透過將檔案移至垃圾箱而不是永久刪除它們,為您的命令列體驗增加了一層安全性。有了可自訂的寬限期,您就有機會意識到,「哎呀,我實際上需要這個!」,以免為時已晚。
此外,rrm 不依賴外部設定檔或追蹤系統來管理已刪除的檔案。相反,它利用檔案系統的擴充屬性直接在已回收的項目中儲存基本元資料(例如原始檔案路徑和刪除時間)。
您可能想知道,「既然有類似的、可能更好的工具,為什麼我還要建造這個工具?」 嗯,答案很簡單:
有趣的說明: 在使用 std::Path 時,我在 Rust 標準庫中找到了一個範例,該範例使用名為 laputa
的資料夾。我知道這是天空之城的參考,但對於西班牙語使用者來說,這也是一個詛咒詞,這對我來說是一個有趣的時刻!當我開始建立 rrm 時,我需要一種方法來追蹤已刪除檔案的原始路徑以及應永久刪除它們的時間。我不想使用 JSON 檔案或實現包含此資訊的奇怪命名格式 - 特別是如果我想稍後儲存更多資料。對於如此小的任務來說,資料庫感覺有點大材小用。
就在那時我發現了擴充屬性。
現在,我不了解你,但我沒有意識到有一個內建機制可以讓你為檔案添加自訂元數據,大多數 Linux 檔案系統和類 Unix 系統(例如 macOS)都支援該機制。此功能稱為擴充檔案屬性。不同的系統有其自身的限制,例如可以添加多少資料或使用的特定命名空間,但它們確實允許您儲存使用者定義的元資料。
擴充屬性本質上是與檔案和目錄永久關聯的名稱:值對。正如我之前提到的,系統處理此問題的方式有所不同。例如,在 Linux 中,名稱以名稱空間識別碼開頭。有四個這樣的命名空間:安全性、系統、可信任和使用者。在 Linux 中,名稱以其中之一開頭,後面跟著一個點(“.”),然後是以 null 結尾的字串。在 macOS 上,情況有些不同。 macOS 根本不需要命名空間,這要歸功於它的統一元數據方法,它將擴展屬性視為直接與文件關聯的附加元數據,而無需進行分類。
在這個小型 CLI 中,我使用 crate xattr,它支援 Linux 和 macOS。關於我之前提到的 Linux 命名空間,我們將專注於使用者命名空間,因為這些屬性是供使用者使用的。所以,在程式碼中,你會看到類似這樣的內容:
Rust 中的 #[cfg(target_os = "macos")] 屬性用於根據目標作業系統有條件地編譯程式碼。在這種情況下,它確保僅在針對 macOS 進行編譯時才包含程式碼區塊。這是相關的,因為如前所述,macOS 不需要擴展屬性的命名空間,因此 XATTR_NAMESPACE 設定為空字串。對於其他作業系統,命名空間設定為“user.”。這種條件編譯允許程式碼無縫適應不同平台,使 CLI 與 Linux 和 macOS 交叉相容。
我發現擴充屬性非常酷的一件事是它們不會修改檔案本身。元資料位於單獨的磁碟空間中,由索引節點引用。這意味著文件的實際內容保持不變。例如,如果我們建立一個簡單的檔案並使用 shasum 來取得其校驗和:
inode(索引節點)是Unix 風格檔案系統中的一種資料結構,用於描述檔案系統對象,例如檔案或目錄。連結
使用 rrm 刪除文件後,我們可以列出已刪除的文件,並看到該文件已被移至垃圾箱,元數據完好無損:
如您所見,檔案名稱已變更為 UUID。這樣做是為了避免刪除同名檔案時發生名稱衝突。透過為每個文件分配唯一的標識符,rrm 確保每個已刪除的文件,即使它們具有相同的名稱,也可以毫無問題地追蹤和恢復。
我們可以導航到垃圾資料夾並檢查檔案以確認其內容保持不變:
此外,透過在 macOS 上使用 xattr,我們可以驗證檔案是否具有其元數據,例如刪除日期和原始路徑:
您可以想像使用此元資料進行簡單驗證或操作的潛在用例範圍。由於擴充屬性無需修改檔案本身即可運作,因此它們允許您檢查檔案完整性或執行其他操作,而不會影響原始內容。
這只是對擴充屬性以及它們在這個專案中的使用方式的一個小介紹。這並不是一個深入的解釋,但如果您有興趣了解更多信息,那裡有大量詳細的資源。以下是一些關於該主題的最有用且描述良好的資源的連結:
我用 Go 工作了幾年,我開始喜歡某些模式——mocking 就是其中之一。在 Go 中,如果可以避免不必要的導入或給我更大的靈活性,我通常會自己實現一些東西。我已經習慣了這種方法,以至於當我開始用 Rust 編寫測試時,我發現自己更喜歡手動模擬某些東西,例如創建特徵的模擬實現。
例如,在這個小型 CLI 中,我創建了一個特徵,將垃圾管理器與其與擴充屬性互動的方式分開。這個特徵名為 ExtendedAttributes,最初是為了測試目的,但也是因為我不確定是否會使用 xattr 還是其他實作。因此,我定義了以下特徵:
在 Go 中,我將創建如下所示的內容,它提供了前面提到的介面的簡單實作。下面的程式碼很簡單,生成時沒有太多考慮,只是為了範例:
然後,我將使用我的模擬並注入每個測試所需的特定行為。再次強調,這是簡單的程式碼,只是為了範例:
我已經習慣了 Go 中的這種模式,並且我打算繼續使用它。但我也在 Rust 中做了類似的事情。對於這個項目,我決定嘗試mockall crate,我發現它非常有用。
首先,我使用了模擬!巨集來手動模擬我的結構。我知道mockall有一個automock功能,但我更喜歡直接在我的測試中使用它來定義mock結構。 請告訴我這是否常見,或者社區對此有不同的標準。
我發現mockall非常有用,它允許我將特定行為注入到我的測試中,而無需使用舊模式的冗長。
如我們所見,mockall 使我們能夠使用其模擬方法為測試定義特定行為:
你們中的一些人可能會覺得這非常基本或沒那麼有趣,但正如我提到的,在這個 YOLO 系列中,我正在分享我覺得有趣或只是想談論的事情。我不太喜歡在 Go 中使用這種函式庫,部分原因是 Go 的限制,但在 Rust 中,我發現 mockall 非常有用。它甚至讓我想起了以前使用 Python 的日子。
再次強調,本節並不是解釋 Rust 或 mockall 中的模擬。我確信有很多很棒的資源詳細介紹了它。我只是想簡單提一下。
在這篇文章中,我分享了建立 rrm 背後的一些原因以及我在過程中使用的工具。從使用擴展屬性來簡化元資料處理,到嘗試使用模擬箱進行 Rust 測試,這些都激起了我的興趣。
這個 YOLO 系列的目標是強調建構簡單工具所帶來的樂趣和學習。我希望您在這裡找到有用的東西,我期待在未來的帖子中分享更多的項目和見解。一如既往,歡迎反饋!
編碼愉快!
以上是玩 Rust:建立更安全的公司並一路享受樂趣的詳細內容。更多資訊請關注PHP中文網其他相關文章!