Selamat datang ke siri YOLO saya, di mana saya akan mempamerkan alatan dan projek mudah yang telah saya bina—kadangkala untuk berseronok, kadangkala untuk menyelesaikan masalah tertentu, dan pada masa lain hanya kerana rasa ingin tahu. Matlamat di sini bukan hanya untuk membentangkan alat; Saya juga akan menyelami sesuatu yang menarik berkaitan dengan proses itu, sama ada cerapan teknikal atau pengajaran yang dipelajari semasa membuat eksperimen kecil ini.
Tiada sesiapa yang memintanya, dan tiada siapa yang menginginkannya—tetapi inilah ia. Temui rrm, alat yang menyelesaikan masalah hanya saya yang ada (tetapi hei, ini mungkin isu Lapisan 8—atau, lebih berkemungkinan, isu kemahiran!).
rrm menambah lapisan keselamatan pada pengalaman baris arahan anda dengan mengalihkan fail ke tong sampah dan bukannya memadamkannya secara kekal. Dengan tempoh tangguh yang boleh disesuaikan, anda berpeluang untuk menyedari, "Op, saya sebenarnya memerlukannya!" sebelum terlambat.
Apatah lagi, rrm tidak bergantung pada fail konfigurasi luaran atau sistem penjejakan untuk mengurus fail yang dipadamkan. Sebaliknya, ia memanfaatkan atribut lanjutan sistem fail anda untuk menyimpan metadata penting—seperti laluan fail asal dan masa pemadaman—terus dalam item yang dibuang.
Anda mungkin tertanya-tanya, "Mengapa saya membina alat ini sedangkan terdapat alat yang serupa, mungkin lebih baik di luar sana?" Nah, jawapannya mudah:
Nota menyeronokkan: Semasa bekerja dengan std::Path, saya menemui contoh dalam pustaka standard Rust yang menggunakan folder bernama laputa
. Saya tahu ia merujuk kepada Castle in the Sky, tetapi bagi penutur bahasa Sepanyol, ia juga merupakan perkataan kutukan, yang menjadikannya sebagai detik lucu bagi saya!<script> // Detect dark theme var iframe = document.getElementById('tweet-1844834987184410735-190'); if (document.body.className.includes('dark-theme')) { iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1844834987184410735&theme=dark" } </script>Apabila saya mula membina rrm, saya memerlukan cara untuk menjejaki laluan asal fail yang dipadamkan dan masa ia harus dialih keluar secara kekal. Saya tidak mahu menggunakan fail JSON atau melaksanakan format penamaan pelik yang menyertakan maklumat ini—terutamanya jika saya mahu menyimpan lebih banyak data kemudian. Pangkalan data terasa seperti berlebihan untuk tugasan sekecil itu.
Ketika itulah saya menemui atribut lanjutan.
Sekarang, saya tidak tahu tentang anda, tetapi saya tidak menyedari terdapat mekanisme terbina dalam yang membolehkan anda menambah metadata tersuai pada fail, yang disokong oleh kebanyakan sistem fail Linux dan sistem seperti Unix seperti macOS . Ciri ini dipanggil Atribut Fail Lanjutan. Sistem yang berbeza mempunyai hadnya sendiri—seperti jumlah data yang boleh ditambah atau ruang nama tertentu yang digunakan—tetapi sistem tersebut mempunyai membolehkan anda menyimpan metadata yang ditentukan pengguna.
Atribut lanjutan pada asasnya ialah pasangan nama:nilai yang dikaitkan secara kekal dengan fail dan direktori. Seperti yang saya nyatakan sebelum ini, sistem berbeza dalam cara mereka mengendalikan ini. Contohnya, dalam Linux, nama bermula dengan pengecam ruang nama. Terdapat empat ruang nama sedemikian: keselamatan, sistem, dipercayai dan pengguna. Di Linux, nama bermula dengan salah satu daripada ini, diikuti dengan titik (".") dan kemudian rentetan yang ditamatkan nol. Pada macOS, keadaan agak berbeza. macOS tidak memerlukan ruang nama sama sekali, terima kasih kepada Pendekatan Metadata Bersatunya, yang menganggap atribut lanjutan sebagai metadata tambahan yang terikat secara langsung dengan fail tanpa perlu dikategorikan.
Dalam CLI kecil ini, saya menggunakan peti xattr, yang menyokong kedua-dua Linux dan macOS. Mengenai ruang nama yang saya nyatakan sebelum ini untuk Linux, kami akan menumpukan pada ruang nama pengguna kerana atribut ini dimaksudkan untuk digunakan oleh pengguna. Jadi, dalam kod, anda akan melihat sesuatu seperti ini:
/// Namespace for extended attributes (xattrs) on macOS and other operating systems. /// On macOS, this is an empty string, while on other operating systems, it is "user.". #[cfg(target_os = "macos")] const XATTR_NAMESPACE: &str = ""; #[cfg(not(target_os = "macos"))] const XATTR_NAMESPACE: &str = "user."; ... fn set_attr(&self, path: &Path, attr: &str, value: &str) -> Result<()> { let attr_name = format!("{}{}", XATTR_NAMESPACE, attr); ... }
Atribut #[cfg(target_os = "macos")] dalam Rust digunakan untuk menyusun kod secara bersyarat berdasarkan sistem pengendalian sasaran. Dalam kes ini, ia memastikan bahawa blok kod hanya disertakan semasa menyusun untuk macOS. Ini berkaitan kerana, seperti yang dinyatakan sebelum ini, macOS tidak memerlukan ruang nama untuk atribut lanjutan, jadi XATTR_NAMESPACE ditetapkan kepada rentetan kosong. Untuk sistem pengendalian lain, ruang nama ditetapkan kepada "pengguna.". Penyusunan bersyarat ini membolehkan kod menyesuaikan dengan lancar merentas platform yang berbeza, menjadikan CLI serasi silang dengan kedua-dua Linux dan macOS.
Satu perkara yang saya dapati cukup menarik tentang atribut lanjutan ialah mereka tidak mengubah suai fail itu sendiri. Metadata tinggal dalam ruang cakera yang berasingan, dirujuk oleh inod. Ini bermakna kandungan sebenar fail kekal tidak berubah. Contohnya, jika kita mencipta fail mudah dan menggunakan shasum untuk mendapatkan checksumnya:
Inode (nod indeks) ialah struktur data dalam sistem fail gaya Unix yang menerangkan objek sistem fail seperti fail atau direktori. Pautan
/// Namespace for extended attributes (xattrs) on macOS and other operating systems. /// On macOS, this is an empty string, while on other operating systems, it is "user.". #[cfg(target_os = "macos")] const XATTR_NAMESPACE: &str = ""; #[cfg(not(target_os = "macos"))] const XATTR_NAMESPACE: &str = "user."; ... fn set_attr(&self, path: &Path, attr: &str, value: &str) -> Result<()> { let attr_name = format!("{}{}", XATTR_NAMESPACE, attr); ... }
Selepas menggunakan rrm untuk memadam fail, kami boleh menyenaraikan fail yang dipadam dan melihat bahawa fail telah dialihkan ke tong sampah dengan metadatanya utuh:
$ cat a.txt https://www.kungfudev.com/ $ shasum a.txt e4c51607d5e7494143ffa5a20b73aedd4bc5ceb5 a.txt
Seperti yang anda lihat, nama fail ditukar kepada UUID. Ini dilakukan untuk mengelakkan perlanggaran nama semasa memadam fail dengan nama yang sama. Dengan memberikan pengecam unik pada setiap fail, rrm memastikan setiap fail yang dipadamkan, walaupun mempunyai nama yang sama, boleh dijejaki dan dipulihkan tanpa sebarang isu.
Kami boleh menavigasi ke folder sampah dan memeriksa fail untuk mengesahkan bahawa kandungannya kekal tidak berubah:
$ rrm rm a.txt $ rrm list ╭──────────────────────────────────────────────────────┬──────────────────────────────────────┬──────┬─────────────────────╮ │ Original Path ┆ ID ┆ Kind ┆ Deletion Date │ ╞══════════════════════════════════════════════════════╪══════════════════════════════════════╪══════╪═════════════════════╡ │ /Users/douglasmakey/workdir/personal/kungfudev/a.txt ┆ 3f566788-75dc-4674-b069-0faeaa86aa55 ┆ File ┆ 2024-10-27 04:10:19 │ ╰──────────────────────────────────────────────────────┴──────────────────────────────────────┴──────┴─────────────────────╯
Selain itu, dengan menggunakan xattr pada macOS, kami boleh mengesahkan bahawa fail tersebut mempunyai metadatanya, seperti tarikh pemadaman dan laluan asal:
$ shasum 3f566788-75dc-4674-b069-0faeaa86aa55 e4c51607d5e7494143ffa5a20b73aedd4bc5ceb5 3f566788-75dc-4674-b069-0faeaa86aa55
Anda boleh bayangkan julat kes penggunaan yang berpotensi untuk pengesahan atau tindakan mudah menggunakan metadata ini. Memandangkan atribut lanjutan berfungsi tanpa mengubah suai fail itu sendiri, ia membenarkan anda menyemak integriti fail atau melakukan operasi lain tanpa menjejaskan kandungan asal.
Ini hanyalah pengenalan kecil kepada atribut lanjutan dan cara ia digunakan dalam projek ini. Ia tidak bermaksud untuk menjadi penjelasan yang mendalam, tetapi jika anda berminat untuk mengetahui lebih lanjut, terdapat banyak sumber terperinci di luar sana. Berikut ialah beberapa pautan ke sumber yang paling berguna dan diterangkan dengan baik mengenai topik:
Saya telah menghabiskan beberapa tahun bekerja dengan Go, dan saya menjadi gemar corak tertentu—mengejek menjadi salah satu daripadanya. Dalam Go, saya biasanya melaksanakan perkara sendiri jika ia mengelakkan import yang tidak perlu atau memberi saya lebih fleksibiliti. Saya sangat terbiasa dengan pendekatan ini sehingga apabila saya mula menulis ujian dalam Rust, saya mendapati diri saya lebih suka mengejek perkara tertentu secara manual, seperti mencipta pelaksanaan olok-olok ciri.
Sebagai contoh, dalam CLI kecil ini, saya mencipta sifat untuk memisahkan pengurus sampah daripada cara ia berinteraksi dengan atribut lanjutan. Sifat itu, bernama ExtendedAttributes, pada mulanya bertujuan untuk tujuan ujian, tetapi juga kerana saya tidak pasti sama ada saya akan menggunakan xattr atau pelaksanaan lain. Jadi, saya mentakrifkan sifat berikut:
$ xattr -l 3f566788-75dc-4674-b069-0faeaa86aa55 deletion_date: 2024-10-27T04:10:19.875614+00:00 original_path: /Users/douglasmakey/workdir/personal/kungfudev/a.txt
Dalam Go, saya akan mencipta sesuatu seperti berikut, yang menyediakan pelaksanaan mudah antara muka yang dinyatakan sebelum ini. Kod di bawah adalah mudah dan dijana tanpa banyak pertimbangan, hanya untuk contoh:
/// Namespace for extended attributes (xattrs) on macOS and other operating systems. /// On macOS, this is an empty string, while on other operating systems, it is "user.". #[cfg(target_os = "macos")] const XATTR_NAMESPACE: &str = ""; #[cfg(not(target_os = "macos"))] const XATTR_NAMESPACE: &str = "user."; ... fn set_attr(&self, path: &Path, attr: &str, value: &str) -> Result<()> { let attr_name = format!("{}{}", XATTR_NAMESPACE, attr); ... }
Kemudian, saya akan menggunakan olok-olok saya dan menyuntik tingkah laku khusus yang diperlukan untuk setiap ujian. Sekali lagi, ini adalah kod mudah hanya untuk contoh:
$ cat a.txt https://www.kungfudev.com/ $ shasum a.txt e4c51607d5e7494143ffa5a20b73aedd4bc5ceb5 a.txt
Saya sudah terbiasa dengan corak ini dalam Go, dan saya bercadang untuk terus menggunakannya. Tetapi saya juga telah melakukan sesuatu yang serupa dalam Rust. Untuk projek ini, saya memutuskan untuk mencuba peti mockall, dan saya mendapati ia sangat berguna.
Pertama, saya menggunakan mock! makro untuk mengejek struktur saya secara manual. Saya tahu mockall mempunyai ciri automock, tetapi saya lebih suka untuk menentukan struktur olok-olok secara langsung dalam ujian saya di mana ia akan digunakan. Beri tahu saya jika ini perkara biasa atau jika komuniti mempunyai standard yang berbeza untuk ini.
$ rrm rm a.txt $ rrm list ╭──────────────────────────────────────────────────────┬──────────────────────────────────────┬──────┬─────────────────────╮ │ Original Path ┆ ID ┆ Kind ┆ Deletion Date │ ╞══════════════════════════════════════════════════════╪══════════════════════════════════════╪══════╪═════════════════════╡ │ /Users/douglasmakey/workdir/personal/kungfudev/a.txt ┆ 3f566788-75dc-4674-b069-0faeaa86aa55 ┆ File ┆ 2024-10-27 04:10:19 │ ╰──────────────────────────────────────────────────────┴──────────────────────────────────────┴──────┴─────────────────────╯
Saya mendapati mockall sangat berguna, membolehkan saya menyuntik gelagat tertentu ke dalam ujian saya tanpa keterlaluan corak lama saya.
$ shasum 3f566788-75dc-4674-b069-0faeaa86aa55 e4c51607d5e7494143ffa5a20b73aedd4bc5ceb5 3f566788-75dc-4674-b069-0faeaa86aa55
Seperti yang kita lihat, mockall memberi kita keupayaan untuk menentukan tingkah laku khusus untuk ujian kami menggunakan kaedah olok-oloknya:
Sesetengah daripada anda mungkin mendapati ini sangat asas atau tidak begitu menarik, tetapi seperti yang saya nyatakan, dalam siri YOLO ini, saya berkongsi perkara yang saya rasa menarik atau hanya ingin dibincangkan. Saya bukan peminat besar menggunakan perpustakaan jenis ini dalam Go, sebahagiannya disebabkan oleh kekangan Go, tetapi dalam Rust, saya mendapati mockall sangat berguna. Ia juga mengingatkan saya pada zaman dahulu saya dengan Python.
Sekali lagi, bahagian ini tidak bertujuan untuk menerangkan ejekan dalam Rust atau mockall. Saya pasti terdapat banyak sumber hebat yang merangkuminya secara terperinci. Saya cuma ingin menyebutnya secara ringkas.
Dalam siaran ini, saya telah berkongsi beberapa alasan di sebalik membina rrm dan alatan yang saya gunakan sepanjang perjalanan. Daripada menggunakan atribut lanjutan untuk memudahkan pengendalian metadata kepada bereksperimen dengan peti mockall untuk ujian dalam Rust, ini hanyalah perkara yang menarik minat saya.
Matlamat siri YOLO ini adalah untuk menyerlahkan keseronokan dan pembelajaran yang datang dengan membina walaupun alat mudah. Saya harap anda menemui sesuatu yang berguna di sini, dan saya berharap untuk berkongsi lebih banyak projek dan cerapan dalam siaran akan datang. Seperti biasa, maklum balas adalah dialu-alukan!
Selamat mengekod!
Atas ialah kandungan terperinci Bermain dengan Karat: Membina rm yang Lebih Selamat dan Bergembira Sepanjang Perjalanan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!