현재 리비전의 저장소에서 버그가 난다고 가정.

만약 버그의 원인이 되는 파일과 내용을 알면 해당 내용을 누가 언제 추가했는지 hg annotate 명령어로 알 수 있음.



// 원인은 lib.js 의 3번째 라인의 // bug 라는 문자열일 경우
// lib.js 파일의 anno 출력
// 저 옵션이면 각 라인별로 아래의 형태로 출력됨 
// [author] [revision_number] [라인번호]: [라인내용]
// 이 내용을 바탕으로 범인색출 가능
C:\rep> hg anno -unl lib.js
lu bu feng xian 0: 1: function sum(a, b)
lu bu feng xian 0: 2: {
cdbaek 5: 3:     // bug
cdbaek 5: 4:
lu bu feng xian 0: 3:     return a+b;
cdbaek 2: 6: }
cdbaek 2: 7:
cdbaek 2: 8: function minus(a, b)
cdbaek 2: 9: {
cdbaek 2:10:     return a-b;
lu bu feng xian 0: 4: }

// cdbaek이 범인. 이제 족치면 됨.







만약 리비전이 얽히고 섥히고 나타났다 사라졌다 복잡한 상황인데,

해당 버그를 일으키는 원인을 최초에 저장소에 추가시킨 리비전을 알아내려면,

의심되는 리비전별로 hg update를 통해 바꿔가면서 일일이 하나씩 체크해봐야 하는데,

이걸 효율적이고 간단하게 해주는 명령어가 hg bisect 임.


원리는 나쁜(bad) 리비전과 좋은(good) 리비전을 지정한 후,

절반씩 나눠가며 최초의 bad 리비전을 찾아내는 것.

그 리비전의 author가 범인이고, 그 리비전의 diff가 범행의 기록인것이다.



// hg bisect 를 이용하여 lib.js 파일에서 최초로 // bug 라는 문자열이 나타난 리비전 찾기 예제
// 총 10개의 리비전이 있고 알고 있는 정보는 리비전10은 bad, 리비전1은 good이라고 가정함.

// 우선 bisect 초기화
C:\rep> hg bisect -r

// 지금 리비전10은 bad 라고 지정
C:\rep> hg bisect -b

// good 이었던 리비전 번호(=1) 세팅
C:\rep> hg bisect -g 1 
Testing changeset 5:77639473615b (9 changesets remaining, ~3 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

// 이 시점에서 저장소는 절반인 리비전 5로 업데이트 됨
// lib.js 파일을 보고 // bug 라는 문자열이 있는지 체크. 없으면 good, 있으면 bad
// 이 시점에는 있다고 가정
C:\rep> hg bisect -b
Testing changeset 3:47e5f718b4fc (4 changesets remaining, ~2 tests)
1 files updated, 0 files merged, 0 files removed, 0 files unresolved

// 그럼 그 절반에 해당하는 리비전인 3으로 업데이트 됨.
// 이 시점에는 // bug 라는 문자열이 없다고 가정
C:\rep> hg bisect -g

// 그럼 3~5 사이인 리비전4로 업데이트 됨.
// 이 시점도 good
C:\rep> hg bisect -g
The first bad revision is:
changeset:   5:77639473615b
user:        cdbaek
date:        Fri Aug 01 17:46:40 2014 +0900
summary:     bug

// 찾았음!
// cdbaek이 범인


위 예제는 파일의 내용중 어느것이 버그를 유발하는지 알고 있을 때 찾는 방법이고,

그게 아니라면 hg bisect를 하면서 컴파일을 하고 직접 테스트 케이스를 돌려보는 수 밖에 없음.


위 예제는 수동으로 해주는 방법이고,

hg bisect 에서 제공되는 -c 혹은 --command 옵션을 사용하면 자동화가 가능함.


hg bisect -c 다음에 커맨드를 하나 주게 되면,

hg bisect 는 해당 커맨드의 exit 코드가 0 이면 good, 125면 skip, 127이면 abort, 나머지 0 이 아닌 정수는 전부 bad 으로 간주함.

이 exit 코드값으로 최초 bad 리비전을 찾을 때까지 hg bisect가 알아서 실행되는 형태.


lib.js 파일내용을 읽어와서 // bug 라는 문자열이 있으면 exit(1) =bad,없으면 exit(0) =good 인 스크립트 파일을 하나 만들어서 hg bisect -c 의 매개변수로 실행시켜 주면 됨.


아래는 예제.



// reset, 최초의 good, bad 지정은 해줘야 함
C:\rep> hg bisect -r

C:\rep> hg bisect -b

C:\rep> hg bisect -g 1

// 이제 -c 옵션으로 실행할 스크립트 파일을 하나 던져 넣으면 hg bisect 가 알아서 최초의 bad 리비전을 찾아줌.
// 여기에 사용된 bisect_check.php 파일 내용은 아래에 있음.
C:\rep> hg bisect -c "C:\php\php.exe C:\scripts\bisect_check.php"
Changeset 5:77639473615b: bad
Changeset 3:47e5f718b4fc: good
Changeset 4:731949c8ae81: good
The first bad revision is:
changeset:   5:77639473615b
user:        cdbaek
date:        Fri Aug 01 17:46:40 2014 +0900
summary:     bug

// 찾았음!




위 예제에서 사용한 php 스크립트 파일 소스코드.

스크립트 파일의 조건을 마음대로 할 수 있으므로 다양한 이용이 가능함.


<?PHP
// bisect test
// lib.js 파일에 // bug 라는 주석이 있으면 bad, 없으면 good

// good
if (strpos(file_get_contents('C:\rep\lib.js'), '// bug') === false) exit(0);
// bad
else exit(1);















Posted by bloodguy
,