﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>PHP博客-为了忘却的纪念   $bestmost-&gt;save("多多益善")-随笔分类-软件工程</title><link>http://www.phpweblog.net/fuyongjie/category/611.html</link><description>言己及众</description><language>zh-cn</language><lastBuildDate>Mon, 05 Jan 2009 18:56:25 GMT</lastBuildDate><pubDate>Mon, 05 Jan 2009 18:56:25 GMT</pubDate><ttl>60</ttl><item><title>（转）Windows下Subversion配置管理员指南</title><link>http://www.phpweblog.net/fuyongjie/archive/2009/01/05/6265.html</link><dc:creator>bestmost</dc:creator><author>bestmost</author><pubDate>Mon, 05 Jan 2009 06:07:00 GMT</pubDate><guid>http://www.phpweblog.net/fuyongjie/archive/2009/01/05/6265.html</guid><wfw:comment>http://www.phpweblog.net/fuyongjie/comments/6265.html</wfw:comment><comments>http://www.phpweblog.net/fuyongjie/archive/2009/01/05/6265.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.phpweblog.net/fuyongjie/comments/commentRss/6265.html</wfw:commentRss><trackback:ping>http://www.phpweblog.net/fuyongjie/services/trackbacks/6265.html</trackback:ping><description><![CDATA[<table width="760" align="center" border="0" cellpadding="0" cellspacing="0">
    <tbody>
        <tr>
            <td class="title" valign="middle" align="center" height="56"><strong><font size="3" color="#ff0000"><br>
            </font></strong></td>
        </tr>
        <tr>
            <td class="formtitle" align="center" height="40"><!-- #BeginEditable "2" -->作者：
            rocksun 　来源：Subversion<br>
            <!-- #EndEditable --></td>
        </tr>
    </tbody>
</table>
<table width="760" align="center" border="0" cellpadding="0" cellspacing="0" height="65">
    <tbody>
        <tr>
            <td class="content" height="65"><!-- #BeginEditable "3" -->
            <table class="content" width="100%" align="center" border="0">
                <tbody>
                    <tr>
                        <td class="content">
                        <p><strong> Subversion安装成service
                        </strong> <br>
                        <br>
                        以前的svnserve要想成为windows服务，必须依赖于svnservice或其他工具。从Subversion1.4开始，Subversion本身就集成Windows服务的工具。
                        </p>
                        <p><strong> 1，安装svnservice</strong> <br>
                        <br>
                        在Windows NT中（包括Windows XP, Windows 2000, Windows 2003 Server）本身包含了一个安装服务的工具，叫做"Service
                        Control"，也就是sc.exe。</p>
                        <p>例如我的Subversion安装在"D:\Subversion"，版本库在"D:\svnroot"，而我希望对应的Subversion服务名为svnservice，安装这个svn服务的命令就可以这样写：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">sc create svnservice<br>
                                    binpath= "D:\Subversion\bin\svnserve.exe --service -r D:\svnroot"<br>
                                    displayname= "SVNService"<br>
                                    depend= Tcpip</td>
                                </tr>
                            </tbody>
                        </table>
                        <p> 请注意，因为便于察看，上面的命令分为多行，但在实际执行时应该在一行里。另外，在以前启动svnserve时会使用"-d"选项，也就是守护进程模式，在这里不能使用，会导致服务无法启动。同样，"-i"和"-t"选项也不能使用。</p>
                        <p>在命令行窗口执行完这个命令之后，服务还没有启动，你可以继续运行"net start
                        svnservice"启动这个服务，然后使用"net stop svnservice"停止服务。</p>
                        <p>另外还有两点需要小心处理。首先，如果路径中包括空格，一定要用&#8220;\&#8221;处理&#8220;"&#8221;号，例如上面的例子中如果svnserve.exe在&#8220;c:\program
                        files\subversion\&#8221;中，则命令应该写为&#8220;binpath= "\"c:\program files\subversion\bin\svnserve.exe\"&#8221;（&#8220;&#8221;中的内容），整个命令如下，红色部分是改变部分：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">sc create svnservice<br>
                                    binpath= "\"D:\program files\Subversion\bin\svnserve.exe\"
                                    --service -r D:\svnroot"<br>
                                    displayname= "SVNService"<br>
                                    depend= Tcpip</td>
                                </tr>
                            </tbody>
                        </table>
                        <p> 其次，sc对选项的格式还有要求，例如&#8220;depend= Tcpip&#8221;不能写为&#8220;depend =
                        Tcpip&#8221;或&#8220;depend=Tcpip&#8221;，也就是&#8220;=&#8221;前不能有空各，而后面必须有空格。</p>
                        <p><strong> 2，删除服务</strong> <br>
                        <br>
                        如果服务安装的有问题，你可能需要删除服务。要删除前面添加的服务，只需要运行"net start svnservice"，"svnservice"就是我们创建服务时使用的名字。</p>
                        <p><strong> 3，配置服务是自动启动</strong> <br>
                        <br>
                        默认情况下安装的服务不会随Windows的启动而启动，为了使svn服务能够随Windows启动而启动，需要修改一下"sc
                        create"命令（首先要删除），增加"start= auto"选项：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">sc create svnservice<br>
                                    binpath= "D:\Subversion\bin\svnserve.exe --service -r D:\svnroot"<br>
                                    displayname= "SVNService"<br>
                                    depend= Tcpip<br>
                                    start= auto</td>
                                </tr>
                            </tbody>
                        </table>
                        <p> 当然你也可以使用图形化的工具修改服务的属性，你可以在&#8220;开始-&gt;运行...&#8221;中执行"services.msc"，然后在界面中修改。</p>
                        <p><strong>  Subversion的权限控制</strong>  <br>
                        <strong> <br>
                        1，认证（Authentication）和授权（Authorization）</strong> <br>
                        <br>
                        这两个术语经常一起出现。其中认证的意思就是鉴别用户的身份，最常见的方式就是使用用户名和密码，授权就是判断用户是否具备某种操作的权限，在
                        Subversion里提供了&#8220;authz-db&#8221;文件，实现了以路径为基础的授权，也就是判断用户是否有操作对应路径的权限，在Subversion
                        1.3之后，svnserve和Apache一样都可以使用&#8220;authz-db&#8221;文件。 </p>
                        <p><strong> 2. svnserve下的配置文件</strong> <br>
                        <br>
                        因为本文是以svnserve为例的，所以先介绍一下版本库目录的结构：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">D:\SVNROOT\PROJECT1<br>
                                    ├─conf<br>
                                    ├─dav<br>
                                    ├─db<br>
                                    │ ├─revprops<br>
                                    │ ├─revs<br>
                                    │ └─transactions<br>
                                    ├─hooks<br>
                                    └─locks</td>
                                </tr>
                            </tbody>
                        </table>
                        <p>其中conf下面有三个文件：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">authz<br>
                                    passwd<br>
                                    svnserve.conf</td>
                                </tr>
                            </tbody>
                        </table>
                        <p>其中的&#8220;svnserve.conf&#8221;是这个版本库的配置文件，当使用svnserve时，这个配置文件决定了使用什么认证和授权文件：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">password-db = passwd<br>
                                    authz-db = authz</td>
                                </tr>
                            </tbody>
                        </table>
                        <p> 上面的配置说明使用&#8220;svnserve.conf&#8221;同目录的passwd和authz，其中的password-db指定了用户密码文件，authz-db是我们的授权文件，也就是我们本文主要介绍的文件。</p>
                        <p>注意：使用Apache作为服务器时，根本就不会参考&#8220;svnserve.conf&#8221;文件的内容，而是会参考Apache的配置。</p>
                        <p><strong> 3，基于svnserve的版本库文件布局</strong> <br>
                        <br>
                        使用svnserve时，为了管理的方便，应该使用相同的认证和授权文件，所以应该让所有版本库的配置文件svnserve.conf指向同一个password-db和authz-db文件。下面是一个多版本库的目录：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">D:\SVNROOT<br>
                                    ├─project1<br>
                                    │ ├─conf<br>
                                    │ ├─dav<br>
                                    │ ├─db<br>
                                    │ │ ├─revprops<br>
                                    │ │ ├─revs<br>
                                    │ │ └─transactions<br>
                                    │ ├─hooks<br>
                                    │ └─locks<br>
                                    └─project2<br>
                                    ├─conf<br>
                                    ├─dav<br>
                                    ├─db<br>
                                    │ ├─revprops<br>
                                    │ ├─revs<br>
                                    │ └─transactions<br>
                                    ├─hooks<br>
                                    └─locks</td>
                                </tr>
                            </tbody>
                        </table>
                        <p> D:\SVNROOT下有两个目录project1和project2，都已经创建了版本库，所以我们修改每个conf目录下的svnserve.conf，使之指向同一个password-db和authz-db文件。</p>
                        <p>password-db = ..\..\passwd<br>
                        <br>
                        authz-db =
                        ..\..\authz这样，D:\SVNROOT\passwd和D:\SVNROOT\authz就控制了所有版本库的svnserve访问。另外在
                        后面的操作中要关闭匿名访问，应该去掉&#8220;anon-access = none&#8221;前的&#8220;#&#8221;号，保证只有认证用户可以访问。</p>
                        <p>注意：还有一点需要注意，那就是svnserve的&#8220;realm&#8221;的值，在上面的设置下，应该保证所有的版本库使用相同的realm值，这样，对版本库的密码缓存可以在多个版本库之间共享，更多细节见客户端凭证缓存。</p>
                        <p><strong> 4，测试用户和组说明</strong> <br>
                        <br>
                        版本库禁止任何匿名用户的访问，只对认证用户有效。</p>
                        <p>root:配置管理管理员，对版本库有完全的管理权限。</p>
                        <p>p1_admin1:project1的管理员，对project1有完全权限。<br>
                        p1_d1:project1的开发者，对project1的trunk有完全的权限，但是对其中的/trunk/admin目录没有任何权限。<br>
                        p1_t1:project1的测试者，对project1的trunk有完全的读权限，但是对其中的/trunk/admin目录没有任何权限。</p>
                        <p>p2_admin1:project2的管理员，对project2有完全权限。<br>
                        p2_d1:project2的开发者，对project2的trunk有完全的权限，但是对其中的/trunk/admin目录没有任何权限。<br>
                        p2_t1:project2的测试者，对project2的trunk有完全的读权限，但是对其中的/trunk/admin目录没有任何权限。</p>
                        <p>对应的组及组的用户：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">p1_group_a:p1_admin1<br>
                                    p1_group_d:p1_d1<br>
                                    p1_group_t:p1_t1<br>
                                    p2_group_a:p2_admin1<br>
                                    p2_group_d:p2_d1<br>
                                    p2_group_t:p2_t1</td>
                                </tr>
                            </tbody>
                        </table>
                        <p> <strong> 5，修改D:\SVNROOT\passwd文件</strong> </p>
                        <p>前面已经说过了，用户和密码文件应该是在D:\SVNROOT\passwd，所以我们为每一位用户设置权限，文件内容如下：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">[users]<br>
                                    p1_admin1 = p1_admin1<br>
                                    p1_d1 = p1_d1<br>
                                    p1_t1 = p1_t1<br> <br>
                                    p2_admin1 = p2_admin1<br>
                                    p2_d1 = p2_d1</td>
                                </tr>
                            </tbody>
                        </table>
                        <p>p2_t1 = p2_t1为了便于验证，所有密码和用户名一致，如果你使用的是其他认证方式，这一步可能不同，但是用户名应该都是一样的。</p>
                        <p><strong> 6，配置授权，修改D:\SVNROOT\authz</strong> </p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">
                                    <p>[groups]<br>
                                    # 定义组信息</p>
                                    <p>p1_group_a = p1_admin1<br>
                                    p1_group_d = p1_d1<br>
                                    p1_group_t = p1_t1</p>
                                    <p>p2_group_a = p2_admin1<br>
                                    p2_group_d = p2_d1<br>
                                    p2_group_t = p2_t1</p>
                                    <p>[/]<br>
                                    # 指定所有的版本库默认只读，root可读写<br>
                                    * = r<br>
                                    root = rw</p>
                                    <p>[project1:/]<br>
                                    # 指定对版本库project1根目录的权限<br>
                                    @p1_group_a = rw<br>
                                    @p1_group_d = rw<br>
                                    @p1_group_t = r</p>
                                    <p>[project1:/trunk/admin]<br>
                                    # 指定对版本库project1的/trunk/admin根目录的权限，<br>
                                    # p1_group_a读写，p1_group_d和p1_group_t没有任何权限。<br>
                                    @p1_group_a = rw<br>
                                    @p1_group_d = <br>
                                    @p1_group_t = </p>
                                    <p>[project2:/]<br>
                                    # 指定对版本库project2根目录的权限<br>
                                    @p2_group_a = rw<br>
                                    @p2_group_d = rw<br>
                                    @p2_group_t = r</p>
                                    <p>[project2:/trunk/admin]<br>
                                    # 指定对版本库project1的/trunk/admin根目录的权限<br>
                                    @p2_group_a = rw<br>
                                    @p2_group_d = <br>
                                    @p2_group_t = </p>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>经过以上设置以后，你会发现一些有趣的事情。当使用用户&#8220;p1_d1&#8221;，检出project1的trunk时，目录是空的，好像admin目录根本不存在一样，当使用p1_d1用户浏览版本库时，能够看到admin目录，但是其中的内容却无法看到。</p>
                        <p>关
                        于中文目录，也是没有问题的，只是注意要把authz文件转化为UTF-8格式，在我的WINXP的UltraEdit里显示的文件格式为U8-DOS，
                        具体的做法是用UltraEdit打开authz文件，然后选择&#8220;文件-&gt;转换-&gt;ASCII转UTF-8&#8221;，然后保存。</p>
                        <p>再复杂的情况也不过如此，在实际的工作中要首先规划好权限，只赋给用户最小的权限，保证以最小的配置实现最复杂的权限控制。</p>
                        <strong>  Subversion备份<br>
                        <br>
                        </strong> 版本控制最关键的一件事是保证数据的安全性，不能因为磁盘损坏，程序故障造成版本库无可挽回的错误，为此必须制定较完备的备份策略。在Subversion中，我们有三种备份方式：完全备份，增量备份和同步版本库。
                        <p><strong> 1, 完全备份</strong> <br>
                        <br>
                        最常见和简单的备份就是直接使用拷贝命令，将版本库目录拷贝到备份目录上，就可以了。但是这样不是很安全的方式，因为如果在拷贝时版本库发生变化，将会
                        造成备份的结果不够准确，失去备份的作用，为此Subversion提供了&#8220;svnadmin hotcopy&#8221;命令，可以防止这种问题。</p>
                        <p>还记得我们的版本库目录吗？</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">D:\SVNROOT<br>
                                    ├─project1<br>
                                    │ ├─conf<br>
                                    │ ├─dav<br>
                                    │ ├─db<br>
                                    │ │ ├─revprops<br>
                                    │ │ ├─revs<br>
                                    │ │ └─transactions<br>
                                    │ ├─hooks<br>
                                    │ └─locks<br>
                                    └─project2<br>
                                    ├─conf<br>
                                    ├─dav<br>
                                    ├─db<br>
                                    │ ├─revprops<br>
                                    │ ├─revs<br>
                                    │ └─transactions<br>
                                    ├─hooks<br>
                                    └─locks<br> </td>
                                </tr>
                            </tbody>
                        </table>
                        <p> 如果要把project1备份到d:\svnrootbak目录下，只需要运行：</p>
                        <p>svnadmin hotcopy d:\svnroot\project1 d:\svnrootbak\project1</p>
                        <p>但是我们作为配置管理员，必须想办法优化这个过程，如果我们这个目录下有许多版本库，需要为每个版本库写这样一条语句备份，为此我写了下面的脚本，实现备份一个目录下的所有版本库。我们在D:\SVNROOT下创建了两个文件，simpleBackup.bat：</p>
                        <p>@echo 正在备份版本库%1......<br>
                        @%SVN_HOME%\bin\svnadmin hotcopy %1 %BACKUP_DIRECTORY%\%2<br>
                        @echo 版本库%1成功备份到了%2！</p>
                        <p>这个文件仅仅是对&#8220;svnadmin hotcopy&#8221;的包装，然后是backup.bat：</p>
                        <p>echo off</p>
                        <p>rem Subversion的安装目录<br>
                        set SVN_HOME="D:\Subversion"</p>
                        <p>rem 所有版本库的父目录<br>
                        set SVN_ROOT=D:\svnroot</p>
                        <p>rem 备份的目录<br>
                        set BACKUP_SVN_ROOT=D:\svnrootbak</p>
                        <p>set BACKUP_DIRECTORY=%BACKUP_SVN_ROOT%\%date:~0,10%<br>
                        if exist %BACKUP_DIRECTORY% goto checkBack<br>
                        echo 建立备份目录%BACKUP_DIRECTORY%&gt;&gt;%SVN_ROOT%/backup.log</p>
                        <p>mkdir %BACKUP_DIRECTORY%</p>
                        <p>rem 验证目录是否为版本库，如果是则取出名称备份<br>
                        for /r %SVN_ROOT% %%I in (.) do @if exist "%%I\conf\svnserve.conf"
                        %SVN_ROOT%\simpleBackup.bat "%%~fI" %%~nI<br>
                        goto end</p>
                        <p>:checkBack<br>
                        echo 备份目录%BACKUP_DIRECTORY%已经存在，请清空。<br>
                        goto end</p>
                        <p>:end</p>
                        <p>你
                        在使用的时候，只需要修改backup.bat开头的三个路径，将两个脚本拷贝到&#8220;SVN_ROOT&#8221;下就可以了。根据以上的配置，你只需要运行
                        backup.bat，就可以把&#8220;SVN_ROOT&#8221;下的版本库都备份到&#8220;BACKUP_SVN_ROOT&#8221;里，并且存放在备份所在日的目录里，例如
                        &#8220;D:\svnrootbak\2006-10-22&#8221;。</p>
                        <p>虽然这部分工作很简单，可是必须有人定时地去执行这个操作（例如每周一凌晨），为了避免发生遗忘的情况，我们可以将这个操作加入到系统的at任务当中去，例如还是上面的环境，为了安装at任务，我们运行：</p>
                        <p>at 1:00 /every:M D:\svnroot\backup.bat这样在每周一凌晨1:00都会执行这个备份过程。当然备份在本机也是不安全的，你也许需要上传到别的机器，这个就要靠你自己去实现了。</p>
                        <p><strong> 2, 增量备份</strong> <br>
                        <br>
                        尽管完全备份非常简单，但是也是有代价的，当版本库非常巨大时，经常进行完全备份是不现实的，也并不必要，但是一旦版本库在备份之间发生问题，该如何呢，这里我们就用到了增量备份。</p>
                        <p>增量备份通常要与完全备份结合使用，就像oracle数据库的归档日志，记录着每次Subversion提交的变化，然后在需要恢复时能够回到最新的可用状态。在我们这个例子中我们使用的是，svnadmin
                        dump命令进行增量的备份，使用方法是：</p>
                        <p>svnadmin dump project1 --revision 15 --incremental
                        &gt; dumpfile2</p>
                        <p>上面的命令实现了对修订版本15进行增量的备份，其中的输出文件dumpfile2只保存了修订版本15更改的内容。</p>
                        <p>为了记录每次提交的结果，我们需要使用一项Subversion的特性--钩子（hook），看看我们的project1目录：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">├─project1<br>
                                    │ ├─conf<br>
                                    │ ├─dav<br>
                                    │ ├─db<br>
                                    │ │ ├─revprops<br>
                                    │ │ ├─revs<br>
                                    │ │ └─transactions<br>
                                    │ ├─hooks<br>
                                    │ └─locks</td>
                                </tr>
                            </tbody>
                        </table>
                        <p>其中的hooks目录里存放的就是钩子脚本，我们在此处只使用post-commit钩子，这个钩子会在每次提交之后执行，为了实现我们的备份功能，我们在hooks下建立一个文件post-commit.bat，内容如下：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">echo off<br>
                                    set SVN_HOME="C:\Program Files\Subversion"<br>
                                    set SVN_ROOT=D:\svnroot<br>
                                    set UNIX_SVN_ROOT=D:/svnroot<br>
                                    set DELTA_BACKUP_SVN_ROOT=D:\svnrootbak\delta<br>
                                    set LOG_FILE=%1\backup.log<br>
                                    echo backup revision %2 &gt;&gt; %LOG_FILE%<br>
                                    for /r %SVN_ROOT% %%I in (.) do if D:/svnroot/%%~nI == %1 %SVN_ROOT%\%%~nI\hooks\deltaBackup.bat
                                    %%~nI %2<br>
                                    goto end<br>
                                    :end</td>
                                </tr>
                            </tbody>
                        </table>
                        <p>通过这个脚本，可以实现D:\svnroot下的版本库提交时自动增量备份到D:\svnrootbak\delta（确定这个目录存在），其中使用的deltaBackup.bat其实可以放在任何地方，只是对脚本的svnadmin
                        dump的包装，内容如下：</p>
                        <p>@echo 正在备份版本库%2......<br>
                        %SVN_HOME%\bin\svnadmin dump %SVN_ROOT%\%1 --incremental --revision
                        %2 &gt;&gt; %DELTA_BACKUP_SVN_ROOT%\%1.dump<br>
                        @echo 版本库%2成功备份到了%3！</p>
                        <p>以上两个脚本可以直接拷贝到project2的hooks目录下，不需要修改就可以实现project2的自动备份。</p>
                        <p>以上的操作已经OK了，现在需要做的是将完全备份和增量备份结合起来，也就是在完全备份后清理增量备份的结果，使之只保存完全备份后的结果。</p>
                        <p>当果真出现版本库的故障，就要求我们实现版本库的恢复操作了，这是用要使用svnadmin load命令，同时也需要上次的完全备份例如要把上次完全备份backuprepo，和之后的增量备份dumpfile：</p>
                        <p>svnadmin load backuprepo &lt; dumpfile</p>
                        <p>最后的结果，可以下载svnroot.rar，将之解压缩到d:\下，然后修改几个bat文件的SVN_HOME就可以使用了。</p>
                        <p><strong> 3, 版本库同步</strong> <br>
                        <br>
                        Subversion 1.4增加了同步机制，可以实现一个版本库同另一个版本库的同步（但好像只是单向的），我们可以用来实现版本库的备份或镜像。</p>
                        <p><strong> 3.1. 对目标库初始化</strong> <br>
                        <br>
                        svnsync init svn://localhost/project2 svn://localhost/project1
                        <br>
                        其中project2是目标的版本库，而project1是源版本库。其中的目标版本库必须为空，而且必须允许修订版本属性的修改，也就是在目标的版本
                        库的hooks目录里添加一个文件pre-revprop-change.bat，内容为空即可。</p>
                        <p><strong> 3.2. 同步project2到project1</strong> <br>
                        <br>
                        svnsync sync svn://localhost/project2 <br>
                        这时候你update一下你的project2的一个工作拷贝，就会发现有了project1的所有内容。如果project1又有提交，这时候
                        project2的版本库无法看到最新的变化，还需要再运行一遍sync操作，这样才能将最新的变化同步。需要注意的是，目标版本库只能做成只读的，如果
                        目标版本库发生了变更，则无法继续同步了。</p>
                        <p><strong> 3.3. 同步历史属性的修改</strong> <br>
                        <br>
                        因为同步不会更新对历史属性的修改，所以svnsync还有子命令copy-revprops，可以同步某个版本的属性。</p>
                        <p><strong> 3.4. 钩子自动同步</strong> <br>
                        <br>
                        希望在每次提交时同步，则需要在源版本库增加post-commit脚本，内容如下：</p>
                        <table width="70%">
                            <tbody>
                                <tr>
                                    <td class="content" bgcolor="#cccccc">echo off<br>
                                    set SVN_HOME="D:\Subversion"<br>
                                    %SVN_HOME%\bin\svnsync sync --non-interactive svn://localhost/project2
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                        <p>把以上内容存放为post-commit.bat，然后放到版本库project1下的hooks目录下，这样project1每次提交，都会引起project2的同步。</p>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><img src ="http://www.phpweblog.net/fuyongjie/aggbug/6265.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.phpweblog.net/fuyongjie/" target="_blank">bestmost</a> 2009-01-05 14:07 <a href="http://www.phpweblog.net/fuyongjie/archive/2009/01/05/6265.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>业务逻辑的理解</title><link>http://www.phpweblog.net/fuyongjie/archive/2008/09/25/5819.html</link><dc:creator>bestmost</dc:creator><author>bestmost</author><pubDate>Thu, 25 Sep 2008 03:32:00 GMT</pubDate><guid>http://www.phpweblog.net/fuyongjie/archive/2008/09/25/5819.html</guid><wfw:comment>http://www.phpweblog.net/fuyongjie/comments/5819.html</wfw:comment><comments>http://www.phpweblog.net/fuyongjie/archive/2008/09/25/5819.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.phpweblog.net/fuyongjie/comments/commentRss/5819.html</wfw:commentRss><trackback:ping>http://www.phpweblog.net/fuyongjie/services/trackbacks/5819.html</trackback:ping><description><![CDATA[<span style="COLOR: red">*</span>业务，就是business，就是一个单元（个人，组织等）给另一个单元提供的服务。逻辑（logic）就是指人们思考问题，从某些已知条件出发推出合理的结论的规律。所以逻辑不可能离开业务，这个逻辑也就是常说的业务逻辑（business logic），它是用来管理业务功能的一系列guildlines。你看到的
<div class=quote_title>&nbsp;</div>
里的业务应该是如richard所说的业务实体（business entities），是一种简化的说法；逻辑也是业务逻辑的简化。&nbsp;&nbsp;<br><br><span style="COLOR: red">*</span>业务逻辑是你在分析阶段对你的软件的应用领域进行分析总结出来的，它存在不依赖于你的软件的存在，相反，它先于你的软件存在并限制了你的软件应有的行为。&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;凡是业务逻辑都应该放到中间层，不能让客户端去决定。有时为了减少网络访问次数，在客户端会有一此与业务逻辑有关的检验，但在中间层这一检验同样不能省略。比如上面说的日期的判断，客户端可以有也可以没有判断，但中间层一定要有这一判断。<br><br><span style="COLOR: red">*</span>&nbsp;举个例子讲 &nbsp; 日期字段 &nbsp; 在数据库逻辑或者说是数据层仅仅需要判断他是不是日期类型的 &nbsp; <br>&nbsp; 但对于业务逻辑来讲仅仅输入一个日期是不够的，比如销售订单的执行日期就不能比销售订单的制定日期早；所以判断用户输入是否正确实际上&nbsp;就是两方面：首先看他是否符合数据规范其次是是否符合业务规范<br><br><span style="COLOR: red">*</span><br>逻辑就是人类思考的过程 <br><br>业务逻辑就是模仿人类思考的过程 <br>(这种方式最好理解,也最好修改) <br><br>页面逻辑, <br>数据库结构, <br>都是电脑想问题的方式 <br>如果想要作逻辑层 <br>那么就要先写好业务逻辑 <br>之后把页面逻辑与数据库语句 <br>向这个方向凑 <br><br>而不是<span style="FONT-SIZE: 14pt">定好数据库之后把业务向数据结构上凑</span> <br><br>这是个想法问题作的时间长了就知道其中的区别了 <br>平时区别不是很大的.... <br><br><span style="COLOR: red">*</span>举一个订单的例子，可能有点文不对题，希望能从另一个侧面加深大家对这个概念的理解：<br>业务逻辑是企业的行业特性、企业文化、能力结构和资源状况所形成的个性特质下对核心业务处理的基本路径和方式。那么我们的业务逻辑到底是什么呢？就是将订单信息快速全息广播到有关岗位，并行配置资源，动态调度岗位任务，让订单有序地在各个岗位间流动，最终在客户的包装物仓库形成物为载体的闭环。这个逻辑是基于流水生产、离散加工、快速交货、规格不一、需求复杂的基本事实和东经人恪守本职的基本属性作出的。<br><br>在这个业务逻辑下，订单应该是什么样的呢？订单除了基本的客户基本信息、产品基本数据和技术要求之外，还必须有工艺路线、运输方案、信用控制等方面的选择与控制，以锁定需求满足的基本路径，这样订单信息才算是丰满的，它全息了订单在公司内部流动的基本行为模式，充分表达了东经的个性。只有这样的订单才算有了基因<img src ="http://www.phpweblog.net/fuyongjie/aggbug/5819.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.phpweblog.net/fuyongjie/" target="_blank">bestmost</a> 2008-09-25 11:32 <a href="http://www.phpweblog.net/fuyongjie/archive/2008/09/25/5819.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>