The Rust package manager
A project for generating C bindings from Rust code
ccache – a fast compiler cache
Rust build dependency for running cmake
Dynamic Instrumentation Tool Platform
Github hooks to provide an encouraging atmosphere for new contributors
The Rust Reference
RFCs for changes to Rust
Pull request review commentrust-lang/docs.rs
+use crate::error::Result;+use crate::{db::Pool, Config};+use chrono::{DateTime, Utc};+use log::{debug, info, trace, warn};+use once_cell::sync::Lazy;+use postgres::Client;+use regex::Regex;+use reqwest::{+ blocking::Client as HttpClient,+ header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, USER_AGENT},+};+use serde::Deserialize;+use std::collections::{HashMap, HashSet};+use std::sync::Arc;++const APP_USER_AGENT: &str = concat!(+ env!("CARGO_PKG_NAME"),+ " ",+ include_str!(concat!(env!("OUT_DIR"), "/git_version"))+);++pub fn graphql_update(ids: &[&str]) -> String {+ format!(+ "\+query {{+ projects(ids: {:?}) {{+ ... on Project {{+ id+ nameWithNamespace+ lastActivityAt+ description+ starCount+ forksCount+ openIssuesCount+ }}+ }}+}}",+ ids+ )+}++pub fn graphql_single(path: &str) -> String {+ format!(+ "\+query {{+ project(fullPath: \"{}\") {{+ id+ nameWithNamespace+ lastActivityAt+ description+ starCount+ forksCount+ openIssuesCount+ }}+}}",+ path+ )+}++/// How many repositories to update in a single chunk. Values over 100 are probably going to be+/// rejected by the GraphQL API.+const UPDATE_CHUNK_SIZE: usize = 100;++fn extract_host(url: &str) -> Option<&str> {+ url.split("//")+ .skip(1)+ .next()+ .and_then(|u| u.split('/').next())+}++pub struct GitlabUpdater {+ client: HttpClient,+ pool: Pool,+ config: Arc<Config>,+}++impl GitlabUpdater {+ /// Returns `Err` if the access token has invalid syntax (but *not* if it isn't authorized).+ /// Returns `Ok(None)` if there is no access token.+ pub fn new(config: Arc<Config>, pool: Pool) -> Result<Option<Self>> {+ let mut headers = HeaderMap::new();+ headers.insert(USER_AGENT, HeaderValue::from_static(APP_USER_AGENT));+ headers.insert(ACCEPT, HeaderValue::from_static("application/json"));++ if let Some(token) = &config.gitlab_accesstoken {+ headers.insert(+ AUTHORIZATION,+ HeaderValue::from_str(&format!("token {}", token))?,+ );+ } else {+ return Ok(None);+ }++ let client = HttpClient::builder().default_headers(headers).build()?;++ Ok(Some(GitlabUpdater {+ client,+ pool,+ config,+ }))+ }++ pub fn backfill_repositories(&self) -> Result<()> {+ info!("started backfilling Gitlab repository stats");++ let mut conn = self.pool.get()?;+ let needs_backfilling = conn.query(+ "SELECT releases.id, crates.name, releases.version, releases.repository_url+ FROM releases+ INNER JOIN crates ON (crates.id = releases.crate_id)+ WHERE gitlab_repo IS NULL AND repository_url LIKE '%gitlab.%/%';",+ &[],+ )?;++ let mut missing_urls = HashSet::new();+ for row in &needs_backfilling {+ let id: i32 = row.get("id");+ let name: String = row.get("name");+ let version: String = row.get("version");+ let url: String = row.get("repository_url");++ if missing_urls.contains(&url) {+ eprintln!("{} {} points to a known missing repo", name, version);+ } else if let Some(node_id) = self.load_repository(&mut conn, &url)? {+ conn.execute(+ "UPDATE releases SET gitlab_repo = $1 WHERE id = $2;",+ &[&node_id, &id],+ )?;+ info!("backfilled Gitlab repository for {} {}", name, version);+ } else {+ eprintln!("{} {} does not point to a Gitlab repository", name, version);+ missing_urls.insert(url);+ }+ }++ Ok(())+ }++ pub(crate) fn load_repository(&self, conn: &mut Client, url: &str) -> Result<Option<String>> {+ let name = match RepositoryName::from_url(url) {+ Some(name) => name,+ None => return Ok(None),+ };++ // Avoid querying the Gitlab API for repositories we already loaded.+ if let Some(row) = conn.query_opt(+ "SELECT id FROM gitlab_repos WHERE name = $1 LIMIT 1;",+ &[&format!("{}/{}", name.owner, name.repo)],+ )? {+ return Ok(Some(row.get("id")));+ }++ if let Some(url) = extract_host(url) {+ // Fetch the latest information from the Gitlab API.+ let response: GraphResponse<GraphProjectNode> = self.graphql(+ url,+ &graphql_single(&format!("{}/{}", name.owner, name.repo)),+ )?;+ if let Some(repo) = response.data.and_then(|d| d.project) {+ self.store_repository(conn, &repo)?;+ Ok(Some(repo.id))+ } else if let Some(error) = response.errors.get(0) {+ failure::bail!("error loading repository: {}", error.message)+ } else {+ panic!("missing repository but there were no errors!");+ }+ } else {+ failure::bail!("failed to extract host from `{}`", url)+ }+ }++ /// Updates gitlab fields in crates table+ pub fn update_all_crates(&self) -> Result<()> {+ info!("started updating Gitlab repository stats");++ let mut conn = self.pool.get()?;+ let needs_update = conn+ .query(+ "SELECT gitlab_repos.id, releases.repository_url+ FROM gitlab_repos+ INNER JOIN releases ON (releases.gitlab_repo = gitlab_repos.id)+ -- WHERE updated_at < NOW() - INTERVAL '1 day';",+ &[],+ )?+ .into_iter()+ .map(|row| (row.get(0), row.get(1)))+ .collect::<Vec<(String, String)>>();++ if needs_update.is_empty() {+ info!("no Gitlab repository stats needed to be updated");+ return Ok(());+ }++ let mut url_map: HashMap<String, Vec<&str>> = HashMap::new();++ for (chunk, url) in &needs_update {+ if let Some(url) = extract_host(url) {+ url_map.entry(url.to_owned()).or_default().push(chunk);+ } else {+ warn!("Couldn't extract host from `{}`", url);+ }+ }++ for (url, chunks) in &url_map {+ for chunk in chunks.chunks(UPDATE_CHUNK_SIZE) {+ if let Err(err) = self.update_repositories(url, &mut conn, &chunk) {+ if err.downcast_ref::<RateLimitReached>().is_some() {+ warn!("rate limit reached, blocked the Gitlab repository stats updater");+ return Ok(());+ }+ return Err(err);+ }+ }+ }++ info!("finished updating Gitlab repository stats");+ Ok(())+ }++ fn update_repositories(&self, url: &str, conn: &mut Client, node_ids: &[&str]) -> Result<()> {+ let response: GraphResponse<GraphNodes<Option<GraphProject>>> =+ self.graphql(url, &graphql_update(node_ids))?;++ // The error is returned *before* we reach the rate limit, to ensure we always have an+ // amount of API calls we can make at any time.+ if let Some(data) = response.data {+ trace!(+ "Gitlab GraphQL rate limit remaining: {}",+ data.rate_limit.remaining+ );+ if data.rate_limit.remaining < self.config.gitlab_updater_min_rate_limit {+ return Err(RateLimitReached.into());+ }++ // When a node is missing (for example if the repository was deleted or made private) the+ // GraphQL API will return *both* a `null` instead of the data in the nodes list and a+ // `NOT_FOUND` error in the errors list.+ for node in &data.nodes {+ if let Some(node) = node {+ self.store_repository(conn, &node)?;+ }+ }+ for error in &response.errors {+ failure::bail!("error updating repositories: {}", error.message);+ }++ Ok(())+ } else {+ failure::bail!("no data")+ }+ }++ fn graphql<T: serde::de::DeserializeOwned + std::fmt::Debug>(+ &self,+ host: &str,+ query: &str,+ ) -> Result<GraphResponse<T>> {+ eprintln!("doing stuff on {:?}", host);+ eprintln!("+++> {:?}", query);+ // Ok(self+ // .client+ // .post(&format!("https://{}/api/graphql", host))+ // .json(&serde_json::json!({+ // "query": query,+ // }))+ // .send()?+ // .error_for_status()?+ // .json()?)+ let tmp = self+ .client+ .post(&format!("https://{}/api/graphql", host))+ .json(&serde_json::json!({+ "query": query,+ }))+ .send()?+ .error_for_status()?;+ eprintln!("---> {:?}", tmp.headers());+ let s: String = tmp.text()?;+ eprintln!("---> {:?}", s);+ panic!("yolo");+ }++ fn store_repository(&self, conn: &mut Client, repo: &GraphProject) -> Result<()> {+ trace!(+ "storing Gitlab repository stats for {}",+ repo.name_with_namespace+ );+ eprintln!("+++> {:?}", repo);+ conn.execute(+ "INSERT INTO gitlab_repos (+ id, name, description, last_commit, stars, forks, issues, updated_at+ ) VALUES ($1, $2, $3, $4, $5, $6, $7, NOW())+ ON CONFLICT (id) DO+ UPDATE SET+ name = $2,+ description = $3,+ last_commit = $4,+ stars = $5,+ forks = $6,+ issues = $7,+ updated_at = NOW();",+ &[+ &repo.id,+ &repo.name_with_namespace,+ &repo.description,+ &repo.last_activity_at,+ &(repo.star_count as i32),+ &(repo.forks_count as i32),+ &(repo.open_issues_count as i32),+ ],+ )?;+ Ok(())+ }++ fn delete_repository(&self, conn: &mut Client, id: &str) -> Result<()> {+ trace!("removing Gitlab repository stats for ID {}", id);+ conn.execute("DELETE FROM gitlab_repos WHERE id = $1;", &[&id])?;+ Ok(())+ }+}++#[derive(Debug, Eq, PartialEq)]+struct RepositoryName<'a> {+ owner: &'a str,+ repo: &'a str,+}++impl<'a> RepositoryName<'a> {+ fn from_url(url: &'a str) -> Option<Self> {+ static RE: Lazy<Regex> = Lazy::new(|| {+ Regex::new(r"https?://(\w\.)*gitlab\.(\w\.?)+/(?P<owner>[\w\._-]+)/(?P<repo>[\w\._-]+)")+ .unwrap()+ });++ match RE.captures(url) {+ Some(cap) => {+ let owner = cap.name("owner").expect("missing group 'owner'").as_str();+ let repo = cap.name("repo").expect("missing group 'repo'").as_str();+ Some(Self {+ owner,+ repo: repo.strip_suffix(".git").unwrap_or(repo),+ })+ }+ None => None,+ }+ }+}++#[derive(Debug, failure::Fail)]+#[fail(display = "rate limit reached")]+struct RateLimitReached;++#[derive(Debug, Deserialize)]+struct GraphResponse<T> {+ data: Option<T>,+ #[serde(default)]+ errors: Vec<GraphError>,+}++#[derive(Debug, Deserialize)]+struct GraphError {+ message: String,+ locations: Vec<GraphErrorLocation>,+}++#[derive(Debug, Deserialize)]+struct GraphErrorLocation {+ line: u32,+ column: u32,+}++#[derive(Debug, Deserialize)]+struct GraphRateLimit {+ remaining: u32,+}++#[derive(Debug, Deserialize)]+#[serde(rename_all = "camelCase")]+struct GraphNodes<T> {+ nodes: Vec<T>,+ rate_limit: GraphRateLimit,+}++#[derive(Debug, Deserialize)]+struct GraphProjectNode {+ project: Option<GraphProject>,+}++#[derive(Debug, Deserialize)]+#[serde(rename_all = "camelCase")]+struct GraphProject {+ id: String,+ name_with_namespace: String,+ last_activity_at: Option<DateTime<Utc>>,+ description: Option<String>,+ star_count: i64,+ forks_count: i64,+ open_issues_count: i64,+}++#[cfg(test)]+mod test {+ use super::*;++ #[test]+ fn test_repository_name() {+ macro_rules! assert_name {+ ($url:expr => ($owner:expr, $repo: expr)) => {+ assert_eq!(+ RepositoryName::from_url($url),+ Some(RepositoryName {+ owner: $owner,+ repo: $repo+ })+ );+ };+ }++ assert_name!("https://gitlab.com/onur/cratesfyi" => ("onur", "cratesfyi"));+ assert_name!("http://gitlab.com/onur/cratesfyi" => ("onur", "cratesfyi"));+ assert_name!("https://www.gitlab.com/onur/cratesfyi" => ("onur", "cratesfyi"));+ assert_name!("http://www.gitlab.com/onur/cratesfyi" => ("onur", "cratesfyi"));+ assert_name!("https://gitlab.com/onur/cratesfyi.git" => ("onur", "cratesfyi"));+ assert_name!("https://gitlab.com/docopt/docopt.rs" => ("docopt", "docopt.rs"));+ assert_name!("https://gitlab.com/onur23cmD_M_R_L_/crates_fy-i" => (+ "onur23cmD_M_R_L_", "crates_fy-i"+ ));+ assert_name!("https://freedesktop.gitlab.org/test/test" => (+ "test", "test"+ ));+ assert_name!("https://gitlab.freedesktop.org/test/test" => (+ "test", "test"+ ));
We must only support gitlab.com, not other GitLab instances. Otherwise someone could publish a crate with an URL that looks like a GitLab instance and extract our API token.
comment created time in 2 minutes
Pull request review commentrust-lang/docs.rs
+use crate::error::Result;+use crate::{db::Pool, Config};+use chrono::{DateTime, Utc};+use log::{debug, info, trace, warn};+use once_cell::sync::Lazy;+use postgres::Client;+use regex::Regex;+use reqwest::{+ blocking::Client as HttpClient,+ header::{HeaderMap, HeaderValue, ACCEPT, AUTHORIZATION, USER_AGENT},+};+use serde::Deserialize;+use std::collections::{HashMap, HashSet};+use std::sync::Arc;++const APP_USER_AGENT: &str = concat!(+ env!("CARGO_PKG_NAME"),+ " ",+ include_str!(concat!(env!("OUT_DIR"), "/git_version"))+);++pub fn graphql_update(ids: &[&str]) -> String {+ format!(+ "\+query {{+ projects(ids: {:?}) {{
We should be using GraphQL variables instead of generating the query dynamically.
comment created time in 5 minutes
push eventrust-lang/crates.io-index
commit sha a0ebf957bf6babbd3f20bb69b7e7c5d324044222
Updating crate `pea2pea#0.15.0`
push time in a minute
pull request commentrust-lang/rust
Force vec![] to expression position only
:pushpin: Commit c127ed6e97535e4a20873d6cfe4fff364a2b9d9b has been approved by oli-obk,m-ou-se
<!-- @bors r=oli-obk,m-ou-se c127ed6e97535e4a20873d6cfe4fff364a2b9d9b --> <!-- homu: {"type":"Approved","sha":"c127ed6e97535e4a20873d6cfe4fff364a2b9d9b","approver":"oli-obk,m-ou-se"} -->
comment created time in 2 minutes
pull request commentrust-lang/rust
Force vec![] to expression position only
Thanks!
@bors r=oli-obk,m-ou-se
comment created time in 2 minutes
pull request commentrust-lang/rust
Re-enable all num tests on WASM
:hourglass: Testing commit e10555c65897e32de6621588946caa8f3c33720b with merge 7d3818152d8ab5649d2e5cc6d7851ed7c03055fe... <!-- homu: {"type":"BuildStarted","head_sha":"e10555c65897e32de6621588946caa8f3c33720b","merge_sha":"7d3818152d8ab5649d2e5cc6d7851ed7c03055fe"} -->
comment created time in 3 minutes
pull request commentrust-lang/rust
:broken_heart: Test failed - checks-actions <!-- homu: {"type":"BuildFailed","builder_url":"https://github.com/rust-lang-ci/rust/runs/1716662000","builder_name":"checks-actions"} -->
comment created time in 4 minutes
pull request commentrust-lang/rust
Could another PR have introduced those errors?
Maybe. I just searched for salsa because of that error message, which popped up a lot in rust-analyzer. Note that it failed on --target arm-unknown-linux-gnueabihf, which might be relevant.
If you think this PR is not the source of the problem, we can just try it again and see what happens.
comment created time in 4 minutes
push eventrust-lang/crates.io-index
commit sha 260a1cdd51630db07979784c5b0ea83618bb46be
Updating crate `liverust_lib#0.1.9`
push time in 6 minutes
pull request commentrust-lang/rust
Allow Trait inheritance with cycles on associated types take 2
@jyn514 what commit should I use with rustup-toolchain-install-master? Neither 03c0e58d18d39a8210f559d280998d06d8f160bc nor 455a0e1d91d3f56c4752a9f035e3622c614b7240 work.
comment created time in 7 minutes
push eventrust-lang/crates.io-index
commit sha 882ceb679ef47292a63d03ae0d743d91273a2b43
Updating crate `vec_mut_scan#0.4.0`
push time in 9 minutes
pull request commentrust-lang/rust
:hourglass: Testing commit 94ec9f91cf8d1f6f8931d8e546de0bcbdb982e96 with merge 8f749e7508ffa94a8c4e69e189caf4bd079cc5e2... <!-- homu: {"type":"BuildStarted","head_sha":"94ec9f91cf8d1f6f8931d8e546de0bcbdb982e96","merge_sha":"8f749e7508ffa94a8c4e69e189caf4bd079cc5e2"} -->
comment created time in 10 minutes
push eventrust-lang/rust
commit sha d199c5b0206b964abadc8539ad4e959ec8e9413b
BTreeMap: expose new_internal function and sanitize from_new_internal
commit sha d51cf9601c714a8383aecade7c98559dd4831625
Auto merge of #81083 - ssomers:btree_drainy_refactor_1, r=Mark-Simulacrum BTreeMap: expose new_internal function and sanitize from_new_internal `new_internal` is the functional core of the imperative `push_internal_level`, and `from_new_internal` can easily do a proper job instead of returning a half-baked node. r? `@Mark-Simulacrum`
push time in 10 minutes
PR merged rust-lang/rust
new_internal is the functional core of the imperative push_internal_level, and from_new_internal can easily do a proper job instead of returning a half-baked node.
r? @Mark-Simulacrum
pr closed time in 10 minutes
pull request commentrust-lang/rust
BTreeMap: expose new_internal function and sanitize from_new_internal
:sunny: Test successful - checks-actions Approved by: Mark-Simulacrum Pushing d51cf9601c714a8383aecade7c98559dd4831625 to master... <!-- homu: {"type":"BuildCompleted","approved_by":"Mark-Simulacrum","base_ref":"master","builders":{"checks-actions":"https://github.com/rust-lang-ci/rust/runs/1716647337"},"merge_sha":"d51cf9601c714a8383aecade7c98559dd4831625"} -->
comment created time in 10 minutes
pull request commentrust-lang/rust
Probably https://github.com/rust-lang/rust/pull/80732.
comment created time in 11 minutes
pull request commentrust-lang/rust
salsa compiles fine with the latest nightly. Could another PR have introduced those errors?
comment created time in 12 minutes
pull request commentrust-lang/rust
:pushpin: Commit 94ec9f91cf8d1f6f8931d8e546de0bcbdb982e96 has been approved by m-ou-se
<!-- @bors r=m-ou-se 94ec9f91cf8d1f6f8931d8e546de0bcbdb982e96 --> <!-- homu: {"type":"Approved","sha":"94ec9f91cf8d1f6f8931d8e546de0bcbdb982e96","approver":"m-ou-se"} -->
comment created time in 13 minutes
pull request commentrust-lang/rust
@bors r+ p=13 rollup=never
comment created time in 13 minutes
PR opened rust-lang/rust
Successful merges:
- #79298 (correctly deal with late-bound lifetimes in anon consts)
- #80031 (resolve: Reject ambiguity built-in attr vs different built-in attr)
- #80201 (Add benchmark and fast path for BufReader::read_exact)
- #80635 (Improve diagnostics when closure doesn't meet trait bound)
- #80765 (resolve: Simplify collection of traits in scope)
- #80932 (Allow downloading LLVM on Windows and MacOS)
- #80983 (Remove is_dllimport_foreign_item definition from cg_ssa)
- #81064 (Support non-stage0 check)
- #81071 (rustc_parse_format: Fix character indices in find_skips)
- #81082 (BTreeMap: clean up a few more comments)
- #81084 (Use Option::map instead of open-coding it)
- #81095 (Use Option::unwrap_or instead of open-coding it)
- #81107 (Add NonZeroUn::is_power_of_two)
Failed merges:
r? @ghost @rustbot modify labels: rollup <!-- homu-ignore:start --> Create a similar rollup <!-- homu-ignore:end -->
pr created time in 13 minutes
PR closed rust-lang/rust
Successful merges:
- #79298 (correctly deal with late-bound lifetimes in anon consts)
- #80031 (resolve: Reject ambiguity built-in attr vs different built-in attr)
- #80635 (Improve diagnostics when closure doesn't meet trait bound)
- #80732 (Allow Trait inheritance with cycles on associated types take 2)
- #80765 (resolve: Simplify collection of traits in scope)
- #80865 (Use PlaceRef projection abstractions more consistently in rustc_mir)
- #80932 (Allow downloading LLVM on Windows and MacOS)
- #80984 (Update rust-analyzer)
- #81038 (Update Clippy)
- #81064 (Support non-stage0 check)
- #81071 (rustc_parse_format: Fix character indices in find_skips)
- #81082 (BTreeMap: clean up a few more comments)
- #81084 (Use Option::map instead of open-coding it)
- #81095 (Use Option::unwrap_or instead of open-coding it)
Failed merges:
r? @ghost @rustbot modify labels: rollup <!-- homu-ignore:start --> Create a similar rollup <!-- homu-ignore:end -->
pr closed time in 17 minutes
pull request commentrust-lang/rust
@bors r-
This failed in https://github.com/rust-lang/rust/pull/81102#issuecomment-761720245
error: could not compile `salsa`
That seems to be a rust-analyzer dependency.
comment created time in 17 minutes
push eventrust-lang/rustlings
commit sha 0b9220c1fc5ae32438f64bf2f5bf5f47d33e3f3f
Add looks_done method to Exercise to expose a resolution state
commit sha 8bbe4ff1385c5c169c90cd3ff9253f9a91daaf8e
feat(cli): Improve the list command with options, and then some 1. `rustlings list` should now display more than just the exercise names. Information such as file paths and exercises statuses should be displayed. The `--paths` option limits the displayed fields to only the path names; while the `--names` option limits the displayed fields to only exercise names. You can also control which exercises are displayed, by using the `--filter` option, or the `--solved` or `--unsolved` flags. Some use cases: - Fetching pending exercise files with the keyword "conversion" to pass to my editor: ```sh vim $(rustlings list --filter "conversion" --paths --unsolved) ``` - Fetching exercise names with keyword "conversion" to pass to `rustlings run`: ```sh for exercise in $(rustlings list --filter "conversion" --names) do rustlings run ${exercise} done ``` 2. This should also fix #465, and will likely fix #585, as well. That bug mentioned in those issues has to do with the way the `watch` command handler fetches the pending exercises. Going forward, the least recently updated exercises along with all the other exercises in a pending state are fetched.
commit sha e8d1baa4b50faf038bec7629b559a0735173ee80
Merge pull request #599 from AbdouSeck/improve-list-command feat(cli): Improve the list command with options, and then some
push time in 17 minutes
PR merged rust-lang/rustlings
The PR is two-fold:
rustlings listshould now display more than just the exercise names. Information such as file paths and exercises statuses should be displayed. The--pathsoption limits the displayed fields to only the path names; while the--namesoption limits the displayed fields to only exercise names. You can also control which exercises are displayed, by using the--filteroption, or the--solvedor--unsolvedflags.
Sample invocations:
# Display exercises that deal with traits, or enums, or structs.
rustlings list --filter "trait,enum,struct"
# Sample output:
# Name Path Status
# structs1 exercises/structs/structs1.rs Pending
# structs2 exercises/structs/structs2.rs Pending
# structs3 exercises/structs/structs3.rs Pending
# enums1 exercises/enums/enums1.rs Pending
# enums2 exercises/enums/enums2.rs Pending
# enums3 exercises/enums/enums3.rs Pending
# traits1 exercises/traits/traits1.rs Pending
# traits2 exercises/traits/traits2.rs Pending
# Display only exercises pending to be solved
rustlings list --unsolved
# Sample output:
# Name Path Status
# structs2 exercises/structs/structs2.rs Pending
# structs3 exercises/structs/structs3.rs Pending
# enums1 exercises/enums/enums1.rs Pending
# enums2 exercises/enums/enums2.rs Pending
# enums3 exercises/enums/enums3.rs Pending
# modules1 exercises/modules/modules1.rs Pending
# modules2 exercises/modules/modules2.rs Pending
# collections1 exercises/collections/vec1.rs Pending
# collections2 exercises/collections/vec2.rs Pending
# collections3 exercises/collections/hashmap1.rs Pending
# collections4 exercises/collections/hashmap2.rs Pending
This portion should also close #281.
Some shell utility use cases:
- Fetching pending exercise file paths with the keyword "conversion" to pass to my editor:
vim $(rustlings list --filter "conversion" --paths --unsolved)
- Fetching exercise names with keyword "conversion" to pass to
rustlings run:
for exercise in $(rustlings list --filter "conversion" --names)
do
rustlings run ${exercise}
done
- The PR should also fix #465, and will likely fix #585, as well. The bug mentioned in those issues has to do with the way the
watchcommand handler fetches the pending exercises. Going forward, the least recently updated exercises along with all the other exercises in a pending state are fetched.
@fmoko @jrvidal if you've got some time, I'd love an eye on this. If there is anyone else with some experience on (or interest in) the CLI component, please feel free to let me know what you think.
Thanks, Abdou
pr closed time in 17 minutes
issue closedrust-lang/rustlings
Hey,
First of all, thank you very much for this instructive course, which helped me to get back into rust very fast.
I noticed that, when I finished the second-to-last exercise, from_str, that rustlings watch immediately told me that I was finished, although I did not touch as_ref_mut. Do you know why that might be?
I am running rustlings 4.1.0 and rustc 1.47.0
Best regards
Anton
closed time in 17 minutes
AntonOellererissue closedrust-lang/rustlings
POC:
- Finish exercises in order while
rustlings watch. - When the current working exercise is
move_semantics2.rs, make a copy of it. - The new file
move_semantics2 copy.rsis generated, then rustlings outputs★ All exercises completed! ★and exits.
I have not verified the file name in the above process is critical or not. In fact, I am not sure that is an issue ... Maybe I should not do that?
Env:
- rustc 1.44.1 (c7087fe00 2020-06-17)
- cargo 1.44.1 (88ba85757 2020-06-11)
- rustlings 4.0.0
closed time in 17 minutes
Wycersissue closedrust-lang/rustlings
Follow `rustlings watch` with editor by opening source files in the same order
First of all, thank you so much for rustlings, this is an amazing project! A well thought-out practice test suite is worth a thousand tutorials.
I got lazy from having to close nvim and open it on the next file to keep up with rustlings watch, so I came up with a little kludge:
cd rustlings # local rustlings repo
rg '^path = "' info.toml | rg '"(.*)"' --only-matching --replace='$1' --null | xargs -J {} nvim '{}'
This is the same as typing:
nvim file1 file2 file3 ...
When you do this, nvim opens one file at a time, and you can navigate between them with :previous and :next.
So after passing the tests for one exercise, I delete the // I AM NOT DONE line, then type :wn on nvim, which saves the file (w is for "write") and opens the next one (n).
That's enough keystroke savings for me, but if this sounds like an interesting idea, maybe it could be turned into a rustlings watch editor command that calls $EDITOR in succession with the file that's currently failing rustlings watch, so both can be kept running side by side in sync.
closed time in 17 minutes
agentofuserpull request commentrust-lang/rust
Fix `unused_unsafe` label with `unsafe_block_in_unsafe_fn
I guess at this point I just as well might.^^ r? @RalfJung
comment created time in 21 minutes
push eventrust-lang/crates.io-index
commit sha 531a1c796ae213a321e5f8d9f512e9ff41d84277
Updating crate `minhook-sys#0.1.1`
push time in 24 minutes
pull request commentrust-lang/rust
Force vec![] to expression position only
Apart from the fact that I accidentally committed it, I have no idea. I'll fix it asap, thanks for noticing :)
leave implementation details like this out of the root of the crate.
Fair enough :)
comment created time in 25 minutes