Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

バージョニング

バージョン文字列を解析してインクリメントする。

semver-badge cat-config-badge

Version::parse を使用して文字列リテラルから semver::Version を構築し、 その後、パッチ、マイナー、メジャーの各バージョン番号を順にインクリメントします。

Semantic Versioning Specification に従い、 マイナーのバージョン番号をインクリメントするとパッチのバージョン番号は 0 に リセットされ、メジャーのバージョン番号をインクリメントするとマイナーとパッチの バージョン番号の両方が 0 にリセットされることに注意してください。

use semver::{Version, Error as SemVerError};

fn main() -> Result<(), SemVerError> {
    let mut parsed_version = Version::parse("0.2.6")?;

    assert_eq!(
        parsed_version,
        Version::new(0, 2, 6)
    );

    parsed_version.patch += 1;
    assert_eq!(parsed_version.to_string(), "0.2.7");
    println!("New patch release: v{}", parsed_version);

    parsed_version.minor += 1;
    parsed_version.patch = 0;
    assert_eq!(parsed_version.to_string(), "0.3.0");
    println!("New minor release: v{}", parsed_version);

    parsed_version.major += 1;
    parsed_version.minor = 0;
    parsed_version.patch = 0;
    assert_eq!(parsed_version.to_string(), "1.0.0");
    println!("New major release: v{}", parsed_version);

    Ok(())
}

複雑なバージョン文字列を解析する。

semver-badge cat-config-badge

Version::parse を使用して、複雑なバージョン文字列から semver::Version を構築します。文字列 には、Semantic Versioning Specification で定義されているプレリリースとビルドメタデータが含まれます。

なお、仕様に従い、ビルドメタデータは解析されますが、バージョンを比較する際には 考慮されません。言い換えると、ビルド文字列が異なっていても、2 つのバージョンが等しい場合があります。

use semver::{Version, Prerelease, BuildMetadata, Error};

fn main() -> Result<(), Error> {
    let version_str = "1.0.49-125+g72ee7853";
    let parsed_version = Version::parse(version_str)?;

    assert_eq!(parsed_version.major, 1);
    assert_eq!(parsed_version.minor, 0);
    assert_eq!(parsed_version.patch, 49);
    assert_eq!(parsed_version.pre, Prerelease::new("125")?);
    assert_eq!(parsed_version.build, BuildMetadata::new("g72ee7853")?);

    let serialized_version = parsed_version.to_string();
    assert_eq!(&serialized_version, version_str);

    Ok(())
}

指定されたバージョンがプレリリースかどうかを確認する。

semver-badge cat-config-badge

2 つのバージョンが与えられたとき、[is_prerelease] は一方がプレリリースで、もう一方がそうでないことをアサートします。

use semver::{Version, Error};

fn main() -> Result<(), Error> {
    let version_1 = Version::parse("1.0.0-alpha")?;
    let version_2 = Version::parse("1.0.0")?;

    assert!(!version_1.pre.is_empty());
    assert!(version_2.pre.is_empty());

    Ok(())
}

指定した範囲を満たす最新バージョンを見つける

semver-badge cat-config-badge

バージョン &str のリストが与えられると、最新の semver::Version を見つけます。 semver::VersionReqVersionReq::matches を使ってリストを絞り込みます。 また、semver のプレリリースの優先順位も示しています。

use anyhow::Result;
use semver::{Version, VersionReq};

fn find_max_matching_version<'a, I>(version_req_str: &str, iterable: I) -> Result<Option<Version>>
where
    I: IntoIterator<Item = &'a str>,
{
    let vreq = VersionReq::parse(version_req_str)?;

    Ok(
        iterable
            .into_iter()
            .filter_map(|s| Version::parse(s).ok())
            .filter(|s| vreq.matches(s))
            .max(),
    )
}

fn main() -> Result<()> {
    assert_eq!(
        find_max_matching_version("<= 1.0.0", vec!["0.9.0", "1.0.0", "1.0.1"])?,
        Some(Version::parse("1.0.0")?)
    );

    assert_eq!(
        find_max_matching_version(
            ">1.2.3-alpha.3",
            vec![
                "1.2.3-alpha.3",
                "1.2.3-alpha.4",
                "1.2.3-alpha.10",
                "1.2.3-beta.4",
                "3.4.5-alpha.9",
            ]
        )?,
        Some(Version::parse("1.2.3-beta.4")?)
    );

    Ok(())
}

互換性を確認するために外部コマンドのバージョンをチェックする

semver-badge cat-text-processing-badge cat-os-badge

Command を使用して git --version を実行し、その後バージョン番号を Version::parse を使用して semver::Version に解析します。VersionReq::matchessemver::VersionReq を解析済みのバージョンと比較します。コマンドの出力は “git version x.y.z” のようになります。

use anyhow::{Result, anyhow};
use std::process::Command;
use semver::{Version, VersionReq};

fn main() -> Result<()> {
    let version_constraint = "> 1.12.0";
    let version_test = VersionReq::parse(version_constraint)?;
    let output = Command::new("git").arg("--version").output()?;

    if !output.status.success() {
        return Err(anyhow!("コマンドは失敗したエラーコードで実行されました"));
    }

    let stdout = String::from_utf8(output.stdout)?;
    let version = stdout.split(" ").last().ok_or_else(|| {
        anyhow!("無効なコマンド出力です")
    })?;
    let parsed_version = Version::parse(version)?;

    if !version_test.matches(&parsed_version) {
        return Err(anyhow!("コマンドのバージョンがサポートされる最小バージョンより低くなっています(検出: {}、必要: {})",
            parsed_version, version_constraint));
    }

    Ok(())
}