+4
.github/workflows/ci.yaml
+4
.github/workflows/ci.yaml
···
420
420
run: make test
421
421
working-directory: ./test/running_modules
422
422
423
+
- name: test/multi_namespace
424
+
run: ./test.sh
425
+
working-directory: ./test/multi_namespace
426
+
423
427
- name: Test FFI in subdirectories
424
428
run: make
425
429
working-directory: ./test/subdir_ffi
+46
-1
compiler-cli/src/publish.rs
+46
-1
compiler-cli/src/publish.rs
···
5
5
build::{Codegen, Compile, Mode, Options, Package, Target},
6
6
config::{PackageConfig, SpdxLicense},
7
7
docs::DocContext,
8
-
error::SmallVersion,
8
+
error::{wrap, SmallVersion},
9
9
hex,
10
10
paths::{self, ProjectPaths},
11
11
requirement::Requirement,
···
56
56
} = do_build_hex_tarball(&paths, &mut config)?;
57
57
58
58
check_for_name_squatting(&compile_result)?;
59
+
check_for_multiple_top_level_modules(&compile_result, i_am_sure)?;
59
60
60
61
// Build HTML documentation
61
62
let docs_tarball = fs::create_tar_archive(docs::build_documentation(
···
118
119
119
120
if main.body.first().is_println() {
120
121
return Err(Error::HexPackageSquatting);
122
+
}
123
+
124
+
Ok(())
125
+
}
126
+
127
+
fn check_for_multiple_top_level_modules(package: &Package, i_am_sure: bool) -> Result<(), Error> {
128
+
// Collect top-level module names
129
+
let mut top_level_module_names = package
130
+
.modules
131
+
.iter()
132
+
.filter_map(|module| module.name.split('/').next())
133
+
.collect::<Vec<_>>();
134
+
135
+
// Remove duplicates
136
+
top_level_module_names.sort_unstable();
137
+
top_level_module_names.dedup();
138
+
139
+
// If more than one top-level module name is found, prompt for confirmation
140
+
if top_level_module_names.len() > 1 {
141
+
let text = wrap(&format!(
142
+
"Your package defines multiple top-level modules: {}.
143
+
144
+
Defining multiple top-level modules can lead to namespace pollution \
145
+
and potential conflicts for consumers.
146
+
147
+
To fix this, move all your modules under a single top-level module of your choice.
148
+
149
+
For example:
150
+
src/{1}.gleam
151
+
src/{1}/module1.gleam
152
+
src/{1}/module2.gleam",
153
+
top_level_module_names.join(", "),
154
+
package.config.name
155
+
));
156
+
println!("{text}\n");
157
+
158
+
let should_publish =
159
+
i_am_sure || cli::confirm("\nDo you wish to continue publishing this package?")?;
160
+
println!();
161
+
162
+
if !should_publish {
163
+
println!("Not publishing.");
164
+
std::process::exit(0);
165
+
}
121
166
}
122
167
123
168
Ok(())
+4
test/multi_namespace/gleam.toml
+4
test/multi_namespace/gleam.toml
+7
test/multi_namespace/manifest.toml
+7
test/multi_namespace/manifest.toml
+3
test/multi_namespace/src/multi_namespace.gleam
+3
test/multi_namespace/src/multi_namespace.gleam
+26
test/multi_namespace/test.sh
+26
test/multi_namespace/test.sh
···
1
+
#!/bin/sh
2
+
3
+
set -eu
4
+
5
+
GLEAM_COMMAND=${GLEAM_COMMAND:-"cargo run --quiet --"}
6
+
7
+
g() {
8
+
echo "Running: $GLEAM_COMMAND $@"
9
+
$GLEAM_COMMAND "$@"
10
+
}
11
+
12
+
echo Resetting the build directory to get to a known state
13
+
rm -fr build
14
+
15
+
echo Running publish should not publish anything
16
+
output=$(yes "n" | g publish)
17
+
if echo "$output" | grep -q "Your package defines multiple top-level modules"; then
18
+
echo "Publish was correctly prevented with warning"
19
+
else
20
+
echo "Expected publish to be aborted"
21
+
exit 1
22
+
fi
23
+
24
+
echo
25
+
echo Success! 💖
26
+
echo