程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> SVNKit學習——使用低級別的API(ISVNEditor接口)直接操作Repository的目錄和文件(五),svnkitisvneditor

SVNKit學習——使用低級別的API(ISVNEditor接口)直接操作Repository的目錄和文件(五),svnkitisvneditor

編輯:JAVA綜合教程

SVNKit學習——使用低級別的API(ISVNEditor接口)直接操作Repository的目錄和文件(五),svnkitisvneditor


本文是參考官方文檔的實現,官方wiki:https://wiki.svnkit.com/Committing_To_A_Repository

本文核心使用的是ISVNEditor這個接口直接對Repository進行各種AM操作~

 

以下兩張示例圖分別代表我們操作前、操作後倉庫的結構:

  

具體實現:

package com.demo;

import com.google.gson.Gson;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;

/**
 * 提交到倉庫
 * 這塊看官方demno的意思如果不用權限認證,會使用a session user name作為提交的author,但是我試了會報錯401,author required~
 * 本例是基於初始倉庫圖A轉換為目標倉庫圖B的過程,我們需要執行的操作有:
 * 1.刪除nodeB/itemB1
 * 2.編輯nodeC/itemC1
 * 3.新增nodeC/itemC2,並設置itemC2的文件屬性
 * 4.新增nodeB子節點nodeD
 */
public class CommitToRepository {
    public static void main(String[] args) throws Exception{
        //1.根據訪問協議初始化工廠
        DAVRepositoryFactory.setup();;
        //2.初始化倉庫,由於我們所有的操作都是基於nodeB節點以下的,所以我們將nodeB作為本次操作的root節點
        String url = "https://wlyfree-PC:8443/svn/svnkitRepository2/trunk/nodeB";
        SVNRepository svnRepository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
        //3.初始化權限
        String username = "wly";
        String password = "wly";
        char[] pwd = password.toCharArray();
        ISVNAuthenticationManager isvnAuthenticationManager = SVNWCUtil.createDefaultAuthenticationManager(username,pwd);
        svnRepository.setAuthenticationManager(isvnAuthenticationManager);
        //====================================DEMO START=========================================
        ISVNEditor editor = null;
        long revisionNo = -1; //指定版本號為最新版本
        //4.1.刪除nodeB/itemB1
        try{
            //獲取編輯器
            editor = svnRepository.getCommitEditor("delete file",null,true,null);
            String itemB1Path = "itemB1";//要刪除的文件路徑
            SVNCommitInfo svnCommitInfo = deleteFile(editor,revisionNo);//執行刪除並返回執行結果
            System.out.println("執行刪除操作的返回結果:" + svnCommitInfo);
        }catch (SVNException e){
            //發生異常需要終止操作
            editor.abortEdit();
            e.printStackTrace();;
        }
        //4.2.編輯nodeC/itemC1
        try{
            //獲取編輯器
            editor = svnRepository.getCommitEditor("modify file",null,true,null);
            SVNCommitInfo svnCommitInfo = modifyFile(editor,revisionNo);
            System.out.println("執行編輯操作的返回結果:" + svnCommitInfo);
        }catch(SVNException e){
            //發生異常需要終止操作
            editor.abortEdit();
            e.printStackTrace();;
        }
        //4.3.新增nodeC/itemC2,並設置itemC2的文件屬性
        try{
            editor = svnRepository.getCommitEditor("add file",null,true,null);
            SVNCommitInfo svnCommitInfo = addFile(editor,revisionNo);
            System.out.println("執行新增文件操作的返回結果:" + svnCommitInfo);
            //校驗nodeC/itemC2的屬性是否成功設置進去
            SVNProperties s = new SVNProperties();
            svnRepository.getFile("nodeC/itemC2",-1,s,null);
            Gson gson = new Gson();
            System.err.println(gson.toJson(s));
        }catch (SVNException e){
            editor.abortEdit();
            e.printStackTrace();
        }

        //4.4.新增nodeB子節點nodeD
        try{
           editor = svnRepository.getCommitEditor("add dir",null,true,null);
           SVNCommitInfo svnCommitInfo = addDir(editor,revisionNo);
           System.out.println("執行新增目錄操作的返回結果:" + svnCommitInfo);
        }catch (SVNException e){
            editor.abortEdit();
            e.printStackTrace();
        }
    }

    /**
     *  刪除文件
     *  @param editor 編輯器
     *  @param revisionNo 修訂版版本號
     *  @return  SVNCommitInfo 提交結果信息
     *  @throws SVNException
     */
    private static SVNCommitInfo deleteFile(ISVNEditor editor,long revisionNo) throws SVNException{
        // 進入Root節點,即nodeB
        editor.openRoot(revisionNo);
        //4.3.刪除文件
        editor.deleteEntry("itemB1",revisionNo);
        //操作完成要關閉編輯器,並返回操作結果
        return editor.closeEdit();
    }

    /**
     * 編輯文件
     *  @param editor 編輯器
     *  @param revisionNo 修訂版版本號
     *  @return  SVNCommitInfo 提交結果信息
     *  @throws SVNException
     */
    private static SVNCommitInfo modifyFile(ISVNEditor editor,long revisionNo) throws SVNException{
        // 進入Root節點,即nodeB
        editor.openRoot(revisionNo);
        //.進入nodeC節點
        editor.openDir("nodeC",revisionNo);
        // 編輯nodeC/itemC1的內容
        String itemC1Path = "nodeC/itemC1";//路徑都是相對於root的
        editor.openFile(itemC1Path,revisionNo);
        //確保客戶端這個文件的內容和服務端的是一樣的,如果不一致的話是不允許提交的。底層實現使用MD5
        String baseChecksum = null;
        editor.applyTextDelta(itemC1Path,baseChecksum);
        //提交文件變更的數據,windows默認是100kb大小
        byte[] oldData = new byte[]{};
        byte[] newData = null;
        try {
            newData = "我來測試一下編輯2".getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ByteArrayInputStream baseData = new ByteArrayInputStream(oldData);
        ByteArrayInputStream workingData = new ByteArrayInputStream(newData);
        SVNDeltaGenerator svnDeltaGenerator = new SVNDeltaGenerator();//100KB-windows generator
        String checksum = svnDeltaGenerator.sendDelta(itemC1Path,baseData,0,workingData,editor,true);
        // 關閉文件
        editor.closeFile(itemC1Path,checksum);
        // 關閉目錄nodeC
        editor.closeDir();
        // 關閉根目錄nodeB
        editor.closeDir();
        // 關閉編輯器,並返回執行結果
        return editor.closeEdit();
    }

    /**
     * 新增文件
     * @param editor
     * @param revisionNo
     * @return
     * @throws SVNException
     */
    private static SVNCommitInfo addFile(ISVNEditor editor,long revisionNo) throws SVNException{
        // 進入Root節點,即nodeB
        editor.openRoot(revisionNo);
        //.進入nodeC節點
        editor.openDir("nodeC",revisionNo);
        // 新增itemC2文件
        editor.addFile("nodeC/itemC2",null,revisionNo);
        //確保客戶端這個文件的內容和服務端的是一樣的,如果不一致的話是不允許提交的。底層實現使用MD5
        String itemC2Path = "nodeC/itemC2";
        String baseChecksum = null;
        editor.applyTextDelta(itemC2Path,baseChecksum);
        //提交文件變更的數據,windows默認是100kb大小
        byte[] oldData = new byte[]{};//舊數據
        byte[] newData = null;//新數據
        try {
            newData = "我來測試一下 - addFile".getBytes("utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ByteArrayInputStream baseData = new ByteArrayInputStream(oldData);
        ByteArrayInputStream workingData = new ByteArrayInputStream(newData);
        SVNDeltaGenerator svnDeltaGenerator = new SVNDeltaGenerator();//100KB-windows generator
        String checksum = svnDeltaGenerator.sendDelta(itemC2Path,baseData,0,workingData,editor,true);
        //設置文件的屬性,key是字符串,值被包裝成SVNProperyValue了
        editor.changeFileProperty("nodeC/itemC2","properName1",SVNPropertyValue.create("properValue1"));
        editor.changeFileProperty("nodeC/itemC2","properName2",SVNPropertyValue.create("properValue2"));
        System.out.println("checksum:" + checksum );
        //關閉文件
        editor.closeFile("nodeC/itemC2",checksum);
        //關閉目錄nodeC
        editor.closeDir();
        //關閉root
        editor.closeDir();
        return editor.closeEdit();
    }

    /**
     * 新增目錄
     * @param editor 編輯器
     * @param revisionNo 修訂版本號
     * @return  SVNCommitInfo 提交結果信息
     * @throws SVNException
     */
    private static SVNCommitInfo addDir(ISVNEditor editor,long revisionNo) throws SVNException{
        // 進入Root節點,即nodeB
        editor.openRoot(revisionNo);
        //新增目錄
        editor.addDir("nodeD",null,revisionNo);
        editor.closeDir();//nodeD
        editor.closeDir();//nodeB
        return editor.closeEdit();
    }
}

運行效果:

 

執行刪除操作的返回結果:r51 by 'wly' at Wed Dec 07 13:48:15 CST 2016
執行編輯操作的返回結果:r52 by 'wly' at Wed Dec 07 13:48:15 CST 2016
checksum:a107fb58070bfbaf11513c8750f87466
執行新增文件操作的返回結果:r53 by 'wly' at Wed Dec 07 13:48:15 CST 2016
{"myProperties":{"svn:entry:uuid":{"myValue":"e5dd1e38-0390-574a-b68d-e269ce50c382"},"svn:entry:revision":{"myValue":"53"},"properName1":{"myData":[112,114,111,112,101,114,86,97,108,117,101,49]},"svn:entry:committed-date":{"myValue":"2016-12-07T05:48:15.464756Z"},"properName2":{"myData":[112,114,111,112,101,114,86,97,108,117,101,50]},"svn:wc:ra_dav:version-url":{"myValue":"/svn/svnkitRepository2/!svn/ver/53/trunk/nodeB/nodeC/itemC2"},"svn:entry:checksum":{"myValue":"a107fb58070bfbaf11513c8750f87466"},"svn:entry:committed-rev":{"myValue":"53"},"svn:entry:last-author":{"myValue":"wly"}}}
執行新增目錄操作的返回結果:r54 by 'wly' at Wed Dec 07 13:48:15 CST 2016

 

 

 

總結:

  其實走讀一遍代碼就知道,無論進行什麼操作都是有一定規律性的。

  無論是操作目錄還是文件,大的框架可以大體總結為以下幾步:

//1.根據訪問協議初始化工廠
//2.初始化倉庫,由於我們所有的操作都是基於nodeB節點以下的,所以我們將nodeB作為本次操作的root節點
//3.初始化權限
//4.獲取編輯器對象
//5.進入目錄/文件
//6.執行操作
//7.關閉目錄/文件
//8.關閉編輯器

  實際工作中,感覺這種方式不是特別靈活,不一定適用於普通的應用場景,相對來講,High-Level API更傾向於用戶和SVN的交互。

 

  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved