더 자세한 내용은 윈도우 프로젝트 필수 유틸리티 Subversion, Trac, CruiseControl.NET을 참고하세요.

윈도우에서 Subversion과 ViewVC 사용하기

이재홍 http://www.pyrasis.com 2007.2.28 버전 1.0

 

Subversion의 웹 인터페이스인 ViewVC를 윈도우(Windows)에서 Apache와 mod_python을 이용해서 사용하는 방법을 설명하도록 하겠습니다. (원래는 ViewCVS 였는데 Subversion을 지원하면서 ViewVC로 이름이 바뀌었습니다.)

목차

필요한 파일들

프로그램 설치

윈도우에서 Subversion과 아파치를 이용한 서버를 구성하는 방법은 SubversionServerForWindows을 참고하세요.

Subversion, Apache, Python, Python extensions for Windows, Subversion Python Bindings, Mod_python은 모두 자동 인스톨러 형식이므로 일반적인 프로그램을 설치하듯이 설치합니다. 단, 설치 경로는 기본 값을 사용합니다

그리고 받은 viewvc-1.0.3.zip를 C:\temp에 압축을 해제합니다.

C:\temp\viewvc-1.0.3\viewvc-1.0.3>c:\python24\python.exe viewvc-install

기본값 대로 설치하면 C:\Program Files\viewvc-1.0.3에 설치됩니다.

Subversion 저장소 만들기

저장소의 기본 경로는 C:\repos로 하겠습니다.

C:\repos>svnadmin create sample

각 프로그램 설정

C:\Program Files\Apache Group\Apache2\conf\httpd.conf

LoadModule python_module modules/mod_python.so

ScriptAlias /viewvc "C:/Program Files/viewvc-1.0.3/bin/mod_python/viewvc.py"
<Location /viewvc>
    AddHandler mod_python .py
    PythonPath "[r'C:\\Program Files\\viewvc-1.0.3\\bin\\mod_python']+sys.path"
    PythonHandler handler
    PythonDebug On
    AddDefaultCharset UTF-8
    Options +Includes
</Location>

403 Error가 발생할 때에는 </Directory> 부분에 아래와 같이 Allow from all을 추가해줍니다.

<Directory />
    Options FollowSymLinks
    AllowOverride None
    #Order deny,allow
    #Deny from all
    Allow from all
    Satisfy all
</Directory>

C:\Program Files\viewvc-1.0.3\viewvc.conf

[general]
# 저장소의 최상위 디렉토리를 설정합니다.
root_parents = c:\repos : svn

# default_root는 주석 처리합니다.
#default_root = cvs

# Subversion이 설치된 경로
svn_path = C:\Program Files\Subversion\bin

[options]
# URL로 저장소를 구분합니다. 
# 이것을 0으로 하면 위의 default_root에서 기본 저장소를 지정해줘야 합니다.
root_as_url_component = 1

# UTC를 사용하지 않고 대한민국 표준시를 사용합니다.
use_localtime = 1

ViewVC의 handler.py 파일의 apache.import_module 부분을 다음과 같이 수정합니다. 이것을 수정하지 않으면 mod_python에서 모듈을 찾지 못하여 ViewVC를 실행할 수 없습니다. C:\Program Files\viewvc-1.0.3\bin\mod_python\handler.py

def handler(req):
  path, module_name = os.path.split(req.filename)
  module_name, module_ext = os.path.splitext(module_name)
  try:
    #module = apache.import_module(module_name, path=[path])
    module = apache.import_module(module_name, path)
  except ImportError:
    raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND

  req.add_common_vars()
  module.index(req)

  return apache.OK

diff, enscript, sed 설정

diff는 각 리비전간의 차이점을 볼 때 꼭 필요한 프로그램입니다.

enscript는 소스 코드 컬러링(Syntax highlighting)에 필요한 프로그램이며, sed는 enscript로 변환된 html 파일에서 특정 태그를 제거할 때 필요합니다.

diffutils와 ensript, sed는 설치파일 형태이기 때문에 별다른 설정 없이 바로 설치하면 됩니다. 설치경로는 기본값 그대로 합니다.

diff와 sed를 사용하기 위해 시스템 환경변수의 Path에 ‘'’C:\Program Files\GnuWin32\bin’'’를 추가합니다.

enscript 경로를 설정합니다. C:\Program Files\viewvc-1.0.3\viewvc.conf

# 0을 1로 수정합니다.
use_enscript = 1

# enscript.exe가 있는 디렉토리를 설정해줍니다.
enscript_path = C:\Program Files\GnuWin32\bin

한글 설정

ViewVC는 기본적으로 로그는 UTF-8로 표시해주지만 소스코드는 변환없이 그대로 출력합니다. 그래서 윈도우에서 저장한 소스파일은 cp949(euc-kr)이기 때문에 브라우저에서는 깨져서 출력됩니다. 브라우저의 인코딩을 euc-kr로 바꾸면 잘 보이지만 UTF-8로 인코딩된 로그가 깨져서 볼 수 없게 됩니다.

그래서 소스코드도 UTF-8로 변환하도록 ViewVC를 수정해 줘야 합니다. use_localtime을 1로 설정했을 경우 나오는 “대한민국 표준시”도 깨지지 않도록 UTF-8로 변환합니다. 아래는 패치입니다. (버전 1.0.3 기준) (http://plone.mucius.jp/blog/y2006m02d27e01 페이지를 참고하였습니다.) 소스를 직접 수정하기 귀찮으신 분들은 아래 패치가 적용된 handler.py viewvc.py blame.py을 사용하세요.

Index: blame.py
===================================================================
--- blame.py	(revision 5)
+++ blame.py	(working copy)
@@ -34,6 +34,7 @@
 import cgi
 import vclib
 import vclib.ccvs.blame
+import viewvc
 
 
 re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
@@ -82,7 +83,7 @@
     diff_url = None
     if item.prev_rev:
       diff_url = '%sr1=%s&amp;r2=%s' % (self.diff_url, item.prev_rev, item.rev)
-    thisline = link_includes(cgi.escape(item.text), self.repos,
+    thisline = link_includes(cgi.escape(viewvc.to_utf8(item.text)), self.repos,
                              self.path_parts, self.include_url)
     return _item(text=thisline, line_number=item.line_number,
                  rev=item.rev, prev_rev=item.prev_rev,
Index: viewvc.py
===================================================================
--- viewvc.py	(revision 5)
+++ viewvc.py	(working copy)
@@ -971,6 +971,7 @@
 _re_rewrite_url = re.compile('((http|https|ftp|file|svn|svn\+ssh)
(://[-a-zA-Z0-9%.~:_/]+)((\?|\&amp;)([-a-zA-Z0-9%.~:_]+)=
([-a-zA-Z0-9%.~:_])+)*(#([-a-zA-Z0-9%.~:_]+)?)?)')
 _re_rewrite_email = re.compile('([-a-zA-Z0-9_.\+]+)@(([-a-zA-Z0-9]+\.)+[A-Za-z]{2,4})')
 def htmlify(html):
+  html = to_utf8(html)
   html = cgi.escape(html)
   html = re.sub(_re_rewrite_url, r'<a href="\1">\1</a>', html)
   html = re.sub(_re_rewrite_email, r'<a href="mailto:\1&#64;\2">\1&#64;\2</a>', html)
@@ -1159,7 +1160,16 @@
         time.sleep(1)
         continue
     return chunk
-  
+
+def to_utf8(txt):
+  for enc in ['utf-8', 'euc-kr', 'cp949']:
+    try:
+      u = unicode(txt, enc)
+      return u.encode('utf-8')
+    except UnicodeError:
+      pass
+  return txt
+
 def copy_stream(src, dst=None, htmlize=0):
   if dst is None:
     dst = sys.stdout
@@ -1169,6 +1179,8 @@
       break
     if htmlize:
       chunk = htmlify(chunk)
+    else:
+      chunk = to_utf8(chunk)
     dst.write(chunk)
 
 class MarkupPipeWrapper:
@@ -1341,7 +1353,7 @@
     return 'Unknown date'
   if cfg.options.use_localtime:
     localtime = time.localtime(date)
-    return time.asctime(localtime) + ' ' + time.tzname[localtime[8]]
+    return time.asctime(localtime) + ' ' + to_utf8(time.tzname[localtime[8]])
   else:
     return time.asctime(time.gmtime(date)) + ' UTC'

사용하기

이제 아파치를 재시작 하면 ViewVC를 사용할 수 있습니다.

아파치는 재부팅을 하지 않으면 시스템 환경변수의 Path를 인식하지 못합니다. 그래서 diff, enscript, sed가 제대로 실행되지 않기 때문에 꼭 재부팅을 해줘야 합니다.
ViewVC 소스를 수정하였을 경우 아파치를 재시작 해야 적용이 되며, 그래도 적용이 안될 경우 ViewVC 아래에 있는 확장자가 .pyc 파일을 모두 삭제하면 됩니다.


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.

Published

28 February 2007