mirror of
https://github.com/rust-lang/cargo
synced 2024-10-02 05:53:53 +00:00
Add documentation for creating test dependencies.
Using `Package` has always been a little unclear to me. I think I understand it now. Maybe this will help.
This commit is contained in:
parent
676d866fee
commit
d970d05f06
|
@ -106,7 +106,7 @@ source, but available on the local filesystem (aka vendoring). Local registries
|
|||
are downloaded ahead of time, typically sync'd with a `Cargo.lock`, and are
|
||||
made up of a set of `*.crate` files and an index like the normal registry is.
|
||||
|
||||
The primary way to manage and crate local registry sources is through the
|
||||
The primary way to manage and create local registry sources is through the
|
||||
[`cargo-local-registry`][cargo-local-registry] subcommand, available on
|
||||
crates.io and can be installed with `cargo install cargo-local-registry`.
|
||||
|
||||
|
|
|
@ -1,3 +1,43 @@
|
|||
/*
|
||||
# Git Testing Support
|
||||
|
||||
## Creating a git dependency
|
||||
`git::new()` is an easy way to create a new git repository containing a
|
||||
project that you can then use as a dependency. It will automatically add all
|
||||
the files you specify in the project and commit them to the repository.
|
||||
Example:
|
||||
|
||||
```
|
||||
let git_project = git::new("dep1", |project| {
|
||||
project
|
||||
.file("Cargo.toml", &basic_manifest("dep1"))
|
||||
.file("src/lib.rs", r#"pub fn f() { println!("hi!"); } "#)
|
||||
}).unwrap();
|
||||
|
||||
// Use the `url()` method to get the file url to the new repository.
|
||||
let p = project()
|
||||
.file("Cargo.toml", &format!(r#"
|
||||
[package]
|
||||
name = "a"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
dep1 = {{ git = '{}' }}
|
||||
"#, git_project.url()))
|
||||
.file("src/lib.rs", "extern crate dep1;")
|
||||
.build();
|
||||
```
|
||||
|
||||
## Manually creating repositories
|
||||
`git::repo()` can be used to create a `RepoBuilder` which provides a way of
|
||||
adding files to a blank repository and committing them.
|
||||
|
||||
If you want to then manipulate the repository (such as adding new files or
|
||||
tags), you can use `git2::Repository::open()` to open the repository and then
|
||||
use some of the helper functions in this file to interact with the repository.
|
||||
|
||||
*/
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -16,6 +56,9 @@ pub struct RepoBuilder {
|
|||
|
||||
pub struct Repository(git2::Repository);
|
||||
|
||||
/// Create a `RepoBuilder` to build a new git repository.
|
||||
///
|
||||
/// Call `build()` to finalize and create the repository.
|
||||
pub fn repo(p: &Path) -> RepoBuilder {
|
||||
RepoBuilder::init(p)
|
||||
}
|
||||
|
@ -35,12 +78,15 @@ impl RepoBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add a file to the repository.
|
||||
pub fn file(self, path: &str, contents: &str) -> RepoBuilder {
|
||||
let mut me = self.nocommit_file(path, contents);
|
||||
me.files.push(PathBuf::from(path));
|
||||
me
|
||||
}
|
||||
|
||||
/// Add a file that will be left in the working directory, but not added
|
||||
/// to the repository.
|
||||
pub fn nocommit_file(self, path: &str, contents: &str) -> RepoBuilder {
|
||||
let dst = self.repo.workdir().unwrap().join(path);
|
||||
t!(fs::create_dir_all(dst.parent().unwrap()));
|
||||
|
@ -48,6 +94,7 @@ impl RepoBuilder {
|
|||
self
|
||||
}
|
||||
|
||||
/// Create the repository and commit the new files.
|
||||
pub fn build(self) -> Repository {
|
||||
{
|
||||
let mut index = t!(self.repo.index());
|
||||
|
@ -80,6 +127,7 @@ impl Repository {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new git repository with a project.
|
||||
pub fn new<F>(name: &str, callback: F) -> Result<Project, ProcessError>
|
||||
where
|
||||
F: FnOnce(ProjectBuilder) -> ProjectBuilder,
|
||||
|
@ -98,6 +146,7 @@ where
|
|||
Ok(git_project)
|
||||
}
|
||||
|
||||
/// Add all files in the working directory to the git index.
|
||||
pub fn add(repo: &git2::Repository) {
|
||||
// FIXME(libgit2/libgit2#2514): apparently add_all will add all submodules
|
||||
// as well, and then fail b/c they're a directory. As a stopgap, we just
|
||||
|
@ -121,6 +170,7 @@ pub fn add(repo: &git2::Repository) {
|
|||
t!(index.write());
|
||||
}
|
||||
|
||||
/// Add a git submodule to the repository.
|
||||
pub fn add_submodule<'a>(
|
||||
repo: &'a git2::Repository,
|
||||
url: &str,
|
||||
|
@ -137,6 +187,7 @@ pub fn add_submodule<'a>(
|
|||
s
|
||||
}
|
||||
|
||||
/// Commit changes to the git repository.
|
||||
pub fn commit(repo: &git2::Repository) -> git2::Oid {
|
||||
let tree_id = t!(t!(repo.index()).write_tree());
|
||||
let sig = t!(repo.signature());
|
||||
|
@ -155,6 +206,7 @@ pub fn commit(repo: &git2::Repository) -> git2::Oid {
|
|||
))
|
||||
}
|
||||
|
||||
/// Create a new tag in the git repository.
|
||||
pub fn tag(repo: &git2::Repository, name: &str) {
|
||||
let head = repo.head().unwrap().target().unwrap();
|
||||
t!(repo.tag(
|
||||
|
|
|
@ -15,6 +15,9 @@ let p = project()
|
|||
.build();
|
||||
```
|
||||
|
||||
If you do not specify a `Cargo.toml` manifest using `file()`, one is
|
||||
automatically created with a project name of `foo` using `basic_manifest()`.
|
||||
|
||||
To run cargo, call the `cargo` method and use the `hamcrest` matchers to check
|
||||
the output.
|
||||
|
||||
|
@ -78,6 +81,34 @@ or overwrite a binary immediately after running it. Under some conditions
|
|||
Windows will fail with errors like "directory not empty" or "failed to remove"
|
||||
or "access is denied".
|
||||
|
||||
## Specifying Dependencies
|
||||
|
||||
You should not write any tests that use the network such as contacting
|
||||
crates.io. Typically, simple path dependencies are the easiest way to add a
|
||||
dependency. Example:
|
||||
|
||||
```
|
||||
let p = project()
|
||||
.file("Cargo.toml", r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
bar = {path = "bar"}
|
||||
"#)
|
||||
.file("src/lib.rs", "extern crate bar;")
|
||||
.file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0"))
|
||||
.file("bar/src/lib.rs", "")
|
||||
.build();
|
||||
```
|
||||
|
||||
If you need to test with registry dependencies, see
|
||||
`support::registry::Package` for creating packages you can depend on.
|
||||
|
||||
If you need to test git dependencies, see `support::git` to create a git
|
||||
dependency.
|
||||
|
||||
*/
|
||||
|
||||
use std::env;
|
||||
|
@ -530,6 +561,8 @@ impl Execs {
|
|||
}
|
||||
|
||||
/// Verify the exit code from the process.
|
||||
///
|
||||
/// This is not necessary if the expected exit code is `0`.
|
||||
pub fn with_status(mut self, expected: i32) -> Execs {
|
||||
self.expect_exit_code = Some(expected);
|
||||
self
|
||||
|
|
|
@ -49,6 +49,70 @@ pub fn alt_api_url() -> Url {
|
|||
Url::from_file_path(&*alt_api_path()).ok().unwrap()
|
||||
}
|
||||
|
||||
/// 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();
|
||||
///
|
||||
/// assert_that(
|
||||
/// p.cargo("run"),
|
||||
/// execs().with_stdout("24"));
|
||||
/// ```
|
||||
pub struct Package {
|
||||
name: String,
|
||||
vers: String,
|
||||
|
@ -128,6 +192,8 @@ pub fn init() {
|
|||
}
|
||||
|
||||
impl Package {
|
||||
/// Create a new package builder.
|
||||
/// Call `publish()` to finalize and build the package.
|
||||
pub fn new(name: &str, vers: &str) -> Package {
|
||||
init();
|
||||
Package {
|
||||
|
@ -143,47 +209,92 @@ impl Package {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn local(&mut self, local: bool) -> &mut Package {
|
||||
self.local = local;
|
||||
self
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn alternative(&mut self, alternative: bool) -> &mut Package {
|
||||
self.alternative = alternative;
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a file to the package.
|
||||
pub fn file(&mut self, name: &str, contents: &str) -> &mut Package {
|
||||
self.files.push((name.to_string(), contents.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn extra_file(&mut self, name: &str, contents: &str) -> &mut Package {
|
||||
self.extra_files
|
||||
.push((name.to_string(), contents.to_string()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a normal dependency. Example:
|
||||
/// ```
|
||||
/// [dependencies]
|
||||
/// foo = {version = "1.0"}
|
||||
/// ```
|
||||
pub fn dep(&mut self, name: &str, vers: &str) -> &mut Package {
|
||||
self.full_dep(name, vers, None, "normal", &[], None)
|
||||
}
|
||||
|
||||
/// Add a dependency with the given feature. Example:
|
||||
/// ```
|
||||
/// [dependencies]
|
||||
/// foo = {version = "1.0", "features": ["feat1", "feat2"]}
|
||||
/// ```
|
||||
pub fn feature_dep(&mut self, name: &str, vers: &str, features: &[&str]) -> &mut Package {
|
||||
self.full_dep(name, vers, None, "normal", features, None)
|
||||
}
|
||||
|
||||
/// Add a platform-specific dependency. Example:
|
||||
/// ```
|
||||
/// [target.'cfg(windows)'.dependencies]
|
||||
/// foo = {version = "1.0"}
|
||||
/// ```
|
||||
pub fn target_dep(&mut self, name: &str, vers: &str, target: &str) -> &mut Package {
|
||||
self.full_dep(name, vers, Some(target), "normal", &[], None)
|
||||
}
|
||||
|
||||
/// Add a dependency to an alternative registry.
|
||||
/// The given registry should be a URI to the alternative registry.
|
||||
pub fn registry_dep(&mut self, name: &str, vers: &str, registry: &str) -> &mut Package {
|
||||
self.full_dep(name, vers, None, "normal", &[], Some(registry))
|
||||
}
|
||||
|
||||
/// Add a dev-dependency. Example:
|
||||
/// ```
|
||||
/// [dev-dependencies]
|
||||
/// foo = {version = "1.0"}
|
||||
/// ```
|
||||
pub fn dev_dep(&mut self, name: &str, vers: &str) -> &mut Package {
|
||||
self.full_dep(name, vers, None, "dev", &[], None)
|
||||
}
|
||||
|
||||
/// Add a build-dependency. Example:
|
||||
/// ```
|
||||
/// [build-dependencies]
|
||||
/// foo = {version = "1.0"}
|
||||
/// ```
|
||||
pub fn build_dep(&mut self, name: &str, vers: &str) -> &mut Package {
|
||||
self.full_dep(name, vers, None, "build", &[], None)
|
||||
}
|
||||
|
@ -208,11 +319,18 @@ impl Package {
|
|||
self
|
||||
}
|
||||
|
||||
/// Specify whether or not the package is "yanked".
|
||||
pub fn yanked(&mut self, yanked: bool) -> &mut Package {
|
||||
self.yanked = yanked;
|
||||
self
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn publish(&self) -> String {
|
||||
self.make_archive();
|
||||
|
||||
|
@ -358,6 +476,7 @@ impl Package {
|
|||
t!(ar.append(&header, contents.as_bytes()));
|
||||
}
|
||||
|
||||
/// Returns the path to the compressed package file.
|
||||
pub fn archive_dst(&self) -> PathBuf {
|
||||
if self.local {
|
||||
registry_path().join(format!("{}-{}.crate", self.name, self.vers))
|
||||
|
|
Loading…
Reference in a new issue