• Yunlong Song's avatar
    perf tools: Avoid confusion with preloaded bash function for perf bash completion · 1312c8a8
    Yunlong Song authored
    Since some functions (e.g. '_get_comp_words_by_ref()') in perf bash
    completion script are originally taken from git bash completion script,
    these functions may be preloaded before perf bash completion script
    runs.
    
    In order to avoid repeating loading the same function twice, some test
    constraints are used before these function definitions in the perf bash
    completion script (e.g. 'type _get_comp_words_by_ref &>/dev/null ||').
    
    The problem is that, if these functions in perf bash completion script
    are changed for some reason, perf will still use the preloaded bash
    functions rather than the customized functions of its own.
    
    As a result, the perf bash completion will behave incorrectly. To get
    rid of this problem, a flag can be defined to determine the proper
    situation.
    
    And to avoid overwriting the preloaded functions, the names of these
    functions in perf bash completion script should be renamed to the
    perf-customized ones.
    
    Example:
    
    Before this patch:
    
     $ type _get_comp_words_by_ref
     _get_comp_words_by_ref is a function
     _get_comp_words_by_ref ()
     {
         local exclude flag i OPTIND=1;
         local cur cword words=();
         local upargs=() upvars=() vcur vcword vprev vwords;
         while getopts "c:i:n:p:w:" flag "$@"; do
             case $flag in
                 c)
                     vcur=$OPTARG
                 ;;
                 i)
                     vcword=$OPTARG
                 ;;
                 n)
                     exclude=$OPTARG
                 ;;
                 p)
                     vprev=$OPTARG
                 ;;
                 w)
                     vwords=$OPTARG
                 ;;
             esac;
         done;
         while [[ $# -ge $OPTIND ]]; do
             case ${!OPTIND} in
                 cur)
                     vcur=cur
                 ;;
                 prev)
                     vprev=prev
                 ;;
                 cword)
                     vcword=cword
                 ;;
                 words)
                     vwords=words
                 ;;
                 *)
                     echo "bash: $FUNCNAME(): \`${!OPTIND}': unknown argument" 1>&2;
                     return 1
                 ;;
             esac;
             let "OPTIND += 1";
         done;
         __get_cword_at_cursor_by_ref "$exclude" words cword cur;
         [[ -n $vcur ]] && {
             upvars+=("$vcur");
             upargs+=(-v $vcur "$cur")
         };
         [[ -n $vcword ]] && {
             upvars+=("$vcword");
             upargs+=(-v $vcword "$cword")
         };
         [[ -n $vprev && $cword -ge 1 ]] && {
             upvars+=("$vprev");
             upargs+=(-v $vprev "${words[cword - 1]}")
         };
         [[ -n $vwords ]] && {
             upvars+=("$vwords");
             upargs+=(-a${#words[@]} $vwords "${words[@]}")
         };
         (( ${#upvars[@]} )) && local "${upvars[@]}" && _upvars "${upargs[@]}"
     }
    
    As shown above, the _get_comp_words_by_ref is the preloaded function in
    fact, rather than the function defined in perf-completion.sh. So if we
    happen to change the function for some reason, the result will behave in
    a wrong state.
    
    After this patch:
    
    We can set preload_get_comp_words_by_ref="false" to not use the preloaded
    function. Instead, it will use the function defined in perf-completion.sh,
    which is renamed as __perf_get_comp_words_by_ref to avoid overwriting
    the preloaded function _get_comp_words_by_ref.
    
     $ type __perf_get_comp_words_by_ref
     __perf_get_comp_words_by_ref is a function
     __perf_get_comp_words_by_ref ()
     {
         local exclude cur_ words_ cword_;
         if [ "$1" = "-n" ]; then
             exclude=$2;
             shift 2;
         fi;
         __my_reassemble_comp_words_by_ref "$exclude";
         cur_=${words_[cword_]};
         while [ $# -gt 0 ]; do
             case "$1" in
                 cur)
                     cur=$cur_
                 ;;
                 prev)
                     prev=${words_[$cword_-1]}
                 ;;
                 words)
                     words=("${words_[@]}")
                 ;;
                 cword)
                     cword=$cword_
                 ;;
             esac;
             shift;
         done
     }
    
    As shown above, the function __perf_get_comp_words_by_ref is loaded and
    can work this time.
    
    Note that we do not change the original behavior when those functions are
    not preloaded before perf bash completion script runs. In this case,
    although the flag is set to "true", the code will still change it to
    "false" to use the function defined in perf-completion.sh.
    Signed-off-by: default avatarYunlong Song <yunlong.song@huawei.com>
    Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Paul Mackerras <paulus@samba.org>
    Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Wang Nan <wangnan0@huawei.com>
    Link: http://lkml.kernel.org/r/1426685758-25488-14-git-send-email-yunlong.song@huawei.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
    1312c8a8
perf-completion.sh 5.34 KB