Skip to content
Open
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
1,803 changes: 1,454 additions & 349 deletions Cargo.lock

Large diffs are not rendered by default.

15 changes: 9 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ keywords = ["single-file", "bundle", "merge", "expand", "cli"]
categories = ["command-line-utilities"]
readme = "README.md"
license = "MIT"
edition = "2018"

[badges]
travis-ci = { repository = "slava-sh/rust-bundler" }
Expand All @@ -20,11 +21,13 @@ name = "bundle"
path = "src/main.rs"

[dependencies]
cargo_metadata = "0.5"
quote = "0.5"
rustfmt = "0.10"
syn = { version = "0.13", features = ["full", "extra-traits", "visit-mut"] }
cargo_metadata = "0.12.1"
syn = { version = "1.0.51", features = ["full", "extra-traits", "visit-mut"] }
rustfmt-nightly = { version = "1.4.21", optional = true }

[dev-dependencies]
goldenfile = "0.5"
assert_cli = "0.5"
goldenfile = "1.1.0"
assert_cli = "0.6.3"

[features]
inner_rustfmt = ["rustfmt-nightly"]
62 changes: 43 additions & 19 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
//! See [README.md](https://github.com/slava-sh/rust-bundler/blob/master/README.md)
extern crate cargo_metadata;
extern crate quote;
extern crate rustfmt;
extern crate syn;

use std::fs::File;
use std::io::{Read, Sink};
use std::io::Read;
use std::mem;
use std::path::Path;

use quote::ToTokens;
use syn::export::ToTokens;
use syn::punctuated::Punctuated;
use syn::visit_mut::VisitMut;

/// Creates a single-source-file version of a Cargo package.
pub fn bundle<P: AsRef<Path>>(package_path: P) -> String {
let manifest_path = package_path.as_ref().join("Cargo.toml");
let metadata = cargo_metadata::metadata_deps(Some(&manifest_path), false)
.expect("failed to obtain cargo metadata");
let targets = &metadata.packages[0].targets;
let mut cmd = cargo_metadata::MetadataCommand::new();
cmd.manifest_path(&manifest_path);
let metadata = cmd.exec().unwrap();
let targets = &metadata.root_package().unwrap().targets;
let bins: Vec<_> = targets.iter().filter(|t| target_is(t, "bin")).collect();
assert!(bins.len() != 0, "no binary target found");
assert!(bins.len() == 1, "multiple binary targets not supported");
Expand All @@ -30,14 +26,14 @@ pub fn bundle<P: AsRef<Path>>(package_path: P) -> String {
.parent()
.expect("lib.src_path has no parent");
let crate_name = &lib.name;
eprintln!("expanding binary {}", bin.src_path);
eprintln!("expanding binary {:?}", bin.src_path);
let code = read_file(&Path::new(&bin.src_path)).expect("failed to read binary target source");
let mut file = syn::parse_file(&code).expect("failed to parse binary target source");
Expander {
base_path,
crate_name,
}.visit_file_mut(&mut file);
let code = file.into_tokens().to_string();
let code = file.into_token_stream().to_string();
prettify(code)
}

Expand Down Expand Up @@ -166,7 +162,7 @@ fn is_extern_crate(item: &syn::Item, crate_name: &str) -> bool {

fn path_starts_with(path: &syn::Path, segment: &str) -> bool {
if let Some(el) = path.segments.first() {
if el.value().ident == segment {
if el.ident == segment {
return true;
}
}
Expand All @@ -190,11 +186,39 @@ fn read_file(path: &Path) -> Option<String> {
Some(buf)
}

#[cfg(feature = "inner_rustfmt")]
fn prettify(code: String) -> String {
let config = Default::default();
let out: Option<&mut Sink> = None;
let result =
rustfmt::format_input(rustfmt::Input::Text(code), &config, out).expect("rustfmt failed");
let code = &result.1.first().expect("rustfmt returned no code").1;
format!("{}", code)
use rustfmt_nightly::{Input, Session, Config, EmitMode, Verbosity};
let mut out = Vec::with_capacity(code.len() * 2);
{
let mut config = Config::default();
config.set().emit_mode(EmitMode::Stdout);
config.set().verbose(Verbosity::Quiet);
let input = Input::Text(code.into());
let mut session = Session::new(config, Some(&mut out));
session.format(input).expect("rustfmt failed");
}
String::from_utf8(out).unwrap()
}

#[cfg(not(feature = "inner_rustfmt"))]
fn prettify(code: String) -> String {
use std::io::Write;
use std::process;
let mut command = process::Command::new("rustfmt")
.stdin(process::Stdio::piped())
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.spawn()
.expect("Failed to spawn rustfmt process");
{
let mut stdin = command.stdin.take().unwrap();
write!(stdin, "{}", code).unwrap();
}
let out = command.wait_with_output().unwrap();
if !out.status.success() {
panic!("rustfmt failed");
}
let stdout = out.stdout;
String::from_utf8(stdout).unwrap()
}
2 changes: 1 addition & 1 deletion tests/bin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use assert_cli::Assert;
#[test]
fn usage() {
Assert::main_binary()
.with_args(&[])
.with_args(&[] as &[&str])
.fails()
.stderr()
.contains("Usage: bundle")
Expand Down
1 change: 1 addition & 0 deletions tests/testdata/input/complicated/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
name = "complicated"
version = "0.1.0"
authors = ["Slava Shklyaev <[email protected]>"]
edition = "2018"

[lib]
name = "my_lib"
Expand Down
2 changes: 1 addition & 1 deletion tests/testdata/input/complicated/src/b.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use a;
use crate::a;

pub fn b() {
a::a();
Expand Down
6 changes: 3 additions & 3 deletions tests/testdata/input/complicated/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
extern crate my_lib;

use my_lib::{a, b};
use my_lib::{a, b, c};

fn main() {
a::a();
::b::b();
::my_lib::c::d::d();
self::b::b();
self::c::d::d();
}
1 change: 1 addition & 0 deletions tests/testdata/input/hello-world/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
name = "hello-world"
version = "0.1.0"
authors = ["Slava Shklyaev <[email protected]>"]
edition = "2018"

[dependencies]
1 change: 1 addition & 0 deletions tests/testdata/input/simple/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
name = "simple"
version = "0.1.0"
authors = ["Slava Shklyaev <[email protected]>"]
edition = "2018"

[dependencies]
6 changes: 3 additions & 3 deletions tests/testdata/output/complicated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pub mod a {
}
}
pub mod b {
use a;
use crate::a;
pub fn b() {
a::a();
}
Expand All @@ -18,6 +18,6 @@ pub mod c {
}
fn main() {
a::a();
::b::b();
::c::d::d();
self::b::b();
self::c::d::d();
}