You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
19 KiB

<!doctype html><html lang=zh-CN class="sidebar-visible no-js light"><meta charset=UTF-8><title>版本号 - Rusty Book(锈书)</title><meta content="text/html; charset=utf-8" http-equiv=Content-Type><meta name=description content=""><meta name=viewport content="width=device-width,initial-scale=1"><meta name=theme-color content=#ffffff><link rel=icon href=../favicon.svg><link rel="shortcut icon" href=../favicon.png><link rel=stylesheet href=../css/variables.css><link rel=stylesheet href=../css/general.css><link rel=stylesheet href=../css/chrome.css><link rel=stylesheet href=../css/print.css media=print><link rel=stylesheet href=../FontAwesome/css/font-awesome.css><link rel=stylesheet href=../fonts/fonts.css><link rel=stylesheet href=../highlight.css><link rel=stylesheet href=../tomorrow-night.css><link rel=stylesheet href=../ayu-highlight.css><link rel=stylesheet href=../theme/style1.css><body><script>var path_to_root="../",default_theme=window.matchMedia("(prefers-color-scheme: dark)").matches?"navy":"light"</script><script>try{var theme=localStorage.getItem("mdbook-theme"),sidebar=localStorage.getItem("mdbook-sidebar");theme.startsWith('"')&&theme.endsWith('"')&&localStorage.setItem("mdbook-theme",theme.slice(1,theme.length-1)),sidebar.startsWith('"')&&sidebar.endsWith('"')&&localStorage.setItem("mdbook-sidebar",sidebar.slice(1,sidebar.length-1))}catch(e){}</script><script>var theme;try{theme=localStorage.getItem("mdbook-theme")}catch(e){}null==theme&&(theme=default_theme);var html=document.querySelector("html");html.classList.remove("no-js"),html.classList.remove("light"),html.classList.add(theme),html.classList.add("js")</script><script>var html=document.querySelector("html"),sidebar="hidden";if(document.body.clientWidth>=1080){try{sidebar=localStorage.getItem("mdbook-sidebar")}catch(e){}sidebar=sidebar||"visible"}html.classList.remove("sidebar-visible"),html.classList.add("sidebar-"+sidebar)</script><nav id=sidebar class=sidebar aria-label="Table of contents"><div class=sidebar-scrollbox><ol class=chapter><li class="chapter-item expanded affix"><a href=../about.html>Rusty Book</a><li class="chapter-item expanded affix"><li class=part-title>Awesome<li class=spacer><li class="chapter-item expanded"><a href=../daily-dev.html>日常开发常用库</a><li class="chapter-item expanded"><a href=../superstar.html>Rust 明星项目</a><li class="chapter-item expanded"><a href=../empowering-js.html>使用 Rust 增强 JS</a><li class="chapter-item expanded"><a href=../games.html>Rust开发的游戏</a><li class="chapter-item expanded"><a href=../gamedev.html>游戏引擎</a><li class="chapter-item expanded affix"><li class=part-title>Awesome + Cookbook<li class=spacer><li class="chapter-item expanded"><a href=../algos/awesome.html>实用算法</a><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../algos/randomness.html>生成随机值</a><li class="chapter-item expanded"><a href=../algos/sorting.html>Vec 排序</a><li class="chapter-item expanded"><div>压缩算法</div><a class=toggle><div></div></a><li><ol class=section><li class=chapter-item><a href=../algos/compression/tar.html>使用.tar包</a></ol><li class="chapter-item expanded"><div>密码学</div><a class=toggle><div></div></a><li><ol class=section><li class=chapter-item><a href=../algos/cryptography/hashing.html>哈希</a><li class=chapter-item><a href=../algos/cryptography/encryption.html>加密</a></ol><li class="chapter-item expanded"><div>数学计算</div><a class=toggle><div></div></a><li><ol class=section><li class=chapter-item><a href=../algos/math/linear-algebra.html>线性代数</a><li class=chapter-item><a href=../algos/math/trigonometry.html>三角函数</a><li class=chapter-item><a href=../algos/math/complex.html>复数</a><li class=chapter-item><a href=../algos/math/statistics.html>统计学</a><li class=chapter-item><a href=../algos/math/misc.html>杂项</a></ol></ol><li class="chapter-item expanded"><a href=../datastructures/awesome.html>数据结构</a><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../datastructures/bitfield.html>位字段</a></ol><li class="chapter-item expanded"><a href=../cmd/awesome.html>命令行</a><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../cmd/parsing.html>参数解析</a><li class="chapter-item expanded"><a href=../cmd/ansi.html>终端输出格式化</a></ol><li class="chapter-item expanded"><a href=../os/awesome.html>操作系统</a><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../os/processor.html>处理器</a><li class="chapter-item expanded"><a href=../os/command.html>调用系统命令</a></ol><li class="chapter-item expanded"><div>并发</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../cocurrency/threads.html>线程</a><li class="chapter-item expanded"><a href=../cocurrency/parallel.html>使用rayon并行处理数据</a></ol><li class="chapter-item expanded"><div>数据库</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../database/sqlite.html>SQLite</a><li class="chapter-item expanded"><a href=../database/postgres.html>Postgres</a></ol><li class="chapter-item expanded"><div>日期和时间</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../datetime/duration.html>时间计算和转换</a><li class="chapter-item expanded"><a href=../datetime/parsing.html>解析和显示</a></ol><li class="chapter-item expanded"><div>开发者工具</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../devtools/log.html>日志</a><li class="chapter-item expanded"><a href=../devtools/config-log.html>配置日志</a><li class="chapter-item expanded"><a href=../devtools/version.html class=active>版本号</a><li class="chapter-item expanded"><a href=../devtools/build-tools.html>构建时工具</a></ol><li class="chapter-item expanded"><div>编解码</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../encoding/strings.html>字符编码</a><li class="chapter-item expanded"><a href=../encoding/csv.html>CSV</a><li class="chapter-item expanded"><a href=../encoding/structured.html>结构化数据</a></ol><li class="chapter-item expanded"><div>错误处理</div><li class="chapter-item expanded"><div>文件操作</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../files/read-write.html>文件读写</a><li class="chapter-item expanded"><a href=../files/dir.html>目录访问</a></ol><li class="chapter-item expanded"><div>内存管理</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../memory/global-vars.html>全局变量</a></ol><li class="chapter-item expanded"><div>网络协议</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../protocols/tcpip.html>TCP/IP</a></ol><li class="chapter-item expanded"><div>文本处理</div><a class=toggle><div></div></a><li><ol class=section><li class="chapter-item expanded"><a href=../text/regex.html>正则表达式</a><li class="chapter-item expanded"><a href=../text/string.html>字符串解析</a></ol></ol></div><div id=sidebar-resize-handle class=sidebar-resize-handle></div></nav><div id=page-wrapper class=page-wrapper><div class=page><div id=menu-bar-hover-placeholder></div><div id=menu-bar class="menu-bar sticky bordered"><div class=left-buttons><button id=sidebar-toggle class=icon-button type=button title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls=sidebar><i class="fa fa-bars"></i></button> <button id=theme-toggle class=icon-button type=button title="Change theme" aria-label="Change theme" aria-haspopup=true aria-expanded=false aria-controls=theme-list><i class="fa fa-paint-brush"></i></button><ul id=theme-list class=theme-popup aria-label=Themes role=menu><li role=none><button role=menuitem class=theme id=light>Light (default)</button><li role=none><button role=menuitem class=theme id=rust>Rust</button><li role=none><button role=menuitem class=theme id=coal>Coal</button><li role=none><button role=menuitem class=theme id=navy>Navy</button><li role=none><button role=menuitem class=theme id=ayu>Ayu</button></ul><button id=search-toggle class=icon-button type=button title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded=false aria-keyshortcuts=S aria-controls=searchbar><i class="fa fa-search"></i></button></div><h1 class=menu-title>Rusty Book(锈书)</h1><div class=right-buttons><a href=../print.html title="Print this book" aria-label="Print this book"><i id=print-button class="fa fa-print"></i> </a><a href=https://github.com/studyrs/rusty-book title="Git repository" aria-label="Git repository"><i id=git-repository-button class="fa fa-github"></i> </a><a href=https://github.com/studyrs/rusty-book/edit/main/src/devtools/version.md title="Suggest an edit" aria-label="Suggest an edit"><i id=git-edit-button class="fa fa-edit"></i></a></div></div><div id=search-wrapper class=hidden><form id=searchbar-outer class=searchbar-outer><input type=search id=searchbar name=searchbar placeholder="Search this book ..." aria-controls=searchresults-outer aria-describedby=searchresults-header></form><div id=searchresults-outer class="searchresults-outer hidden"><div id=searchresults-header class=searchresults-header></div><ul id=searchresults></ul></div></div><script>document.getElementById("sidebar-toggle").setAttribute("aria-expanded","visible"===sidebar),document.getElementById("sidebar").setAttribute("aria-hidden","visible"!==sidebar),Array.from(document.querySelectorAll("#sidebar a")).forEach((function(e){e.setAttribute("tabIndex","visible"===sidebar?0:-1)}))</script><div id=content class=content><div class=sidetoc><nav class=pagetoc></nav></div><main><h1 id=版本号><a class=header href=#版本号>版本号</a></h1><h3 id=解析并增加版本号><a class=header href=#解析并增加版本号>解析并增加版本号</a></h3><p>下面例子使用 <a href=https://docs.rs/semver/*/semver/struct.Version.html#method.parse>Version::parse</a> 将一个字符串转换成 <a href=https://docs.rs/semver/*/semver/struct.Version.html>semver::Version</a> 版本号,然后将它的 patch, minor, major 版本号都增加 1。<p>注意,为了符合<a href=http://semver.org>语义化版本的说明</a>,增加 <code>minor</code> 版本时,<code>patch</code> 版本会被重设为 <code>0</code>,当增加 <code>major</code> 版本时,<code>minor</code><code>patch</code> 都将被重设为 <code>0</code><pre><pre class=playground><code class="language-rust editable edition2021">use semver::{Version, SemVerError};
fn main() -&gt; Result&lt;(), SemVerError&gt; {
let mut parsed_version = Version::parse(&quot;0.2.6&quot;)?;
assert_eq!(
parsed_version,
Version {
major: 0,
minor: 2,
patch: 6,
pre: vec![],
build: vec![],
}
);
parsed_version.increment_patch();
assert_eq!(parsed_version.to_string(), &quot;0.2.7&quot;);
println!(&quot;New patch release: v{}&quot;, parsed_version);
parsed_version.increment_minor();
assert_eq!(parsed_version.to_string(), &quot;0.3.0&quot;);
println!(&quot;New minor release: v{}&quot;, parsed_version);
parsed_version.increment_major();
assert_eq!(parsed_version.to_string(), &quot;1.0.0&quot;);
println!(&quot;New major release: v{}&quot;, parsed_version);
Ok(())
}
</code></pre></pre><h3 id=解析一个复杂的版本号字符串><a class=header href=#解析一个复杂的版本号字符串>解析一个复杂的版本号字符串</a></h3><p>这里的版本号字符串还将包含 <code>SemVer</code> 中定义的预发布和构建元信息。<p>值得注意的是,为了符合 <code>SemVer</code> 的规则,构建元信息虽然会被解析,但是在做版本号比较时,该信息会被忽略。换而言之,即使两个版本号的构建字符串不同,它们的版本号依然可能相同。<pre><pre class=playground><code class="language-rust editable edition2021">use semver::{Identifier, Version, SemVerError};
fn main() -&gt; Result&lt;(), SemVerError&gt; {
let version_str = &quot;1.0.49-125+g72ee7853&quot;;
let parsed_version = Version::parse(version_str)?;
assert_eq!(
parsed_version,
Version {
major: 1,
minor: 0,
patch: 49,
pre: vec![Identifier::Numeric(125)],
build: vec![],
}
);
assert_eq!(
parsed_version.build,
vec![Identifier::AlphaNumeric(String::from(&quot;g72ee7853&quot;))]
);
let serialized_version = parsed_version.to_string();
assert_eq!(&amp;serialized_version, version_str);
Ok(())
}
</code></pre></pre><h3 id=检查给定的版本号是否是预发布><a class=header href=#检查给定的版本号是否是预发布>检查给定的版本号是否是预发布</a></h3><p>下面例子给出两个版本号,然后通过 <a href=https://docs.rs/semver/1.0.7/semver/struct.Version.html#method.is_prerelease>is_prerelease</a> 判断哪个是预发布的版本号。<pre><pre class=playground><code class="language-rust editable edition2021">use semver::{Version, SemVerError};
fn main() -&gt; Result&lt;(), SemVerError&gt; {
let version_1 = Version::parse(&quot;1.0.0-alpha&quot;)?;
let version_2 = Version::parse(&quot;1.0.0&quot;)?;
assert!(version_1.is_prerelease());
assert!(!version_2.is_prerelease());
Ok(())
}
</code></pre></pre><h3 id=找出给定范围内的最新版本><a class=header href=#找出给定范围内的最新版本>找出给定范围内的最新版本</a></h3><p>下面例子给出了一个版本号列表,我们需要找到其中最新的版本。<pre><pre class=playground><code class="language-rust editable edition2021"><span class=boring>use error_chain::error_chain;
</span>
use semver::{Version, VersionReq};
<span class=boring>error_chain! {
</span><span class=boring> foreign_links {
</span><span class=boring> SemVer(semver::SemVerError);
</span><span class=boring> SemVerReq(semver::ReqParseError);
</span><span class=boring> }
</span>3}
fn find_max_matching_version&lt;'a, I&gt;(version_req_str: &amp;str, iterable: I) -&gt; Result&lt;Option&lt;Version&gt;&gt;
where
I: IntoIterator&lt;Item = &amp;'a str&gt;,
{
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() -&gt; Result&lt;()&gt; {
assert_eq!(
find_max_matching_version(&quot;&lt;= 1.0.0&quot;, vec![&quot;0.9.0&quot;, &quot;1.0.0&quot;, &quot;1.0.1&quot;])?,
Some(Version::parse(&quot;1.0.0&quot;)?)
);
assert_eq!(
find_max_matching_version(
&quot;&gt;1.2.3-alpha.3&quot;,
vec![
&quot;1.2.3-alpha.3&quot;,
&quot;1.2.3-alpha.4&quot;,
&quot;1.2.3-alpha.10&quot;,
&quot;1.2.3-beta.4&quot;,
&quot;3.4.5-alpha.9&quot;,
]
)?,
Some(Version::parse(&quot;1.2.3-beta.4&quot;)?)
);
Ok(())
}
</code></pre></pre><h3 id=检查外部命令的版本号兼容性><a class=header href=#检查外部命令的版本号兼容性>检查外部命令的版本号兼容性</a></h3><p>下面将通过 <a href=https://doc.rust-lang.org/std/process/struct.Command.html>Command</a> 来执行系统命令 <code>git --version</code>,并对该系统命令返回的 <code>git</code> 版本号进行解析。<pre><pre class=playground><code class="language-rust editable edition2021"><span class=boring>use error_chain::error_chain;
</span>
use std::process::Command;
use semver::{Version, VersionReq};
<span class=boring>error_chain! {
</span><span class=boring> foreign_links {
</span><span class=boring> Io(std::io::Error);
</span><span class=boring> Utf8(std::string::FromUtf8Error);
</span><span class=boring> SemVer(semver::SemVerError);
</span><span class=boring> SemVerReq(semver::ReqParseError);
</span><span class=boring> }
</span><span class=boring>}
</span>
fn main() -&gt; Result&lt;()&gt; {
let version_constraint = &quot;&gt; 1.12.0&quot;;
let version_test = VersionReq::parse(version_constraint)?;
let output = Command::new(&quot;git&quot;).arg(&quot;--version&quot;).output()?;
if !output.status.success() {
error_chain::bail!(&quot;Command executed with failing error code&quot;);
}
let stdout = String::from_utf8(output.stdout)?;
let version = stdout.split(&quot; &quot;).last().ok_or_else(|| {
&quot;Invalid command output&quot;
})?;
let parsed_version = Version::parse(version)?;
if !version_test.matches(&amp;parsed_version) {
error_chain::bail!(&quot;Command version lower than minimum supported version (found {}, need {})&quot;,
parsed_version, version_constraint);
}
Ok(())
}
</code></pre></pre><div id=giscus-container></div></main><nav class=nav-wrapper aria-label="Page navigation"><a rel=prev href=../devtools/config-log.html class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts=Left><i class="fa fa-angle-left"></i> </a><a rel=next href=../devtools/build-tools.html class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts=Right><i class="fa fa-angle-right"></i></a><div style=clear:both></div></nav></div></div><nav class=nav-wide-wrapper aria-label="Page navigation"><a rel=prev href=../devtools/config-log.html class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts=Left><i class="fa fa-angle-left"></i> </a><a rel=next href=../devtools/build-tools.html class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts=Right><i class="fa fa-angle-right"></i></a></nav></div><script>window.playground_copyable=!0</script><script src=../ace.js charset=utf-8></script><script src=../editor.js charset=utf-8></script><script src=../mode-rust.js charset=utf-8></script><script src=../theme-dawn.js charset=utf-8></script><script src=../theme-tomorrow_night.js charset=utf-8></script><script src=../elasticlunr.min.js charset=utf-8></script><script src=../mark.min.js charset=utf-8></script><script src=../searcher.js charset=utf-8></script><script src=../clipboard.min.js charset=utf-8></script><script src=../highlight.js charset=utf-8></script><script src=../book.js charset=utf-8></script><script>var pagePath="devtools/version.md"</script><script src=../assets/custom1.js></script><script src=../assets/bigPicture.js></script>