Skip to content

Commit

Permalink
feat: check for exposing multiple modules on publish
Browse files Browse the repository at this point in the history
  • Loading branch information
Guria committed Nov 27, 2024
1 parent 5bb0390 commit 369d83f
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ jobs:
run: make test
working-directory: ./test/running_modules

- name: test/multi_namespace
run: ./test.sh
working-directory: ./test/multi_namespace

- name: Test FFI in subdirectories
run: make
working-directory: ./test/subdir_ffi
48 changes: 48 additions & 0 deletions compiler-cli/src/publish.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl PublishCommand {
} = do_build_hex_tarball(&paths, &mut config)?;

check_for_name_squatting(&compile_result)?;
check_for_multiple_top_level_modules(&compile_result, i_am_sure)?;

// Build HTML documentation
let docs_tarball = fs::create_tar_archive(docs::build_documentation(
Expand Down Expand Up @@ -123,6 +124,53 @@ fn check_for_name_squatting(package: &Package) -> Result<(), Error> {
Ok(())
}

fn check_for_multiple_top_level_modules(package: &Package, i_am_sure: bool) -> Result<(), Error> {
// Collect top-level module names
let mut top_level_module_names = package
.modules
.iter()
.filter_map(|module| module.name.split('/').next())
.collect::<Vec<_>>();

// Remove duplicates
top_level_module_names.sort_unstable();
top_level_module_names.dedup();

// If more than one top-level module name is found, prompt for confirmation
if top_level_module_names.len() > 1 {
println!(
"Your package defines multiple top-level modules: {}",
top_level_module_names.join(", ")
);
println!(
"Defining multiple top-level modules can lead to namespace pollution \
and potential conflicts for consumers."
);
println!();
println!(
"To fix this, move all your modules under a single top-level module of your choice."
);
println!();
println!("For example:");
println!(
" src/{}.gleam\n src/{}/module1.gleam\n src/{}/module2.gleam",
&package.config.name, &package.config.name, &package.config.name
);
println!();

let should_publish =
i_am_sure || cli::confirm("\nDo you wish to continue publishing this package?")?;
println!();

if !should_publish {
println!("Not publishing.");
std::process::exit(0);
}
}

Ok(())
}

fn check_repo_url(config: &PackageConfig, i_am_sure: bool) -> Result<bool, Error> {
let Some(url) = config.repository.url() else {
return Ok(true);
Expand Down
3 changes: 3 additions & 0 deletions test/multi_namespace/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.beam
*.ez
build
4 changes: 4 additions & 0 deletions test/multi_namespace/gleam.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name = "multi_namespace"
version = "1.0.0"
description = "Test project for multi namespace"
licences = ["Apache-2.0"]
7 changes: 7 additions & 0 deletions test/multi_namespace/manifest.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# This file was generated by Gleam
# You typically do not need to edit this file

packages = [
]

[requirements]
3 changes: 3 additions & 0 deletions test/multi_namespace/src/multi_namespace.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub fn main() {
"Hello from multi_namespace!"
}
3 changes: 3 additions & 0 deletions test/multi_namespace/src/second.gleam
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub fn main() {
"Hello from second!"
}
26 changes: 26 additions & 0 deletions test/multi_namespace/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/sh

set -eu

GLEAM_COMMAND=${GLEAM_COMMAND:-"cargo run --quiet --"}

g() {
echo "Running: $GLEAM_COMMAND $@"
$GLEAM_COMMAND "$@"
}

echo Resetting the build directory to get to a known state
rm -fr build

echo Running publish should not publish anything
output=$(yes "n" | g publish)
if echo "$output" | grep -q "Your package defines multiple top-level modules"; then
echo "Publish was correctly prevented with warning"
else
echo "Expected publish to be aborted"
exit 1
fi

echo
echo Success! 💖
echo

0 comments on commit 369d83f

Please sign in to comment.