Skip to content

Commit 5861e4b

Browse files
committed
Address PR feedback
1 parent f76e93f commit 5861e4b

11 files changed

Lines changed: 207 additions & 201 deletions

File tree

Cargo.lock

Lines changed: 0 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/uv-cli/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use url::Url;
1414
use uv_cache::CacheArgs;
1515
use uv_configuration::{
1616
ConfigSettingEntry, ExportFormat, IndexStrategy, KeyringProviderType, PackageNameSpecifier,
17-
TargetTriple, TrustedHost, TrustedPublishing, VersionControl,
17+
TargetTriple, TrustedHost, TrustedPublishing, VersionControlSystem,
1818
};
1919
use uv_normalize::{ExtraName, PackageName};
2020
use uv_python::{PythonDownloads, PythonPreference, PythonVersion};
@@ -2373,12 +2373,12 @@ pub struct InitArgs {
23732373
#[arg(long, alias="script", conflicts_with_all=["app", "lib", "package"])]
23742374
pub r#script: bool,
23752375

2376-
/// Initialize a new repository for the given version control system.
2376+
/// Initialize a version control system for the project.
23772377
///
2378-
/// By default, uv will try to initialize a Git repository (`git`).
2379-
/// Use `none` to skip repository initialization.
2380-
#[arg(long, value_enum)]
2381-
pub vcs: Option<VersionControl>,
2378+
/// By default, uv will initialize a Git repository (`git`). Use `--vcs none` to explicitly
2379+
/// avoid initializing a version control system.
2380+
#[arg(long, value_enum, conflicts_with = "script")]
2381+
pub vcs: Option<VersionControlSystem>,
23822382

23832383
/// Do not create a `README.md` file.
23842384
#[arg(long)]

crates/uv-configuration/Cargo.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,11 @@ pypi-types = { workspace = true }
2020
uv-auth = { workspace = true }
2121
uv-cache = { workspace = true }
2222
uv-cache-info = { workspace = true }
23-
uv-fs = { workspace = true }
2423
uv-normalize = { workspace = true }
25-
uv-warnings = { workspace = true }
2624

27-
anyhow = { workspace = true }
2825
clap = { workspace = true, features = ["derive"], optional = true }
2926
either = { workspace = true }
3027
fs-err = { workspace = true }
31-
indoc = { workspace = true }
3228
rustc-hash = { workspace = true }
3329
schemars = { workspace = true, optional = true }
3430
serde = { workspace = true }

crates/uv-configuration/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use sources::*;
1717
pub use target_triple::*;
1818
pub use trusted_host::*;
1919
pub use trusted_publishing::*;
20-
pub use vcs_options::*;
20+
pub use vcs::*;
2121

2222
mod authentication;
2323
mod build_options;
@@ -38,4 +38,4 @@ mod sources;
3838
mod target_triple;
3939
mod trusted_host;
4040
mod trusted_publishing;
41-
mod vcs_options;
41+
mod vcs;

crates/uv-configuration/src/vcs.rs

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use std::io::Write;
2+
use std::path::{Path, PathBuf};
3+
use std::process::{Command, Stdio};
4+
5+
use serde::Deserialize;
6+
use tracing::debug;
7+
8+
#[derive(Debug, thiserror::Error)]
9+
pub enum VersionControlError {
10+
#[error("Attempted to initialize a Git repository, but `git` was not found in PATH")]
11+
GitNotInstalled,
12+
#[error("Failed to initialize Git repository at `{0}`\nstdout: {1}\nstderr: {2}")]
13+
GitInit(PathBuf, String, String),
14+
#[error("`git` command failed")]
15+
GitCommand(#[source] std::io::Error),
16+
#[error(transparent)]
17+
Io(#[from] std::io::Error),
18+
}
19+
20+
/// The version control system to use.
21+
#[derive(Clone, Copy, Debug, PartialEq, Default, Deserialize)]
22+
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
23+
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
24+
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
25+
pub enum VersionControlSystem {
26+
/// Use Git for version control.
27+
#[default]
28+
Git,
29+
/// Do not use any version control system.
30+
None,
31+
}
32+
33+
impl VersionControlSystem {
34+
/// Initializes the VCS system based on the provided path.
35+
pub fn init(&self, path: &Path) -> Result<(), VersionControlError> {
36+
match self {
37+
Self::Git => {
38+
let Ok(git) = which::which("git") else {
39+
return Err(VersionControlError::GitNotInstalled);
40+
};
41+
42+
if path.join(".git").try_exists()? {
43+
debug!("Git repository already exists at: `{}`", path.display());
44+
} else {
45+
let output = Command::new(git)
46+
.arg("init")
47+
.current_dir(path)
48+
.stdout(Stdio::piped())
49+
.stderr(Stdio::piped())
50+
.output()
51+
.map_err(VersionControlError::GitCommand)?;
52+
if !output.status.success() {
53+
let stdout = String::from_utf8_lossy(&output.stdout);
54+
let stderr = String::from_utf8_lossy(&output.stderr);
55+
return Err(VersionControlError::GitInit(
56+
path.to_path_buf(),
57+
stdout.to_string(),
58+
stderr.to_string(),
59+
));
60+
}
61+
}
62+
63+
// Create the `.gitignore`, if it doesn't exist.
64+
match fs_err::OpenOptions::new()
65+
.write(true)
66+
.create_new(true)
67+
.open(path.join(".gitignore"))
68+
{
69+
Ok(mut file) => file.write_all(GITIGNORE.as_bytes())?,
70+
Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => (),
71+
Err(err) => return Err(err.into()),
72+
}
73+
74+
Ok(())
75+
}
76+
Self::None => Ok(()),
77+
}
78+
}
79+
80+
/// Detects the VCS system based on the provided path.
81+
pub fn detect(path: &Path) -> Option<Self> {
82+
// Determine whether the path is inside a Git work tree.
83+
if which::which("git").is_ok_and(|git| {
84+
Command::new(git)
85+
.arg("rev-parse")
86+
.arg("--is-inside-work-tree")
87+
.current_dir(path)
88+
.stdout(Stdio::null())
89+
.stderr(Stdio::null())
90+
.status()
91+
.map(|status| status.success())
92+
.unwrap_or(false)
93+
}) {
94+
return Some(Self::Git);
95+
}
96+
97+
None
98+
}
99+
}
100+
101+
impl std::fmt::Display for VersionControlSystem {
102+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103+
match self {
104+
Self::Git => write!(f, "git"),
105+
Self::None => write!(f, "none"),
106+
}
107+
}
108+
}
109+
110+
const GITIGNORE: &str = "# Python-generated files
111+
__pycache__/
112+
*.py[oc]
113+
build/
114+
dist/
115+
wheels/
116+
*.egg-info
117+
118+
# Virtual environments
119+
.venv
120+
";

crates/uv-configuration/src/vcs_options.rs

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

0 commit comments

Comments
 (0)