diff --git a/documentation/man/features/kw-build.rst b/documentation/man/features/kw-build.rst index 8fd82b455..3346e388b 100644 --- a/documentation/man/features/kw-build.rst +++ b/documentation/man/features/kw-build.rst @@ -17,6 +17,7 @@ SYNOPSIS | *kw* (*b* | *build*) [(-c | \--clean)] [\--alert=(s | v | (sv | vs) | n)] | *kw* (*b* | *build*) [(-f | \--full-cleanup)] [\--alert=(s | v | (sv | vs) | n)] | *kw* (*b* | *build*) [\--cflags] +| *kw* (*b* | *build*) [\--from-sha ] | *kw* (*b* | *build*) [\--verbose] DESCRIPTION @@ -102,6 +103,10 @@ OPTIONS | **sv** or **vs** enables both. | **n** (or any other option) disables notifications (this is the default). +\--from-sha: + Build every commit from to branch head. Useful for testing if all patches in + patchset compiles. + EXAMPLES ======== For these examples, we suppose the fields in your **kworkflow.config** file are @@ -158,3 +163,7 @@ If you want to reset the kernel tree to its default, `all config and script outp If you want to use cflags:: kw b --cflags "-O3 -pipe -march=native" + +If you want to build every commit from HEAD~2 to HEAD:: + + kw b --from-sha HEAD~2 diff --git a/documentation/tutorials/buildlinux.rst b/documentation/tutorials/buildlinux.rst index d2932b802..81c644bd6 100644 --- a/documentation/tutorials/buildlinux.rst +++ b/documentation/tutorials/buildlinux.rst @@ -80,3 +80,12 @@ Well, that's it. kw will automatically infer the number of job slots for compiling based on the number of cores of your machine (i.e. when running make ``-j``, ** is an integer that specifies the number of processes that will run at the same time), and compilation will begin! + +Compiling patchsets +------------------- +You may want to try compiling every patch in your patchset to test if everything is alright. +You can do this by using the "from-sha" flag:: + + kw build --from-sha SHA + +This will compile every path from the commit with given SHA to the branch HEAD. diff --git a/src/bash_autocomplete.sh b/src/bash_autocomplete.sh index 4fb435e81..a56e76874 100644 --- a/src/bash_autocomplete.sh +++ b/src/bash_autocomplete.sh @@ -21,7 +21,7 @@ function _kw_autocomplete() kw_options['init']='--arch --remote --target --force --template --verbose' kw_options['build']='--help --info --menu --cpu-scaling --ccache --llvm --clean - --full-cleanup --verbose --doc --warnings --save-log-to --cflags' + --full-cleanup --verbose --doc --warnings --save-log-to --cflags --from-sha' kw_options['b']="${kw_options['build']}" diff --git a/src/build.sh b/src/build.sh index c8221f69b..01265affc 100644 --- a/src/build.sh +++ b/src/build.sh @@ -33,6 +33,9 @@ function build_kernel_main() local clean local output_kbuild_flag='' local cflags + local from_sha_arg + local sha_base + local merge_base parse_build_options "$@" @@ -59,6 +62,7 @@ function build_kernel_main() clean=${options_values['CLEAN']} full_cleanup=${options_values['FULL_CLEANUP']} cflags=${options_values['CFLAGS']} + from_sha_arg=${options_values['FROM_SHA_ARG']} [[ -n "${options_values['VERBOSE']}" ]] && flag='VERBOSE' flag=${flag:-'SILENT'} @@ -124,6 +128,32 @@ function build_kernel_main() return "$?" fi + if [[ -n "$from_sha_arg" ]]; then + # Check if there is a rebase in process. + if [[ -e .git/rebase-merge/done ]]; then + printf '%s\n' 'ERROR: Abort the repository rebase before continuing with build from sha (use "git rebase --abort")!' + return 22 #EINVAL + fi + + # Check if given SHA represents real commit + cmd_manager "SILENT" "git cat-file -e ${from_sha_arg}^{commit} 2> /dev/null" + if [[ "$?" != 0 ]]; then + printf '%s\n' 'ERROR: The given SHA does not represent a real commit in this repository.' + return 22 #EINVAL + fi + + # Check if given SHA is in working tree. + sha_base=$(git rev-parse --verify "$from_sha_arg") + merge_base=$(git merge-base "$from_sha_arg" HEAD) + if [[ "$sha_base" != "$merge_base" ]]; then + printf '%s\n' 'ERROR: Given SHA is invalid. Check if it is an ancestor of the branch head.' + return 22 #EINVAL + fi + + build_from_sha "$flag" "$from_sha_arg" + return "$?" + fi + command="make ${optimizations} ${llvm}ARCH=${platform_ops}${warnings}" if [[ -n "$cflags" ]]; then @@ -247,9 +277,33 @@ function full_cleanup() cmd_manager "$flag" "$cmd" } +# This functions uses iteractive 'git rebase' with '--exec' flag under the hood +# to apply a 'kw build' over each commit from SHA to branch head. +# +# @flag How to display a command, see `src/lib/kwlib.sh` function `cmd_manager`. +# @sha The SHA from the first commit to be compiled until the branch head. +# +# Return: +# 0 if successfully compiled patchset, 1 otherwise. +function build_from_sha() +{ + local flag="$1" + local sha="$2" + local cmd + + flag=${flag:-'SILENT'} + cmd="git rebase ${sha} --exec 'kw build'" + cmd_manager "$flag" "$cmd" + + if [[ "$?" != 0 ]]; then + printf '%s\n' 'kw build failed during the compilation of a patch! Check the rebase in progress for more information.' + return 1 + fi +} + function parse_build_options() { - local long_options='help,info,menu,doc,ccache,cpu-scaling:,warnings::,save-log-to:,llvm,clean,full-cleanup,verbose,cflags:' + local long_options='help,info,menu,doc,ccache,cpu-scaling:,warnings::,save-log-to:,llvm,clean,full-cleanup,verbose,cflags:,from-sha:' local short_options='h,i,n,d,S:,w::,s:,c,f' local doc_type local file_name_size @@ -279,6 +333,7 @@ function parse_build_options() options_values['FULL_CLEANUP']='' options_values['VERBOSE']='' options_values['CFLAGS']="${build_config[cflags]}" + options_values['FROM_SHA_ARG']='' # Check llvm option if [[ ${options_values['USE_LLVM_TOOLCHAIN']} =~ 'yes' ]]; then @@ -362,6 +417,10 @@ function parse_build_options() options_values['LOG_PATH']="$2" shift 2 ;; + --from-sha) + options_values['FROM_SHA_ARG']="$2" + shift 2 + ;; --) shift ;; @@ -394,7 +453,8 @@ function build_help() ' build (-c | --clean) - Clean option integrated into env' \ ' build (-f | --full-cleanup) - Reset the kernel tree to its default option integrated into env' \ ' build (--cflags) - Customize kernel compilation with specific flags' \ - ' build (--verbose) - Show a detailed output' + ' build (--verbose) - Show a detailed output' \ + ' build (--from-sha ) - Build all commits from to actual commit' } # Every time build.sh is loaded its proper configuration has to be loaded as well diff --git a/tests/unit/build_test.sh b/tests/unit/build_test.sh index 1c5473461..d3ebaeb84 100755 --- a/tests/unit/build_test.sh +++ b/tests/unit/build_test.sh @@ -861,6 +861,57 @@ function test_kernel_build_cpu_scaling_llvm_warning_sava_log_to() compare_command_sequence '' "($LINENO)" 'expected_result' "$output" } +function test_kernel_build_from_sha() +{ + local expected_result + local output + local sha="HEAD^" + + mk_fake_git + + output=$(build_kernel_main 'TEST_MODE' --from-sha ${sha}) + declare -a expected_result=( + "git rebase HEAD^ --exec 'kw build'" + ) + compare_command_sequence '' "($LINENO)" 'expected_result' "$output" +} + +function test_kernel_build_from_sha_nonexisting_sha() +{ + local expected_result + local output + local sha="fakesha" + + mk_fake_git + + output=$(build_kernel_main 'TEST_MODE' --from-sha ${sha}) + declare -a expected_result=( + "ERROR: The given SHA does not represent a real commit in this repository." + ) + compare_command_sequence '' "($LINENO)" 'expected_result' "$output" +} + +function test_kernel_build_from_sha_sha_not_ancestor() +{ + local expected_result + local output + + mk_fake_git + + git checkout -q HEAD^ + git checkout -q -b branch + touch branch_file + git add branch_file + git commit -m "create_branch" -q + git checkout -q master + + output=$(build_kernel_main 'TEST_MODE' --from-sha branch) + declare -a expected_result=( + "ERROR: Given SHA is invalid. Check if it is an ancestor of the branch head." + ) + compare_command_sequence '' "($LINENO)" 'expected_result' "$output" +} + function test_kernel_build_inside_an_env() { local output