Crates.io'da Kasa Yayınlama
Biz crates.io'daki paketleri projemizin bağımlılıkları olarak kullandık, ancak siz de kendi paketlerinizi yayınlayarak kodunuzu diğer insanlarla paylaşabilirsiniz. crates.io'daki kasa kaydı, paketlerinizin kaynak kodunu dağıtır, bu nedenle öncelikle açık kaynak kodunu barındırır.
Rust ve Cargo, yayınladığınız paketin insanlar tarafından bulunmasını ve kullanılmasını kolaylaştıran özelliklere sahiptir. Şimdi bu özelliklerden bazılarından bahsedeceğiz ve ardından bir paketin nasıl yayınlanacağını açıklayacağız.
Faydalı Dokümantasyon Yorumları Yapmak
Paketlerinizi doğru bir şekilde belgelendirmek, diğer kullanıcıların bunları nasıl ve ne zaman kullanacaklarını bilmelerine
yardımcı olacaktır, bu nedenle belge yazmak için zaman ayırmaya değer. Bölüm 3'te, iki eğik çizgi (//
) kullanarak Rust
kodunu nasıl yorumlayacağımızı tartıştık. Rust ayrıca, HTML dokümantasyonu oluşturacak, dokümantasyon
yorumu olarak bilinen, dokümantasyon için özel bir yorum türüne sahiptir. HTML, kasanızın nasıl süreklendiğinden ziyade
kasanızın nasıl kullanılacağını bilmek isteyen programcılara yönelik genel API öğeleri için dokümantasyon yorumlarının içeriğini
görüntüler.
Dokümantasyon yorumları iki yerine üç eğik çizgi (///
) kullanır ve metni biçimlendirmek için Markdown
gösterimini destekler. Dokümantasyon yorumlarını belgeledikleri öğeden hemen önce yerleştirin.
Liste 14-1, my_crate
adlı kasadaki add_one
fonksiyonu için dokümantasyon yorumlarını göstermektedir.
Dosya adı: src/lib.rs
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
Burada, add_one
fonksiyonunun ne işe yaradığına dair bir açıklama veriyoruz, Examples
başlıklı bir bölüm
açıyoruz ve ardından add_one
fonksiyonunun nasıl kullanılacağını gösteren bir kod sunuyoruz.
Bu dokümantasyon yorumundan, cargo doc
çalıştırarak HTML dokümantasyonunu oluşturabiliriz.
Bu komut, Rust ile birlikte dağıtılan rustdoc
aracını çalıştırır ve oluşturulan HTML belgelerini
target/doc dizinine koyar.
Kolaylık sağlamak için, cargo doc --open
komutunu çalıştırmak mevcut kasanızın dokümantasyonu için HTML oluşturacak
(ayrıca kasanızın tüm bağımlılıkları için dokümantasyon) ve sonucu bir web tarayıcısında açacaktır.
add_one
fonksiyonuna gidin ve Şekil 14-1'de gösterildiği gibi dokümantasyon yorumlarındaki metnin nasıl oluşturulduğunu
göreceksiniz:
Sıkça Kullanılan Bölümler
HTML'de “Examples” başlıklı bir bölüm oluşturmak için Liste 14-1'deki # Examples
başlığını kullandık.
İşte kasa yazarlarının belgelerinde yaygın olarak kullandıkları diğer bazı bölümler:
- Panikler: Belgelenen fonksiyonun panik yapabileceği senaryolar. Programlarının paniklemesini istemeyen fonksiyonu çağıranlar, bu durumlarda fonksiyonu çağırmadıklarından emin olmalıdırlar.
- Hatalar: Fonksiyon
Result
döndürüyorsa, oluşabilecek hata türlerini ve hangi koşulların bu hataların
döndürülmesine neden olabileceğini açıklamak, arayanlara yardımcı olabilir, böylece farklı hata türlerini farklı şekillerde ele almak için kod yazabilirler. - Güvenlik: Eğer fonksiyon çağrılması güvenli değilse (güvensizliği Bölüm 19'da tartışacağız), fonksiyonun neden güvensiz olduğunu açıklayan ve fonksiyonun çağıranların uymasını beklediği değişmezleri kapsayan bir bölüm olmalıdır.
Çoğu dokümantasyon açıklamasında bu bölümlerin hepsine gerek yoktur, ancak bu, kodunuzun kullanıcıların bilmek isteyeceği yönlerini size hatırlatmak için iyi bir kontrol listesidir.
Test Olarak Dokümantasyon Yorumları
Belge açıklamalarınıza örnek kod blokları eklemek, kütüphanenizin nasıl kullanılacağını göstermeye yardımcı olabilir ve
bunu yapmanın ek bir avantajı vardır: cargo test
'i çalıştırmak, belgelerinizdeki kod örneklerini test olarak
çalıştıracaktır! Hiçbir şey örnekli dokümantasyondan daha iyi olamaz. Ancak hiçbir şey, dokümantasyonun yazılmasından
bu yana kod değiştiği için çalışmayan örneklerden daha kötü olamaz. Liste 14-1'deki add_one
fonksiyonunun dokümantasyonu ile
cargo test
'i çalıştırırsak, test sonuçlarında aşağıdaki gibi bir bölüm görürüz:
Doc-tests my_crate
running 1 test
test src/lib.rs - add_one (line 5) ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s
Şimdi fonksiyonu ya da örneği değiştirirsek, örnekteki assert_eq!
panik yapar ve cargo test
'i tekrar çalıştırırsak,
dokümantasyon testlerinin örnek ve kodun birbiriyle senkronize olmadığını yakaladığını göreceğiz!
İçerdiği Öğeleri Yorumlama
Dokümantasyon yorum satırı (//!
) stili, belgeleri yorumları takip eden öğeler yerine yorumları içeren öğeye ekler.
Bu dokümantasyon yorumları genellikle kasa kök dosyasının içinde (geleneksel olarak src/lib.rs) veya bir modülün
içinde kasayı veya modülü bir bütün olarak belgelemek için kullanırız.
Örneğin, add_one
fonksiyonunu içeren my_crate
kasasının amacını açıklayan belgeler eklemek için,
Liste 14-2'de gösterildiği gibi src/lib.rs dosyasının başına //!
ile başlayan belge yorumları ekleriz:
Dosya adı: src/lib.rs
//! # My Crate
//!
//! `my_crate` is a collection of utilities to make performing certain
//! calculations more convenient.
/// Adds one to the number given.
// --snip--
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
Son satırdan sonra //!
ile başlayan herhangi bir kod olmadığına dikkat edin.
Yorumlara ///
yerine //!
ile başladığımız için, bu yorumu takip eden bir öğe yerine bu yorumu içeren öğeyi
belgeliyoruz. Bu durumda, bu öğe kasa kökü olan src/lib.rs dosyasıdır. Bu yorumlar tüm kasayı tanımlar.
cargo doc --open
komutunu çalıştırdığımızda, bu yorumlar Şekil 14-2'de gösterildiği gibi my_crate
dokümantasyonunun
ön sayfasında kasadaki genel öğelerin listesinin üzerinde görüntülenecektir:
Öğeler içindeki dokümantasyon yorumları özellikle kasaları ve modülleri tanımlamak için kullanışlıdır. Kullanıcılarınızın kasanın organizasyonunu anlamalarına yardımcı olmak için konteynerin genel amacını açıklamak için bunları kullanın.
pub use
ile Kullanışlı Genel API'yi Dışa Aktarma
Genel API'nizin yapısı, bir kasa yayınlarken göz önünde bulundurulması gereken önemli bir husustur. Kasanızı kullanan kişiler yapıya sizden daha az aşinadır ve kasanızın büyük bir modül hiyerarşisine sahipse kullanmak istedikleri parçaları bulmakta zorluk çekebilirler.
Bölüm 7'de, pub
anahtar sözcüğünü kullanarak öğeleri nasıl herkese açık hale getireceğimizi ve use
anahtar sözcüğünü
kullanarak öğeleri bir kapsama nasıl dahil edeceğimizi ele almıştık. Ancak, bir kasa geliştirirken size mantıklı gelen yapı,
kullanıcılarınız için çok uygun olmayabilir. Yapılarınızı birden fazla seviye içeren bir hiyerarşide
düzenlemek isteyebilirsiniz, ancak bu durumda hiyerarşinin derinliklerinde tanımladığınız bir türü kullanmak isteyen
kişiler bu türün var olduğunu bulmakta zorlanabilir. Ayrıca, use my_crate::UsefulType;
yerine use
my_crate::some_module::another_module::UsefulType;
girmek zorunda kalmaktan da rahatsız olabilirler.
İyi haber şu ki, yapı başkalarının başka bir kütüphaneden kullanması için uygun değilse, iç organizasyonunuzu
yeniden düzenlemeniz gerekmez: bunun yerine, pub use
kullanarak özel yapınızdan farklı bir genel yapı
oluşturmak için öğeleri yeniden dışa aktarabilirsiniz. Yeniden dışa aktarma, bir konumdaki herkese açık bir
öğeyi alır ve sanki diğer konumda tanımlanmış gibi başka bir konumda herkese açık hale getirir.
Örneğin, sanatsal kavramları modellemek için art
adında bir kütüphane oluşturduğumuzu varsayalım.
Bu kütüphanede iki modül vardır: PrimaryColor
ve SecondaryColor
adında iki enum
içeren bir kinds
modülü ve
Liste 14-3'te gösterildiği gibi mix
adında bir fonksiyon içeren bir utils
modülü:
Dosya adı: src/lib.rs
//! # Art
//!
//! A library for modeling artistic concepts.
pub mod kinds {
/// The primary colors according to the RYB color model.
pub enum PrimaryColor {
Red,
Yellow,
Blue,
}
/// The secondary colors according to the RYB color model.
pub enum SecondaryColor {
Orange,
Green,
Purple,
}
}
pub mod utils {
use crate::kinds::*;
/// Combines two primary colors in equal amounts to create
/// a secondary color.
pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
// --snip--
unimplemented!();
}
}
Şekil 14-3, bu kasa için cargo doc
tarafından oluşturulan belgelerin ön sayfasının nasıl görüneceğini
göstermektedir:
PrimaryColor
ve SecondaryColor
türlerinin ön sayfada listelenmediğine ve mix
fonksiyonunun da bulunmadığına
dikkat edin. Bunları görmek için türlere ve yardımcı programlara tıklamamız gerekiyor.
Bu kütüphaneye bağlı olan başka bir kasa, şu anda tanımlanmış olan modül yapısını belirterek,
art
'taki öğeleri kapsama getiren use
ifade yapılarına ihtiyaç duyacaktır. Liste 14-4, art
kasasındaki
PrimaryColor
ve mix
öğelerini kullanan bir kasa örneğini göstermektedir:
Dosya adı: src/main.rs
use art::kinds::PrimaryColor;
use art::utils::mix;
fn main() {
let red = PrimaryColor::Red;
let yellow = PrimaryColor::Yellow;
mix(red, yellow);
}
Liste 14-4'teki art
kasasını kullanan kodun yazarı,
PrimaryColor
'ın kinds
modülünde ve mix
'in utils
modülünde olduğunu anlamak zorunda kalmıştır.
art
kasasının modül yapısı, onu kullananlardan ziyade art
kasası üzerinde çalışan geliştiriciler için
daha önemlidir. İç yapı, art
kasasının nasıl kullanılacağını anlamaya çalışan biri için herhangi
bir yararlı bilgi içermez, aksine kafa karışıklığına neden olur, çünkü onu kullanan geliştiriciler nereye bakacaklarını
bulmak ve use deyimlerinde modül adlarını belirtmek zorundadır.
Dahili organizasyonu genel API'den kaldırmak için, Liste 14-3'teki art
kasa kodunu değiştirerek,
Liste 14-5'te gösterildiği gibi üst düzeydeki öğeleri yeniden dışa aktarmak için pub use
ifade yapısını
ekleyebiliriz:
Dosya adı: src/lib.rs
//! # Art
//!
//! A library for modeling artistic concepts.
pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;
pub mod kinds {
// --snip--
/// The primary colors according to the RYB color model.
pub enum PrimaryColor {
Red,
Yellow,
Blue,
}
/// The secondary colors according to the RYB color model.
pub enum SecondaryColor {
Orange,
Green,
Purple,
}
}
pub mod utils {
// --snip--
use crate::kinds::*;
/// Combines two primary colors in equal amounts to create
/// a secondary color.
pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
SecondaryColor::Orange
}
}
cargo doc
'un bu kasa için oluşturduğu API dokümantasyonu artık Şekil 14-4'te gösterildiği gibi ön
sayfada yeniden dışa aktarmaları listeleyecek ve bağlayacak, böylece PrimaryColor
ve
SecondaryColor
türleri ile mix
fonksiyonunun bulunması kolaylaşacaktır.
art
kasası kullanıcıları, Liste 14-4'te gösterildiği gibi Liste 14-3'teki dahili yapıyı
görmeye ve kullanmaya devam edebilir ya da Liste 14-6'da gösterildiği gibi Liste 14-5'teki
daha kullanışlı yapıyı kullanabilirler:
Dosya adı: src/main.rs
use art::mix;
use art::PrimaryColor;
fn main() {
// --snip--
let red = PrimaryColor::Red;
let yellow = PrimaryColor::Yellow;
mix(red, yellow);
}
İç içe geçmiş çok sayıda modülün bulunduğu durumlarda, en üst seviyedeki türlerin pub
kullanımıyla
yeniden dışa aktarılması, kasayı kullanan kişilerin deneyiminde önemli bir fark yaratabilir.
Kullanışlı bir genel API yapısı oluşturmak bilimden çok bir sanattır ve kullanıcılarınız
için en iyi çalışan API'yi bulmak için yineleme yapabilirsiniz. pub
kullanımını seçmek, kasanızı dahili
olarak nasıl yapılandırdığınız konusunda size esneklik sağlar ve bu dahili yapıyı kullanıcılarınıza
sunduğunuzdan ayırır. İç yapılarının genel API'lerinden farklı olup olmadığını görmek için yüklediğiniz
bazı kasaların kodlarına bakın.
Crates.io Hesabı Oluşturma
Herhangi bir kasayı yayınlayabilmeniz için önce crates.io'da bir hesap
oluşturmanız ve bir API anahtarı almanız gerekir. Bunu yapmak için crates.io adresindeki
ana sayfayı ziyaret edin ve bir GitHub hesabı aracılığıyla oturum açın. (GitHub hesabı şu anda bir gerekliliktir,
ancak site gelecekte hesap oluşturmanın diğer yollarını da gelecekte destekleyebilir).
Giriş yaptıktan sonra https://crates.io/me/ adresinden hesap
ayarlarınızı ziyaret edin ve API anahtarınızı alın. Ardından cargo login
komutunu API
anahtarınızla aşağıdaki gibi çalıştırın:
$ cargo login abcdefghijklmnopqrstuvwxyz012345
Bu komut Cargo'ya API token'ınızı bildirecek ve yerel olarak ~/.cargo/credentials içinde saklayacaktır. Bu belirtecin bir sır olduğunu unutmayın: başkasıyla paylaşmayın. Herhangi bir nedenle herhangi biriyle paylaşırsanız, iptal etmeli ve crates.io'dan yeni bir token oluşturmalısınız.
Yeni Bir Kasaya Meta Veri Ekleme
Diyelim ki yayınlamak istediğiniz bir kasanız var. Yayınlamadan önce,
kasanın Cargo.toml dosyasının [package]
bölümüne bazı meta veriler eklemeniz gerekir.
Kasanızın benzersiz bir isme ihtiyacı olacaktır. Yerel olarak bir kasa üzerinde çalışırken,
sandığa istediğiniz adı verebilirsiniz. Ancak crates.io'daki kasa
adları ilk gelene ilk hizmet esasına göre tahsis edilir. Bir kasa adı alındıktan sonra,
başka hiç kimse bu adla bir kasa yayınlayamaz. Bir kasa yayınlamaya çalışmadan önce,
kullanmak istediğiniz adı arayın. İsim kullanılmışsa, başka bir isim bulmanız ve
Cargo.toml dosyasında [package]
bölümü altındaki name
alanını, yayınlama için yeni ismi
kullanacak şekilde düzenlemeniz gerekecektir:
Dosya adı: Cargo.toml
[package]
name = "guessing_game"
Benzersiz bir ad seçmiş olsanız bile, bu noktada kasayı yayınlamak için cargo publish
'i çalıştırdığınızda,
bir uyarı ve ardından bir hata alırsınız:
$ cargo publish
Updating crates.io index
warning: manifest has no description, license, license-file, documentation, homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
--snip--
error: failed to publish to registry at https://crates.io
Caused by:
the remote server responded with an error: missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadata
Bu hata, bazı önemli bilgilerin eksik olmasından kaynaklanmaktadır:
insanların kasanızın ne işe yaradığını ve hangi koşullar altında kullanabileceklerini bilmeleri için
bir açıklama ve lisans gereklidir. Cargo.toml dosyasına sadece bir veya iki cümlelik bir açıklama ekleyin,
çünkü bu açıklama arama sonuçlarında kasanızla birlikte görünecektir. license
alanı için bir lisans
tanımlayıcı değeri vermeniz gerekir. Linux Foundation’un Software Package Data Exchange (SPDX) listesi
bu değer için kullanabileceğiniz tanımlayıcıları listeler. Örneğin, kasanızı MIT Lisansı kullanarak
lisansladığınızı belirtmek için MIT
tanımlayıcısını ekleyin:
Dosya adı: Cargo.toml
[package]
name = "guessing_game"
license = "MIT"
SPDX'te görünmeyen bir lisans kullanmak istiyorsanız, bu lisansın metnini bir dosyaya yerleştirmeniz,
dosyayı projenize dahil etmeniz ve ardından lisans anahtarını kullanmak yerine bu dosyanın adını belirtmek
için license-file
kullanmanız gerekir.
Projeniz için hangi lisansın uygun olduğuna ilişkin rehberlik bu kitabın kapsamı dışındadır.
Rust topluluğundaki birçok kişi, MIT VEYA Apache-2.0
ikili lisansını kullanarak projelerini Rust ile
aynı şekilde lisanslar. Bu uygulama, projeniz için birden fazla lisansa sahip olmak için OR
ile ayrılmış
birden fazla lisans tanımlayıcısı da belirtebileceğinizi göstermektedir.
Benzersiz bir ad, sürüm, açıklamanız ve bir lisans eklendiğinde, yayınlamaya hazır bir proje için Cargo.toml dosyası aşağıdaki gibi görünebilir:
Dosya adı: Cargo.toml
[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"
description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.0"
[dependencies]
Cargo’nun dokümantasyonunda, başkalarının kasanızı daha kolay keşfedip kullanabilmesini sağlamak için belirtebileceğiniz diğer meta veriler açıklanmaktadır.
Crates.io'da Yayınlama Süreci
Artık bir hesap oluşturduğunuza, API token'ınızı kaydettiğinize, kasanız için bir ad seçtiğinize ve gerekli meta verileri belirlediğinize göre yayınlamaya hazırsınız! Bir kasa yayınlamak, başkalarının kullanması için crates.io'ya belirli bir sürümü yükler.
Dikkatli olun, çünkü yayınlama kalıcıdır. Sürümün üzerine asla yazılamaz ve kod silinemez. crates.io'nun en önemli amaçlarından biri kalıcı bir kod arşivi olarak hareket etmektir, böylece crates.io'daki kasalara bağlı olan tüm projelerin yapıları çalışmaya devam edecektir. Sürüm silme işlemlerine izin vermek bu hedefin gerçekleştirilmesini imkansız hale getirecektir. Bununla birlikte, yayınlayabileceğiniz kasa sürümlerinin sayısında bir sınır yoktur.
cargo publish
komutunu tekrar çalıştırın. Şimdi çalışması gerekir:
$ cargo publish
Updating crates.io index
Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
Compiling guessing_game v0.1.0
(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
Finished dev [unoptimized + debuginfo] target(s) in 0.19s
Uploading guessing_game v0.1.0 (file:///projects/guessing_game)
Tebrikler! Artık kodunuzu Rust topluluğu ile paylaştınız ve herkes kasanızı kolayca projelerinin bir bağımlılığı olarak ekleyebilir.
Mevcut Bir Kasanın Yeni Sürümünü Yayınlama
Sandığınızda değişiklikler yaptığınızda ve yeni bir sürüm yayınlamaya hazır olduğunuzda,
Cargo.toml dosyanızda belirtilen sürüm değerini değiştirir ve yeniden yayınlarsınız.
Yaptığınız değişiklik türlerine göre uygun bir sonraki sürüm numarasının ne olduğuna
karar vermek için Anlamsal Sürüm Oluşturma kurallarını kullanın.
Ardından yeni sürümü göndermek için cargo publish
'ı çalıştırın.
cargo yank
ile Crates.io'dan Sürümleri Kaldırma
Bir sandığın önceki sürümlerini kaldıramasanız da, gelecekteki projelerin bunları yeni bir bağımlılık olarak eklemesini önleyebilirsiniz. Bu, bir kasa sürümü bir nedenle bozulduğunda kullanışlıdır. Bu gibi durumlarda, Cargo kasa sürümünün kaldırılmasını destekler.
Bir sürümü çekmek, yeni projelerin o sürüme bağlı olmasını engellerken, ona bağlı olan tüm mevcut projelerin devam etmesine izin verir. Esasen, çekme, Cargo.lock'a sahip tüm projelerin bozulmayacağı ve gelecekte üretilen herhangi bir Cargo.lock dosyasının çekilmiş sürümü kullanmayacağı anlamına gelir.
Bir kasanın sürümünü çekmek için, daha önce yayınladığınız kasanın dizininde cargo yank
komutunu çalıştırın ve hangi sürümü çekmek istediğinizi belirtin:
$ cargo yank --vers 1.0.1
Ayrıca komuta --undo
ekleyerek bir çekme işlemini geri alabilir ve projelerin yeniden
bir sürüme bağlı olarak başlamasına izin verebilirsiniz:
$ cargo yank --vers 1.0.1 --undo
Bir çekme herhangi bir kodu silmez. Örneğin, yanlışlıkla yüklenen sırları silemez. Böyle bir durumda, bu sırları derhal sıfırlamanız gerekir.