diff --git a/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh b/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh index bb36f913019eb7..3015a110f38b87 100755 --- a/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh +++ b/hadoop-common-project/hadoop-common/src/main/bin/hadoop-functions.sh @@ -1177,6 +1177,10 @@ function hadoop_add_profile ## @return 1 = failure (doesn't exist or some other reason) function hadoop_add_classpath { + declare -a classpath_entries + declare idx + declare rebuilt_classpath="" + # However, with classpath (& JLP), we can do dedupe # along with some sanity checking (e.g., missing directories) # since we have a better idea of what is legal @@ -1209,7 +1213,26 @@ function hadoop_add_classpath hadoop_debug "Append CLASSPATH: $1" fi else - hadoop_debug "Dupe CLASSPATH: $1" + if [[ "$2" = "before" ]] && [[ "${CLASSPATH%%:*}" != "$1" ]]; then + IFS=':' read -r -a classpath_entries <<< "${CLASSPATH}" + for idx in "${classpath_entries[@]}"; do + if [[ "${idx}" != "$1" ]]; then + if [[ -z "${rebuilt_classpath}" ]]; then + rebuilt_classpath="${idx}" + else + rebuilt_classpath="${rebuilt_classpath}:${idx}" + fi + fi + done + if [[ -n "${rebuilt_classpath}" ]]; then + CLASSPATH="$1:${rebuilt_classpath}" + else + CLASSPATH="$1" + fi + hadoop_debug "Moved CLASSPATH to front: $1" + else + hadoop_debug "Dupe CLASSPATH: $1" + fi fi return 0 } diff --git a/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_add_classpath.bats b/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_add_classpath.bats index 8bc50d0e0921ec..84b44ebb468da0 100644 --- a/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_add_classpath.bats +++ b/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_add_classpath.bats @@ -80,6 +80,15 @@ load hadoop-functions_test_helper [ "${CLASSPATH}" = "/tmp:${TMP}/*" ] } +@test "hadoop_add_classpath (duplicate before moves to front)" { + mkdir "${TMP}/first" "${TMP}/second" + hadoop_add_classpath "${TMP}/first" + hadoop_add_classpath "${TMP}/second" + hadoop_add_classpath "${TMP}/second" before + echo ">${CLASSPATH}<" + [ "${CLASSPATH}" = "${TMP}/second:${TMP}/first" ] +} + @test "hadoop_add_classpath (complex ordering)" { local j local style="after" @@ -97,4 +106,4 @@ load hadoop-functions_test_helper done echo ">${CLASSPATH}<" [ "${CLASSPATH}" = "${TMP}/4:${TMP}/2:${TMP}/1:${TMP}/3:${TMP}/5" ] -} \ No newline at end of file +} diff --git a/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_finalize_classpath.bats b/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_finalize_classpath.bats index ac0d4c120e5075..d7c03357e868fe 100644 --- a/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_finalize_classpath.bats +++ b/hadoop-common-project/hadoop-common/src/test/scripts/hadoop_finalize_classpath.bats @@ -61,4 +61,18 @@ load hadoop-functions_test_helper hadoop_add_to_classpath_userpath () { true; } hadoop_finalize_classpath -} \ No newline at end of file +} + +@test "hadoop_finalize_classpath (user classpath duplicate stays first)" { + mkdir -p "${TMP}/new" "${TMP}/old" + CLASSPATH="" + HADOOP_CONF_DIR="${TMP}" + HADOOP_CLASSPATH="${TMP}:${TMP}/new:${TMP}/old" + HADOOP_USER_CLASSPATH_FIRST="true" + + hadoop_translate_cygwin_path () { true; } + + hadoop_finalize_classpath + + [ "${CLASSPATH}" = "${TMP}:${TMP}/new:${TMP}/old" ] +}