diff --git a/.ci/check-whitespace.jl b/.ci/check-whitespace.jl new file mode 100755 index 00000000..604af8dc --- /dev/null +++ b/.ci/check-whitespace.jl @@ -0,0 +1,98 @@ +#!/usr/bin/env julia + +const patterns = split(""" + *.jl + *.md + *.yml + *Makefile +""") + +const is_gha = something(tryparse(Bool, get(ENV, "GITHUB_ACTIONS", "false")), false) + +# Note: `git ls-files` gives `/` as a path separator on Windows, +# so we just use `/` for all platforms. +allow_tabs(path) = + endswith(path, "Makefile") || + endswith(path, ".make") || + endswith(path, ".mk") + +function check_whitespace() + errors = Set{Tuple{String,Int,String}}() + files_to_check = filter(arg -> !startswith(arg, "-"), ARGS) + if isempty(files_to_check) + if "--stdin" in ARGS + files_to_check = collect(eachline(stdin)) + else + files_to_check = collect(eachline(`git ls-files -- $patterns`)) + end + end + + files_fixed = 0 + if "--fix" in ARGS + for path in files_to_check + content = newcontent = read(path, String) + isempty(content) && continue + if !allow_tabs(path) + tabpattern = r"^([ \t]+)"m => (x -> replace(x, r"((?: {4})*)( *\t)" => s"\1 ")) # Replace tab sequences at start of line after any number of 4-space groups + newcontent = replace(newcontent, tabpattern) + end + newcontent = replace(newcontent, + r"\s*$" => '\n', # Remove trailing whitespace and normalize line ending at eof + r"\s*?[\r\n]" => '\n', # Remove trailing whitespace and normalize line endings on each line + r"\xa0" => ' ' # Replace non-breaking spaces + ) + if content != newcontent + write(path, newcontent) + files_fixed += 1 + end + end + if files_fixed > 0 + println(stderr, "Fixed whitespace issues in $files_fixed files.") + end + end + + for path in files_to_check + lineno = 0 + non_blank = 0 + + file_err(msg) = push!(errors, (path, 0, msg)) + line_err(msg) = push!(errors, (path, lineno, msg)) + + isfile(path) || continue + for line in eachline(path, keep=true) + lineno += 1 + contains(line, '\r') && file_err("non-UNIX line endings") + contains(line, '\ua0') && line_err("non-breaking space") + allow_tabs(path) || + contains(line, '\t') && line_err("tab") + endswith(line, '\n') || line_err("no trailing newline") + line = chomp(line) + endswith(line, r"\s") && line_err("trailing whitespace") + contains(line, r"\S") && (non_blank = lineno) + end + non_blank < lineno && line_err("trailing blank lines") + end + + if isempty(errors) + println(stderr, "Whitespace check found no issues.") + exit(0) + else + println(stderr, "Whitespace check found $(length(errors)) issues:") + for (path, lineno, msg) in sort!(collect(errors)) + if lineno == 0 + println(stderr, "$path -- $msg") + if is_gha + println(stdout, "::warning title=Whitespace check,file=", path, "::", msg) + end + else + println(stderr, "$path:$lineno -- $msg") + if is_gha + println(stdout, "::warning title=Whitespace check,file=", path, ",line=", lineno, "::", msg) + end + end + end + exit(1) + end +end + +check_whitespace() diff --git a/.github/workflows/Whitespace.yml b/.github/workflows/Whitespace.yml new file mode 100644 index 00000000..3931cba2 --- /dev/null +++ b/.github/workflows/Whitespace.yml @@ -0,0 +1,26 @@ +name: Whitespace + +permissions: {} + +on: + push: + branches: + - main + pull_request: + +jobs: + whitespace: + name: Check whitespace + runs-on: ubuntu-latest + timeout-minutes: 2 + steps: + - name: Checkout the JuliaSparse/SparseArrays.jl repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + - uses: julia-actions/setup-julia@f6f565d9f7cf12f53dc8045742460d6260ad3b39 # v3.0.1 + with: + version: '1.11.6' + - name: Check whitespace + run: | + julia .ci/check-whitespace.jl diff --git a/gen/Makefile b/gen/Makefile index e19103fc..132889fc 100755 --- a/gen/Makefile +++ b/gen/Makefile @@ -7,7 +7,7 @@ all: clean download julia --project generator.jl ./SuiteSparse-$(VER) clean: - rm -fr *.tar.gz SuiteSparse* + rm -fr *.tar.gz SuiteSparse* download: curl -L -O https://github.com/JuliaBinaryWrappers/SuiteSparse_jll.jl/releases/download/SuiteSparse-v$(VER)%2B0/SuiteSparse.v$(VER).x86_64-linux-gnu.tar.gz diff --git a/src/solvers/spqr.jl b/src/solvers/spqr.jl index 31890889..2f71dd65 100644 --- a/src/solvers/spqr.jl +++ b/src/solvers/spqr.jl @@ -85,7 +85,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, # Free memory allocated by SPQR. This call will make sure that the # correct deallocator function is called and that the memory count in # the common struct is updated - Ti === Int64 ? + Ti === Int64 ? cholmod_l_free(n, sizeof(Ti), e, CHOLMOD.getcommon(Ti)) : cholmod_free(n, sizeof(Ti), e, CHOLMOD.getcommon(Ti)) end @@ -100,7 +100,7 @@ function _qr!(ordering::Integer, tol::Real, econ::Integer, getCTX::Integer, # Free memory allocated by SPQR. This call will make sure that the # correct deallocator function is called and that the memory count in # the common struct is updated - Ti === Int64 ? + Ti === Int64 ? cholmod_l_free(m, sizeof(Ti), hpinv, CHOLMOD.getcommon(Ti)) : cholmod_free(m, sizeof(Ti), hpinv, CHOLMOD.getcommon(Ti)) end diff --git a/src/sparseconvert.jl b/src/sparseconvert.jl index 479654b7..80854331 100644 --- a/src/sparseconvert.jl +++ b/src/sparseconvert.jl @@ -280,4 +280,3 @@ function _sparse_gen(m, n, newcolptr, newrowval, newnzval) newcolptr[1] = 1 SparseMatrixCSC(m, n, newcolptr, newrowval, newnzval) end - diff --git a/test/cholmod.jl b/test/cholmod.jl index 7fd1692d..95772144 100644 --- a/test/cholmod.jl +++ b/test/cholmod.jl @@ -1026,7 +1026,7 @@ end end f = ones(size(K, 1)) - u = K \ f + u = K \ f residual = norm(f - K * u) / norm(f) @test residual < 1e-6 end diff --git a/test/fixed.jl b/test/fixed.jl index 59c10346..e477363d 100644 --- a/test/fixed.jl +++ b/test/fixed.jl @@ -118,7 +118,7 @@ end @test f(x, y, z) == 0 t = similar(x) @test typeof(t) == typeof(x) - @test struct_eq(t, x) + @test struct_eq(t, x) end @testset "Issue #190" begin