Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Auto-correct #1456

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions dylint/src/package_options/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use anyhow::{Context, Result};
use dylint_internal::{clone, git2::Repository};
use std::{cell::RefCell, rc::Rc};
use tempfile::{tempdir, TempDir};

const RUST_CLIPPY_URL: &str = "https://github.com/rust-lang/rust-clippy";

// smoelius: `thread_local!` because `git2::Repository` cannot be shared between threads safely.
thread_local! {
static TMPDIR_AND_REPOSITORY: RefCell<Option<(TempDir, Rc<Repository>)>> = const { RefCell::new(None) };
}

pub fn clippy_repository(quiet: bool) -> Result<Rc<Repository>> {
TMPDIR_AND_REPOSITORY.with_borrow_mut(|cell| {
if let Some((_, repository)) = cell {
return Ok(repository.clone());
}

let tempdir = tempdir().with_context(|| "`tempdir` failed")?;

let repository = clone(RUST_CLIPPY_URL, "master", tempdir.path(), quiet).map(Rc::new)?;

cell.replace((tempdir, repository.clone()));

Ok(repository)
})
}

pub fn parse_as_nightly(channel: &str) -> Option<[u32; 3]> {
channel.strip_prefix("nightly-").and_then(parse_date)
}

fn parse_date(date_str: &str) -> Option<[u32; 3]> {
date_str
.split('-')
.map(str::parse::<u32>)
.map(Result::ok)
.collect::<Option<Vec<_>>>()
.map(<[u32; 3]>::try_from)
.and_then(Result::ok)
}
17 changes: 3 additions & 14 deletions dylint/src/package_options/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ use std::{
use tempfile::tempdir;
use walkdir::WalkDir;

mod common;
use common::parse_as_nightly;

mod revs;
use revs::Revs;

Expand Down Expand Up @@ -158,17 +161,3 @@ pub fn upgrade_package(opts: &opts::Dylint, upgrade_opts: &opts::Upgrade) -> Res

Ok(())
}

fn parse_as_nightly(channel: &str) -> Option<[u32; 3]> {
channel.strip_prefix("nightly-").and_then(parse_date)
}

fn parse_date(date_str: &str) -> Option<[u32; 3]> {
date_str
.split('-')
.map(str::parse::<u32>)
.map(Result::ok)
.collect::<Option<Vec<_>>>()
.map(<[u32; 3]>::try_from)
.and_then(Result::ok)
}
44 changes: 21 additions & 23 deletions dylint/src/package_options/revs.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use super::common::clippy_repository;
use anyhow::{anyhow, Context, Result};
use dylint_internal::{
clippy_utils::{clippy_utils_package_version, toolchain_channel},
clone,
git2::{Commit, ObjectType, Oid, Repository},
};
use if_chain::if_chain;
use tempfile::{tempdir, TempDir};

const RUST_CLIPPY_URL: &str = "https://github.com/rust-lang/rust-clippy";
use std::rc::Rc;

#[derive(Debug, Eq, PartialEq)]
pub struct Rev {
Expand All @@ -17,30 +15,28 @@ pub struct Rev {
}

pub struct Revs {
tempdir: TempDir,
repository: Repository,
repository: Rc<Repository>,
}

pub struct RevIter<'revs> {
revs: &'revs Revs,
repository: Rc<Repository>,
commit: Commit<'revs>,
curr_rev: Option<Rev>,
}

impl Revs {
pub fn new(quiet: bool) -> Result<Self> {
let tempdir = tempdir().with_context(|| "`tempdir` failed")?;

let repository = clone(RUST_CLIPPY_URL, "master", tempdir.path(), quiet)?;
let repository = clippy_repository(quiet)?;

Ok(Self {
tempdir,
repository,
})
Ok(Self { repository })
}

#[allow(clippy::iter_not_returning_iterator)]
pub fn iter(&self) -> Result<RevIter> {
let path = self
.repository
.workdir()
.ok_or_else(|| anyhow!("Could not get working directory"))?;
let object = {
let head = self.repository.head()?;
let oid = head.target().ok_or_else(|| anyhow!("Could not get HEAD"))?;
Expand All @@ -49,11 +45,11 @@ impl Revs {
let commit = object
.as_commit()
.ok_or_else(|| anyhow!("Object is not a commit"))?;
let version = clippy_utils_package_version(self.tempdir.path())?;
let channel = toolchain_channel(self.tempdir.path())?;
let version = clippy_utils_package_version(path)?;
let channel = toolchain_channel(path)?;
let oid = commit.id();
Ok(RevIter {
revs: self,
repository: self.repository.clone(),
commit: commit.clone(),
curr_rev: Some(Rev {
version,
Expand All @@ -79,6 +75,10 @@ impl Iterator for RevIter<'_> {
let curr_rev = if let Some(rev) = self.curr_rev.take() {
rev
} else {
let path = self
.repository
.workdir()
.ok_or_else(|| anyhow!("Could not get working directory"))?;
// smoelius: Note that this is not `git log`'s default behavior. Rather, this
// behavior corresponds to:
// git log --first-parent
Expand All @@ -88,20 +88,18 @@ impl Iterator for RevIter<'_> {
} else {
return Ok(None);
};
self.revs
.repository
self.repository
.checkout_tree(commit.as_object(), None)
.with_context(|| {
format!("`checkout_tree` failed for `{:?}`", commit.as_object())
})?;
self.revs
.repository
self.repository
.set_head_detached(commit.id())
.with_context(|| {
format!("`set_head_detached` failed for `{}`", commit.id())
})?;
let version = clippy_utils_package_version(self.revs.tempdir.path())?;
let channel = toolchain_channel(self.revs.tempdir.path())?;
let version = clippy_utils_package_version(path)?;
let channel = toolchain_channel(path)?;
let oid = commit.id();
Rev {
version,
Expand Down
Loading