پالت فرمان

دنبال فرمانی برای اجرا بگردید…

ZarynZaryn
بسته‌ها·۶ دقیقه مطالعه

آینه برای pypi.org، npm، crates.io، Rust، Zig و کامپایلرهایشان

وقتی crates.io، گیت‌هاب، static.rust-lang.org یا ziglang.org کند یا در دسترس نیستند، دانلودهای cargo، rustup و zig را از راه زرین بگیرید. هر فایل با هشی که ابزارهایتان از قبل می‌دانند سنجیده می‌شود، پس آینه نمی‌تواند چیزی را عوض کند.

**آینه** (mirror) رونوشتی از فایل‌های یک سایت دیگر است که نزدیک‌تر به شما نگه داشته می‌شود. وقتی pypi.org، npmjs.com، crates.io، گیت‌هاب یا ziglang.org کند، مسدود یا از کار افتاده‌اند، pip، uv، npm، cargo، rustup و zig می‌توانند از راه زرین دانلود کنند. ## چرا می‌شود به این آینه اعتماد کرد معمولاً آینه یک خطر است: کسی که آن را می‌گرداند می‌تواند فایل تغییریافته‌ای به شما بدهد. این آینه‌ها طوری ساخته شده‌اند که چنین چیزی ممکن نباشد: 1. زرین پیش از نگه داشتن هر فایل، آن را با هشی می‌سنجد که از منبع اصلی می‌آید: sha256 فهرست pypi.org برای بسته‌های پایتون، مقدار integrity سند بستهٔ npm برای بسته‌های npm، چک‌سام فهرست crates.io برای crateها، و هشی که در `build.zig.zon` شما نوشته شده برای بسته‌های Zig. 2. وقتی فایل به شما می‌رسد، cargo یا zig همان هش را دوباره روی رایانهٔ خودتان می‌سنجد. فایلی که جور نباشد رد می‌شود. پس بدترین کاری که آینه می‌تواند بکند پاسخ ندادن است؛ هرگز نمی‌تواند کد دیگری به شما بدهد. (نصب خود Rust با rustup کمی فرق دارد؛ [بخش خودش](#خود-rust-rustup) می‌گوید چطور.) فایلی هم که زرین یک بار آورده، وقتی سایت اصلی از کار افتاده باشد همچنان کار می‌کند. ## همه با هم: zev mirror اگر دستور `zev` را دارید ([نصبش کنید](/docs/fa/installation))، یک خط pip، uv، npm، cargo و rustup را تنظیم می‌کند: ```bash zev mirror on ``` `zev mirror` نشان می‌دهد چه چیزی تنظیم شده، `zev mirror on pip cargo` فقط چندتا را انتخاب می‌کند، و `zev mirror off` همه را برمی‌گرداند. zev فقط یک بخش با علامت روشن به فایل تنظیمات خود هر ابزار اضافه می‌کند و هرگز تنظیمی را که خودتان گذاشته‌اید عوض نمی‌کند: اگر مثلاً `~/.npmrc` شما از قبل به رجیستری دیگری اشاره دارد، zev آن را دست نمی‌زند و به شما می‌گوید. برای پروژهٔ Zig، دستور `zev mirror zig` (در پوشهٔ پروژه) `build.zig.zon` را به آینه ارجاع می‌دهد و آنچه وابستگی‌هایش لازم دارند را می‌آورد؛ `zev mirror zig --undo` نشانی‌ها را برمی‌گرداند. بخش‌های زیر هر ابزار را دستی توضیح می‌دهند. ## پایتون: pip و uv فهرست پایتون زرین هم پروژه‌های خودتان در زرین را دارد و هم همهٔ pypi.org را: ```bash pip config set global.index-url https://api.zaryn.xyz/v1/packages/pypi/all/simple/ # uv export UV_DEFAULT_INDEX=https://api.zaryn.xyz/v1/packages/pypi/all/simple/ # و خود پایتون، برای uv python install export UV_PYTHON_INSTALL_MIRROR=https://api.zaryn.xyz/v1/packages/python/-/standalone ``` هر فایل pypi.org با sha256 فهرست pypi.org سنجیده می‌شود و ساخت‌های پایتون با SHA256SUMS انتشار خودشان. نامی که در زرین هست همیشه از زرین می‌آید، پس بستهٔ هم‌نامی که کسی در pypi.org منتشر کند نمی‌تواند وارد شود. بیشتر در [بسته‌های پایتون](/docs/fa/packages-pypi). ## جاوااسکریپت: npm ```bash npm config set registry https://api.zaryn.xyz/v1/packages/npm-mirror/ ``` pnpm، yarn و bun همین تنظیم را می‌خوانند. هر tarball با مقدار *integrity* (sha512) سند بستهٔ npm سنجیده می‌شود؛ همان مقداری که npm پس از دانلود می‌سنجد. بسته‌هایی که در زرین منتشر می‌کنید خط scope خودشان را در `.npmrc` نگه می‌دارند ([بسته‌های npm](/docs/fa/packages-npm) را ببینید)؛ آینه برای بقیه است. ## crateهای Rust این را به `~/.cargo/config.toml` اضافه کنید (فایل تنظیماتی که cargo هر بار می‌خواند؛ اگر نیست بسازیدش): ```toml [source.crates-io] replace-with = "zaryn" [source.zaryn] registry = "sparse+https://api.zaryn.xyz/v1/packages/cargo/mirror/index/" ``` - `[source.crates-io] replace-with = "zaryn"` به cargo می‌گوید: هر وقت می‌خواستی به crates.io بروی، به منبعی به نام `zaryn` برو. - `[source.zaryn]` می‌گوید آن کجاست. همین. `cargo build`، `cargo add`، `cargo update` و `cargo install` حالا crateهای crates.io را از راه زرین می‌گیرند و در پروژه‌هایتان چیز دیگری عوض نمی‌شود: `Cargo.toml` و `Cargo.lock` همان می‌مانند، و هم‌تیمی‌هایی که این تنظیم را ندارند همچنان از crates.io دانلود می‌کنند. پشت صحنه چه می‌شود: - cargo فایل فهرست یک crate را (فهرست نسخه‌ها و چک‌سام‌هایشان) از زرین می‌خواهد. اگر رونوشت زرین کمتر از ۵ دقیقه عمر داشته باشد همان را می‌دهد، وگرنه از crates.io می‌پرسد. اگر crates.io پاسخ ندهد، رونوشتی را که زرین دارد می‌گیرید. - cargo یک فایل `.crate` می‌خواهد. زرین رونوشتش را می‌فرستد، یا آن را از crates.io دانلود می‌کند، SHA-256 اش را با چک‌سام فهرست مقایسه می‌کند، و فقط آن وقت نگهش می‌دارد و می‌فرستد. برای کنار گذاشتن آینه، همان خط‌ها را پاک کنید. ## خود Rust (rustup) rustup، ابزاری که Rust را نصب و به‌روز می‌کند، هم می‌تواند از راه زرین دانلود کند. پیش از اجرایش دو متغیر را تنظیم کنید: ```bash export RUSTUP_DIST_SERVER=https://api.zaryn.xyz/v1/packages/rust/- export RUSTUP_UPDATE_ROOT=https://api.zaryn.xyz/v1/packages/rust/-/rustup ``` - `RUSTUP_DIST_SERVER` جایی است که خود Rust از آن می‌آید (کامپایلر، cargo، کتابخانهٔ استاندارد). - `RUSTUP_UPDATE_ROOT` جایی است که rustup نسخه‌های تازهٔ خودش را از آن می‌گیرد. این دو خط را در `~/.bashrc` (یا فایل شروع شل خودتان) بگذارید تا همیشه تنظیم بمانند. سپس rustup را مثل همیشه به کار ببرید: ```bash # نصب اول، با اسکریپت نصب که آن هم از راه زرین می‌آید curl -sSf https://api.zaryn.xyz/v1/packages/rust/-/rustup/rustup-init.sh | sh # بعدها rustup update rustup target add wasm32-unknown-unknown ``` زرین پیش از نگه داشتن هر فایل، آن را با فایل `.sha256` که static.rust-lang.org کنارش منتشر می‌کند می‌سنجد، و rustup هر دانلود را با چک‌سام‌های فایل channel می‌سنجد. خود فایل channel را زرین از static.rust-lang.org با HTTPS گرفته و به شما می‌دهد؛ این تنها جایی است که به زرین تکیه می‌کنید، مثل هر آینهٔ دیگر Rust. وقتی static.rust-lang.org در دسترس نیست، آخرین channel که زرین دارد کار می‌کند. ## وابستگی‌های Zig Zig تنظیمی برای آینه ندارد: هر وابستگی در `build.zig.zon` نشانی خودش را دارد. پس به جایش نشانی‌ها عوض می‌شوند تا از راه زرین بروند، در حالی که هش‌ها دقیقاً همان می‌مانند (و zig همچنان می‌سنجدشان). **در وب:** [بسته‌ها](/packages) را باز کنید، تا **آینه‌ها** پایین بروید، `build.zig.zon` تان را بچسبانید و **ارجاع به زرین** را بزنید؛ یا **ارجاع به زرین و بررسی همه** تا زرین همین حالا هر وابستگی را دانلود کند و هر مشکلی را گزارش دهد. نتیجه را کپی یا دانلود کنید و جای فایلتان بگذارید. **از ترمینال** (`jq` فایل را از پاسخ بیرون می‌کشد): ```bash curl --data-binary @build.zig.zon \ "https://api.zaryn.xyz/v1/packages/zig/-/mirror-zon?warm=1" | jq -r .zon > build.zig.zon.new mv build.zig.zon.new build.zig.zon ``` وابستگی‌ای مثل ```zig .known_folders = .{ .url = "https://github.com/ziglibs/known-folders/archive/207c34a16e4365edc20d92c7892f962b3bed46e8.tar.gz", .hash = "known_folders-0.0.0-Fy-PJsbKAACbDh9bBxR0MMThxZSS6A9RH4apWphNHY70", }, ``` می‌شود ```zig .known_folders = .{ .url = "https://api.zaryn.xyz/v1/packages/zig/-/mirror/known_folders-0.0.0-Fy-PJsbKAACbDh9bBxR0MMThxZSS6A9RH4apWphNHY70/github.com/ziglibs/known-folders/archive/207c34a16e4365edc20d92c7892f962b3bed46e8.tar.gz", .hash = "known_folders-0.0.0-Fy-PJsbKAACbDh9bBxR0MMThxZSS6A9RH4apWphNHY70", }, ``` نشانی تازه هش و نشانی اصلی را در خود دارد، پس دستی هم می‌شود نوشتش: `https://api.zaryn.xyz/v1/packages/zig/-/mirror/<هش>/<نشانی اصلی بدون https://>`. زرین نسخهٔ اصلی را یک بار دانلود می‌کند، بررسی می‌کند هش Zig آن همان هش نشانی باشد، و نگهش می‌دارد. اگر فایل نشانی اصلی تغییر کرده باشد، زرین ردش می‌کند؛ درست همان کاری که zig می‌کرد. برای برگشتن به نشانی‌های اصلی، در وب **برگرداندن** را بزنید، یا به جای `?warm=1` از `?undo=1` استفاده کنید. ### وابستگی‌های وابستگی‌هایتان وابستگی‌هایتان `build.zig.zon` خودشان را با نشانی‌های خودشان دارند که نمی‌توانید عوضشان کنید. ولی zig فقط بسته‌ای را دانلود می‌کند که از قبل ندارد؛ پس یک بار آن‌ها را از راه زرین بگیرید تا zig به سایت اصلی نیازی نداشته باشد. **ارجاع به زرین و بررسی همه** آن‌ها را فهرست می‌کند و برای هر بسته دستوری آماده می‌دهد: ```bash zig fetch https://api.zaryn.xyz/v1/packages/zig/-/mirror/<hash>/<address> ``` ### چه چیزهایی آینه می‌شوند - آرشیوهای `https://` از گیت‌هاب، Codeberg، GitLab، SourceHut، Bitbucket، ziglang.org و چند میزبان کد شناخته‌شدهٔ دیگر (مدیر سرور می‌تواند بیشتر اضافه کند). نشانی‌های دیگر همان‌طور می‌مانند. - آرشیوهای `.tar.gz`، `.tar.xz`، `.tar.zst`، `.tar` و `.zip`. - وابستگی‌های `git+https://` با `#ref` (zig fetch --save همان commit را آنجا می‌نویسد). زرین آن commit را همان‌طور که zig می‌کند checkout می‌کند و به شکل `.tar.gz` می‌دهد؛ هش همان است، چون zig فایل‌ها را هش می‌کند نه آرشیو را. نشانی آینه این شکلی است: `…/mirror/<hash>/git/github.com/owner/repo?ref=<commit>`. - وابستگی‌هایی که از قبل `.hash` دارند. وابستگی تازه اولین بار که `zig build` یا `zig fetch --save` را اجرا می‌کنید هش می‌گیرد؛ پس از آن آینه‌اش کنید. هر بسته‌ای که زرین از قبل دارد با هشش به‌تنهایی هم گرفتنی است: `https://api.zaryn.xyz/v1/packages/zig/-/hash/<هش>`. ## کامپایلرهای Zig خود کامپایلر Zig از ziglang.org، با نام فایلش: ```bash curl -LO https://api.zaryn.xyz/v1/packages/zig/-/toolchain/zig-x86_64-linux-0.15.1.tar.xz curl -LO https://api.zaryn.xyz/v1/packages/zig/-/toolchain/zig-x86_64-linux-0.15.1.tar.xz.minisig ``` - نام دقیق فایل‌ها را از [ziglang.org/download](https://ziglang.org/download/) بردارید: نسخه‌های منتشرشده (`zig-<cpu>-<system>-<version>.tar.xz`، و `.zip` برای ویندوز) و ساخت‌های dev (`…-0.16.0-dev.…`). - ساخت‌های dev پس از اینکه ziglang.org پاکشان کرد در زرین می‌مانند، پس پروژه‌ای که به یکی از آن‌ها بسته است همچنان ساخته می‌شود. - `https://api.zaryn.xyz/v1/packages/zig/-/toolchain/index.json` فهرست نسخه‌های ziglang.org است. دانلود را با کلید بنیاد نرم‌افزار Zig بسنجید، درست مثل وقتی از ziglang.org دانلود می‌کنید: ```bash minisign -Vm zig-x86_64-linux-0.15.1.tar.xz -P RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U ``` ابزارهایی که آینه‌های جامعهٔ Zig را پشتیبانی می‌کنند می‌توانند `https://api.zaryn.xyz/v1/packages/zig/-/toolchain` را یکی از آن‌ها قرار دهند. ## آینه‌ها چقدر نگه می‌دارند `https://api.zaryn.xyz/v1/packages/-/mirrors` نشان می‌دهد هر آینه چه دارد و در ۳۰ روز گذشته به چند دانلود پاسخ داده. وقتی کش پر شود، فایل‌هایی که مدت بیشتری کسی نخواسته‌شان جا باز می‌کنند؛ اگر کسی دوباره لازمشان داشت دوباره دانلود می‌شوند.