mirror of
https://github.com/rust-lang/cargo.git
synced 2025-09-28 11:20:36 +00:00
Implement cargo-package
This command will assemble the current package into a tarball ready for uploading to the cargo registry. Currently no further verification is done beyond packaging the local repository into a tarball, but in the future this could execute other operations such as api stability tools.
This commit is contained in:
parent
6f765b358f
commit
69c16fc6c8
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -4,8 +4,10 @@ version = "0.0.1-pre"
|
||||
dependencies = [
|
||||
"docopt 0.6.0 (git+https://github.com/burntsushi/docopt.rs#fc7ba2f1a5a351f7874257d880223d2ff5c75d36)",
|
||||
"docopt_macros 0.6.0 (git+https://github.com/burntsushi/docopt.rs#fc7ba2f1a5a351f7874257d880223d2ff5c75d36)",
|
||||
"flate2 0.0.1 (git+https://github.com/alexcrichton/flate2-rs#12593d1b9ccf09c2eabac176a6e233b171eed843)",
|
||||
"hamcrest 0.1.0 (git+https://github.com/carllerche/hamcrest-rust.git#f0fd1546b0a7a278a12658ab8602b5c827cc3a42)",
|
||||
"semver 0.0.1 (git+https://github.com/rust-lang/semver#c78b40d7fdf8acd99b503e6ce394fbcf9eb8982f)",
|
||||
"tar 0.0.1 (git+https://github.com/alexcrichton/tar-rs#689bbc003ae47feae5bc99c53b56736e4ad994ba)",
|
||||
"toml 0.1.0 (git+https://github.com/alexcrichton/toml-rs#8c128cb550ba66d4962cd81acca93857c605eaa0)",
|
||||
"url 0.1.0 (git+https://github.com/servo/rust-url#23fb9ec22cca9d643ad2cce9894a947c005b7fe2)",
|
||||
]
|
||||
@ -28,6 +30,11 @@ name = "encoding"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/lifthrasiir/rust-encoding#7e7950ddbd46428a439db3e2594fa78f0972ef2e"
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/alexcrichton/flate2-rs#12593d1b9ccf09c2eabac176a6e233b171eed843"
|
||||
|
||||
[[package]]
|
||||
name = "hamcrest"
|
||||
version = "0.1.0"
|
||||
@ -38,6 +45,11 @@ name = "semver"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/rust-lang/semver#c78b40d7fdf8acd99b503e6ce394fbcf9eb8982f"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/alexcrichton/tar-rs#689bbc003ae47feae5bc99c53b56736e4ad994ba"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.1.0"
|
||||
|
@ -26,6 +26,12 @@ git = "https://github.com/servo/rust-url"
|
||||
[dependencies.semver]
|
||||
git = "https://github.com/rust-lang/semver"
|
||||
|
||||
[dependencies.tar]
|
||||
git = "https://github.com/alexcrichton/tar-rs"
|
||||
|
||||
[dependencies.flate2]
|
||||
git = "https://github.com/alexcrichton/flate2-rs"
|
||||
|
||||
[[bin]]
|
||||
name = "cargo"
|
||||
test = false
|
||||
|
@ -59,6 +59,7 @@ macro_rules! each_subcommand( ($macro:ident) => ({
|
||||
$macro!(git_checkout)
|
||||
$macro!(locate_project)
|
||||
$macro!(new)
|
||||
$macro!(package)
|
||||
$macro!(read_manifest)
|
||||
$macro!(run)
|
||||
$macro!(test)
|
||||
|
31
src/bin/package.rs
Normal file
31
src/bin/package.rs
Normal file
@ -0,0 +1,31 @@
|
||||
use docopt;
|
||||
use cargo::ops;
|
||||
use cargo::core::{MultiShell};
|
||||
use cargo::util::{CliResult, CliError};
|
||||
use cargo::util::important_paths::find_root_manifest_for_cwd;
|
||||
|
||||
docopt!(Options, "
|
||||
Assemble a the local package into a distributable tarball
|
||||
|
||||
Usage:
|
||||
cargo package [options]
|
||||
|
||||
Options:
|
||||
-h, --help Print this message
|
||||
--manifest-path PATH Path to the manifest to compile
|
||||
-v, --verbose Use verbose output
|
||||
|
||||
", flag_manifest_path: Option<String>)
|
||||
|
||||
pub fn execute(options: Options, shell: &mut MultiShell) -> CliResult<Option<()>> {
|
||||
shell.set_verbose(options.flag_verbose);
|
||||
let Options {
|
||||
flag_manifest_path,
|
||||
..
|
||||
} = options;
|
||||
|
||||
let root = try!(find_root_manifest_for_cwd(flag_manifest_path.clone()));
|
||||
ops::package(&root, shell).map(|_| None).map_err(|err| {
|
||||
CliError::from_boxed(err, 101)
|
||||
})
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use semver;
|
||||
use std::hash::Hash;
|
||||
use std::fmt::{mod, Show, Formatter};
|
||||
use collections::hash;
|
||||
use std::hash;
|
||||
use serialize::{
|
||||
Encodable,
|
||||
Encoder,
|
||||
|
@ -5,19 +5,19 @@
|
||||
#![feature(default_type_params)]
|
||||
#![deny(warnings)]
|
||||
|
||||
extern crate collections;
|
||||
extern crate debug;
|
||||
extern crate glob;
|
||||
extern crate regex;
|
||||
extern crate semver;
|
||||
extern crate serialize;
|
||||
extern crate term;
|
||||
extern crate time;
|
||||
extern crate url;
|
||||
#[phase(plugin)] extern crate regex_macros;
|
||||
#[phase(plugin, link)] extern crate log;
|
||||
|
||||
extern crate semver;
|
||||
extern crate docopt;
|
||||
extern crate flate2;
|
||||
extern crate tar;
|
||||
extern crate url;
|
||||
extern crate toml;
|
||||
#[cfg(test)] extern crate hamcrest;
|
||||
|
||||
|
60
src/cargo/ops/cargo_package.rs
Normal file
60
src/cargo/ops/cargo_package.rs
Normal file
@ -0,0 +1,60 @@
|
||||
use std::io::File;
|
||||
|
||||
use tar::Archive;
|
||||
use flate2::{GzBuilder, BestCompression};
|
||||
|
||||
use core::source::Source;
|
||||
use core::{Package, MultiShell};
|
||||
use sources::PathSource;
|
||||
use util::{CargoResult, human, internal, ChainError, Require};
|
||||
|
||||
pub fn package(manifest_path: &Path,
|
||||
shell: &mut MultiShell) -> CargoResult<Path> {
|
||||
let mut src = try!(PathSource::for_path(&manifest_path.dir_path()));
|
||||
try!(src.update());
|
||||
let pkg = try!(src.get_root_package());
|
||||
|
||||
let filename = format!("{}-{}.tar.gz", pkg.get_name(), pkg.get_version());
|
||||
let dst = pkg.get_manifest_path().dir_path().join(filename);
|
||||
try!(shell.status("Packaging", pkg.get_package_id().to_string()));
|
||||
try!(tar(&pkg, &src, shell, &dst).chain_error(|| {
|
||||
human("failed to prepare local package for uploading")
|
||||
}));
|
||||
|
||||
Ok(dst)
|
||||
}
|
||||
|
||||
fn tar(pkg: &Package, src: &PathSource, shell: &mut MultiShell,
|
||||
dst: &Path) -> CargoResult<()> {
|
||||
|
||||
if dst.exists() {
|
||||
return Err(human(format!("destination already exists: {}",
|
||||
dst.display())))
|
||||
}
|
||||
let tmpfile = try!(File::create(dst));
|
||||
|
||||
// Prepare the encoder and its header
|
||||
let encoder = GzBuilder::new().filename(dst.filename().unwrap())
|
||||
.writer(tmpfile, BestCompression);
|
||||
|
||||
// Put all package files into a compressed archive
|
||||
let ar = Archive::new(encoder);
|
||||
for file in try!(src.list_files(pkg)).iter() {
|
||||
let relative = file.path_relative_from(&dst.dir_path()).unwrap();
|
||||
let relative = try!(relative.as_str().require(|| {
|
||||
human(format!("non-utf8 path in source directory: {}",
|
||||
relative.display()))
|
||||
}));
|
||||
let mut file = try!(File::open(file));
|
||||
try!(shell.verbose(|shell| {
|
||||
shell.status("Archiving", relative.as_slice())
|
||||
}));
|
||||
let path = format!("{}-{}/{}", pkg.get_name(),
|
||||
pkg.get_version(), relative);
|
||||
try!(ar.append(path.as_slice(), &mut file).chain_error(|| {
|
||||
internal(format!("could not archive source file `{}`", relative))
|
||||
}));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
@ -8,6 +8,7 @@ pub use self::cargo_doc::{doc, DocOptions};
|
||||
pub use self::cargo_generate_lockfile::{generate_lockfile, write_resolve};
|
||||
pub use self::cargo_generate_lockfile::{update_lockfile, load_lockfile};
|
||||
pub use self::cargo_test::{run_tests, run_benches, TestOptions};
|
||||
pub use self::cargo_package::package;
|
||||
|
||||
mod cargo_clean;
|
||||
mod cargo_compile;
|
||||
@ -18,3 +19,4 @@ mod cargo_new;
|
||||
mod cargo_doc;
|
||||
mod cargo_generate_lockfile;
|
||||
mod cargo_test;
|
||||
mod cargo_package;
|
||||
|
@ -507,3 +507,4 @@ pub static COMPILING: &'static str = " Compiling";
|
||||
pub static FRESH: &'static str = " Fresh";
|
||||
pub static UPDATING: &'static str = " Updating";
|
||||
pub static DOCTEST: &'static str = " Doc-tests";
|
||||
pub static PACKAGING: &'static str = " Packaging";
|
||||
|
27
tests/test_cargo_package.rs
Normal file
27
tests/test_cargo_package.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use support::{project, execs};
|
||||
use support::{PACKAGING};
|
||||
use hamcrest::{assert_that, existing_file};
|
||||
|
||||
fn setup() {
|
||||
}
|
||||
|
||||
test!(simple {
|
||||
let p = project("foo")
|
||||
.file("Cargo.toml", r#"
|
||||
[project]
|
||||
name = "foo"
|
||||
version = "0.0.1"
|
||||
authors = []
|
||||
"#)
|
||||
.file("src/main.rs", r#"
|
||||
fn main() { println!("hello"); }
|
||||
"#);
|
||||
|
||||
assert_that(p.cargo_process("package"),
|
||||
execs().with_status(0).with_stdout(format!("\
|
||||
{packaging} foo v0.0.1 ({dir})
|
||||
",
|
||||
packaging = PACKAGING,
|
||||
dir = p.url()).as_slice()));
|
||||
assert_that(&p.root().join("foo-0.0.1.tar.gz"), existing_file());
|
||||
})
|
@ -37,3 +37,4 @@ mod test_cargo_compile_plugins;
|
||||
mod test_cargo_doc;
|
||||
mod test_cargo_freshness;
|
||||
mod test_cargo_generate_lockfile;
|
||||
mod test_cargo_package;
|
||||
|
Loading…
x
Reference in New Issue
Block a user