파일의 명령 옵션을 명령에 삽입

파일의 명령 옵션을 명령에 삽입

컨텍스트: Mercurial 확장 오류를 추적하려고 합니다.

Mercurial에는 Mercurial의 기본 기능을 확장하는 확장 기능이 있습니다. 필요한 만큼 이러한 확장을 로드하도록 선택할 수 있습니다. 때로는 서로 간섭하기도 합니다.

Evolve 확장의 명령이 hg fold예상대로 작동하지 않습니다. 문제는 로드된 다른 확장 중 하나에 있는 것 같습니다. Evolve 확장만 로드된 경우에만 명령이 제대로 작동하기 때문입니다. Evolve를 로드하면 다음과 같습니다.

HGRCPATH=/dev/null hg fold --config extensions.hgext3rd.evolve= --exact  -r  2024:8679fc70eae8  -r  2021:8b3257871eac -m "Fold"

문제가 되는 확장을 격리하기 위해 로드한 모든 확장에 대해 이진 검색을 수행하고 싶습니다. 내가 가지고 있는 것 같은 목록 hg debugconfig은 다음과 같습니다.

extensions.hgext.churn=
extensions.hgext.color=
extensions.hgext.convert=
extensions.hgext.extdiff=
extensions.hgext.graphlog=
extensions.hgext.hgk=
extensions.hgext.journal=
extensions.hgext.keyword=
extensions.hgext.mq=
extensions.hgext.pager=
extensions.hgext.patchbomb=
extensions.hgext.purge=
extensions.hgext.rebase=
extensions.hgext.record=
extensions.hgext.schemes=
extensions.hgext.progress=
extensions.hgext.histedit=
extensions.hgext.shelve=
extensions.hgext.narrow=
extensions.hgext.show=
extensions.hgext.share=
extensions.hgext3rd.evolve=
extensions.hgext3rd.topic=

줄 번호별로 포함할 확장자 목록을 지정할 수 있는 명령이 필요합니다. 그처럼

HGRCPATH=/dev/null hg fold something(1, 3, 5) --exact  -r  2024:8679fc70eae8  -r  2021:8b3257871eac -m "Fold"

여기에는 파일의 1, 3, 5행에 대한 확장자가 포함됩니다. 이것은 다음으로 출력되어야합니다

HGRCPATH=/dev/null hg fold --config extensions.hgext.churn= --config extensions.hgext.convert= --config extensions.hgext.graphlog= --exact  -r  2024:8679fc70eae8  -r  2021:8b3257871eac -m "Fold"

명령줄을 사용하여 오류를 확인하려면 를 확인해야 합니다 hg log. Mercurial의 Python API를 사용하여 자동 확인을 수행할 수 있지만 누군가 나에게 방법을 알려주지 않는 한 이는 엄청난 작업이 될 것입니다. 그럴 가치가 없어. 이를 감안할 때 가능한 한 적은 양의 테스트를 수행하는 것이 합리적입니다. 따라서 이진 검색.

--config옵션은 전역적이므로 작업이 더 간단해지면 명령 끝에 넣을 수 있습니다.

답변1

이 기능은 어떻습니까?

hg_fold() {
    local -a config
    mapfile -t config < <(hg debugconfig)

    local -a opts
    for i in "$@"; do
        opts+=( --config "${config[i-1]}" )
    done
    opts+=(
        --exact  
        -r  2024:8679fc70eae8  
        -r  2021:8b3257871eac 
        -m "Fold"
    )

    echo HGRCPATH=/dev/null hg fold "${opts[@]}"
}

hg_fold 1 3 5

echo괜찮아 보이면 삭제하세요.


좀 더 상호작용적인 것을 원한다면 아마도

hg_fold() {
    local -a opts
    select_options opts

    opts+=(
        --exact  
        -r  2024:8679fc70eae8  
        -r  2021:8b3257871eac 
        -m "Fold"
    )

    echo HGRCPATH=/dev/null hg fold "${opts[@]}"
}

select_options() {
    local -n options=$1
    local -a config
    mapfile -t config < <(hg debugconfig)

    local selecting=true
    PS3="Select a debugconfig item: "

    while $selecting; do
        select item in "${config[@]}" Done; do
            if [[ $item == "Done" ]]; then
                selecting=false
                break
            elif [[ -n $item ]]; then
                options+=( --config "$item" )
                config[REPLY-1]="*$item"  # mark it as selected
                break
            fi
        done
    done
}

hg_fold

답변2

문제가 되는 확장을 격리하기 위해 로드한 모든 확장에 대해 이진 검색을 수행하고 싶습니다.

분할 정복의 관점에서 이 문제에 대한 해결책은 다음과 같습니다. 기본 아이디어는 입력 파일을 약간 준비한 다음 이를 두 부분으로 재귀적으로 분할하는 것입니다. 각 절반은 예제 명령으로 출력된 다음 해당 절반에서 반복됩니다. 명령이 성공했는지 실패했는지 확인하는 데 필요한 육안 검사를 기반으로 실행할 예제 명령을 선택할 수 있습니다. 범인을 찾으려면 이 명령 중 4개만 실행하면 됩니다.

다음은 진행 상황을 더 잘 이해할 수 있도록 프로세스에 대한 간단한 데모입니다. 스크립트는 23줄 이상 반복되며 각 줄을 다음 형식으로 인쇄합니다.

$key = sed -n $start, $end p 파일

출력은 다음과 같습니다

11 = sed -n 1,12p file
12 = sed -n 13,23p file
111 = sed -n 1,6p file
112 = sed -n 7,12p file
1111 = sed -n 1,3p file
1112 = sed -n 4,6p file
11111 = sed -n 1,2p file
11112 = sed -n 3,3p file
11121 = sed -n 4,5p file
11122 = sed -n 6,6p file
1121 = sed -n 7,9p file
1122 = sed -n 10,12p file
11211 = sed -n 7,8p file
11212 = sed -n 9,9p file
11221 = sed -n 10,11p file
11222 = sed -n 12,12p file
121 = sed -n 13,18p file
122 = sed -n 19,23p file
1211 = sed -n 13,15p file
1212 = sed -n 16,18p file
12111 = sed -n 13,14p file
12112 = sed -n 15,15p file
12121 = sed -n 16,17p file
12122 = sed -n 18,18p file
1221 = sed -n 19,21p file
1222 = sed -n 22,23p file
12211 = sed -n 19,20p file
12212 = sed -n 21,21p file

각 재귀에는 이전 실행의 "1" 또는 "2"가 접미사로 붙습니다. 1..23~1..12행의 첫 번째 구분선으로 "11"을 따릅니다. 거기에서 각각 1..6행과 7..12행인 "111"과 "112"로 나누어집니다. "11" 명령인 경우성공적인, 너뛰어 넘다이후의 모든 줄에는 "11.."이라는 접두사가 붙습니다. "11" 명령인 경우실패, 당신은 집중할 것입니다오직후속 "11.." 접두사 줄. 각 하위 그룹의 라인을 헹구고 반복합니다.

아래 스크립트는 동일한 기본 알고리즘을 사용하지만 출력을 실제 명령과 sed출력으로 처리합니다.

#!/bin/sh

# prepare the file a bit
file=./extensions-file
sed 's/^/ --config /' "$file" > "$file".prepared

# specifically a () subshell instead of {} grouping, to insulate "N" variable changes
divide() (
  # args = prefix, start, end, suffix
  # output: recursive breakout of:
  #   $prefix $(sed start .. N) $suffix
  #   $prefix $(sed N+1 .. end) $suffix
  # N = (end-start)/2

  n=$(( $2 + ($3-$2)/2 ))
  printf '%s %s %s\n' "${1}" "$(sed -n $2,${n}p "$file".prepared | tr -d '\n')"       "$4"
  printf '%s %s %s\n' "${1}" "$(sed -n $((n+1)),${3}p "$file".prepared | tr -d '\n')" "$4"
  if [ $((n - $2)) -gt 1 ]
  then
    divide "${1}" "$2" "$n" "$4"
  fi
  if [ $(( $3 - (n+1) )) -gt 1 ]
  then
    divide "${1}" "$((n+1))" "$3" "$4"
  fi
)

divide  "HGRCPATH=/dev/null hg fold"    \
        1                               \
        "$(wc -l < "$file".prepared)"   \
        "--exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m \"Fold\""

rm "$file".prepared

이 스크립트는 인쇄할 때마다 조작할 필요가 없도록 각 줄 앞에 공백과 "--config" 텍스트를 추가하여 확장 출력 파일을 준비합니다. 마지막으로 임시 파일을 삭제하십시오.

Divide() 함수를 정의하고 호출합니다. Divide() 함수는 먼저 입력 범위의 중간점(하한)을 계산합니다. 그런 다음 (start)..(n) 및 (n+1)..(end) 줄을 사용하여 예제 명령을 인쇄하는 것을 기반으로 합니다. 의 세 가지 매개변수는 printf접두사, 출력 sed및 접미사입니다. Divide()에 대한 초기 호출에서 접두사와 접미사를 정의합니다. 이는 확장 비트의 양쪽에 있는 텍스트일 뿐입니다. 이 sed명령은 파일에서 요청된 줄을 인쇄한 다음 이를 전달하여 tr개행을 제거하여 출력이 모두 한 줄이 되도록 합니다. 여기에서 준비 작업이 약간 도움이 됩니다. 각 줄 앞에 공백을 추가하면 해당 줄을 상당히 간단하게 연결할 수 있습니다.

상황을 더 쉽게 추적하려면 위 스크립트의 출력을 필터링하여 nl각 줄에 식별자를 제공할 수 있습니다. 아래 스크립트의 출력(파이핑됨)과 비교하여 이러한 식별자를 추적합니다 nl.

다음 스크립트는 위의 초기 "barebones" 출력을 생성합니다.

#!/bin/sh
# specifically a () subshell instead of {} grouping, to insulate "N" variable changes
divide() (
  # args = prefix, start, end
  # output: recursive breakout of:
  #   "$prefix"1 = start .. N
  #   "$prefix"2 = N+1 .. end
  # N = (end-start)/2

  n=$(( $2 + ($3-$2)/2 ))
  printf '%s = sed -n %d,%dp file\n' "${1}1" "$2" "$n"
  printf '%s = sed -n %d,%dp file\n' "${1}2" "$((n+1))" "$3"
  if [ $((n - $2)) -gt 1 ]
  then
    divide "${1}1" "$2" "$n"
  fi
  if [ $(( $3 - (n+1) )) -gt 1 ]
  then
    divide "${1}2" "$((n+1))" "$3"
  fi
)

divide 1 1 23

완성도를 높이기 위해 최종 스크립트의 출력은 다음과 같습니다. 참고 - 일부 줄은 매우 깁니다!

HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --config extensions.hgext.convert= --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --config extensions.hgext.hgk= --config extensions.hgext.journal= --config extensions.hgext.keyword= --config extensions.hgext.mq= --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --config extensions.hgext.schemes= --config extensions.hgext.progress= --config extensions.hgext.histedit= --config extensions.hgext.shelve= --config extensions.hgext.narrow= --config extensions.hgext.show= --config extensions.hgext.share= --config extensions.hgext3rd.evolve= --config extensions.hgext3rd.topic= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --config extensions.hgext.convert= --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --config extensions.hgext.hgk= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.journal= --config extensions.hgext.keyword= --config extensions.hgext.mq= --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --config extensions.hgext.convert= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --config extensions.hgext.hgk= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.churn= --config extensions.hgext.color= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.convert= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.extdiff= --config extensions.hgext.graphlog= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.hgk= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.journal= --config extensions.hgext.keyword= --config extensions.hgext.mq= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.journal= --config extensions.hgext.keyword= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.mq= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.pager= --config extensions.hgext.patchbomb= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.purge= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --config extensions.hgext.schemes= --config extensions.hgext.progress= --config extensions.hgext.histedit= --config extensions.hgext.shelve= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.narrow= --config extensions.hgext.show= --config extensions.hgext.share= --config extensions.hgext3rd.evolve= --config extensions.hgext3rd.topic= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --config extensions.hgext.schemes= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.progress= --config extensions.hgext.histedit= --config extensions.hgext.shelve= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.rebase= --config extensions.hgext.record= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.schemes= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.progress= --config extensions.hgext.histedit= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.shelve= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.narrow= --config extensions.hgext.show= --config extensions.hgext.share= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext3rd.evolve= --config extensions.hgext3rd.topic= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.narrow= --config extensions.hgext.show= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"
HGRCPATH=/dev/null hg fold  --config extensions.hgext.share= --exact -r 2024:8679fc70eae8 -r 2021:8b3257871eac -m "Fold"

출력을 사용하여 문제가 있는 확장을 찾으려면 이전 출력에 번호를 매깁니다(아마도 파이핑하여 nl). 이제 28개의 명령 목록이 생겼습니다. 명령 #1을 실행합니다. 계속하려면 아래 지침을 따르십시오.

  • #1이 성공하면 명령 #17을 실행합니다. #1이 실패하면 #3 명령을 실행합니다.
  • #3이 성공하면 명령 #11을 실행합니다. #3이 실패하면 #5 명령을 실행합니다.
  • #5가 성공하면 명령 #9를 실행합니다. #5가 실패하면 #7 명령을 실행합니다.
  • #7이 성공하면 확장 3에 문제가 있는 것입니다. #7이 실패하면 확장 1 또는 2에 문제가 있는 것입니다.
  • #9가 성공하면 확장 6에 문제가 있는 것입니다. #9가 실패하면 확장 4 또는 5에 문제가 있는 것입니다.
  • #11이 성공하면 명령 #15를 실행합니다. #11이 실패하면 #13 명령을 실행합니다.
  • #13이 성공하면 확장 9에 문제가 있는 것입니다. #13이 실패하면 확장 7 또는 8에 문제가 있는 것입니다.
  • #15가 성공하면 확장 12에 문제가 있는 것입니다. #15가 실패하면 확장 10 또는 11에 문제가 있는 것입니다.
  • #17이 성공하면 명령 #25를 실행합니다. #17이 실패하면 #19 명령을 실행합니다.
  • #19가 성공하면 명령 #21을 실행합니다. #19가 실패하면 #23 명령을 실행합니다.
  • #21이 성공하면 확장 15에 문제가 있는 것입니다. #21이 실패하면 확장 13 또는 14에 문제가 있는 것입니다.
  • #23이 성공하면 확장 18에 문제가 있는 것입니다. #23이 실패하면 확장 16 또는 17에 문제가 있는 것입니다.
  • #25가 성공하면 확장 22 또는 23에 문제가 있는 것입니다. #25가 실패하면 #27 명령을 실행합니다.
  • #27이 성공하면 확장 21에 문제가 있는 것입니다. #27이 실패하면 확장 19 또는 20에 문제가 있는 것입니다.

문제가 있는 확장자는 출력 파일의 줄 번호로 식별됩니다 hg debugconfig.

관련 정보