2016-03-14 22:45:05 +00:00
|
|
|
use std::collections::HashMap;
|
2015-02-27 01:04:25 +00:00
|
|
|
use std::fs::{self, File};
|
|
|
|
use std::io::prelude::*;
|
2018-03-14 15:17:44 +00:00
|
|
|
use std::path::{Path, PathBuf};
|
2014-10-23 05:05:30 +00:00
|
|
|
|
2018-03-01 17:45:56 +00:00
|
|
|
use cargo::util::Sha256;
|
2015-02-27 01:04:25 +00:00
|
|
|
use flate2::write::GzEncoder;
|
2018-08-28 09:20:03 +00:00
|
|
|
use flate2::Compression;
|
2014-10-23 05:05:30 +00:00
|
|
|
use git2;
|
2018-02-12 20:42:31 +00:00
|
|
|
use hex;
|
2016-01-20 17:07:47 +00:00
|
|
|
use tar::{Builder, Header};
|
2014-10-23 05:05:30 +00:00
|
|
|
use url::Url;
|
|
|
|
|
2018-12-06 19:17:36 +00:00
|
|
|
use crate::support::git::repo;
|
|
|
|
use crate::support::paths;
|
2014-10-23 05:05:30 +00:00
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn registry_path() -> PathBuf {
|
|
|
|
paths::root().join("registry")
|
|
|
|
}
|
|
|
|
pub fn registry() -> Url {
|
|
|
|
Url::from_file_path(&*registry_path()).ok().unwrap()
|
|
|
|
}
|
2018-07-17 02:20:39 +00:00
|
|
|
pub fn api_path() -> PathBuf {
|
|
|
|
paths::root().join("api")
|
|
|
|
}
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn dl_path() -> PathBuf {
|
|
|
|
paths::root().join("dl")
|
|
|
|
}
|
|
|
|
pub fn dl_url() -> Url {
|
|
|
|
Url::from_file_path(&*dl_path()).ok().unwrap()
|
|
|
|
}
|
|
|
|
pub fn alt_registry_path() -> PathBuf {
|
|
|
|
paths::root().join("alternative-registry")
|
|
|
|
}
|
|
|
|
pub fn alt_registry() -> Url {
|
|
|
|
Url::from_file_path(&*alt_registry_path()).ok().unwrap()
|
|
|
|
}
|
|
|
|
pub fn alt_dl_path() -> PathBuf {
|
|
|
|
paths::root().join("alt_dl")
|
|
|
|
}
|
2017-12-18 23:22:04 +00:00
|
|
|
pub fn alt_dl_url() -> String {
|
2017-12-19 00:45:24 +00:00
|
|
|
let base = Url::from_file_path(&*alt_dl_path()).ok().unwrap();
|
|
|
|
format!("{}/{{crate}}/{{version}}/{{crate}}-{{version}}.crate", base)
|
2017-12-18 23:22:04 +00:00
|
|
|
}
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn alt_api_path() -> PathBuf {
|
|
|
|
paths::root().join("alt_api")
|
|
|
|
}
|
|
|
|
pub fn alt_api_url() -> Url {
|
|
|
|
Url::from_file_path(&*alt_api_path()).ok().unwrap()
|
|
|
|
}
|
2014-10-23 05:05:30 +00:00
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// A builder for creating a new package in a registry.
|
|
|
|
///
|
|
|
|
/// This uses "source replacement" using an automatically generated
|
|
|
|
/// `.cargo/config` file to ensure that dependencies will use these packages
|
|
|
|
/// instead of contacting crates.io. See `source-replacement.md` for more
|
|
|
|
/// details on how source replacement works.
|
|
|
|
///
|
|
|
|
/// Call `publish` to finalize and create the package.
|
|
|
|
///
|
|
|
|
/// If no files are specified, an empty `lib.rs` file is automatically created.
|
|
|
|
///
|
|
|
|
/// The `Cargo.toml` file is automatically generated based on the methods
|
|
|
|
/// called on `Package` (for example, calling `dep()` will add to the
|
|
|
|
/// `[dependencies]` automatically). You may also specify a `Cargo.toml` file
|
|
|
|
/// to override the generated one.
|
|
|
|
///
|
|
|
|
/// This supports different registry types:
|
|
|
|
/// - Regular source replacement that replaces `crates.io` (the default).
|
|
|
|
/// - A "local registry" which is a subset for vendoring (see
|
|
|
|
/// `Package::local`).
|
|
|
|
/// - An "alternative registry" which requires specifying the registry name
|
|
|
|
/// (see `Package::alternative`).
|
|
|
|
///
|
|
|
|
/// This does not support "directory sources". See `directory.rs` for
|
|
|
|
/// `VendorPackage` which implements directory sources.
|
|
|
|
///
|
|
|
|
/// # Example
|
|
|
|
/// ```
|
|
|
|
/// // Publish package "a" depending on "b".
|
|
|
|
/// Package::new("a", "1.0.0")
|
|
|
|
/// .dep("b", "1.0.0")
|
|
|
|
/// .file("src/lib.rs", r#"
|
|
|
|
/// extern crate b;
|
|
|
|
/// pub fn f() -> i32 { b::f() * 2 }
|
|
|
|
/// "#)
|
|
|
|
/// .publish();
|
|
|
|
///
|
|
|
|
/// // Publish package "b".
|
|
|
|
/// Package::new("b", "1.0.0")
|
|
|
|
/// .file("src/lib.rs", r#"
|
|
|
|
/// pub fn f() -> i32 { 12 }
|
|
|
|
/// "#)
|
|
|
|
/// .publish();
|
|
|
|
///
|
|
|
|
/// // Create a project that uses package "a".
|
|
|
|
/// let p = project()
|
|
|
|
/// .file("Cargo.toml", r#"
|
|
|
|
/// [package]
|
|
|
|
/// name = "foo"
|
|
|
|
/// version = "0.0.1"
|
|
|
|
///
|
|
|
|
/// [dependencies]
|
|
|
|
/// a = "1.0"
|
|
|
|
/// "#)
|
|
|
|
/// .file("src/main.rs", r#"
|
|
|
|
/// extern crate a;
|
|
|
|
/// fn main() { println!("{}", a::f()); }
|
|
|
|
/// "#)
|
|
|
|
/// .build();
|
|
|
|
///
|
2018-08-29 06:37:21 +00:00
|
|
|
/// p.cargo("run").with_stdout("24").run();
|
2018-08-24 22:09:38 +00:00
|
|
|
/// ```
|
2015-11-11 02:08:06 +00:00
|
|
|
pub struct Package {
|
|
|
|
name: String,
|
|
|
|
vers: String,
|
2016-03-14 22:45:05 +00:00
|
|
|
deps: Vec<Dependency>,
|
2015-11-11 02:08:06 +00:00
|
|
|
files: Vec<(String, String)>,
|
2017-09-14 17:07:15 +00:00
|
|
|
extra_files: Vec<(String, String)>,
|
2015-11-11 02:08:06 +00:00
|
|
|
yanked: bool,
|
2016-03-14 22:45:05 +00:00
|
|
|
features: HashMap<String, Vec<String>>,
|
2016-02-05 23:14:17 +00:00
|
|
|
local: bool,
|
2017-08-30 05:55:31 +00:00
|
|
|
alternative: bool,
|
2016-03-14 22:45:05 +00:00
|
|
|
}
|
|
|
|
|
2018-09-07 16:37:06 +00:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Dependency {
|
2016-03-14 22:45:05 +00:00
|
|
|
name: String,
|
|
|
|
vers: String,
|
|
|
|
kind: String,
|
|
|
|
target: Option<String>,
|
|
|
|
features: Vec<String>,
|
2017-10-22 07:44:11 +00:00
|
|
|
registry: Option<String>,
|
2018-09-07 16:37:06 +00:00
|
|
|
package: Option<String>,
|
|
|
|
optional: bool,
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
|
|
|
|
Add sha256 checksums to the lockfile
This commit changes how lock files are encoded by checksums for each package in
the lockfile to the `[metadata]` section. The previous commit implemented the
ability to redirect sources, but the core assumption there was that a package
coming from two different locations was always the same. An inevitable case,
however, is that a source gets corrupted or, worse, ships a modified version of
a crate to introduce instability between two "mirrors".
The purpose of adding checksums will be to resolve this discrepancy. Each crate
coming from crates.io will now record its sha256 checksum in the lock file. When
a lock file already exists, the new checksum for a crate will be checked against
it, and if they differ compilation will be aborted. Currently only registry
crates will have sha256 checksums listed, all other sources do not have
checksums at this time.
The astute may notice that if the lock file format is changing, then a lock file
generated by a newer Cargo might be mangled by an older Cargo. In anticipation
of this, however, all Cargo versions published support a `[metadata]` section of
the lock file which is transparently carried forward if encountered. This means
that older Cargos compiling with a newer lock file will not verify checksums in
the lock file, but they will carry forward the checksum information and prevent
it from being removed.
There are, however, a few situations where problems may still arise:
1. If an older Cargo takes a newer lockfile (with checksums) and updates it with
a modified `Cargo.toml` (e.g. a package was added, removed, or updated), then
the `[metadata]` section will not be updated appropriately. This modification
would require a newer Cargo to come in and update the checksums for such a
modification.
2. Today Cargo can only calculate checksums for registry sources, but we may
eventually want to support other sources like git (or just straight-up path
sources). If future Cargo implements support for this sort of checksum, then
it's the same problem as above where older Cargos will not know how to keep
the checksum in sync
2016-02-03 19:04:07 +00:00
|
|
|
pub fn init() {
|
2014-11-21 17:36:18 +00:00
|
|
|
let config = paths::home().join(".cargo/config");
|
2016-05-26 00:06:25 +00:00
|
|
|
t!(fs::create_dir_all(config.parent().unwrap()));
|
2015-11-11 02:08:06 +00:00
|
|
|
if fs::metadata(&config).is_ok() {
|
2018-03-14 15:17:44 +00:00
|
|
|
return;
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
2018-03-14 15:17:44 +00:00
|
|
|
t!(t!(File::create(&config)).write_all(
|
|
|
|
format!(
|
|
|
|
r#"
|
2014-10-23 05:05:30 +00:00
|
|
|
[registry]
|
2018-07-17 02:20:39 +00:00
|
|
|
token = "api-token"
|
2016-02-03 18:54:07 +00:00
|
|
|
|
|
|
|
[source.crates-io]
|
|
|
|
registry = 'https://wut'
|
|
|
|
replace-with = 'dummy-registry'
|
|
|
|
|
|
|
|
[source.dummy-registry]
|
|
|
|
registry = '{reg}'
|
2017-08-30 05:55:31 +00:00
|
|
|
|
|
|
|
[registries.alternative]
|
|
|
|
index = '{alt}'
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
reg = registry(),
|
|
|
|
alt = alt_registry()
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.as_bytes()
|
2018-03-14 15:17:44 +00:00
|
|
|
));
|
2014-10-23 05:05:30 +00:00
|
|
|
|
|
|
|
// Init a new registry
|
2017-07-22 03:12:21 +00:00
|
|
|
let _ = repo(®istry_path())
|
2018-03-14 15:17:44 +00:00
|
|
|
.file(
|
|
|
|
"config.json",
|
|
|
|
&format!(
|
|
|
|
r#"
|
2016-02-03 18:54:07 +00:00
|
|
|
{{"dl":"{0}","api":"{0}"}}
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
dl_url()
|
|
|
|
),
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.build();
|
2016-02-03 18:54:07 +00:00
|
|
|
fs::create_dir_all(dl_path().join("api/v1/crates")).unwrap();
|
2017-08-30 05:55:31 +00:00
|
|
|
|
|
|
|
// Init an alt registry
|
|
|
|
repo(&alt_registry_path())
|
2018-03-14 15:17:44 +00:00
|
|
|
.file(
|
|
|
|
"config.json",
|
|
|
|
&format!(
|
|
|
|
r#"
|
2017-12-18 23:22:04 +00:00
|
|
|
{{"dl":"{}","api":"{}"}}
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
alt_dl_url(),
|
|
|
|
alt_api_url()
|
|
|
|
),
|
2018-12-08 11:19:47 +00:00
|
|
|
)
|
|
|
|
.build();
|
2017-12-18 23:22:04 +00:00
|
|
|
fs::create_dir_all(alt_api_path().join("api/v1/crates")).unwrap();
|
2014-10-23 05:05:30 +00:00
|
|
|
}
|
|
|
|
|
2015-11-11 02:08:06 +00:00
|
|
|
impl Package {
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Create a new package builder.
|
|
|
|
/// Call `publish()` to finalize and build the package.
|
2015-11-11 02:08:06 +00:00
|
|
|
pub fn new(name: &str, vers: &str) -> Package {
|
|
|
|
init();
|
|
|
|
Package {
|
|
|
|
name: name.to_string(),
|
|
|
|
vers: vers.to_string(),
|
|
|
|
deps: Vec::new(),
|
|
|
|
files: Vec::new(),
|
2017-09-14 17:07:15 +00:00
|
|
|
extra_files: Vec::new(),
|
2015-11-11 02:08:06 +00:00
|
|
|
yanked: false,
|
2016-03-14 22:45:05 +00:00
|
|
|
features: HashMap::new(),
|
2016-02-05 23:14:17 +00:00
|
|
|
local: false,
|
2017-08-30 05:55:31 +00:00
|
|
|
alternative: false,
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
2014-10-23 05:05:30 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Call with `true` to publish in a "local registry".
|
|
|
|
///
|
|
|
|
/// See `source-replacement.html#local-registry-sources` for more details
|
|
|
|
/// on local registries. See `local_registry.rs` for the tests that use
|
|
|
|
/// this.
|
2016-02-05 23:14:17 +00:00
|
|
|
pub fn local(&mut self, local: bool) -> &mut Package {
|
|
|
|
self.local = local;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Call with `true` to publish in an "alternative registry".
|
|
|
|
///
|
|
|
|
/// The name of the alternative registry is called "alternative".
|
|
|
|
///
|
|
|
|
/// See `unstable.html#alternate-registries` for more details on
|
|
|
|
/// alternative registries. See `alt_registry.rs` for the tests that use
|
|
|
|
/// this.
|
2017-08-30 05:55:31 +00:00
|
|
|
pub fn alternative(&mut self, alternative: bool) -> &mut Package {
|
|
|
|
self.alternative = alternative;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a file to the package.
|
2015-11-11 02:08:06 +00:00
|
|
|
pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {
|
|
|
|
self.files.push((name.to_string(), contents.to_string()));
|
|
|
|
self
|
|
|
|
}
|
2014-10-23 05:05:30 +00:00
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add an "extra" file that is not rooted within the package.
|
|
|
|
///
|
|
|
|
/// Normal files are automatically placed within a directory named
|
|
|
|
/// `$PACKAGE-$VERSION`. This allows you to override that behavior,
|
|
|
|
/// typically for testing invalid behavior.
|
2017-09-14 17:07:15 +00:00
|
|
|
pub fn extra_file(&mut self, name: &str, contents: &str) -> &mut Package {
|
2018-03-14 15:17:44 +00:00
|
|
|
self.extra_files
|
|
|
|
.push((name.to_string(), contents.to_string()));
|
2017-09-14 17:07:15 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a normal dependency. Example:
|
|
|
|
/// ```
|
|
|
|
/// [dependencies]
|
|
|
|
/// foo = {version = "1.0"}
|
|
|
|
/// ```
|
2015-11-11 02:08:06 +00:00
|
|
|
pub fn dep(&mut self, name: &str, vers: &str) -> &mut Package {
|
2018-09-07 16:37:06 +00:00
|
|
|
self.add_dep(&Dependency::new(name, vers))
|
2016-03-14 22:45:05 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a dependency with the given feature. Example:
|
|
|
|
/// ```
|
|
|
|
/// [dependencies]
|
|
|
|
/// foo = {version = "1.0", "features": ["feat1", "feat2"]}
|
|
|
|
/// ```
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn feature_dep(&mut self, name: &str, vers: &str, features: &[&str]) -> &mut Package {
|
2018-09-07 16:37:06 +00:00
|
|
|
self.add_dep(Dependency::new(name, vers).enable_features(features))
|
2016-01-26 00:54:10 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a platform-specific dependency. Example:
|
|
|
|
/// ```
|
|
|
|
/// [target.'cfg(windows)'.dependencies]
|
|
|
|
/// foo = {version = "1.0"}
|
|
|
|
/// ```
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn target_dep(&mut self, name: &str, vers: &str, target: &str) -> &mut Package {
|
2018-09-07 16:37:06 +00:00
|
|
|
self.add_dep(Dependency::new(name, vers).target(target))
|
2017-10-22 06:46:50 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a dependency to an alternative registry.
|
|
|
|
/// The given registry should be a URI to the alternative registry.
|
2018-03-14 15:17:44 +00:00
|
|
|
pub fn registry_dep(&mut self, name: &str, vers: &str, registry: &str) -> &mut Package {
|
2018-09-07 16:37:06 +00:00
|
|
|
self.add_dep(Dependency::new(name, vers).registry(registry))
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
2014-10-23 19:21:08 +00:00
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a dev-dependency. Example:
|
|
|
|
/// ```
|
|
|
|
/// [dev-dependencies]
|
|
|
|
/// foo = {version = "1.0"}
|
|
|
|
/// ```
|
2015-11-11 02:08:06 +00:00
|
|
|
pub fn dev_dep(&mut self, name: &str, vers: &str) -> &mut Package {
|
2018-09-07 16:37:06 +00:00
|
|
|
self.add_dep(Dependency::new(name, vers).dev())
|
2016-03-14 22:45:05 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Add a build-dependency. Example:
|
|
|
|
/// ```
|
|
|
|
/// [build-dependencies]
|
|
|
|
/// foo = {version = "1.0"}
|
|
|
|
/// ```
|
2018-08-24 04:49:43 +00:00
|
|
|
pub fn build_dep(&mut self, name: &str, vers: &str) -> &mut Package {
|
2018-09-07 16:37:06 +00:00
|
|
|
self.add_dep(Dependency::new(name, vers).build())
|
2018-08-24 04:49:43 +00:00
|
|
|
}
|
|
|
|
|
2018-09-07 16:37:06 +00:00
|
|
|
pub fn add_dep(&mut self, dep: &Dependency) -> &mut Package {
|
|
|
|
self.deps.push(dep.clone());
|
2015-11-11 02:08:06 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Specify whether or not the package is "yanked".
|
2015-11-11 02:08:06 +00:00
|
|
|
pub fn yanked(&mut self, yanked: bool) -> &mut Package {
|
|
|
|
self.yanked = yanked;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-09-07 16:37:06 +00:00
|
|
|
/// Add an entry in the `[features]` section
|
|
|
|
pub fn feature(&mut self, name: &str, deps: &[&str]) -> &mut Package {
|
|
|
|
let deps = deps.iter().map(|s| s.to_string()).collect();
|
|
|
|
self.features.insert(name.to_string(), deps);
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Create the package and place it in the registry.
|
|
|
|
///
|
|
|
|
/// This does not actually use Cargo's publishing system, but instead
|
|
|
|
/// manually creates the entry in the registry on the filesystem.
|
|
|
|
///
|
|
|
|
/// Returns the checksum for the package.
|
2016-07-05 17:28:51 +00:00
|
|
|
pub fn publish(&self) -> String {
|
2015-11-11 02:08:06 +00:00
|
|
|
self.make_archive();
|
2014-10-23 05:05:30 +00:00
|
|
|
|
2015-11-11 02:08:06 +00:00
|
|
|
// Figure out what we're going to write into the index
|
2018-08-28 09:20:03 +00:00
|
|
|
let deps = self
|
|
|
|
.deps
|
2018-03-14 15:17:44 +00:00
|
|
|
.iter()
|
|
|
|
.map(|dep| {
|
2018-12-11 01:55:13 +00:00
|
|
|
serde_json::json!({
|
2018-09-07 16:37:06 +00:00
|
|
|
"name": dep.name,
|
|
|
|
"req": dep.vers,
|
|
|
|
"features": dep.features,
|
|
|
|
"default_features": true,
|
|
|
|
"target": dep.target,
|
|
|
|
"optional": dep.optional,
|
|
|
|
"kind": dep.kind,
|
|
|
|
"registry": dep.registry,
|
|
|
|
"package": dep.package,
|
|
|
|
})
|
2018-12-08 11:19:47 +00:00
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
2015-11-11 02:08:06 +00:00
|
|
|
let cksum = {
|
|
|
|
let mut c = Vec::new();
|
2016-05-26 00:06:25 +00:00
|
|
|
t!(t!(File::open(&self.archive_dst())).read_to_end(&mut c));
|
2015-11-11 02:08:06 +00:00
|
|
|
cksum(&c)
|
|
|
|
};
|
2018-12-11 01:55:13 +00:00
|
|
|
let line = serde_json::json!({
|
2017-02-10 20:01:52 +00:00
|
|
|
"name": self.name,
|
|
|
|
"vers": self.vers,
|
|
|
|
"deps": deps,
|
|
|
|
"cksum": cksum,
|
|
|
|
"features": self.features,
|
|
|
|
"yanked": self.yanked,
|
2018-12-08 11:19:47 +00:00
|
|
|
})
|
|
|
|
.to_string();
|
2016-03-14 22:45:05 +00:00
|
|
|
|
2015-11-11 02:08:06 +00:00
|
|
|
let file = match self.name.len() {
|
|
|
|
1 => format!("1/{}", self.name),
|
|
|
|
2 => format!("2/{}", self.name),
|
|
|
|
3 => format!("3/{}/{}", &self.name[..1], self.name),
|
|
|
|
_ => format!("{}/{}/{}", &self.name[0..2], &self.name[2..4], self.name),
|
|
|
|
};
|
|
|
|
|
2018-03-14 15:17:44 +00:00
|
|
|
let registry_path = if self.alternative {
|
|
|
|
alt_registry_path()
|
|
|
|
} else {
|
|
|
|
registry_path()
|
|
|
|
};
|
2017-08-30 05:55:31 +00:00
|
|
|
|
2015-11-11 02:08:06 +00:00
|
|
|
// Write file/line in the index
|
2016-02-05 23:14:17 +00:00
|
|
|
let dst = if self.local {
|
2017-08-30 05:55:31 +00:00
|
|
|
registry_path.join("index").join(&file)
|
2016-02-05 23:14:17 +00:00
|
|
|
} else {
|
2017-08-30 05:55:31 +00:00
|
|
|
registry_path.join(&file)
|
2016-02-05 23:14:17 +00:00
|
|
|
};
|
2015-02-27 01:04:25 +00:00
|
|
|
let mut prev = String::new();
|
|
|
|
let _ = File::open(&dst).and_then(|mut f| f.read_to_string(&mut prev));
|
2016-05-26 00:06:25 +00:00
|
|
|
t!(fs::create_dir_all(dst.parent().unwrap()));
|
2018-03-14 15:17:44 +00:00
|
|
|
t!(t!(File::create(&dst)).write_all((prev + &line[..] + "\n").as_bytes()));
|
2015-11-11 02:08:06 +00:00
|
|
|
|
|
|
|
// Add the new file to the index
|
2016-02-05 23:14:17 +00:00
|
|
|
if !self.local {
|
2017-08-30 05:55:31 +00:00
|
|
|
let repo = t!(git2::Repository::open(®istry_path));
|
2016-02-05 23:14:17 +00:00
|
|
|
let mut index = t!(repo.index());
|
|
|
|
t!(index.add_path(Path::new(&file)));
|
|
|
|
t!(index.write());
|
|
|
|
let id = t!(index.write_tree());
|
|
|
|
|
|
|
|
// Commit this change
|
|
|
|
let tree = t!(repo.find_tree(id));
|
|
|
|
let sig = t!(repo.signature());
|
|
|
|
let parent = t!(repo.refname_to_id("refs/heads/master"));
|
|
|
|
let parent = t!(repo.find_commit(parent));
|
2018-03-14 15:17:44 +00:00
|
|
|
t!(repo.commit(
|
|
|
|
Some("HEAD"),
|
|
|
|
&sig,
|
|
|
|
&sig,
|
|
|
|
"Another commit",
|
|
|
|
&tree,
|
|
|
|
&[&parent]
|
|
|
|
));
|
2016-02-05 23:14:17 +00:00
|
|
|
}
|
2016-07-05 17:28:51 +00:00
|
|
|
|
2018-08-08 22:57:20 +00:00
|
|
|
cksum
|
2014-10-23 05:05:30 +00:00
|
|
|
}
|
|
|
|
|
2015-11-11 02:08:06 +00:00
|
|
|
fn make_archive(&self) {
|
2018-03-14 15:17:44 +00:00
|
|
|
let mut manifest = format!(
|
|
|
|
r#"
|
2015-11-11 02:08:06 +00:00
|
|
|
[package]
|
|
|
|
name = "{}"
|
|
|
|
version = "{}"
|
|
|
|
authors = []
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
self.name, self.vers
|
|
|
|
);
|
2016-03-14 22:45:05 +00:00
|
|
|
for dep in self.deps.iter() {
|
|
|
|
let target = match dep.target {
|
|
|
|
None => String::new(),
|
2016-10-20 22:07:18 +00:00
|
|
|
Some(ref s) => format!("target.'{}'.", s),
|
2016-01-26 00:54:10 +00:00
|
|
|
};
|
2016-03-14 22:45:05 +00:00
|
|
|
let kind = match &dep.kind[..] {
|
2015-11-11 02:08:06 +00:00
|
|
|
"build" => "build-",
|
|
|
|
"dev" => "dev-",
|
2018-03-14 15:17:44 +00:00
|
|
|
_ => "",
|
2016-01-26 00:54:10 +00:00
|
|
|
};
|
2018-03-14 15:17:44 +00:00
|
|
|
manifest.push_str(&format!(
|
|
|
|
r#"
|
2016-01-26 00:54:10 +00:00
|
|
|
[{}{}dependencies.{}]
|
|
|
|
version = "{}"
|
2018-03-14 15:17:44 +00:00
|
|
|
"#,
|
|
|
|
target, kind, dep.name, dep.vers
|
|
|
|
));
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
2014-10-23 05:05:30 +00:00
|
|
|
|
2015-11-11 02:08:06 +00:00
|
|
|
let dst = self.archive_dst();
|
2016-05-26 00:06:25 +00:00
|
|
|
t!(fs::create_dir_all(dst.parent().unwrap()));
|
|
|
|
let f = t!(File::create(&dst));
|
2018-03-14 15:17:44 +00:00
|
|
|
let mut a = Builder::new(GzEncoder::new(f, Compression::default()));
|
2016-01-20 17:07:47 +00:00
|
|
|
self.append(&mut a, "Cargo.toml", &manifest);
|
2016-01-15 14:51:28 +00:00
|
|
|
if self.files.is_empty() {
|
2016-01-20 17:07:47 +00:00
|
|
|
self.append(&mut a, "src/lib.rs", "");
|
2015-11-11 02:08:06 +00:00
|
|
|
} else {
|
|
|
|
for &(ref name, ref contents) in self.files.iter() {
|
2016-01-20 17:07:47 +00:00
|
|
|
self.append(&mut a, name, contents);
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
|
|
|
}
|
2017-09-14 17:07:15 +00:00
|
|
|
for &(ref name, ref contents) in self.extra_files.iter() {
|
|
|
|
self.append_extra(&mut a, name, contents);
|
|
|
|
}
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
|
|
|
|
2016-01-20 17:07:47 +00:00
|
|
|
fn append<W: Write>(&self, ar: &mut Builder<W>, file: &str, contents: &str) {
|
2018-03-14 15:17:44 +00:00
|
|
|
self.append_extra(
|
|
|
|
ar,
|
|
|
|
&format!("{}-{}/{}", self.name, self.vers, file),
|
|
|
|
contents,
|
|
|
|
);
|
2017-09-14 17:07:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn append_extra<W: Write>(&self, ar: &mut Builder<W>, path: &str, contents: &str) {
|
2016-01-20 17:07:47 +00:00
|
|
|
let mut header = Header::new_ustar();
|
2015-11-11 02:08:06 +00:00
|
|
|
header.set_size(contents.len() as u64);
|
2017-09-14 17:07:15 +00:00
|
|
|
t!(header.set_path(path));
|
2015-11-11 02:08:06 +00:00
|
|
|
header.set_cksum();
|
2016-05-26 00:06:25 +00:00
|
|
|
t!(ar.append(&header, contents.as_bytes()));
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
|
|
|
|
2018-08-24 22:09:38 +00:00
|
|
|
/// Returns the path to the compressed package file.
|
2015-11-11 02:08:06 +00:00
|
|
|
pub fn archive_dst(&self) -> PathBuf {
|
2016-02-05 23:14:17 +00:00
|
|
|
if self.local {
|
2018-03-14 15:17:44 +00:00
|
|
|
registry_path().join(format!("{}-{}.crate", self.name, self.vers))
|
2017-12-18 23:22:04 +00:00
|
|
|
} else if self.alternative {
|
|
|
|
alt_dl_path()
|
|
|
|
.join(&self.name)
|
|
|
|
.join(&self.vers)
|
|
|
|
.join(&format!("{}-{}.crate", self.name, self.vers))
|
2016-02-05 23:14:17 +00:00
|
|
|
} else {
|
2017-12-18 23:22:04 +00:00
|
|
|
dl_path().join(&self.name).join(&self.vers).join("download")
|
2016-02-05 23:14:17 +00:00
|
|
|
}
|
2015-11-11 02:08:06 +00:00
|
|
|
}
|
2014-10-23 05:05:30 +00:00
|
|
|
}
|
|
|
|
|
2016-07-05 17:28:51 +00:00
|
|
|
pub fn cksum(s: &[u8]) -> String {
|
2014-10-23 05:05:30 +00:00
|
|
|
let mut sha = Sha256::new();
|
|
|
|
sha.update(s);
|
2018-02-12 20:42:31 +00:00
|
|
|
hex::encode(&sha.finish())
|
2014-10-23 05:05:30 +00:00
|
|
|
}
|
2018-09-07 16:37:06 +00:00
|
|
|
|
|
|
|
impl Dependency {
|
|
|
|
pub fn new(name: &str, vers: &str) -> Dependency {
|
|
|
|
Dependency {
|
|
|
|
name: name.to_string(),
|
|
|
|
vers: vers.to_string(),
|
|
|
|
kind: "normal".to_string(),
|
|
|
|
target: None,
|
|
|
|
features: Vec::new(),
|
|
|
|
package: None,
|
|
|
|
optional: false,
|
|
|
|
registry: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Change this to `[build-dependencies]`
|
|
|
|
pub fn build(&mut self) -> &mut Self {
|
|
|
|
self.kind = "build".to_string();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Change this to `[dev-dependencies]`
|
|
|
|
pub fn dev(&mut self) -> &mut Self {
|
|
|
|
self.kind = "dev".to_string();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Change this to `[target.$target.dependencies]`
|
|
|
|
pub fn target(&mut self, target: &str) -> &mut Self {
|
|
|
|
self.target = Some(target.to_string());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add `registry = $registry` to this dependency
|
|
|
|
pub fn registry(&mut self, registry: &str) -> &mut Self {
|
|
|
|
self.registry = Some(registry.to_string());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add `features = [ ... ]` to this dependency
|
|
|
|
pub fn enable_features(&mut self, features: &[&str]) -> &mut Self {
|
|
|
|
self.features.extend(features.iter().map(|s| s.to_string()));
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add `package = ...` to this dependency
|
|
|
|
pub fn package(&mut self, pkg: &str) -> &mut Self {
|
|
|
|
self.package = Some(pkg.to_string());
|
|
|
|
self
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Change this to an optional dependency
|
|
|
|
pub fn optional(&mut self, optional: bool) -> &mut Self {
|
|
|
|
self.optional = optional;
|
|
|
|
self
|
|
|
|
}
|
|
|
|
}
|