ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • CVS diff 사용
    기타 2010. 8. 9. 09:36
    반응형
    출처 : http://blog.naver.com/paradox1573?Redirect=Log&logNo=40019304078

    CVS 사용

    CVS는 약자 중 Concurrent가 의미하듯이 한번에 여러 명의 개발자가 동일한 소스코드 트리에 동시에 수정을 가하면서 작업을 할 수 있도록 도와주는 도구이다. 사실 오픈소스 프로젝트에 참가하는 일반 개발자의 입장에서는 CVS에 대한 일반적인 지식은 별다른 필요가 없다고 생각해도 무방하다. 실제 소스코드 트리를 수정할 수 있는 권한을 갖고 있는 사람들은 프로젝트 리더인 자비로운 독재자 한 사람이나 프로젝트와 관련이 깊은 소수의 개발자들일 것이기 때문이다.

    즉, 소스코드 수정 사항이 생기면 CVS를 굳이 쓸 필요가 없이 그냥 FTP나 http로 다운받은 소스코드 위에 diff를 돌려서 패치만 이메일과 같은 수단으로 보내 주면 소스코드 수정 권한이 있는 그쪽 사람들이(보통 ‘커미터’라고 부른다) 알아서 처리를 해 줄 것이기 때문이다.
    하지만 가장 최신 버전의 nightly build된 소프트웨어는 CVS 서버에 접속해야만 구할 수 있는 경우가 대부분이다. 따라서 오픈소스 개발 프로젝트에 관심이 있는 개발자라면 다음 측면에서 CVS 사용법을 알아야 할 필요가 있을 것이다.

    [1] FTP나 http 서버에서 소스코드를 다운받는 대신에
    [2] CVS 서버에서 가장 최신 소스코드를 다운 받고
    [3] 자신이 패치한 소스코드와 CVS 서버의 소스코드의 diff를 생성하는 방법

    익명 CVS 체크아웃
    이제 CVS에서 소스코드를 다운받는 방법을 알아보기로 하자. 일반적으로 오픈소스 프로젝트들은 대부분 CVS 서버를 읽기 전용으로 세팅해 놓고 누구든지 들어와서 소스코드를 다운받아 갈 수 있도록 해 놓고 있다. 익명 FTP(anonymous FTP)와 비슷한 개념으로 생각하면 되겠다. CVS 서버에 사용자가 접속을 해서 소스코드를 한 카피 다운받아 가는 것을 CVS에서는 체크아웃(check-out)이라는 용어로 표현한다.
    참고로 CVS는 로컬 서버에서 사용할 수도 있고, 따로 CVS 서버를 두고 원격으로 접속할 수도 있다. 여기서는 CVS가 원격 서버라고 가정하기로 한다. CVS 서버에서 소스코드를 다운받는 명령은 다음과 같다. KLDP.net 서버에 위치한 moniwiki 프로젝트를 예로 들어 보겠다.

    $ cvs -d:pserver:anonymous@cvs.kldp.net:cvsroot/moniwiki login
    $ cvs -d:pserver:anonymous@cvs.kldp.net:cvsroot/moniwiki checkout moniwiki

    익명 FTP에 접속할 때 보다는 조금 복잡해 보인다. 우선, 첫줄의 cvs 명령은 CVS 서버에 anonmous, 즉 익명 사용자로 로그인하는 과정이다. CVS 서버가 암호를 요구하면 그냥 엔터 키를 쳐 주면 인증이 끝나고 읽기 권한이 부여된다. 일단 로그인을 한번 한 다음부터는 사용자의 홈 디렉토리에 .cvspass 파일이 생기면서 인증 절차가 생략된다. 즉, 매번 접속할 때마다 anonymous 인증 과정을 거쳐야 하는 익명 FTP와는 달리, CVS에서는 한번만 익명 로그인을 해서 .cvspass 파일을 생성하고 나면 다시 cvs login 명령으로 인증 과정을 거칠 필요가 없다.

    그 다음 -d 옵션은 CVS 서버에서 제공하고 있는 루트 디렉토리를 의미한다. moniwiki 프로젝트의 경우는 cvsroot/moniwiki로 지정되어 있다. 앞의 pserver는 CVS 명령이 소스코드를 다운받으면서 쓸 프로토콜명이며 뒤의 anonymous@cvs.kldp.net은 CVS 로그인시 사용할 계정이다.

    두 번째 cvs 명령은 소스코드 한 카피를 다운받는 체크아웃 과정을 실행하게 된다. 체크아웃(checkout)한 다음의 moniwki는 CVS 서버에서 지정해 놓은 프로젝트 이름이며(모듈이라고 부른다) 이곳 CVS 서버에서는 moniwki로 지정해 두었다. 두 번째 명령을 실행하면 사용자의 현재 디렉토리에 moniwiki라는 디렉토리가 생성되고 소스코드 다운로드가 시작된다. 여기에, -z3 옵션을 주면 전송시 압축을 사용하기 때문에 전송 속도가 빨라진다.

    $ cvs -z3 -d:pserver:anonymous@cvs.kldp.net:cvsroot/moniwiki checkout moniwiki

    그런데 CVS 서버에 접속할 때마다 -d 옵션 뒤의 긴 디렉토리 이름을 타이핑하기는 아무래도 불편한 감이 있다. -d 옵션을 생략하려면 환경변수 CVSROOT에 -d 옵션을 등록해 둔다.

    $ export CVSROOT=:pserver:anonymous@cvs.kldp.net:/cvsroot/moniwiki

    그 다음부터는 다음 명령으로도 충분하다.

    $ cvs login
    $ cvs checkout moniwiki

    소스코드를 받은 지 시간이 어느 정도 지났다면 그동안 CVS 서버의 내용이 새롭게 업데이트되어 있을 수도 있다. 바뀐 부분을 다운받으려면 CVS에서 update 명령을 사용한다.

    $ cvs update -dP

    여기서 -P 옵션은 Prune 옵션으로 비어있는 디렉토리를 자동으로 삭제해 주는 역할을 한다. -d 옵션은 그동안 서버 쪽에 새로 만들어진 디렉토리가 있으면 다운 받은 이쪽에도 동일한 디렉토리를 만들어 준다.

    CVS 서버 원본에서 diff로 패치 파일 만들기
    이제 기본적인 CVS 서버에서 소스코드 다운로드 방법을 알았으니 직접 CVS 서버의 소스코드를 이용해서 패치 파일을 만들어 보자. CVS는 diff 명령을 아예 자체적으로 내장하고 있다. 조금 전 다운받은 moniwiki의 소스코드를 예로 들어보자. 여기서, 필자는 monisetup.php 파일에 간단히 /* testing one two three */라는 주석문을 하나 삽입했다.

    $ cd moniwiki
    $ ls
    COPYING                 doc                     secure.sh
    CVS                     imgs                    theme
    INSTALL                 index.html              tools
    README                  lib                     wiki.php
    THANKS                  locale                  wikihttpd.php
    applets                 monisetup.bat           wikilib.php
    config.php.default      monisetup.php           wikismiley.php
    css                     monisetup.sh
    data                    plugin
    $ cvs diff -u -p monisetup.php
    Index: monisetup.php
    ===================================================================
    RCS file: /cvsroot/moniwiki/moniwiki/monisetup.php,v
    retrieving revision 1.11
    diff -u -p -r1.11 monisetup.php
    --- monisetup.php       3 Jan 2004 14:26:50 -0000       1.11
    +++ monisetup.php       3 Aug 2004 09:14:21 -0000
    @@ -486,4 +486,5 @@ if ($_SERVER['REQUEST_METHOD']!="POST")

    }

    +/* testing one two three */
    ?>

    cvs diff 명령이 마치 로컬에서 monisetup.php 파일에 diff 명령을 실행한 것과 같은 결과가 나왔음을 알 수 있다. cvs diff 명령 뒤의 -u 옵션은 diff와 마찬가지로 unified format을 의미하며 -p 옵션은 cvs diff 의 출력을 표준 출력(standard output)으로 보내라는 의미이다. 디렉토리 안의 모든 파일에 대해 diff 명령으로 비교를 하려면 다음과 같은 방법을 사용한다.

    $ cvs -Q diff -u -p              
    Index: monisetup.php
    ===================================================================
    RCS file: /cvsroot/moniwiki/moniwiki/monisetup.php,v
    retrieving revision 1.11
    diff -u -p -r1.11 monisetup.php
    --- monisetup.php       3 Jan 2004 14:26:50 -0000       1.11
    +++ monisetup.php       3 Aug 2004 09:19:27 -0000
    @@ -486,4 +486,5 @@ if ($_SERVER['REQUEST_METHOD']!="POST")

    }

    +/* testing one two three */
    ?>
    Index: css/log.css
    ===================================================================
    RCS file: /cvsroot/moniwiki/moniwiki/css/log.css,v
    retrieving revision 1.1
    diff -u -p -r1.1 log.css
    --- css/log.css 11 Feb 2004 08:48:27 -0000      1.1
    +++ css/log.css 3 Aug 2004 09:19:27 -0000
    @@ -1,4 +1,5 @@
    /* MoniWiki CSS 2003/11/01 by wkpark */
    +/* another testing comment */
    body {
       font-family:Georgia,Verdana,Lucida,sans-serif;font-size:12px;
       background-color:#FFFFFF;

    여기서는 monisetup.php 파일과 css/log.css 파일에 수정된 부분이 있음을 알 수 있다. cvs diff 명령에서 -Q 옵션은 Quiet 옵션으로 diff 출력 이외의 다른 메시지를 출력하지 않도록 해 준다. 그런데 여기서 하나 의문이 들 수 있다. 분명히 CVS에서는 cvs를 이용해서 직접 소스코드에 수정을 가할 수 있을 것인데 여기에서 왜 굳이 구식 diff를 이용한 방법을 또 사용하고 있는 것을까?

    그 이유는 앞에서도 잠깐 언급했듯이, CVS 서버의 내용을 수정할 수 있는 권한이 있는 개발자는 소수이기 때문이다. 그리고 자비로운 독재자라는 용어에서 알 수 있듯이 제출된 패치를 받아들일지 아닐지의 여부는 관습적으로 보통 그쪽 프로젝트 리더들의 몫이 된다.

    따라서 CVS 서버에 읽기 전용의 권한만을 갖고 있는 일반 오픈소스 프로젝트 참가자들은 이메일이나 혹은 메일링 리스트에 diff를 이용해서 패치 파일을 포스팅하는 것이 오픈소스 프로젝트에 참가하는 가장 무난한 방법이다. 일반적으로 프로젝트의 참가자가 지나치게 많지 않은 경우를 제외하고는 오픈소스 프로젝트에 올라오는 패치는 아무리 사소한 것이라도 쉽게 CVS 서버의 원본 소스코드에(repository라고 부른다) 반영 된다.

    따라서 일반 개발자의 입장에서는 프로젝트 리더나 메인 개발자가 되기 전에는 CVS 서버에서 쓰기 권한이 그다지 필요하지는 않다. 이제 간단하게 CVS 서버에서 자주 쓰이는 기본적인 개념과 용어에 대해 알아보기로 하자.

    CVS의 개념과 여러 용어
    CVS 모델, copy-moodify-merge model
    CVS는 이전에 많이 쓰이던 RCS(Revision Control System)과는 달리 lock-modify-unlock이 아닌 copy-modify-merge 모델을 사용한다. 여러 명의 개발자가 하나의 소스코드 트리에서 개발 작업을 할 때 가장 큰 문제는 같은 부분의 소스코드에 두 명 이상의 개발자가 서로 다른 소스코드를 작성하고 있을 때 발생한다. 이것을 CVS에서는 conflict이 발생했다고 한다.

    RCS의 lock-modify-unlock 접근방식은 이러한 conflict를 한번에 두 명 이상의 개발자가 같은 소스코드 부분에 접근할 수 없도록 해서 conflict 상황을 미연에 방지한다. 하지만 CVS에서는 이러한 conflict 상황이 발생하는 것을 허용한다. 그렇다면 CVS에서는 이런 소스코드 conflict 상황이 발생하면 어떻게 대처할까?

    재미있게도 CVS에서는 이런 상황에서 아무 일도 하지 않는다. 다만, CVS는 어느 부분에서 소스코드 conflict가 발생했는지, 그리고 어떤 사람이 conflict에 관계되어 있는지만 정확하게 알려 준다. 따라서 소스코드의 conflict 문제를 해결하는 것은 기계가 아닌 사람의 몫이 된다.

    lock-modify-unlock 모델은 프로젝트의 전체 개발자 숫자가 소수이고 각각의 개발자들이 다른 개발자들이 현재 어떤 작업을 하고 있는지 쉽게 알 수 있는 상황에 유리하다. 그러나 개발자의 숫자가 많아지면 이미 잠금이 걸려 있는 파일에는 다른 개발자들이 접근할 수 없기 때문에 전체적인 업데이트가 늦어지는 문제가 발생하게 되고 좀 더 유연한 환경을 제공하기 위해 CVS가 도입되기에 이르렀다. 따라서 copy-modify-merge 모델의 CVS를 사용하는 개발자는 기본적으로 다음과 같은 과정을 거치며 개발 작업을 진행해 나가게 된다.

    [1] 개발자는 CVS 서버로부터 소스코드 카피를 다운로드(check-out)한 다음
    [2] 소스코드를 수정하고
    [3] 완료된 작업은 다시 CVS 서버로 올려준다(check-in, commit)

    여기서 conflict의 발생 여부는 commit 작업 단계에서 알 수 있다. 그리고 조금 전에 잠깐 살펴보았듯이 현재 개발자의 컴퓨터의 소스코드를 cvs 서버 쪽과 가능한 한 동일하게 유지하려면 update를 자주 해 주는 것이 좋다.

    CVS와 관련된 용어
    CVS와 관련된 용어는 통일된 번역이 아직 존재하지 않는 것 같아 원문 그대로 싣고 여기에 설명을 덧붙이도록 하겠다.

    ◆ repository : CVS 서버에 들어가 있는 바로 그 원본(master copy) 소스코드를 의미한다. 나중에 최종 출시가 되는 소스코드가 바로 이 repository이며 repository는 그동안 버전업되어 온 정보를 모두 포함하고 있다. cvs respository의 개수는 하나가 된다.

    ◆ working copy : 각각의 개발자가 작업을 위해 cvs repository에서 복사해 갖고 나간(check-out) 소스코드가 working copy이다. 따라서 working copy는 개발자의 수만큼 존재한다고 볼 수 있다. 개발자는 이 working copy에서 소스코드 수정 작업을 한 다음 나중에 check-in 혹은 commit 단계를 거쳐 원본 cvs repository에 수정을 가하게 된다.

    ◆ check-out : 개발자가 자신이 작업할 working copy를 CVS 서버에서 한 카피 복사해 가는 것을 check-out이라고 한다.

    ◆ update : update는 check-out과 비슷하게 cvs repository에서 원본 소프트웨어를 한 카피 가져오는 역할을 하지만, update는 단어의 원래 뜻 그대로 수정된 부분만 가져와서 현재 개발자가 쓰고 있는 working copy가 항상 최신의 갱신본이 될 수 있도록 해 준다. 일반적으로, 개발자는 한번 working copy를 check-out 한 뒤에는 최신의 소스코드를 유지하기 위해 이 update 명령을 주로 쓰게 된다.

    ◆ check-in 혹은 commit : 여기서 잠깐 조심해서 봐야 할 것이 update와 check-in의 관계이다. 얼핏 보기에는 CVS에서 check-out과 check-in이 반대의 개념이 되어야 할 것 같은데 실상 check-in의 반대 개념은 update이다. check-in은 내가 작성한 소스코드를 repository에 병합시켜서 다른 개발자들도 내가 작성한 수정 부분을 볼 수 있게 해 주는 소위 publish 작업이기 때문이다. 따라서 그 반대 개념은 내가 다른 사람들이 작성한 소스코드 수정본을 나의 working copy에 반영시키는 것인데 이 작업이 update 과정이다. 따라서 check-in 과정은 오히려 commit이라는 단어를 써서 표현하는 것이 혼동을 미리 방지하는 효과가 있지 않나 싶다. 참고로 commit 권한은 잠시 언급했듯이 소수의 주요 프로젝트 리더들이 갖게 되는 경우가 많다. 어떤 오픈소스 프로젝트에서 커미터의 역할을 담당한다는 것은 그 사람의 기여도가 높고 그만큼 높은 위치를 배정받았다는 뜻이 된다.

    update와 commit에 관해서 또 하나 알아놓을 상식은 update와 commit 작업은 가능하면 자주 해 주는 것이 좋다는 사실이다. 다른 사람들이 내가 어떤 작업을 하는지 잘 알고, 나 역시 다른 사람들이 어떤 작업을 하고 있는지 잘 아는 것이 효율적인 협업(collaboration)의 기초가 됨은 두말할 필요가 없다. 추가적으로 CVS의 commit 명령 사용 예는 다음과 같다. -m 옵션 뒤에는 이번 commit에 대한 간략한 설명이나 주석문이 따라온다.

    $ cvs commit -m "added additioinal messages" hello2.c   # 파일 하나 commit 예

    $ pwd
    /home/foobar/projects/src1
    $ cvs commit -m "removed redundant declarations"       # 전체 디렉토리 commit 예

    ◆ log message : 수정된 소스코드를 commit할 때 이 소스코드가 어떤 역할을 하는지, 어떤 부분이 바뀌었는지 등을 기술하는 주석문 역할의 메시지이다. 이것 역시 코딩시 주석문 작성에 신경을 많이 쓰는 것처럼 수정된 소스코드를 commit할 때 마다 간결하고 정확하게 써 주는 것이 좋다.

    오픈소스 프로젝트에 많은 참여를
    지금까지 여러 명의 개발자, 특히 오픈소스 프로젝트에 참가할 때 필수적으로 쓰이는 유틸리티인 diff와 patch, 그리고 CVS의 기본 사용법에 대해서 알아보았다. 최근 들어서는 문서 작성도 오픈소스와 비슷하게 여러 사람이 동시에 같은 페이지를 고쳐 나가는 방식이 정착되어 가고 있다. 위키(wiki)의 사용이 늘어나고 있는 것이 바로 그것인데 위키는 내부적으로 RCS를 사용해서 문서의 버전 컨트롤을 해 나가는 경우가 많다. 즉, 위키를 통한 문서 작성 방식도 CVS를 이용한 오픈소스 소프트웨어 개발과 근본적으로 다르지 않은 것이다.

    앞에서도 강조했듯이, 오픈소스 프로젝트에 참여하기 위해서 가장 중요한 것은 diff와 patch의 사용법을 아는 것이다. 일견 간단해 보이는 이 유틸리티들이 이메일, 그리고 이메일의 확장판인 메일링 리스트와 초기 유즈넷 뉴스그룹과 결합되면서 인터넷상에서 중요 오픈소스 소프트웨어 개발의 문을 열어젖힌 주역들이다.

    또한, 이렇게 오픈소스 프로젝트에 참여하는 것이 생각만큼 어렵지 않다는 점을 일반 개발자들이 인지하는 것도 중요하다고 하겠다. 필자 역시 CVS의 사용법을 알기 전에는 내가 CVS의 사용법을 모르는데 오픈소스 프로젝트 참여가 가능하겠는가라는 쓸모없는 생각을 했던 적이 있다. 필자의 경우는 실제 떨어지는 코딩 능력이 오픈소스 프로젝트 참여에 장벽이 되고 있는데 이 글을 읽는 많은 독자들이 이번 연재를 계기로 오픈소스 프로젝트에 좀 더 많이 참여해 보는 기회를 가질 수 있으면 좋겠다는 것이 필자의 바람이다. 단 한 줄의 diff로 만든 패치라도 오픈소스 개발자에게는 많은 도움이 되며 또한 격려의 응원이 된다.
    반응형

    '기타' 카테고리의 다른 글

    초보자를 위한 Oracle 10g  (0) 2010.09.30
    스마트폰 보급이 1인 개발자 시대를 열 수 있을 것인가?  (0) 2010.09.09
    제로보드4 한글 안 나올때  (0) 2010.04.07
    wincvs 세팅  (0) 2010.04.07
    CVS 사용하기  (0) 2010.04.07

    댓글

Designed by Tistory.