Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a JSON output mode to cargo package. #14262

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions src/bin/cargo/commands/package.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
use crate::command_prelude::*;

use cargo::ops::{self, PackageOpts};
use cargo::ops::{self, ListMode, PackageOpts};
use clap::builder::PossibleValuesParser;

pub fn cli() -> Command {
subcommand("package")
.about("Assemble the local package into a distributable tarball")
.arg(
flag(
opt(
"list",
"Print files included in a package without making one",
)
.short('l'),
.short('l')
.default_missing_value("basic")
.num_args(0..=1)
.require_equals(true)
.value_name("MODE")
.value_parser(PossibleValuesParser::new(["basic", "json"])),
)
.arg(flag(
"no-verify",
Expand Down Expand Up @@ -56,7 +62,11 @@ pub fn exec(gctx: &mut GlobalContext, args: &ArgMatches) -> CliResult {
&PackageOpts {
gctx,
verify: !args.flag("no-verify"),
list: args.flag("list"),
list: match args.get_one::<String>("list").map(String::as_str) {
Some("json") => ListMode::Json,
Some(_) => ListMode::Basic,
None => ListMode::Disabled,
},
check_metadata: !args.flag("no-metadata"),
allow_dirty: args.flag("allow-dirty"),
to_package: specs,
Expand Down
62 changes: 47 additions & 15 deletions src/cargo/ops/cargo_package.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::collections::{BTreeSet, HashMap};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fs::{self, File};
use std::io::prelude::*;
use std::io::SeekFrom;
Expand Down Expand Up @@ -31,7 +31,7 @@ use unicase::Ascii as UncasedAscii;
#[derive(Clone)]
pub struct PackageOpts<'gctx> {
pub gctx: &'gctx GlobalContext,
pub list: bool,
pub list: ListMode,
pub check_metadata: bool,
pub allow_dirty: bool,
pub verify: bool,
Expand All @@ -42,6 +42,25 @@ pub struct PackageOpts<'gctx> {
pub cli_features: CliFeatures,
}

/// Possible values for the --list flag.
#[derive(Clone, Copy)]
pub enum ListMode {
/// Basic mode: just output the paths that would be included in the package file.
Basic,

/// JSON mode: output the paths that would be included and their sources.
Json,

/// Listing disabled; normal package operation.
Disabled,
}

impl ListMode {
fn is_disabled(&self) -> bool {
matches!(self, &ListMode::Disabled)
}
}

const ORIGINAL_MANIFEST_FILE: &str = "Cargo.toml.orig";
const VCS_INFO_FILE: &str = ".cargo_vcs_info.json";

Expand All @@ -55,13 +74,15 @@ struct ArchiveFile {
contents: FileContents,
}

#[derive(Serialize)]
enum FileContents {
/// Absolute path to the file on disk to add to the archive.
OnDisk(PathBuf),
/// Generates a file.
Generated(GeneratedFile),
}

#[derive(Serialize)]
enum GeneratedFile {
/// Generates `Cargo.toml` by rewriting the original.
Manifest,
Expand Down Expand Up @@ -98,7 +119,7 @@ pub fn package_one(
pkg: &Package,
opts: &PackageOpts<'_>,
) -> CargoResult<FileLock> {
assert!(!opts.list);
assert!(opts.list.is_disabled());

let ar_files = prepare_archive(ws, pkg, opts)?;
let tarball = create_package(ws, pkg, ar_files)?;
Expand Down Expand Up @@ -194,25 +215,36 @@ pub fn package(ws: &Workspace<'_>, opts: &PackageOpts<'_>) -> CargoResult<Option
};
let ar_files = prepare_archive(ws, pkg, &opts)?;

if opts.list {
for ar_file in ar_files {
drop_println!(ws.gctx(), "{}", ar_file.rel_str);
match opts.list {
ListMode::Basic => {
for ar_file in ar_files {
drop_println!(ws.gctx(), "{}", ar_file.rel_str);
}
}
} else {
let tarball = create_package(ws, pkg, ar_files)?;
if opts.verify {
run_verify(ws, pkg, &tarball, &opts)
.with_context(|| "failed to verify package tarball")?;
ListMode::Json => {
let file_list: BTreeMap<PathBuf, FileContents> = ar_files
.into_iter()
.map(|ar_file| (ar_file.rel_path, ar_file.contents))
.collect();

serde_json::to_writer_pretty(ws.gctx().shell().out(), &file_list)?;
}
ListMode::Disabled => {
let tarball = create_package(ws, pkg, ar_files)?;
if opts.verify {
run_verify(ws, pkg, &tarball, &opts)
.with_context(|| "failed to verify package tarball")?;
}
dsts.push(tarball);
}
dsts.push(tarball);
}
}

if opts.list {
if opts.list.is_disabled() {
Ok(Some(dsts))
} else {
// We're just listing, so there's no file output
Ok(None)
} else {
Ok(Some(dsts))
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub use self::cargo_fetch::{fetch, FetchOptions};
pub use self::cargo_install::{install, install_list};
pub use self::cargo_new::{init, new, NewOptions, NewProjectKind, VersionControl};
pub use self::cargo_output_metadata::{output_metadata, ExportInfo, OutputMetadataOptions};
pub use self::cargo_package::{check_yanked, package, package_one, PackageOpts};
pub use self::cargo_package::{check_yanked, package, package_one, ListMode, PackageOpts};
pub use self::cargo_pkgid::pkgid;
pub use self::cargo_read_manifest::read_package;
pub use self::cargo_run::run;
Expand Down
3 changes: 2 additions & 1 deletion src/cargo/ops/registry/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ use crate::core::PackageIdSpecQuery;
use crate::core::SourceId;
use crate::core::Workspace;
use crate::ops;
use crate::ops::ListMode;
use crate::ops::PackageOpts;
use crate::ops::Packages;
use crate::sources::source::QueryKind;
Expand Down Expand Up @@ -149,7 +150,7 @@ pub fn publish(ws: &Workspace<'_>, opts: &PublishOpts<'_>) -> CargoResult<()> {
&PackageOpts {
gctx: opts.gctx,
verify: opts.verify,
list: false,
list: ListMode::Disabled,
check_metadata: true,
allow_dirty: opts.allow_dirty,
to_package: Packages::Default,
Expand Down
4 changes: 4 additions & 0 deletions src/doc/man/cargo-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ There is no guarantee that the source code in the tarball matches the VCS inform
Print files included in a package without making one.
{{/option}}

{{#option "`-l=json`" "`--list=json`" }}
Output the files included in a package in JSON form, without actually building the package.
{{/option}}

{{#option "`--no-verify`" }}
Don't verify the contents by building them.
{{/option}}
Expand Down
4 changes: 4 additions & 0 deletions src/doc/man/generated_txt/cargo-package.txt
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ OPTIONS
-l, --list
Print files included in a package without making one.

-l=json, --list=json
Output the files included in a package in JSON form, without
actually building the package.

--no-verify
Don’t verify the contents by building them.

Expand Down
5 changes: 5 additions & 0 deletions src/doc/src/commands/cargo-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ There is no guarantee that the source code in the tarball matches the VCS inform
<dd class="option-desc">Print files included in a package without making one.</dd>


<dt class="option-term" id="option-cargo-package--l=json"><a class="option-anchor" href="#option-cargo-package--l=json"></a><code>-l=json</code></dt>
<dt class="option-term" id="option-cargo-package---list=json"><a class="option-anchor" href="#option-cargo-package---list=json"></a><code>--list=json</code></dt>
<dd class="option-desc">Output the files included in a package in JSON form, without actually building the package.</dd>


<dt class="option-term" id="option-cargo-package---no-verify"><a class="option-anchor" href="#option-cargo-package---no-verify"></a><code>--no-verify</code></dt>
<dd class="option-desc">Don’t verify the contents by building them.</dd>

Expand Down
6 changes: 6 additions & 0 deletions src/etc/man/cargo-package.1
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,12 @@ There is no guarantee that the source code in the tarball matches the VCS inform
Print files included in a package without making one.
.RE
.sp
\fB\-l=json\fR,
\fB\-\-list=json\fR
.RS 4
Output the files included in a package in JSON form, without actually building the package.
.RE
.sp
\fB\-\-no\-verify\fR
.RS 4
Don\[cq]t verify the contents by building them.
Expand Down
Loading