Skip to content

Commit e17f2b1

Browse files
bail on existing version | modify test
1 parent bf4a71b commit e17f2b1

File tree

2 files changed

+44
-17
lines changed

2 files changed

+44
-17
lines changed

src/cargo/ops/registry/publish.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,35 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
139139
)?;
140140
verify_dependencies(pkg, &registry, source_ids.original)?;
141141

142+
// Bail before packaging and uploading if same version already exists in the registry
143+
144+
let mut source = SourceConfigMap::empty(opts.gctx)?.load(reg_ids.original, &HashSet::new())?;
145+
146+
let query = Dependency::parse(pkg.name(), Some(&ver), reg_ids.original)?;
147+
148+
let _lock = opts
149+
.gctx
150+
.acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;
151+
152+
let duplicate_query = loop {
153+
match source.query_vec(&query, QueryKind::Exact) {
154+
std::task::Poll::Ready(res) => {
155+
break res?;
156+
}
157+
std::task::Poll::Pending => source.block_until_ready()?,
158+
}
159+
};
160+
161+
drop(_lock);
162+
163+
if !duplicate_query.is_empty() {
164+
bail!(
165+
"crate {} already has version {}. Aborting publish.",
166+
pkg.name(),
167+
pkg.version()
168+
);
169+
}
170+
142171
// Prepare a tarball, with a non-suppressible warning if metadata
143172
// is missing since this is being put online.
144173
let tarball = ops::package_one(

tests/testsuite/publish.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -132,14 +132,18 @@ You may press ctrl-c to skip waiting; the crate should be available shortly.
132132

133133
#[cargo_test]
134134
fn duplicate_version() {
135+
let arc: Arc<Mutex<u32>> = Arc::new(Mutex::new(0));
135136
let registry_dupl = RegistryBuilder::new()
136137
.http_api()
137138
.http_index()
138-
.add_responder("/api/v1/crates/new", move |_req, _server| Response {
139-
code: 200,
140-
headers: vec![],
141-
body: br#"{"errors": [{"detail": "crate version `0.0.1` is already uploaded"}]}"#
142-
.to_vec(),
139+
.add_responder("/index/3/f/foo", move |req, server| {
140+
let mut lock = arc.lock().unwrap();
141+
*lock += 1;
142+
if *lock <= 1 {
143+
server.not_found(req)
144+
} else {
145+
server.index(req)
146+
}
143147
})
144148
.build();
145149

@@ -158,23 +162,17 @@ fn duplicate_version() {
158162
.file("src/main.rs", "fn main() {}")
159163
.build();
160164

165+
p.cargo("publish")
166+
.replace_crates_io(registry_dupl.index_url())
167+
.without_status()
168+
.run();
169+
161170
p.cargo("publish")
162171
.replace_crates_io(registry_dupl.index_url())
163172
.with_stderr(
164173
"\
165174
[UPDATING] crates.io index
166-
[WARNING] [..]
167-
See [..]
168-
[PACKAGING] foo v0.0.1 ([CWD])
169-
[VERIFYING] foo v0.0.1 ([CWD])
170-
[..]
171-
[..]
172-
[..]
173-
[UPLOADING] foo v0.0.1 ([CWD])
174-
error: failed to publish [..]
175-
176-
Caused by:
177-
[..] is already uploaded
175+
error: crate foo already has version 0.0.1. Aborting publish.
178176
",
179177
)
180178
.with_status(101)

0 commit comments

Comments
 (0)