pull/927/merge
Hash 2025-12-06 21:46:55 +07:00 committed by GitHub
commit c571413e67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 87 additions and 12 deletions

@ -0,0 +1,6 @@
[target.wasm32-wasip1]
rustflags = [
"-L/opt/wasi-sdk/share/wasi-sysroot/lib/wasm32-wasi",
"-Clink-arg=-lc++",
"-Clink-arg=-lc++abi"
]

@ -37,6 +37,8 @@ jobs:
# detects that they need cross).
- target: x86_64-unknown-linux-musl
os: ubuntu-22.04
- target: wasm32-wasip1
os: ubuntu-24.04
- target: aarch64-unknown-linux-gnu
os: ubuntu-22.04
- target: aarch64-pc-windows-msvc
@ -46,6 +48,13 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
# v4.2.2
- run: |
wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-29/wasi-sdk-29.0-x86_64-linux.deb
sudo apt-get install ./wasi-sdk-29.0-x86_64-linux.deb
rm ./wasi-sdk-29.0-x86_64-linux.deb
rustup override set stable
rustup target add wasm32-wasip1
if: ${{ matrix.target == 'wasm32-wasip1' }}
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
- uses: taiki-e/upload-rust-binary-action@v1
with:
@ -59,6 +68,11 @@ jobs:
env:
# (required)
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WASI_SDK_PATH: /opt/wasi-sdk
WASI_SYSROOT: /opt/wasi-sdk/share/wasi-sysroot
CC_wasm32_wasip1: /opt/wasi-sdk/bin/clang
AR_wasm32_wasip1: /opt/wasi-sdk/bin/llvm-ar
CFLAGS_wasm32_wasip1: "--sysroot=/opt/wasi-sdk/share/wasi-sysroot"
push_crates_io:
runs-on: ubuntu-22.04

@ -59,7 +59,6 @@ tree_magic_mini = "3.1.6"
bumpalo = "3.16.0"
unicode-width = "0.1.9"
crossterm = { version = "0.28.0", features = ["windows"] }
glob = "0.3.1"
strum = { version = "0.26", features = ["derive"] }
hashbrown = "0.14.0"
@ -128,7 +127,10 @@ tree-sitter-xml = "0.7.0"
tree-sitter-yaml = "0.7.0"
tree-sitter-zig = "1.1.2"
[target.'cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd")))'.dependencies]
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
crossterm = { version = "0.28.0", features = ["windows"] }
[target.'cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd", target_arch = "wasm32")))'.dependencies]
tikv-jemallocator = "0.6"
[dev-dependencies]

@ -78,6 +78,7 @@ fn read_file_arg(file_arg: &FileArgument) -> std::io::Result<Vec<u8>> {
}
/// Write a human-friendly description of `e` to stderr.
#[cfg(not(target_arch = "wasm32"))]
fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
match e.kind() {
std::io::ErrorKind::NotFound => {
@ -95,12 +96,26 @@ fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
};
}
#[cfg(target_arch = "wasm32")]
fn eprint_read_error(file_arg: &FileArgument, e: &std::io::Error) {
// For the browser/WASM demo, fail softly so we can keep running.
println!("WASM read error on {} ({:?})", file_arg, e.kind());
}
pub(crate) fn read_or_die(path: &Path) -> Vec<u8> {
match fs::read(path) {
Ok(src) => src,
Err(e) => {
eprint_read_error(&FileArgument::NamedPath(path.to_path_buf()), &e);
std::process::exit(EXIT_BAD_ARGUMENTS);
#[cfg(target_arch = "wasm32")]
{
// Return empty content in WASM to avoid aborting the demo.
return Vec::new();
}
#[cfg(not(target_arch = "wasm32"))]
{
std::process::exit(EXIT_BAD_ARGUMENTS);
}
}
}
}

@ -98,10 +98,20 @@ use crate::parse::syntax;
///
/// For reference, Jemalloc uses 10-20% more time (although up to 33%
/// more instructions) when testing on sample files.
#[cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd")))]
#[cfg(not(any(
target_env = "msvc",
target_os = "illumos",
target_os = "freebsd",
target_arch = "wasm32"
)))]
use tikv_jemallocator::Jemalloc;
#[cfg(not(any(target_env = "msvc", target_os = "illumos", target_os = "freebsd")))]
#[cfg(not(any(
target_env = "msvc",
target_os = "illumos",
target_os = "freebsd",
target_arch = "wasm32"
)))]
#[global_allocator]
static GLOBAL: Jemalloc = Jemalloc;

@ -8,7 +8,6 @@ use std::{
};
use clap::{crate_authors, crate_description, value_parser, Arg, ArgAction, Command};
use crossterm::tty::IsTty;
use owo_colors::OwoColorize as _;
use crate::{
@ -51,6 +50,30 @@ pub(crate) struct DisplayOptions {
pub(crate) const DEFAULT_TERMINAL_WIDTH: usize = 80;
#[cfg(not(target_arch = "wasm32"))]
fn stdout_is_tty() -> bool {
use crossterm::tty::IsTty;
std::io::stdout().is_tty()
}
#[cfg(target_arch = "wasm32")]
fn stdout_is_tty() -> bool {
false
}
#[cfg(not(target_arch = "wasm32"))]
fn terminal_columns() -> Option<usize> {
crossterm::terminal::size()
.ok()
.map(|(cols, _rows)| cols as usize)
.filter(|cols| *cols > 0)
}
#[cfg(target_arch = "wasm32")]
fn terminal_columns() -> Option<usize> {
None
}
impl Default for DisplayOptions {
fn default() -> Self {
Self {
@ -125,7 +148,7 @@ fn app() -> clap::Command {
));
after_help.push_str("\n\nSee the full manual at ");
if std::io::stdout().is_tty() {
if stdout_is_tty() {
// Make the link to the manual clickable in terminals that
// support OSC 8, the ANSI escape code for hyperlinks.
//
@ -596,6 +619,7 @@ fn common_path_suffix(lhs_path: &Path, rhs_path: &Path) -> Option<String> {
}
/// Does `path` look like "/tmp/git-blob-abcdef/modified_field.txt"?
#[cfg(not(target_arch = "wasm32"))]
fn is_git_tmpfile(path: &Path) -> bool {
let Ok(rel_path) = path.strip_prefix(std::env::temp_dir()) else {
return false;
@ -612,6 +636,12 @@ fn is_git_tmpfile(path: &Path) -> bool {
.starts_with("git-blob-")
}
#[cfg(target_arch = "wasm32")]
fn is_git_tmpfile(_path: &Path) -> bool {
// WASI environments may not have a writable /tmp; skip special-casing.
false
}
fn build_display_path(lhs_path: &FileArgument, rhs_path: &FileArgument) -> String {
match (lhs_path, rhs_path) {
(FileArgument::NamedPath(lhs), FileArgument::NamedPath(rhs)) => {
@ -1002,10 +1032,8 @@ pub(crate) fn parse_args() -> Mode {
/// Try to work out the width of the terminal we're on, or fall back
/// to a sensible default value.
fn detect_terminal_width() -> usize {
if let Ok((columns, _rows)) = crossterm::terminal::size() {
if columns > 0 {
return columns.into();
}
if let Some(columns) = terminal_columns() {
return columns;
}
// If crossterm couldn't detect the terminal width, use the
@ -1036,7 +1064,7 @@ pub(crate) fn should_use_color(color_output: ColorOutput) -> bool {
fn detect_color_support() -> bool {
// TODO: consider following the env parsing logic in git_config_bool
// in config.c.
std::io::stdout().is_tty() || env::var("GIT_PAGER_IN_USE").is_ok()
stdout_is_tty() || env::var("GIT_PAGER_IN_USE").is_ok()
}
#[cfg(test)]