Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/util.mk
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ include $(mb_core_path)/util/os_detection.mk
include $(mb_core_path)/util/cache.mk
include $(mb_core_path)/util/colours.mk
include $(mb_core_path)/util/debug.mk
include $(mb_core_path)/util/git.mk

include $(mb_core_path)/util/variables.mk

Expand Down
63 changes: 63 additions & 0 deletions core/util/git.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#####################################################################################
# Project: MakeBind
# File: core/util/git.mk
# Description: Git utility functions for MakeBind
# Author: AntonioCS
# License: MIT License
#####################################################################################
ifndef __MB_CORE_UTIL_GIT_MK__
__MB_CORE_UTIL_GIT_MK__ := 1

mb_debug_git ?= $(mb_debug)

## Check if git is available (set once at load time)
## Note: Can't use mb_cmd_exists or mb_true here as they may not be defined yet
mb_git_available := $(shell command -v git >/dev/null 2>&1 && echo 1)

## @function mb_staged_files
## @description Returns a space-separated list of staged files, optionally filtered by extension
## @arg 1: extension (optional) - File extension to filter (e.g., php, py, go). If empty, returns all staged files.
## @returns Space-separated list of staged files (paths relative to git root)
## @example $(call mb_staged_files,php) -> src/Foo.php src/Bar.php
## @example $(call mb_staged_files) -> all staged files
define mb_staged_files
$(strip
$(if $(mb_git_available),
$(eval $0_arg1_ext := $(if $(value 1),$(strip $1),))
$(if $($0_arg1_ext),
$(shell git diff --cached --name-only --diff-filter=d 2>/dev/null | grep '\.$($0_arg1_ext)$$' || true),
$(shell git diff --cached --name-only --diff-filter=d 2>/dev/null)
)
)
)
endef

## @function mb_run_on_staged
## @description Runs a command only if there are staged files.
## Optionally filters by extension. The staged files are appended to the command.
## @arg 1: extension (optional) - File extension to filter (e.g., php, py, go). If empty, matches all files.
## @arg 2: command (required) - Command to run (files will be appended)
## @example $(call mb_run_on_staged,php,vendor/bin/phpstan analyse)
## @example $(call mb_run_on_staged,,prettier --write)
define mb_run_on_staged
$(strip
$(if $(mb_git_available),
$(eval $0_arg1_ext := $(if $(value 1),$(strip $1),))
$(eval $0_arg2_cmd := $(if $(value 2),$(strip $2),$(call mb_printf_error,$0: command required)))
$(eval $0_files := $(call mb_staged_files,$($0_arg1_ext)))
$(if $($0_files),
$(call mb_debug_print,Running: $($0_arg2_cmd) $($0_files),$(mb_debug_git))
$($0_arg2_cmd) $($0_files)
,
$(if $($0_arg1_ext),
$(call mb_printf_info,No staged .$($0_arg1_ext) files),
$(call mb_printf_info,No staged files)
)
)
,
$(call mb_printf_info,git not available)
)
)
endef

endif # __MB_CORE_UTIL_GIT_MK__
49 changes: 49 additions & 0 deletions tests/unit/core/util/git_test.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#####################################################################################
# Project: MakeBind
# File: tests/unit/core/util/git_test.mk
# Description: Tests for git utility functions
# Author: AntonioCS
# License: MIT License
#####################################################################################

include $(mb_core_path)/util/variables.mk
include $(mb_core_path)/util/git.mk

mb_debug_git := $(mb_off)

## Test that mb_staged_files returns empty when no files are staged
define test_core_util_git_staged_files_empty_when_none
$(eval $@_result := $(call mb_staged_files,php))
$(call mb_assert_empty,$($@_result),Expected empty result when no PHP files are staged)
endef

## Test that mb_staged_files works with different extensions
define test_core_util_git_staged_files_different_extensions
$(eval $@_result_py := $(call mb_staged_files,py))
$(eval $@_result_go := $(call mb_staged_files,go))
$(eval $@_result_js := $(call mb_staged_files,js))
$(call mb_assert_empty,$($@_result_py),Expected empty result for py)
$(call mb_assert_empty,$($@_result_go),Expected empty result for go)
$(call mb_assert_empty,$($@_result_js),Expected empty result for js)
endef

## Test that mb_run_on_staged does not error when no files staged
## Note: This test verifies the function executes without error
## The actual command won't run since there are no staged files
define test_core_util_git_run_on_staged_no_files
$(eval $@_result := $(call mb_run_on_staged,php,echo "would run"))
$(call mb_assert,1,mb_run_on_staged should complete without error)
endef

## Test that mb_staged_files works without extension (doesn't error)
## Note: Can't assert empty since tests may run with staged files
define test_core_util_git_staged_files_all_no_extension
$(eval $@_result := $(call mb_staged_files))
$(call mb_assert,1,mb_staged_files without extension should complete without error)
endef

## Test that mb_run_on_staged works without extension
define test_core_util_git_run_on_staged_all_no_extension
$(eval $@_result := $(call mb_run_on_staged,,echo "would run"))
$(call mb_assert,1,mb_run_on_staged without extension should complete without error)
endef