diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5c2a0292de9c..3086f00a4dab 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -69,3 +69,10 @@ repos: - id: rst-backticks - id: rst-directive-colons - id: rst-inline-touching-normal + - repo: local + hooks: + - id: check-git-lfs-pointers + name: check Git LFS pointers + entry: tools/pre_commit/check_git_lfs_pointers.sh + language: script + pass_filenames: true diff --git a/source/isaaclab_tasks/changelog.d/huidongc-fix-lfs-pointers.skip b/source/isaaclab_tasks/changelog.d/huidongc-fix-lfs-pointers.skip new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-albedo.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-albedo.png index ed043c2f4e4c..6fc7b1f54ce5 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-albedo.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-albedo.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-depth.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-depth.png index 3acfb75c6ad6..3893ecf7729d 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-depth.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-depth.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgb.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgb.png index 3012dea78338..5e208864f107 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgb.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgb.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgba.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgba.png index 0dd3fd24a0c9..ccb5e911c527 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgba.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-rgba.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-semantic_segmentation.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-semantic_segmentation.png index c0cdc3c0e39f..f00bf60f2ae9 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-semantic_segmentation.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-semantic_segmentation.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png index 50ca06ccafdc..1d935f386c13 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png index 2dd3a7fa3777..44ea63335736 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_full_mdl.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_full_mdl.png index c7541c937cd0..7cd6e4247aaa 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_full_mdl.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-isaacsim_rtx_renderer-simple_shading_full_mdl.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-depth.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-depth.png index f79c54d2910d..3733ffeab59e 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-depth.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-depth.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgb.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgb.png index 71f0cd748deb..efc1240fde1e 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgb.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgb.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgba.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgba.png index 06aeea3d9330..f607be2b12d1 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgba.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-newton_renderer-rgba.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-albedo.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-albedo.png index 7223025531ba..9eebe6989842 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-albedo.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-albedo.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-depth.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-depth.png index 3acfb75c6ad6..3893ecf7729d 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-depth.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-depth.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgb.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgb.png index ab007a1899fc..79c5968703fe 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgb.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgb.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgba.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgba.png index 1af3d524d7c5..492c5050550a 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgba.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-rgba.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-semantic_segmentation.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-semantic_segmentation.png index c0cdc3c0e39f..f00bf60f2ae9 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-semantic_segmentation.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-semantic_segmentation.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_constant_diffuse.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_constant_diffuse.png index 935ec018ebd7..3b132dfe640c 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_constant_diffuse.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_constant_diffuse.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_diffuse_mdl.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_diffuse_mdl.png index 09b40afb1ffb..e888f29f5885 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_diffuse_mdl.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_diffuse_mdl.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_full_mdl.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_full_mdl.png index 93bcffa4df2c..b55faaf3c53a 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_full_mdl.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/newton-ovrtx_renderer-simple_shading_full_mdl.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-albedo.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-albedo.png index 9b60a20634dd..7fc7147f910d 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-albedo.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-albedo.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-depth.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-depth.png index b538c6dfdfa2..df186c373970 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-depth.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-depth.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgb.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgb.png index 5454d788cbde..69d3be9c69a3 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgb.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgb.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgba.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgba.png index 0168d8bd4c07..679fbefce7d1 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgba.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-rgba.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-semantic_segmentation.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-semantic_segmentation.png index 3bca5a971ff0..4bad29d72ce6 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-semantic_segmentation.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-semantic_segmentation.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png index 63b78f748205..830b7ab5464b 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_constant_diffuse.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png index cb5d1afbe067..5e6be299d264 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_diffuse_mdl.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_full_mdl.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_full_mdl.png index 43c9965463c8..2311052e19ce 100755 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_full_mdl.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-isaacsim_rtx_renderer-simple_shading_full_mdl.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-depth.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-depth.png index 8abb9f167e57..1da91b1c4b0b 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-depth.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-depth.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgb.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgb.png index bacc0fcc47cb..05fa5d11e83d 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgb.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgb.png differ diff --git a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgba.png b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgba.png index 8772c6f51e42..59c5d30efda6 100644 Binary files a/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgba.png and b/source/isaaclab_tasks/test/golden_images/shadow_hand/physx-newton_renderer-rgba.png differ diff --git a/tools/pre_commit/check_git_lfs_pointers.sh b/tools/pre_commit/check_git_lfs_pointers.sh new file mode 100755 index 000000000000..14320b182b52 --- /dev/null +++ b/tools/pre_commit/check_git_lfs_pointers.sh @@ -0,0 +1,107 @@ +#!/usr/bin/env bash +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +# Pre-commit hook: ensure Git LFS attribute rules match index storage. +# +# Paths with filter=lfs in .gitattributes must be staged as LFS pointers, not plain +# blobs. When many paths are checked (e.g. pre-commit run --all-files), falls back to +# git lfs fsck --pointers. + +set -euo pipefail + +# Above this count, per-file index checks are slower than a single fsck over HEAD/index. +readonly FSCK_FILE_THRESHOLD=200 + +# --- Prerequisites ----------------------------------------------------------- +# Git LFS must be on PATH; without it, filter=clean/smudge cannot run on commit. +if ! git lfs version >/dev/null 2>&1; then + echo "git-lfs is not installed; install it to work with LFS-tracked files." >&2 + exit 1 +fi + +# --- Helpers: read .gitattributes and index blobs ---------------------------- + +# Return the "filter" attribute value for a path (e.g. "lfs" or "unspecified"). +lfs_filter_attr() { + local path="$1" + git check-attr filter -- "${path}" 2>/dev/null | sed -n 's/.*filter: //p' | tr -d ' \r' +} + +# True when the staged blob (":path") is a well-formed LFS pointer file. +index_blob_is_valid_lfs_pointer() { + local path="$1" + git show ":${path}" 2>/dev/null | git lfs pointer --check --stdin >/dev/null 2>&1 +} + +# True when the staged blob starts with the LFS pointer spec line. +# Used for the reverse check only: "pointer --check" accepts empty files, which +# would false-positive on .gitkeep and other zero-byte paths. +index_blob_has_lfs_pointer_header() { + local path="$1" + git show ":${path}" 2>/dev/null | head -n1 | grep -qxF 'version https://git-lfs.github.com/spec/v1' +} + +# --- User-facing errors ------------------------------------------------------ +print_fix_hint() { + echo >&2 + echo "For LFS-tracked files, re-add after Git LFS is installed:" >&2 + echo " git rm --cached && git add " >&2 +} + +# --- Full-repository check (pre-commit run --all-files / many paths) --------- +# Verifies every path that should use LFS is stored as a pointer in HEAD/index. +run_fsck() { + git lfs fsck --pointers +} + +# --- Incremental check (git commit / small diffs) ------------------------------ +# pre-commit passes staged/changed paths as "$@". For each path in the index: +# 1. filter=lfs -> blob must be a valid LFS pointer +# 2. not filter=lfs but LFS header -> misconfigured .gitattributes +check_paths() { + local path filter_attr + local -a error_messages=() + + for path in "$@"; do + filter_attr="$(lfs_filter_attr "${path}")" + # Skip paths not present in the index (e.g. deleted-only in this commit). + if ! git show ":${path}" >/dev/null 2>&1; then + continue + fi + + if [[ "${filter_attr}" == "lfs" ]]; then + if ! index_blob_is_valid_lfs_pointer "${path}"; then + error_messages+=( + " ${path}: has filter=lfs but is staged as a regular Git blob (not an LFS pointer)" + ) + fi + elif index_blob_has_lfs_pointer_header "${path}"; then + error_messages+=( + " ${path}: is an LFS pointer but is not tracked by filter=lfs in .gitattributes" + ) + fi + done + + if [[ "${#error_messages[@]}" -ne 0 ]]; then + echo "Git LFS pointer check failed:" >&2 + printf '%s\n' "${error_messages[@]}" >&2 + print_fix_hint + return 1 + fi + return 0 +} + +# --- Entry point ------------------------------------------------------------- +# No args or a large file list -> fsck; otherwise check only the given paths. +main() { + if [[ "$#" -eq 0 ]] || [[ "$#" -gt "${FSCK_FILE_THRESHOLD}" ]]; then + run_fsck + return + fi + check_paths "$@" +} + +main "$@"