Skip to content

Commit 70f84bf

Browse files
committed
Rewrite login and registry cleanups.
1 parent d35f1bd commit 70f84bf

File tree

10 files changed

+188
-114
lines changed

10 files changed

+188
-114
lines changed

src/bin/cargo/commands/login.rs

Lines changed: 10 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
use crate::command_prelude::*;
22

3-
use std::io::{self, BufRead};
4-
5-
use cargo::core::{Source, SourceId};
63
use cargo::ops;
7-
use cargo::sources::RegistrySource;
8-
use cargo::util::CargoResultExt;
94

105
pub fn cli() -> App {
116
subcommand("login")
@@ -14,46 +9,19 @@ pub fn cli() -> App {
149
If token is not specified, it will be read from stdin.",
1510
)
1611
.arg(Arg::with_name("token"))
17-
.arg(opt("host", "Host to set the token for").value_name("HOST"))
12+
.arg(
13+
opt("host", "Host to set the token for")
14+
.value_name("HOST")
15+
.hidden(true),
16+
)
1817
.arg(opt("registry", "Registry to use").value_name("REGISTRY"))
1918
}
2019

2120
pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
22-
let registry = args.registry(config)?;
23-
24-
let token = match args.value_of("token") {
25-
Some(token) => token.to_string(),
26-
None => {
27-
let host = match registry {
28-
Some(ref _registry) => {
29-
return Err(failure::format_err!(
30-
"token must be provided when \
31-
--registry is provided."
32-
)
33-
.into());
34-
}
35-
None => {
36-
let src = SourceId::crates_io(config)?;
37-
let mut src = RegistrySource::remote(src, config);
38-
src.update()?;
39-
let config = src.config()?.unwrap();
40-
args.value_of("host")
41-
.map(|s| s.to_string())
42-
.unwrap_or_else(|| config.api.unwrap())
43-
}
44-
};
45-
println!("please visit {}/me and paste the API Token below", host);
46-
let mut line = String::new();
47-
let input = io::stdin();
48-
input
49-
.lock()
50-
.read_line(&mut line)
51-
.chain_err(|| "failed to read stdin")
52-
.map_err(failure::Error::from)?;
53-
line.trim().to_string()
54-
}
55-
};
56-
57-
ops::registry_login(config, token, registry)?;
21+
ops::registry_login(
22+
config,
23+
args.value_of("token").map(String::from),
24+
args.value_of("registry").map(String::from),
25+
)?;
5826
Ok(())
5927
}

src/bin/cargo/commands/package.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
4242
allow_dirty: args.is_present("allow-dirty"),
4343
target: args.target(),
4444
jobs: args.jobs()?,
45-
registry: None,
4645
},
4746
)?;
4847
Ok(())

src/cargo/ops/cargo_package.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ pub struct PackageOpts<'cfg> {
2626
pub verify: bool,
2727
pub jobs: Option<u32>,
2828
pub target: Option<String>,
29-
pub registry: Option<String>,
3029
}
3130

3231
static VCS_INFO_FILE: &'static str = ".cargo_vcs_info.json";

src/cargo/ops/registry.rs

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::BTreeMap;
22
use std::fs::{self, File};
3+
use std::io::{self, BufRead};
34
use std::iter::repeat;
45
use std::str;
56
use std::time::Duration;
@@ -65,6 +66,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
6566
opts.token.clone(),
6667
opts.index.clone(),
6768
opts.registry.clone(),
69+
true,
6870
)?;
6971
verify_dependencies(pkg, reg_id)?;
7072

@@ -80,7 +82,6 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
8082
allow_dirty: opts.allow_dirty,
8183
target: opts.target.clone(),
8284
jobs: opts.jobs,
83-
registry: opts.registry.clone(),
8485
},
8586
)?
8687
.unwrap();
@@ -320,6 +321,7 @@ pub fn registry(
320321
token: Option<String>,
321322
index: Option<String>,
322323
registry: Option<String>,
324+
force_update: bool,
323325
) -> CargoResult<(Registry, SourceId)> {
324326
// Parse all configuration options
325327
let RegistryConfig {
@@ -330,9 +332,17 @@ pub fn registry(
330332
let sid = get_source_id(config, index_config.or(index), registry)?;
331333
let api_host = {
332334
let mut src = RegistrySource::remote(sid, config);
333-
src.update()
334-
.chain_err(|| format!("failed to update {}", sid))?;
335-
(src.config()?).unwrap().api.unwrap()
335+
// Only update the index if the config is not available or `force` is set.
336+
let cfg = src.config();
337+
let cfg = if force_update || cfg.is_err() {
338+
src.update()
339+
.chain_err(|| format!("failed to update {}", sid))?;
340+
cfg.or_else(|_| src.config())?
341+
} else {
342+
cfg.unwrap()
343+
};
344+
cfg.and_then(|cfg| cfg.api)
345+
.ok_or_else(|| failure::format_err!("{} does not support API commands", sid))?
336346
};
337347
let handle = http_handle(config)?;
338348
Ok((Registry::new_handle(api_host, token, handle), sid))
@@ -503,18 +513,51 @@ fn http_proxy_exists(config: &Config) -> CargoResult<bool> {
503513
}
504514
}
505515

506-
pub fn registry_login(config: &Config, token: String, registry: Option<String>) -> CargoResult<()> {
516+
pub fn registry_login(
517+
config: &Config,
518+
token: Option<String>,
519+
reg: Option<String>,
520+
) -> CargoResult<()> {
521+
let (registry, _) = registry(config, token.clone(), None, reg.clone(), false)?;
522+
523+
let token = match token {
524+
Some(token) => token,
525+
None => {
526+
println!(
527+
"please visit {}/me and paste the API Token below",
528+
registry.host()
529+
);
530+
let mut line = String::new();
531+
let input = io::stdin();
532+
input
533+
.lock()
534+
.read_line(&mut line)
535+
.chain_err(|| "failed to read stdin")
536+
.map_err(failure::Error::from)?;
537+
line.trim().to_string()
538+
}
539+
};
540+
507541
let RegistryConfig {
508542
token: old_token, ..
509-
} = registry_configuration(config, registry.clone())?;
543+
} = registry_configuration(config, reg.clone())?;
510544

511545
if let Some(old_token) = old_token {
512546
if old_token == token {
547+
config.shell().status("Login", "already logged in")?;
513548
return Ok(());
514549
}
515550
}
516551

517-
config::save_credentials(config, token, registry)
552+
config::save_credentials(config, token, reg.clone())?;
553+
config.shell().status(
554+
"Login",
555+
format!(
556+
"token for `{}` saved",
557+
reg.as_ref().map_or("crates.io", String::as_str)
558+
),
559+
)?;
560+
Ok(())
518561
}
519562

520563
pub struct OwnersOptions {
@@ -542,6 +585,7 @@ pub fn modify_owners(config: &Config, opts: &OwnersOptions) -> CargoResult<()> {
542585
opts.token.clone(),
543586
opts.index.clone(),
544587
opts.registry.clone(),
588+
true,
545589
)?;
546590

547591
if let Some(ref v) = opts.to_add {
@@ -602,7 +646,7 @@ pub fn yank(
602646
None => failure::bail!("a version must be specified to yank"),
603647
};
604648

605-
let (mut registry, _) = registry(config, token, index, reg)?;
649+
let (mut registry, _) = registry(config, token, index, reg, true)?;
606650

607651
if undo {
608652
config
@@ -658,22 +702,7 @@ pub fn search(
658702
prefix
659703
}
660704

661-
let sid = get_source_id(config, index, reg)?;
662-
663-
let mut regsrc = RegistrySource::remote(sid, config);
664-
let cfg = match regsrc.config() {
665-
Ok(c) => c,
666-
Err(_) => {
667-
regsrc
668-
.update()
669-
.chain_err(|| format!("failed to update {}", &sid))?;
670-
regsrc.config()?
671-
}
672-
};
673-
674-
let api_host = cfg.unwrap().api.unwrap();
675-
let handle = http_handle(config)?;
676-
let mut registry = Registry::new_handle(api_host, None, handle);
705+
let (mut registry, _) = registry(config, None, index, reg, false)?;
677706
let (crates, total_crates) = registry
678707
.search(query, limit)
679708
.chain_err(|| "failed to retrieve search results from the registry")?;

src/cargo/sources/registry/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ pub struct RegistryConfig {
211211

212212
/// API endpoint for the registry. This is what's actually hit to perform
213213
/// operations like yanks, owner modifications, publish new crates, etc.
214+
/// If this is None, the registry does not support API commands.
214215
pub api: Option<String>,
215216
}
216217

src/crates-io/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,12 @@ use url::percent_encoding::{percent_encode, QUERY_ENCODE_SET};
1515
pub type Result<T> = std::result::Result<T, failure::Error>;
1616

1717
pub struct Registry {
18+
/// The base URL for issuing API requests.
1819
host: String,
20+
/// Optional authorization token.
21+
/// If None, commands requiring authorization will fail.
1922
token: Option<String>,
23+
/// Curl handle for issuing requests.
2024
handle: Easy,
2125
}
2226

@@ -51,7 +55,8 @@ pub struct NewCrate {
5155
pub license_file: Option<String>,
5256
pub repository: Option<String>,
5357
pub badges: BTreeMap<String, BTreeMap<String, String>>,
54-
#[serde(default)] pub links: Option<String>,
58+
#[serde(default)]
59+
pub links: Option<String>,
5560
}
5661

5762
#[derive(Serialize)]
@@ -131,6 +136,10 @@ impl Registry {
131136
}
132137
}
133138

139+
pub fn host(&self) -> &str {
140+
&self.host
141+
}
142+
134143
pub fn add_owners(&mut self, krate: &str, owners: &[&str]) -> Result<String> {
135144
let body = serde_json::to_string(&OwnersReq { users: owners })?;
136145
let body = self.put(&format!("/crates/{}/owners", krate), body.as_bytes())?;

tests/testsuite/alt_registry.rs

Lines changed: 95 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::support::registry::{self, alt_api_path, Package};
2-
use crate::support::{basic_manifest, paths, project};
3-
use std::fs::File;
2+
use crate::support::{basic_manifest, git, paths, project};
3+
use std::fs::{self, File};
44
use std::io::Write;
55

66
#[test]
@@ -203,13 +203,13 @@ fn depend_on_alt_registry_depends_on_crates_io() {
203203

204204
p.cargo("build")
205205
.masquerade_as_nightly_cargo()
206-
.with_stderr(&format!(
206+
.with_stderr_unordered(&format!(
207207
"\
208208
[UPDATING] `{alt_reg}` index
209209
[UPDATING] `{reg}` index
210210
[DOWNLOADING] crates ...
211-
[DOWNLOADED] [..] v0.0.1 (registry `[ROOT][..]`)
212-
[DOWNLOADED] [..] v0.0.1 (registry `[ROOT][..]`)
211+
[DOWNLOADED] baz v0.0.1 (registry `[ROOT][..]`)
212+
[DOWNLOADED] bar v0.0.1 (registry `[ROOT][..]`)
213213
[COMPILING] baz v0.0.1 (registry `[ROOT][..]`)
214214
[COMPILING] bar v0.0.1 (registry `[ROOT][..]`)
215215
[COMPILING] foo v0.0.1 ([CWD])
@@ -605,3 +605,93 @@ Caused by:
605605
.run();
606606
}
607607
}
608+
609+
#[test]
610+
fn no_api() {
611+
Package::new("bar", "0.0.1").alternative(true).publish();
612+
// Configure without `api`.
613+
let repo = git2::Repository::open(registry::alt_registry_path()).unwrap();
614+
let cfg_path = registry::alt_registry_path().join("config.json");
615+
fs::write(
616+
cfg_path,
617+
format!(r#"{{"dl": "{}"}}"#, registry::alt_dl_url()),
618+
)
619+
.unwrap();
620+
git::add(&repo);
621+
git::commit(&repo);
622+
623+
// First check that a dependency works.
624+
let p = project()
625+
.file(
626+
"Cargo.toml",
627+
r#"
628+
cargo-features = ["alternative-registries"]
629+
[package]
630+
name = "foo"
631+
version = "0.0.1"
632+
633+
[dependencies.bar]
634+
version = "0.0.1"
635+
registry = "alternative"
636+
"#,
637+
)
638+
.file("src/lib.rs", "")
639+
.build();
640+
641+
p.cargo("build")
642+
.masquerade_as_nightly_cargo()
643+
.with_stderr(&format!(
644+
"\
645+
[UPDATING] `{reg}` index
646+
[DOWNLOADING] crates ...
647+
[DOWNLOADED] bar v0.0.1 (registry `[ROOT][..]`)
648+
[COMPILING] bar v0.0.1 (registry `[ROOT][..]`)
649+
[COMPILING] foo v0.0.1 ([CWD])
650+
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]s
651+
",
652+
reg = registry::alt_registry_path().to_str().unwrap()
653+
))
654+
.run();
655+
656+
// Check all of the API commands.
657+
let err = format!(
658+
"[ERROR] registry `{}` does not support API commands",
659+
registry::alt_registry_path().display()
660+
);
661+
662+
p.cargo("login --registry alternative TOKEN -Zunstable-options")
663+
.masquerade_as_nightly_cargo()
664+
.with_status(101)
665+
.with_stderr_contains(&err)
666+
.run();
667+
668+
p.cargo("publish --registry alternative -Zunstable-options")
669+
.masquerade_as_nightly_cargo()
670+
.with_status(101)
671+
.with_stderr_contains(&err)
672+
.run();
673+
674+
p.cargo("search --registry alternative -Zunstable-options")
675+
.masquerade_as_nightly_cargo()
676+
.with_status(101)
677+
.with_stderr_contains(&err)
678+
.run();
679+
680+
p.cargo("owner --registry alternative -Zunstable-options --list")
681+
.masquerade_as_nightly_cargo()
682+
.with_status(101)
683+
.with_stderr_contains(&err)
684+
.run();
685+
686+
p.cargo("yank --registry alternative -Zunstable-options --vers=0.0.1 bar")
687+
.masquerade_as_nightly_cargo()
688+
.with_status(101)
689+
.with_stderr_contains(&err)
690+
.run();
691+
692+
p.cargo("yank --registry alternative -Zunstable-options --vers=0.0.1 bar")
693+
.masquerade_as_nightly_cargo()
694+
.with_stderr_contains(&err)
695+
.with_status(101)
696+
.run();
697+
}

0 commit comments

Comments
 (0)