Skip to content

Commit 3baf514

Browse files
bail on existing version | modify test
1 parent 4a2480e commit 3baf514

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
@@ -136,6 +136,35 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
136136
)?;
137137
verify_dependencies(pkg, &registry, reg_ids.original)?;
138138

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

tests/testsuite/publish.rs

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

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

@@ -156,23 +160,17 @@ fn duplicate_version() {
156160
.file("src/main.rs", "fn main() {}")
157161
.build();
158162

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

0 commit comments

Comments
 (0)