Compare commits

..
Author SHA1 Message Date
Ian ad26ebc93b logo 2026-10-13 00:14:04 -04:00
Ian 4d29b065b4 Show the cmd doskey alias beside the PowerShell one 2026-10-12 17:54:46 -04:00
Ian Graham MartinezandClaude Opus 5.5 d679fa0fed Show Windows users PowerShell syntax and the name they type
On Windows the help said `firewall.exe`, suggested a bash alias, and
`serve` printed bash-style variable assignments. Drop the extension,
suggest a PowerShell function (Set-Alias cannot carry arguments), and
print `$env:` assignments. Other platforms are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 17:51:34 -04:00
ian-at-strix b2e036f7c6 Run any command after firewall verbatim, -- included (#6)
bpaf always consumes `--`, so `firewall cargo run -- --release` handed
--release to cargo and our --config flags to the program. The CLI is now clap
with one trailing COMMAND argument, which keeps `--`.

Every manager's environment is set on every run, and cargo's and gem's flags
are added when the command is cargo or gem, so `firewall sh -c '…'` is
screened too. Since every command now gets HTTPS_PROXY, HTTPS to hosts that
aren't registries is tunnelled; registry hosts are still refused.
2026-10-12 16:55:27 -04:00
ian-at-strix 7f9e257a38 Merge pull request #3 from usestrix/fix/pipenv-trusted-host
Trust the PyPI hosts for pipenv's pip
2026-10-12 15:49:55 -04:00
Ian Graham MartinezandClaude Opus 5.5 098dea7cc0 Trust the PyPI hosts for pipenv's pip
pipenv installs through pip, which skips the plaintext index on an
untrusted host, so `firewall pipenv install six` fetched nothing and
failed with "No matching distribution found". Set PIP_TRUSTED_HOST as
the pip recipe already does.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-12 15:30:43 -04:00
3 changed files with 30 additions and 4 deletions

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

+2
View File
@@ -9,6 +9,8 @@ pub static PIPENV: Manager = Manager {
("http_proxy", PROXY),
("https_proxy", PROXY),
("PIPENV_PYPI_MIRROR", PYPI_SIMPLE),
// pipenv installs through pip, which skips a plaintext index on a host it doesn't trust.
("PIP_TRUSTED_HOST", "pypi.org files.pythonhosted.org"),
],
args: &[],
};
+28 -4
View File
@@ -25,11 +25,13 @@ fn options() -> Command {
"Run a command through {program} to screen what it installs:\n \
{program} npm install left-pad\n\n\
Alias it to screen every install without changing how you type:\n \
alias npm='{program} npm'\n\n\
{}\n\n\
Supported package managers: {}",
alias(&program),
managers.join(", ")
);
Command::new("firewall")
.bin_name(&program)
.about("Screens package downloads before they reach your machine")
.after_help(footer)
.arg_required_else_help(true)
@@ -91,12 +93,32 @@ fn print_setup(config: &FirewallConfig) {
let base = config.local_url("");
println!("Firewall listening on {base}\n");
println!("Point your package managers at it:");
println!(" npm npm_config_registry={base}/npm/");
println!(" pip PIP_INDEX_URL={base}/pypi/simple/");
println!(" npm {}", variable("npm_config_registry", &format!("{base}/npm/")));
println!(" pip {}", variable("PIP_INDEX_URL", &format!("{base}/pypi/simple/")));
println!(" cargo [source.crates-io] replace-with = \"firewall\"");
println!(" [source.firewall] registry = \"sparse+{base}/cargo/index/\"\n");
}
fn alias(program: &str) -> String {
if cfg!(windows) {
// Set-Alias cannot carry arguments, so a function stands in.
format!(
"PowerShell: function npm {{ {program} npm @args }}\n \
cmd: doskey npm={program} npm $*"
)
} else {
format!("alias npm='{program} npm'")
}
}
fn variable(key: &str, value: &str) -> String {
if cfg!(windows) {
format!("$env:{key} = \"{value}\"")
} else {
format!("{key}={value}")
}
}
fn load() -> FirewallConfig {
match FirewallConfig::load() {
Ok(config) => config,
@@ -113,7 +135,9 @@ fn fail(kind: &'static str, message: &str) -> ! {
fn program_name() -> String {
let arg = std::env::args_os().next().unwrap_or_default();
match Path::new(&arg).file_name() {
// Without `.exe` on Windows, which is how it is typed.
let path = Path::new(&arg);
match if cfg!(windows) { path.file_stem() } else { path.file_name() } {
Some(name) => name.to_string_lossy().into_owned(),
None => "firewall".into(),
}