SVN 서버 구성 팁

SVN 서버 구성시 내가 사용했던 유용한 팁을 일부 정리해 본다.

디렉토리별 권한 할당

  1. 저장소의 디렉토리 별로 사용자마다 다른 엑세스 권한을 할당하고 싶을 때 사용할 수 있다.
  2. 저장소의 conf 디렉토리에 있는 svnserve.conf 파일에서 아래 예와 같이 수정한다.
    [general]
    authz-db = authz
    
  3. 저장소 conf 디렉토리의 authz 파일에서 아래 예와 같이 수정한다. (즉, 디렉토리별로 접근을 허락할 ID와 권한을 입력함, 개별 유저나 group 유저도 가능)
    [groups]
    calc-developers = harry, sally, joe
    paint-developers = frank, sally, jane
    everyone = @calc-developers, @paint-developers
    [/]                     # 최상위 디렉토리
    everyone = r
    [/project/calc]         # project/calc 디렉토리
    @calc-developers = rw
    @paint-developers =     # (read도 안 되게 함)
    user1 = rw
    [/project/paint]        # project/paint 디렉토리
    @paint-developers = rw
    user2 = r
    

SVN 저장소 dump

  1. 저장소 전체 revision 덤프는 아래 예와 같이 할 수 있다.
    $ sudo svnadmin dump repo_name > repo_name.dump
    
  2. 저장소 일부 revision 만 덤프하는 경우에는 아래와 같이 할 수 있다. (LOWER, UPPER는 원하는 revision 번호 범위)
    $ sudo svnadmin dump repo_name --incremental -r LOWER[:UPPER] > repo_name.dump
    

SVN 저장소 load

  1. 아래 예와 같이 저장소를 생성한 후에, load 할 수 있다.
    $ sudo svnadmin create repo_name
    $ sudo svnadmin load repo_name < repo_name.dump
    
  2. 저장소의 일부 revision 만 로드하는 경우에는 아래 예와 같이 할 수 있다. (LOWER, UPPER는 원하는 revision 번호 범위)
    $ sudo svnadmin load repo_name -r LOWER:UPPER < repo_name.dump
    
  3. 참고로 아래 예와 같이 dump 한 저장소를 다른 저장소에 합칠 수도 있다. (--parent-dir 옵션은 저장소의 지정된 디렉토리에 로드하는 옵션임)
    $ sudo svn mkdir file:///srv/repo_name/newly_added_dir
    $ sudo svnadmin load repo_name --parent-dir newly_added_dir < repo_name.dump
    

Commit 로그 미입력시 commit 막기

  1. 일부 개발자들은 고의나 실수로 commit 시 로그를 입력하지 않는 경우가 있는데, 이는 SVN 디폴트가 이것을 허용하기 때문이다. 나는 주로 SVN 저장소 구성시에 아래 방법을 사용하여 commit 로그가 없으면 commit이 실패되게 만든다.
  2. SVN 저장소의 hooks 디렉토리로 이동한 후에, 아래와 같이 pre-commit 파일을 만든다.
    $ sudo cp pre-commit.tmpl pre-commit
    
  3. pre-commit 파일을 열어서 아래 예와 같이 수정한다.
    # Make sure that the log message contains some text.
    ERROR=0
    svnlook log -t "$TXN" "$REPOS" | grep "[a-zA-Z0-9]" > /dev/null || ERROR=1
    if [ $ERROR -eq 1 ]; then
        echo "[Please enter a log message.]" 1>&2
        exit 1
    fi
    
  4. 이제부터는 SVN commit 시 로그를 입력하지 않으면 [Please enter a log message.] 메시지가 뜨면서 commit이 되지 않는다.

Commit 로그 수정하기

  1. SVN 로그 수정은 history 관리상 디폴트로 disable 되어 있다. 그런데 만약 오타 등의 이유로 로그를 수정하고 싶으면 먼저 로그 수정을 enable 시켜야 한다.
    이를 위해서는 SVN 저장소의 hooks 디렉토리로 이동한 후에, 아래와 같이 pre-revprop-change 파일을 생성하면 된다.
    $ sudo cp pre-revprop-change.tmpl pre-revprop-change
    
  2. 다시 로그 수정을 disable 시키려면, 생성했던 pre-revprop-change 파일을 삭제하면 된다.

SVN 동작시 메일 보내기

  1. SVN에서 특정 동작시에 (예: lock, unlock, commit 등) 메일을 보내려면 해당 hook 파일에서 메일을 발송하는 프로그램을 호출하면 되는데, 메일 발송 프로그램은 Python, Java, Javascript, Go 등 본인이 원하는 언어로 작성하면 된다.
    여기서는 가장 간단히 구현하기 위하여 mail 패키지를 이용하는 방법을 소개한다.
  2. 아래 예와 같이 mail 패키지를 설치한다.
    $ sudo apt install mailutils
    
  3. Gmail을 이용한 SMPT 메일 서버를 구축하여 mail 명령이 동작하는 상태로 구성한다.
    아래 예와 같이 테스트시 본인 이메일로 송신시 메일이 수신되어야 한다.
    $ echo "메일 본문 테스트" | mail -s "메일 제목 테스트" your@mailaddress
    
  4. 예를 들어 SVN lock 시에 메일을 보내려면 SVN 저장소의 hooks 디렉토리에서 post-lock 파일을 아래 예와 같이 작성할 수 있다.
    REPOS="$1"
    USER="$2"
    
    read var
    FILENAME="Locked file: \"${REPOS}${var}\" by '${USER}'"
    
    if [ "${USER}" = "user1" ]; then
    mailAddress="user1@mail_address"
    elif [ "${USER}" = "user2" ]; then
    mailAddress="user1@mail_address"
    fi
    
    if [ -n ${mailAddress} ]; then
    echo ${FILENAME} | mail -s "SVN file lock alarm" ${mailAddress}
    fi
    

    SVN unlock 시에도 메일을 보내려면 마찬가지로 SVN 저장소의 hooks 디렉토리의 post-unlock 파일을 수정하면 된다.

Web 환경으로 SVN 접속하기

  1. 별도의 SVN client 없이도 Web으로 바로 SVN 파일들을 읽을 수 있게 하면 유용한 경우가 있다. (나는 이렇게 설정한 후에 팀의 DokuWiki 페이지에서 링크를 걸어서 연계해서 사용하고 있음)
  2. 아래와 같이 필요한 패키지를 설치한다.
    $ sudo apt install subversion apache2 apache2-utils libapache2-svn
    

    만약 libapache2-svn 패키지를 찾을 수 없다고 나오면, 아래와 같이 실행한 후 다시 시도해본다.

    $ sudo add-apt-repository main
    $ sudo add-apt-repository universe
    $ sudo add-apt-repository restricted
    $ sudo add-apt-repository multiverse
    $ sudo apt update
    
  3. 아래 예와 같이 SVN 저장소의 owner를 root에서 www-data로 변경한다. (예로 저장소 이름은 repo_name 사용)
    $ sudo chown -R www-data:www-data /srv/repo_name/
    
  4. /etc/apache2/mods-enabled/dav_svn.conf 파일을 아래 예와 같이 작성한다. (예로 저장소 이름은 repo_name 사용)
    <Location /svn>
      DAV svn
      SVNParentPath /srv/
      AuthType Basic
      AuthName "Subversion Repository"
      AuthUserFile /etc/apache2/dav_svn.passwd
      <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
      </LimitExcept>
    </Location>
    
    <Location /svn/repo_name>
      DAV svn
      SVNParentPath /srv/repo_name/
      AuthType Basic
      AuthName "Subversion Repository"
      AuthUserFile /etc/apache2/dav_svn.passwd
      <LimitExcept GET PROPFIND OPTIONS REPORT>
        Require valid-user
      </LimitExcept>
    </Location>
    
  5. 참고로 만약 아무나 읽지 못하도록 access시 ID/PW로 승인받으려면, 위 conf 파일에서 <LimitExcept>, </LimitExcept> 줄을 막으면 된다. 이때 사용자는 아래 예와 같이 추가할 수 있고 (실행하면 암호 생성 입력 받음), 결과로 /etc/apache2/dav_svn.passwd 파일이 생성된다.
    $ sudo htpasswd -cm /etc/apache2/dav_svn.passwd user1
    $ sudo htpasswd -m /etc/apache2/dav_svn.passwd user2
    
  6. 아래와 같이 아파치 서버를 재시작한다.
    $ sudo service apache2 restart
    
  7. 이제 웹브라우저에서 http://server_address/svn/repo_name/ 주소로 접속하면 웹브라우저에서 바로 SVN 파일들의 내용을 확인할 수 있다.

참고로 svn log 명령 자체에서는 하위 external link 된 저장소의 로그를 재귀적으로 출력해 주는 기능이 없어서 불편하였는데, 아래와 같은 스크립트를 만들어서 이용하니 이 경우에 편리하였다.
아래 스크립트는 입력 base 경로의 SVN log 및 재귀적으로 하위 svn:externals 정보를 파싱하여 각각의 external path의 SVN log를 출력한다.

#!/bin/bash
# IFS: Internal Field Separator

svn_log_externals() {
    local base_path="$1"
    local externals_paths

    echo -e "\e[91m[SVN logs for $base_path]\e[0m"
    svn log "$base_path"

    externals_paths=$(svn propget svn:externals "$base_path" 2> /dev/null)
    if [ -n "$externals_paths" ]; then
        IFS=$'\n'
        for external_path in $externals_paths; do
            if [ ${#external_path} -le 1 ]; then
                break
            fi
            IFS=$' ' read -r str1 str2 <<< "$external_path"
            if (( ${#str1} < ${#str2} )); then
                sub_path=$str1
            else
                sub_path=$str2
            fi
            echo
            svn_log_externals "$base_path/$sub_path"
        done
    fi
}

if [ $# -eq 0 ]; then
    svn_log_externals .
else
    svn_log_externals "${1%/}"
fi

위 스크립트를 /usr/bin/svnlog 이름으로 저장하고 실행 권한을 준 후, 아래 예와 같이 실행하면 해당 디렉토리의 모든 하위 external link 된 저장소의 SVN log가 출력된다.

$ svnlog

또는

$ svnlog <디렉토리>

카테고리:

업데이트: