Skip to content

Commit 5b59378

Browse files
committed
reduce library API surface
disables any API that is specific to building a binary. Thus CLI-specific API is not exposed in the library API. Also reviewed docs
1 parent 342cd3b commit 5b59378

19 files changed

Lines changed: 371 additions & 245 deletions

File tree

clang-installer/src/cli.rs

Lines changed: 0 additions & 41 deletions
This file was deleted.

clang-installer/src/downloader/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ pub mod native_packages;
1515
pub mod pypi;
1616
pub mod static_dist;
1717

18+
/// An enumeration of possible errors during download operations.
1819
#[derive(Debug, thiserror::Error)]
1920
pub enum DownloadError {
21+
/// An error that occurred while making a request or handling the response.
2022
#[error("Request error: {0}")]
2123
RequestError(#[from] reqwest::Error),
24+
25+
/// An error that occurred during interaction with the file system.
2226
#[error("IO error: {0}")]
2327
IoError(#[from] std::io::Error),
28+
29+
/// An error that describes the mismatch between the expected and actual hash of the downloaded file.
2430
#[error("Hash mismatch for downloaded file. Expected: {expected}, Actual: {actual}")]
2531
HashMismatch { expected: String, actual: String },
2632
}

clang-installer/src/downloader/pypi.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use std::{
1414
use url::Url;
1515
use zip::{ZipArchive, result::ZipError};
1616

17+
/// Errors that occur during PyPI downloads.
1718
#[derive(Debug, thiserror::Error)]
1819
pub enum PyPiDownloadError {
1920
/// Errors that occur during HTTP requests.
@@ -335,6 +336,8 @@ impl WheelTags {
335336
self.platform.is_compatible_with_system()
336337
}
337338
}
339+
340+
/// A downloader for PyPI releases.
338341
pub struct PyPiDownloader;
339342

340343
impl Cacher for PyPiDownloader {}

clang-installer/src/downloader/static_dist.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,36 @@ use crate::{
1515
downloader::{download, hashing::HashAlgorithm},
1616
};
1717

18+
/// An error that can occur while downloading a static binary.
1819
#[derive(Debug, thiserror::Error)]
1920
pub enum StaticDistDownloadError {
21+
/// An error that occurred while downloading the binary.
2022
#[error("Failed to download static binary: {0}")]
2123
DownloadError(#[from] DownloadError),
24+
25+
/// The requested version does not match any available versions.
2226
#[error("The requested version does not match any available versions")]
2327
UnsupportedVersion,
28+
29+
/// The static binaries are only built for x86_64 (amd64) architecture.
2430
#[error("The static binaries are only built for x86_64 (amd64) architecture")]
2531
UnsupportedArchitecture,
32+
33+
/// Failed to parse a URL.
2634
#[error("Failed to parse the URL: {0}")]
2735
UrlParseError(#[from] url::ParseError),
36+
37+
/// Failed to read or write a cache file.
2838
#[error("Failed to read or write cache file: {0}")]
2939
IoError(#[from] std::io::Error),
40+
41+
/// Failed to parse the SHA512 sum file.
3042
#[error("Failed to parse the SHA512 sum file")]
3143
Sha512Corruption,
3244
}
3345

46+
/// A downloader that uses statically linked binary distribution files
47+
/// provided by the cpp-linter team.
3448
pub struct StaticDistDownloader;
3549

3650
impl Cacher for StaticDistDownloader {}
@@ -81,7 +95,7 @@ impl StaticDistDownloader {
8195

8296
/// Downloads the `requested_version` of the specified `tool` from a distribution of statically linked binaries.
8397
///
84-
/// The distribution is maintained at https://github.com/cpp-linter/clang-tools-static-binaries.
98+
/// The distribution is maintained at <https://github.com/cpp-linter/clang-tools-static-binaries>.
8599
/// Supported platforms includes Windows, Linux, and MacOS.
86100
/// Supported architectures is limited to `x86_64` (`amd64`).
87101
pub async fn download_tool(

clang-installer/src/lib.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,5 @@ pub mod utils;
2121
mod version;
2222
pub use version::RequestedVersion;
2323

24-
mod cli;
25-
pub use cli::CliOptions;
26-
2724
mod progress_bar;
2825
pub use progress_bar::ProgressBar;

clang-installer/src/main.rs

Lines changed: 111 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,133 @@
11
use anyhow::Result;
2-
use clang_installer::{CliOptions, RequestedVersion};
2+
use clang_installer::{ClangTool, RequestedVersion};
33
use clap::Parser;
4-
use colored::{Colorize, control::set_override};
5-
use log::{Level, LevelFilter, Log, Metadata, Record};
64

7-
use std::{
8-
collections::HashMap,
9-
env,
10-
io::{Write, stdout},
11-
};
5+
use std::{collections::HashMap, path::PathBuf, str::FromStr};
6+
mod logging {
7+
use colored::{Colorize, control::set_override};
8+
use log::{Level, LevelFilter, Log, Metadata, Record};
9+
use std::{
10+
env,
11+
io::{Write, stdout},
12+
};
1213

13-
struct SimpleLogger;
14+
struct SimpleLogger;
1415

15-
impl SimpleLogger {
16-
fn level_color(level: &Level) -> String {
17-
let name = format!("{:>5}", level.as_str().to_uppercase());
18-
match level {
19-
Level::Error => name.red().bold().to_string(),
20-
Level::Warn => name.yellow().bold().to_string(),
21-
Level::Info => name.green().bold().to_string(),
22-
Level::Debug => name.blue().bold().to_string(),
23-
Level::Trace => name.magenta().bold().to_string(),
16+
impl SimpleLogger {
17+
fn level_color(level: &Level) -> String {
18+
let name = format!("{:>5}", level.as_str().to_uppercase());
19+
match level {
20+
Level::Error => name.red().bold().to_string(),
21+
Level::Warn => name.yellow().bold().to_string(),
22+
Level::Info => name.green().bold().to_string(),
23+
Level::Debug => name.blue().bold().to_string(),
24+
Level::Trace => name.magenta().bold().to_string(),
25+
}
2426
}
2527
}
26-
}
2728

28-
impl Log for SimpleLogger {
29-
fn enabled(&self, metadata: &Metadata) -> bool {
30-
metadata.level() <= log::max_level()
31-
}
29+
impl Log for SimpleLogger {
30+
fn enabled(&self, metadata: &Metadata) -> bool {
31+
metadata.level() <= log::max_level()
32+
}
3233

33-
fn log(&self, record: &Record) {
34-
let mut stdout = stdout().lock();
35-
if record.target() == "CI_LOG_GROUPING" {
36-
// this log is meant to manipulate a CI workflow's log grouping
37-
writeln!(stdout, "{}", record.args()).expect("Failed to write log command to stdout");
38-
stdout
39-
.flush()
40-
.expect("Failed to flush log command in stdout");
41-
} else if self.enabled(record.metadata()) {
42-
let module = record.module_path();
43-
if module
44-
.is_none_or(|v| v.starts_with("clang_installer") || v.starts_with("clang_tools"))
45-
{
46-
writeln!(
47-
stdout,
48-
"[{}]: {}",
49-
Self::level_color(&record.level()),
50-
record.args()
51-
)
52-
.expect("Failed to write log message to stdout");
53-
} else if let Some(module) = module {
54-
writeln!(
55-
stdout,
56-
"[{}]{{{}:{}}}: {}",
57-
Self::level_color(&record.level()),
58-
module,
59-
record.line().unwrap_or_default(),
60-
record.args()
61-
)
62-
.expect("Failed to write detailed log message to stdout");
34+
fn log(&self, record: &Record) {
35+
let mut stdout = stdout().lock();
36+
if record.target() == "CI_LOG_GROUPING" {
37+
// this log is meant to manipulate a CI workflow's log grouping
38+
writeln!(stdout, "{}", record.args())
39+
.expect("Failed to write log command to stdout");
40+
stdout
41+
.flush()
42+
.expect("Failed to flush log command in stdout");
43+
} else if self.enabled(record.metadata()) {
44+
let module = record.module_path();
45+
if module.is_none_or(|v| {
46+
v.starts_with("clang_installer") || v.starts_with("clang_tools")
47+
}) {
48+
writeln!(
49+
stdout,
50+
"[{}]: {}",
51+
Self::level_color(&record.level()),
52+
record.args()
53+
)
54+
.expect("Failed to write log message to stdout");
55+
} else if let Some(module) = module {
56+
writeln!(
57+
stdout,
58+
"[{}]{{{}:{}}}: {}",
59+
Self::level_color(&record.level()),
60+
module,
61+
record.line().unwrap_or_default(),
62+
record.args()
63+
)
64+
.expect("Failed to write detailed log message to stdout");
65+
}
66+
stdout
67+
.flush()
68+
.expect("Failed to flush log message in stdout");
6369
}
64-
stdout
65-
.flush()
66-
.expect("Failed to flush log message in stdout");
6770
}
71+
72+
fn flush(&self) {}
6873
}
6974

70-
fn flush(&self) {}
75+
/// A function to initialize the private `LOGGER`.
76+
///
77+
/// The logging level defaults to [`LevelFilter::Info`].
78+
/// This logs a debug message about [`SetLoggerError`](struct@log::SetLoggerError)
79+
/// if the `LOGGER` is already initialized.
80+
pub fn initialize_logger() {
81+
let logger: SimpleLogger = SimpleLogger;
82+
if env::var("CPP_LINTER_COLOR")
83+
.as_deref()
84+
.is_ok_and(|v| matches!(v, "on" | "1" | "true"))
85+
{
86+
set_override(true);
87+
}
88+
if let Err(e) =
89+
log::set_boxed_logger(Box::new(logger)).map(|()| log::set_max_level(LevelFilter::Info))
90+
{
91+
// logger singleton already instantiated.
92+
// we'll just use whatever the current config is.
93+
log::debug!("{e:?}");
94+
}
95+
}
7196
}
7297

73-
/// A function to initialize the private `LOGGER`.
74-
///
75-
/// The logging level defaults to [`LevelFilter::Info`].
76-
/// This logs a debug message about [`SetLoggerError`](struct@log::SetLoggerError)
77-
/// if the `LOGGER` is already initialized.
78-
pub fn initialize_logger() {
79-
let logger: SimpleLogger = SimpleLogger;
80-
if env::var("CPP_LINTER_COLOR")
81-
.as_deref()
82-
.is_ok_and(|v| matches!(v, "on" | "1" | "true"))
83-
{
84-
set_override(true);
85-
}
86-
if let Err(e) =
87-
log::set_boxed_logger(Box::new(logger)).map(|()| log::set_max_level(LevelFilter::Info))
88-
{
89-
// logger singleton already instantiated.
90-
// we'll just use whatever the current config is.
91-
log::debug!("{e:?}");
92-
}
98+
#[derive(clap::Parser, Debug)]
99+
pub struct CliOptions {
100+
/// The desired version of clang to install.
101+
#[arg(
102+
short,
103+
long,
104+
default_missing_value = "CPP-LINTER-VERSION",
105+
num_args = 0..=1,
106+
value_parser = RequestedVersion::from_str,
107+
default_value = "",
108+
)]
109+
pub version: Option<RequestedVersion>,
110+
/// The clang tool to install.
111+
#[arg(
112+
short,
113+
long,
114+
value_delimiter = ' ',
115+
default_value = "clang-format clang-tidy"
116+
)]
117+
pub tool: Option<Vec<ClangTool>>,
118+
/// The directory where the clang tools should be installed.
119+
#[arg(short, long)]
120+
pub directory: Option<PathBuf>,
121+
/// Force overwriting symlink to the installed binary.
122+
///
123+
/// This will only overwrite an existing symlink.
124+
#[arg(short, long)]
125+
pub force: bool,
93126
}
94127

95128
#[tokio::main]
96129
async fn main() -> Result<()> {
97-
initialize_logger();
130+
logging::initialize_logger();
98131
let options = CliOptions::parse();
99132
log::debug!("{:?}", options);
100133

clang-installer/src/tool.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub enum GetClangVersionError {
5252
SemVerParse(#[from] semver::Error),
5353
}
5454

55+
/// A enumeration of supported clang tools.
5556
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
5657
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
5758
pub enum ClangTool {

clang-installer/src/utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! A utility module for path normalization.
12
use std::path::{Component, Path, PathBuf};
23

34
/// This was copied from [cargo source code](https://github.com/rust-lang/cargo/blob/8cc0cb136772b8f54eafe0d163fcb7226a06af0c/crates/cargo-util/src/paths.rs#L84).

0 commit comments

Comments
 (0)