Subversion

オンラインドキュメント

https://subversion.apache.org/docs/

http://svnbook.red-bean.com/index.ja.html

WindowsOS向けGUIを備えたクライアント

TortoiseSVN

GUIでインポート、チェックアウト、コミットが可能である。

ダウンロードは https://tortoisesvn.net/downloads.html から行う。

リポジトリブラウザ

Redmine

各ファイルの内容表示と、任意のリビジョン間での差分表示(View differences)が可能である。

Fedora33での環境の構築

サーバの準備

パッケージをインストールする。

# yum install subversion mod_dav_svn
1

リポジトリを作成する。

# mkdir -p /var/svn/repos
# cd /var/svn/repos
# svnadmin create repo1
# svnadmin create repo2
1
2
3
4

リポジトリ所有者をapacheへ変更する。

# chown -R apache. /var/svn/repos
1

ユーザを作成する。

# htpasswd -c /var/svn/htpasswd user1
# htpasswd /var/svn/htpasswd user2
# htpasswd /var/svn/htpasswd user3
1
2
3

以下の内容で /etc/httpd/conf.d/subversion.conf を作成する。

<Location /svn>
  DAV svn
  SVNListParentPath on
  SVNParentPath /var/svn/repos/
 
  AuthType Basic
  AuthName "Subversion Repositories"
  AuthUserFile /var/svn/htpasswd
  require valid-user
</Location>
1
2
3
4
5
6
7
8
9
10

apacheを再起動する。

# systemctl restart httpd
1

リポジトリバックアップスクリプト

以下の内容で fire_svn.py を作成する。

import fire
import datetime
import os
import shutil
import schedule
import time
import py7zr
import glob
 
 
class Svn(object) :
    """リポジトリのバックアップ、7z圧縮を実行するクラスです。"""
    
    def __init__(self) :
        self.__repo_parent_dir = "/var/svn/repos"
        self.__repo_list = ( "repo1", "repo2" )
        self.__local_backup_dir_path = "/home/eagle_eight/SVN_backup"
        self.__network_drive_dir_path = "/mnt/hgfs/eagle_eight/SVN_backup"
    
    def __svn_dump(self) :
        dt_now = datetime.datetime.now()
        date_str = dt_now.strftime('%Y-%m-%d')
        
        os.chdir(self.__local_backup_dir_path)
        
        for repo in self.__repo_list :
            dump_file_name = "{}_{}.dump".format(repo, date_str)
            command = "svnadmin dump {} > {}".format(os.path.join(self.__repo_parent_dir, repo), dump_file_name)
            print(command)
            os.system(command)
    
    def __get_today_dump_file_list(self) :
        dt_now1 = datetime.datetime.now()
        date_str1 = dt_now1.strftime('%Y-%m-%d')
        
        os.chdir(self.__local_backup_dir_path)
        dump_file_list = glob.glob("*_{}.dump".format(date_str1))
        
        return dump_file_list
    
    def backup(self) :
        """リポジトリのバックアップを実行します。"""
        self.__svn_dump()
        dump_file_list1 = self.__get_today_dump_file_list()
        
        for dump_file1 in dump_file_list1 :
            shutil.copy2(dump_file1, os.path.join(self.__network_drive_dir_path, dump_file1))
    
    def backup_7z(self) :
        """リポジトリのバックアップ、7z圧縮を実行します。"""
        self.__svn_dump()
        dump_file_list2 = self.__get_today_dump_file_list()
        
        dt_now = datetime.datetime.now()
        date_str = dt_now.strftime('%Y-%m-%d')
        archive_file_name = "SVN_backup_{}.7z".format(date_str)
        
        with py7zr.SevenZipFile(archive_file_name, 'w') as archive :
            for file in dump_file_list2 :
                archive.write(file)
        
        shutil.copy2(archive_file_name, os.path.join(self.__network_drive_dir_path, archive_file_name))
    
    def backup_daily(self) :
        """リポジトリの自動デイリーバックアップを実行します。"""
        
        schedule.every().day.at("01:30").do(self.backup)
        
        while True :
            schedule.run_pending()
            time.sleep(1)
    
    def backup_7z_daily(self) :
        """リポジトリの自動デイリーバックアップ、7z圧縮を実行します。"""
        
        schedule.every().day.at("01:30").do(self.backup_7z)
        
        while True :
            schedule.run_pending()
            time.sleep(1)
 
 
if __name__ == '__main__' :
    fire.Fire(Svn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84

ターミナルで python3 fire_svn.py backup_7z_daily を実行する。