SVNKit使用相关工具类

SVNKit操作SVN仓库

导入依赖

<dependency>
    <groupId>org.tmatesoft.svnkit</groupId>
    <artifactId>svnkit</artifactId>
    <version>1.8.5</version>
    <scope>compile</scope>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.3</version>
</dependency>

<dependency>
    <groupId>org.ini4j</groupId>
    <artifactId>ini4j</artifactId>
</dependency>

SVN通过代码操作常用工具类

1、FilePermissionUtil.java

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @author: hanchunyu
 * @since 2022/11/2 下午5:54
 *        <p>
 *        Description:
 */
public class FilePermissionUtil {
	/**
	 * 判断文件是否有读权限
	 * 
	 * @param file
	 *            文件
	 * @return
	 */
	public static Boolean canRead(File file) {
		if (file.isDirectory()) {
			try {
				File[] listFiles = file.listFiles();
				if (listFiles == null) { // 返回null表示无法读取或访问,如果为空目录返回的是一个空数组
					return false;
				} else {
					return true;
				}
			} catch (Exception e) {
				return false;
			}
		} else if (!file.exists()) { // 文件不存在
			return false;
		}
		return checkRead(file);
	}

	/**
	 * 检测文件是否有读权限
	 * 
	 * @param file
	 *            文件
	 * @return
	 */
	private static boolean checkRead(File file) {
		FileReader fd = null;
		try {
			fd = new FileReader(file);
			while ((fd.read()) != -1) {
				break;
			}
			return true;
		} catch (IOException e) {
			return false;
		} finally {
			try {
				fd.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 判断文件是否有写权限
	 * 
	 * @param file
	 *            文件
	 * @return
	 */
	public static Boolean canWrite(File file) {
		if (file.isDirectory()) {
			try {
				file = new File(file, "canWriteTestDeleteOnExit.temp");
				if (file.exists()) {
					boolean checkWrite = checkWrite(file);
					if (!deleteFile(file)) {
						file.deleteOnExit();
					}
					return checkWrite;
				} else if (file.createNewFile()) {
					if (!deleteFile(file)) {
						file.deleteOnExit();
					}
					return true;
				} else {
					return false;
				}
			} catch (Exception e) {
				return false;
			}
		}
		return checkWrite(file);
	}

	/**
	 * 检测文件是否有写权限
	 * 
	 * @param file
	 *            文件
	 * @return
	 */
	private static boolean checkWrite(File file) {
		FileWriter fw = null;
		boolean delete = !file.exists();
		boolean result = false;
		try {
			fw = new FileWriter(file, true);
			fw.write("");
			fw.flush();
			result = true;
			return result;
		} catch (IOException e) {
			return false;
		} finally {
			try {
				fw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
			if (delete && result) {
				deleteFile(file);
			}
		}
	}

	/**
	 * 删除文件,如果要删除的对象是文件夹,先删除所有子文件(夹),再删除该文件
	 * 
	 * @param file
	 *            要删除的文件对象
	 * @return 删除是否成功
	 */
	public static boolean deleteFile(File file) {
		return deleteFile(file, true);
	}

	/**
	 * 删除文件,如果要删除的对象是文件夹,则根据delDir判断是否同时删除文件夹
	 * 
	 * @param file
	 *            要删除的文件对象
	 * @param delDir
	 *            是否删除目录
	 * @return 删除是否成功
	 */
	public static boolean deleteFile(File file, boolean delDir) {
		if (!file.exists()) { // 文件不存在
			return true;
		}
		if (file.isFile()) {
			return file.delete();
		} else {
			boolean result = true;
			File[] children = file.listFiles();
			for (int i = 0; i < children.length; i++) { // 删除所有子文件和子文件夹
				result = deleteFile(children[i], delDir);// 递归删除文件
				if (!result) {
					return false;
				}
			}
			if (delDir) {
				result = file.delete(); // 删除当前文件夹
			}
			return result;
		}
	}
}

2、HttpdUtils.java

import java.io.File;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.RuntimeUtil;

public class HttpdUtils {

	public void modHttpdPort(String port) {
		List<String> lines = FileUtil.readLines(new File("/etc/apache2/httpd.conf"), Charset.forName("UTF-8"));
		List<String> reLines = new ArrayList<String>();
		for (String line : lines) {
			if (line.startsWith("Listen ")) {
				line = "Listen " + port;
			}
			reLines.add(line);
		}
		FileUtil.writeLines(reLines, new File("/etc/apache2/httpd.conf"), Charset.forName("UTF-8"));

	}

	public void releaseFile() {
		ClassPathResource resource = new ClassPathResource("file/dav_svn.conf");
		FileUtil.writeFromStream(resource.getStream(), "/etc/apache2/conf.d/dav_svn.conf");
	}

	public void start() {
		RuntimeUtil.exec("httpd -k start");
	}

	public void stop() {
		RuntimeUtil.exec("pkill httpd");
	}

}

3、RepositoryUtil.java

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.core.util.ZipUtil;
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.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.*;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

/**
 * @author: hanchunyu
 * @since 2022/11/2 下午5:54
 *        <p>
 *        Description: SVN仓库操作工具类
 */
public class RepositoryUtil {

	public static Boolean DoUpdateStatus = true;
	// 声明SVN客户端管理类
	private static SVNClientManager ourClientManager;

	static {
		// 初始化库。 必须先执行此操作。具体操作封装在setupLibrary方法中。
		// For using over http:// and https://
		DAVRepositoryFactory.setup();

		// For using over svn:// and svn+xxx://
		SVNRepositoryFactoryImpl.setup();

		// For using over file://
		FSRepositoryFactory.setup();
	}

	/**
	 * 创建镜像(默认携带admin用户)
	 * 
	 * @param path
	 *            路径
	 * @param name
	 *            仓库名
	 */
	public static void createRepository(String path, String name) {

		// 创建仓库
		String dir = path + "repo" + File.separator + name;
		if (!FileUtil.exist(dir + File.separator + "db")) {
			ClassPathResource resource = new ClassPathResource("file/repo.zip");
			InputStream inputStream = resource.getStream();
			File temp = new File(path + "temp" + File.separator + "file/repo.zip");
			FileUtil.writeFromStream(inputStream, temp);
			FileUtil.mkdir(dir);
			ZipUtil.unzip(temp, new File(dir));
			FileUtil.del(temp);
		}
	}

	/**
	 * 创建仓库(最初形式)
	 * 
	 * @param path
	 *            仓库路径
	 * @return
	 */
	public static Boolean initRepository(String path) {
		try {
			SVNRepositoryFactory.createLocalRepository(new File(path), true, false);
			return true;
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * 检出仓库
	 *
	 * @param svnPath
	 *            SVN路径
	 * @param targetPath
	 *            本地仓库路径
	 * @return
	 */
	public static Long checkOut(String svnPath, String targetPath) {
		return checkOut(svnPath, targetPath, "admin", "admin");
	}

	/**
	 * 拉取镜像
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param targetPath
	 *            本地仓库路径
	 * @param svnUserName
	 *            用户名
	 * @param svnPassWord
	 *            密码
	 * @return -1L发生错误 -- 版本号
	 */
	public static Long checkOut(String svnPath, String targetPath, String svnUserName, String svnPassWord) {

		// 相关变量赋值
		SVNURL repositoryURL = null;
		try {
			repositoryURL = SVNURL.parseURIEncoded(svnPath);
		} catch (SVNException e) {
			e.printStackTrace();
			return -1L;
		}
		DefaultSVNOptions options = new DefaultSVNOptions();
		// 实例化客户端管理类
		SVNClientManager ourClientManager = SVNClientManager.newInstance(options, svnUserName, svnPassWord);
		// 要把版本库的内容check out到的目录
		File wcDir = new File(targetPath);
		// 通过客户端管理类获得updateClient类的实例。
		SVNUpdateClient updateClient = ourClientManager.getUpdateClient();
		updateClient.setIgnoreExternals(false);
		// 执行check out 操作,返回工作副本的版本号。
		long workingVersion = -1;
		try {
			if (wcDir.exists()) {
				ourClientManager.getWCClient().doCleanup(wcDir);
			}
			workingVersion = updateClient.doCheckout(repositoryURL, wcDir, SVNRevision.HEAD, SVNRevision.HEAD,
					SVNDepth.INFINITY, false);

		} catch (Exception e) {
			e.printStackTrace();
			return -1L;
		}

		System.out.println("把版本:" + workingVersion + " check out 到目录:" + wcDir + "中。");
		try {
			ourClientManager.getWCClient().doCleanup(wcDir);
		} catch (SVNException e) {
			throw new RuntimeException(e);
		}
		return workingVersion;
	}

	/**
	 * 更新仓库
	 * 
	 * @param targetPath
	 *            本地仓库路径
	 * @return
	 */
	public static Integer doUpdate(String targetPath) {
		return doUpdate(targetPath, "admin", "admin");
	}

	/**
	 * 更新svn
	 * 
	 * @param targetPath
	 *            本地仓库路径
	 * @param svnUserName
	 *            用户名
	 * @param svnPassWord
	 *            密码
	 * @return int(- 1更新失败 , 1成功 , 0有程序在占用更新)
	 */
	public static Integer doUpdate(String targetPath, String svnUserName, String svnPassWord) {
		if (Boolean.FALSE.equals(RepositoryUtil.DoUpdateStatus)) {
			System.out.println("更新程序已经在运行中,不能重复请求!");
			return 0;
		}
		RepositoryUtil.DoUpdateStatus = false; /* * For using over http:// and https:// */
		try {
			DAVRepositoryFactory.setup();
			ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
			// 实例化客户端管理类
			SVNClientManager ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, svnUserName,
					svnPassWord);
			// 要更新的文件
			File updateFile = new File(targetPath);
			// 获得updateClient的实例
			SVNUpdateClient updateClient = ourClientManager.getUpdateClient();
			updateClient.setIgnoreExternals(false);
			// 执行更新操作
			long versionNum = updateClient.doUpdate(updateFile, SVNRevision.HEAD, SVNDepth.INFINITY, false, false);
			System.out.println("工作副本更新后的版本:" + versionNum);
			DoUpdateStatus = true;
			return 1;
		} catch (SVNException e) {
			DoUpdateStatus = true;
			e.printStackTrace();
			return -1;
		}
	}

	/**
	 * Svn提交 list.add("a.txt")可直接添加单个文件;
	 * list.add("aaa")添加文件夹将添加夹子内所有的文件到svn,预添加文件必须先添加其所在的文件夹;
	 *
	 * @param fileRelativePathList
	 *            文件相对路径
	 * @param targetPath
	 *            本地仓库
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * @return Boolean
	 */
	public static Boolean doCommit(List<String> fileRelativePathList, String targetPath, String username,
			String passWord) {

		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);
		// 要提交的文件夹子
		File commitFile = new File(targetPath);
		// 获取此文件的状态(是文件做了修改还是新添加的文件?)
		SVNStatus status = null;
		File addFile = null;
		String strPath = null;
		try {
			if (fileRelativePathList != null && fileRelativePathList.size() > 0) {
				for (int i = 0; i < fileRelativePathList.size(); i++) {
					strPath = fileRelativePathList.get(i);
					addFile = new File(targetPath + "/" + strPath);
					status = ourClientManager.getStatusClient().doStatus(addFile, true);
					// 如果此文件是新增加的则先把此文件添加到版本库,然后提交。
					if (null == status || status.getContentsStatus() == SVNStatusType.STATUS_UNVERSIONED) {
						// 把此文件增加到版本库中
						ourClientManager.getWCClient().doAdd(addFile, false, false, false, SVNDepth.INFINITY, false,
								false);
						System.out.println("add");
					}
				}
				// 提交此文件
			} // 如果此文件不是新增加的,直接提交。
			ourClientManager.getCommitClient().doCommit(new File[] { commitFile }, true, "", null, null, true, false,
					SVNDepth.INFINITY);
			System.out.println("commit");
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		System.out.println(status.getContentsStatus());
		return true;
	}

	/**
	 * 提交代码
	 * 
	 * @param fileRelativePath
	 *            相对于仓库路径
	 * @param targetPath
	 *            仓库路径
	 * @return
	 */
	public static Boolean doCommit(String fileRelativePath, String targetPath) {
		return doCommit(fileRelativePath, targetPath, "admin", "admin");
	}

	/**
	 * Svn提交
	 *
	 * @param fileRelativePath
	 *            文件相对仓库路径
	 * @param targetPath
	 *            本地仓库
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * 
	 * @return Boolean
	 */
	public static Boolean doCommit(String fileRelativePath, String targetPath, String username, String passWord) {
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);
		// 要提交的文件夹子
		File commitFile = new File(targetPath);
		// 获取此文件的状态(是文件做了修改还是新添加的文件?)
		SVNStatus status = null;
		File addFile = null;
		try {
			if (fileRelativePath != null && fileRelativePath.trim().length() > 0) {
				addFile = new File(ToolUtils.endDir(targetPath) + fileRelativePath);
				status = ourClientManager.getStatusClient().doStatus(addFile, true);
				// 如果此文件是新增加的则先把此文件添加到版本库,然后提交。
				if (null == status || status.getContentsStatus() == SVNStatusType.STATUS_UNVERSIONED) {
					// 把此文件增加到版本库中
					ourClientManager.getWCClient().doAdd(addFile, false, false, false, SVNDepth.INFINITY, false, false);
					System.out.println("add");
				}
				// 提交此文件
			} else if ("".equals(fileRelativePath)) {
				File[] files = FileUtil.ls(targetPath);
				for (File f : files) {
					if (!f.getPath().equals(ToolUtils.endDir(targetPath) + ".svn")) {
						status = ourClientManager.getStatusClient().doStatus(f, true);
						// 如果此文件是新增加的则先把此文件添加到版本库,然后提交。
						if (null == status || status.getContentsStatus() == SVNStatusType.STATUS_UNVERSIONED) {
							// 把此文件增加到版本库中
							ourClientManager.getWCClient().doAdd(f, false, false, false, SVNDepth.INFINITY, false,
									false);
						}
					}
				}

			}
			// 如果此文件不是新增加的,直接提交。
			ourClientManager.getCommitClient().doCommit(new File[] { commitFile }, true, "commit all", null, null, true,
					false, SVNDepth.INFINITY);
			ourClientManager.getWCClient().doCleanup(commitFile);
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 导入文件
	 * 
	 * @param dirPath
	 *            文件加路径
	 * @param svnPath
	 *            SVN仓库路径
	 * @return
	 */
	public static Boolean doImport(String dirPath, String svnPath) {
		return doImport(dirPath, svnPath, "admin", "admin");
	}

	/**
	 * 将文件导入并提交到svn 同路径文件要是已经存在将会报错
	 *
	 * @param dirPath
	 *            文件夹路径
	 * @param svnPath
	 *            仓库路径
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * @return Boolean
	 */
	public static Boolean doImport(String dirPath, String svnPath, String username, String passWord) {
		// 相关变量赋值
		SVNURL repositoryURL = null;
		try {
			repositoryURL = SVNURL.parseURIEncoded(svnPath);
		} catch (SVNException e) {
			e.printStackTrace();
		}
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);
		// 要把此目录中的内容导入到版本库
		File impDir = new File(dirPath);
		// 执行导入操作
		SVNCommitInfo commitInfo = null;
		try {
			commitInfo = ourClientManager.getCommitClient().doImport(impDir, repositoryURL, "import operation!", null,
					false, false, SVNDepth.INFINITY);
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}
		System.out.println(commitInfo.toString());
		return true;
	}

	/**
	 * 删除本地仓库文件夹
	 *
	 * @param dirPath
	 *            本地路径
	 * @return
	 */
	public static Boolean doDeleteLocalDir(String dirPath) {
		return doDeleteLocalDir(dirPath, "admin", "admin");
	}

	/**
	 * 删除本地仓库文件夹
	 * 
	 * @param dirPath
	 *            本地路径
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * @return
	 */
	public static Boolean doDeleteLocalDir(String dirPath, String username, String passWord) {
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);
		// 要把此目录中的内容导入到版本库
		File impDir = new File(dirPath);

		try {
			ourClientManager.getWCClient().doDelete(impDir, false, false);
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 *
	 * @param path
	 *            文件夹路径
	 * 
	 * @return
	 */
	public static Boolean doMkDir(String path) {
		return doMkDir(new String[] { path });
	}

	/**
	 *
	 * @param path
	 *            文件夹路径
	 * 
	 * @return
	 */
	public static Boolean doMkDir(String[] path) {
		return doMkDir(path, "admin", "admin");
	}

	/**
	 * 
	 * @param path
	 *            文件夹路径
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * @return
	 */
	public static Boolean doMkDir(String[] path, String username, String passWord) {

		// 相关变量赋值
		SVNURL[] repositoryURL = new SVNURL[path.length];
		try {
			for (int i = 0; i < path.length; i++) {
				SVNURL svnurl = SVNURL.parseURIEncoded(path[i]);
				repositoryURL[i] = svnurl;
			}
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}

		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);
		SVNCommitInfo commitInfo = null;
		try {
			commitInfo = ourClientManager.getCommitClient().doMkDir(repositoryURL, "mkdir");
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}
		System.out.println(commitInfo);
		return true;
	}

	/**
	 * 删除仓库
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @return
	 */
	public static Boolean doDelete(String svnPath) {
		String[] path = { svnPath };
		return doDelete(path);
	}

	/**
	 * 删除文件夹
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @return
	 */
	public static Boolean doDelete(String[] svnPath) {
		return doDelete(svnPath, "admin", "admin");
	}

	/**
	 * 删除文件夹
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * @return
	 */
	public static Boolean doDelete(String[] svnPath, String username, String passWord) {

		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);

		// 相关变量赋值
		SVNURL[] repositoryURL = new SVNURL[svnPath.length];
		try {
			for (int i = 0; i < svnPath.length; i++) {
				SVNURL svnurl = SVNURL.parseURIEncoded(svnPath[i]);
				repositoryURL[i] = svnurl;
			}
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}

		// 执行导入操作
		SVNCommitInfo commitInfo = null;
		try {
			commitInfo = ourClientManager.getCommitClient().doDelete(repositoryURL, "delete file");
		} catch (SVNException e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}

	/**
	 * 清除仓库中的锁,以及未完成的操作
	 *
	 * @param targetPath
	 *            本地仓库路径
	 * @param username
	 *            用户名
	 * @param passWord
	 *            密码
	 * @return Boolean
	 */
	public static Boolean doCleanup(String targetPath, String username, String passWord) {
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, passWord);
		File wcDir = new File(targetPath);
		if (wcDir.exists()) {
			try {
				ourClientManager.getWCClient().doCleanup(wcDir);
			} catch (SVNException e) {
				e.printStackTrace();
				return false;
			}
		} else {
			return false;
		}
		return true;
	}

	/**
	 * 下载压缩包
	 * 
	 * @param path
	 *            仓库路径
	 */
	public static void checkoutZip(String path) {
		checkoutZip(path, "/data/repo");
	}

	/**
	 * 下载压缩包
	 * 
	 * @param path
	 *            仓库路径
	 * @param targetPath
	 *            本地路径
	 */
	public static void checkoutZip(String path, String targetPath) {
		checkoutZip(path, targetPath, "admin", "admin");
	}

	/**
	 * 下载压缩包
	 * 
	 * @param path
	 *            仓库路径
	 * @param targetPath
	 *            本地路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            密码
	 */
	public static void checkoutZip(String path, String targetPath, String userName, String passWord) {
		Long isSuccess = RepositoryUtil.checkOut(path, targetPath, userName, passWord);

		String[] split = path.split(File.separator);
		String fileName = split[split.length - 1];

		String zipFilePath = targetPath + fileName + ".zip";

		ZipUtil.zip(targetPath, zipFilePath);
		if (isSuccess != -1L) {
			try (FileInputStream is = new FileInputStream(zipFilePath)) {
				EventUtil.post(new DownloadFileEvent(fileName + ".zip", DataConvert.inputStreamToByte(is)));
			} catch (Exception ex) {
				ExtendUtil.error(ex.getMessage());
			} finally {

				Path tempPath = Paths.get(zipFilePath);
				FileUtil.del(tempPath);

			}
		}
	}

	/**
	 * 获取文件,判断是否是.svn文件夹
	 * 
	 * @param f
	 *            文件
	 */
	public static void getFile(File f) {
		File[] files = f.listFiles();
		for (int i = 0; i < files.length; i++) {
			if (".svn".equals(files[i].getName())) {
				continue;
			}
			if (files[i].isDirectory()) {
				getFile(files[i]);
			}
		}
	}

	/**
	 * 获取SVN文件夹
	 * 
	 * @param path
	 *            仓库路径
	 * @param revision
	 *            版本号
	 * @param properties
	 *            SVN配置
	 * @param dirEntries
	 *            文件夹集合
	 * @param svnPath
	 *            SVN路径
	 * @param username
	 *            用户
	 * @param password
	 *            密码
	 * @return
	 * @throws SVNException
	 */
	public static List<DirNodeDTO> getSvnDir(String path, long revision, SVNProperties properties,
			Collection dirEntries, String svnPath, String username, String password) throws SVNException {

		/*
		 * 创建SVNRepository来管理repository. SVNURL 是url的包装对象
		 */
		SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(svnPath));

		// 登录
		ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
		repository.setAuthenticationManager(authManager);

		ArrayList<DirNodeDTO> dirNodes = new ArrayList<>();
		return getDirPath(dirNodes, null, repository, path, revision, properties, dirEntries);
	}

	/**
	 * 获取SVN文件夹
	 *
	 * @param path
	 *            仓库路径
	 * @param revision
	 *            版本号
	 * @param properties
	 *            SVN配置
	 * @param dirEntries
	 *            文件夹集合
	 * @param svnPath
	 *            SVN路径
	 * @return
	 * @throws SVNException
	 */
	public static List<DirNodeDTO> getSvnDir(String path, long revision, SVNProperties properties,
			Collection dirEntries, String svnPath) throws SVNException {
		return getSvnDir(path, revision, properties, dirEntries, svnPath, "admin", "admin");
	}

	/**
	 * 获取SVN文件夹
	 *
	 * @param path
	 *            仓库路径
	 * @param revision
	 *            版本号
	 * @param svnPath
	 *            SVN路径
	 * @return
	 * @throws SVNException
	 */
	public static List<DirNodeDTO> getSvnDir(String path, long revision, String svnPath) throws SVNException {
		return getSvnDir(path, revision, null, null, svnPath);
	}

	/**
	 * 获取SVN文件夹
	 *
	 * @param path
	 *            仓库路径
	 * @param svnPath
	 *            SVN路径
	 * @return
	 * @throws SVNException
	 */
	public static List<DirNodeDTO> getSvnDir(String path, String svnPath) throws SVNException {
		return getSvnDir(path, -1, svnPath);
	}

	/**
	 * 获取SVN文件夹
	 *
	 * @param svnPath
	 *            SVN路径
	 * @return
	 * @throws SVNException
	 */
	public static List<DirNodeDTO> getSvnDir(String svnPath) throws SVNException {
		return getSvnDir("", svnPath);
	}

	/**
	 * 获取文件路径
	 * 
	 * @param list
	 *            文件实体集合
	 * @param dir
	 *            文件实体
	 * @param repository
	 *            SVN仓库
	 * @param path
	 *            路径
	 * @param revision
	 *            版本号
	 * @param properties
	 *            配置
	 * @param dirEntries
	 *            实体集合
	 * @return
	 * @throws SVNException
	 */
	public static List<DirNodeDTO> getDirPath(List<DirNodeDTO> list, DirNodeDTO dir, SVNRepository repository,
			String path, long revision, SVNProperties properties, Collection dirEntries) throws SVNException {
		Collection entries = repository.getDir(path, revision, null, (Collection) null);
		Iterator iterator = entries.iterator();
		while (iterator.hasNext()) {
			SVNDirEntry entry = (SVNDirEntry) iterator.next();
			/*
			 * SVNNodeKind.NONE :无此目录或文件 SVNNodeKind.FILE :该地址是个文件 SVNNodeKind.DIR :该地址是个目录
			 */
			SVNNodeKind nodeKind = repository.checkPath(entry.getName(), -1);

			DirNodeDTO dirNode = new DirNodeDTO();
			dirNode.setSize(entry.getSize());
			dirNode.setRevision(entry.getRevision());
			dirNode.setAuthor(entry.getAuthor());
			dirNode.setUpdateDate(entry.getDate());
			dirNode.setMessage(entry.getCommitMessage());
			dirNode.setPath(path.equals("") ? entry.getName() : path + "/" + entry.getName());
			dirNode.setName(entry.getRelativePath());
			dirNode.setParent(dir);
			if (entry.getKind().toString().equals("file")) {
				dirNode.setDir(false);
			} else {
				dirNode.setDir(true);
			}

			System.out.println(dirNode);

			list.add(dirNode);
			if (entry.getKind().toString().equals("dir")) {
				getDirPath(list, dirNode, repository, dirNode.getPath(), revision, null, (Collection) null);
			}
		}
		return list;
	}

	/**
	 * 获取仓库文件
	 * 
	 * @param path
	 *            路径
	 * @param revision
	 *            版本
	 * @param svnPath
	 *            SVN路径
	 * @param username
	 *            用户名
	 * @param password
	 *            密码
	 * @return
	 * @throws SVNException
	 */
	public static RepositoryFileContentDTO getSvnFile(String path, long revision, String svnPath, String username,
			String password) throws SVNException {

		/*
		 * 创建SVNRepository来管理repository. SVNURL 是url的包装对象
		 */
		SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(svnPath));

		// 登录
		ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
		repository.setAuthenticationManager(authManager);

		return getFileContext(repository, path, revision);
	}

	/**
	 * 获取仓库文件
	 * 
	 * @param path
	 *            路径
	 * @param svnPath
	 *            SVN路径
	 * @param username
	 *            用户名
	 * @param password
	 *            密码
	 * @return
	 * @throws SVNException
	 */
	public static RepositoryFileContentDTO getSvnFile(String path, String svnPath, String username, String password)
			throws SVNException {
		return getSvnFile(path, -1, svnPath, username, password);
	}

	/**
	 * 获取仓库文件
	 * 
	 * @param path
	 *            路径
	 * @param svnPath
	 *            SVN路径
	 * @return
	 * @throws SVNException
	 */
	public static RepositoryFileContentDTO getSvnFile(String path, String svnPath) throws SVNException {
		return getSvnFile(path, -1, svnPath, "admin", "admin");
	}

	/**
	 * 获取仓库文件
	 * 
	 * @param repository
	 *            仓库
	 * @param path
	 *            路径
	 * @param revision
	 *            版本
	 * @return
	 * @throws SVNException
	 */
	public static RepositoryFileContentDTO getFileContext(SVNRepository repository, String path, long revision)
			throws SVNException {

		/*
		 * SVNNodeKind.NONE :无此目录或文件 SVNNodeKind.FILE :该地址是个文件 SVNNodeKind.DIR :该地址是个目录
		 */
		SVNNodeKind nodeKind = repository.checkPath(path, revision);

		if (nodeKind.toString().equals("file")) {
			SVNProperties fileProperties = new SVNProperties();
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			/*
			 * 获取文件内容和属性。-1:最后版本。
			 */
			repository.getFile(path, -1, fileProperties, baos);
			String mimeType = fileProperties.getStringValue(SVNProperty.MIME_TYPE);
			boolean isTextType = SVNProperty.isTextMimeType(mimeType);

			if (isTextType) {
				try {
					System.out.println("@" + new String(baos.toString("UTF-8")));
				} catch (UnsupportedEncodingException e) {
					throw new RuntimeException(e);
				}
			}
			RepositoryFileContentDTO repositoryFileContent = new RepositoryFileContentDTO();
			repositoryFileContent.setIsText(isTextType);
			repositoryFileContent.setBaos(baos);
			return repositoryFileContent;
		}
		return null;
	}

	/**
	 * 对比文件
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param path
	 *            文件路径
	 * @param rivision1
	 *            版本号
	 * @param rivision2
	 *            版本号
	 * @return
	 * @throws SVNException
	 * @throws Exception
	 */
	public static String diff(String svnPath, String path, Long rivision1, Long rivision2)
			throws SVNException, Exception {
		return diff(svnPath, path, rivision1, path, rivision2);
	}

	/**
	 * 对比文件
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param path1
	 *            文件路径
	 * @param rivision1
	 *            版本号
	 * @param path2
	 *            文件路径
	 * @param rivision2
	 *            版本号
	 * @return
	 * @throws SVNException
	 * @throws Exception
	 */
	public static String diff(String svnPath, String path1, Long rivision1, String path2, Long rivision2)
			throws SVNException, Exception {
		return diff(svnPath, "admin", "admin", path1, rivision1, path2, rivision2);
	}

	/**
	 * 对比文件内容
	 *
	 * @param svnPath
	 *            SVN路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            面
	 * @param path1
	 *            路径
	 * @param rivision1
	 *            版本
	 * @param path2
	 *            路径
	 * @param rivision2
	 *            版本
	 * @return
	 * @throws SVNException
	 * @throws Exception
	 */
	public static String diff(String svnPath, String userName, String passWord, String path1, Long rivision1,
			String path2, Long rivision2) throws SVNException, Exception {
		return diff(svnPath, userName, passWord, path1, SVNRevision.create(rivision1), path2,
				SVNRevision.create(rivision2));
	}

	/**
	 * 对比文件内容
	 *
	 * @param svnPath
	 *            SVN路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            面
	 * @param path1
	 *            路径
	 * @param rivision1
	 *            版本
	 * @param path2
	 *            路径
	 * @param rivision2
	 *            版本
	 * @return
	 * @throws SVNException
	 * @throws Exception
	 */
	public static String diff(String svnPath, String userName, String passWord, String path1, SVNRevision rivision1,
			String path2, SVNRevision rivision2) throws SVNException, Exception {
		return diff(svnPath, userName, passWord, path1, rivision1, path2, rivision2, (String) null);
	}

	/**
	 * 对比文件内容
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            面
	 * @param path1
	 *            路径
	 * @param rivision1
	 *            版本
	 * @param path2
	 *            路径
	 * @param rivision2
	 *            版本
	 * @param targetPath
	 *            内容输出文件路径
	 * @return
	 * @throws SVNException
	 * @throws Exception
	 */
	public static String diff(String svnPath, String userName, String passWord, String path1, SVNRevision rivision1,
			String path2, SVNRevision rivision2, String targetPath) throws SVNException, Exception {

		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, userName, passWord);

		SVNDiffClient diffClient = ourClientManager.getDiffClient();
		// StringOutputStream result = new StringOutputStream();
		ByteArrayOutputStream out = new ByteArrayOutputStream();

		SVNURL svnUrl1 = SVNURL.parseURIEncoded(ToolUtils.endDir(svnPath) + path1);
		SVNURL svnUrl2 = SVNURL.parseURIEncoded(ToolUtils.endDir(svnPath) + path2);

		diffClient.doDiff(svnUrl1, rivision1, svnUrl2, rivision2, SVNDepth.INFINITY, true, out);

		if (targetPath != null && "".equals(targetPath)) {
			FileOutputStream fileOutputStream = null;
			try {
				fileOutputStream = new FileOutputStream(targetPath);
				fileOutputStream.write(out.toByteArray());
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

		System.out.println(out.toString("UTF-8"));
		return out.toString("UTF-8");
	}

	/**
	 * 获得指定版本提交日志信息
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @return 日志实体集合
	 * @throws SVNException
	 */
	public static List<SVNCommitLogDTO> getCommitLog(String svnPath) throws SVNException {
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, "admin", "admin");
		SVNRepository repository = ourClientManager.createRepository(SVNURL.parseURIEncoded(svnPath), true);
		SVNDirEntry entry = repository.info(".", -1);
		return getCommitLog(svnPath, (int) entry.getRevision());
	}

	/**
	 * 获得指定版本提交日志信息
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param limit
	 *            展示数
	 * @return 日志实体集合
	 * @throws SVNException
	 */
	public static List<SVNCommitLogDTO> getCommitLog(String svnPath, int limit) throws SVNException {
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, "admin", "admin");
		SVNRepository repository = ourClientManager.createRepository(SVNURL.parseURIEncoded(svnPath), true);
		SVNDirEntry entry = repository.info(".", -1);
		return getCommitLog(svnPath, (int) entry.getRevision(), 1, limit);
	}

	/**
	 * 获得指定版本提交日志信息
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param revision
	 *            版本
	 * @param limit
	 *            展示数
	 * @return 日志实体集合
	 * @throws SVNException
	 */
	public static List<SVNCommitLogDTO> getCommitLog(String svnPath, int revision, int limit) throws SVNException {
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, "admin", "admin");
		SVNRepository repository = ourClientManager.createRepository(SVNURL.parseURIEncoded(svnPath), true);
		SVNDirEntry entry = repository.info(".", -1);
		return getCommitLog(svnPath, (int) entry.getRevision(), revision, limit);
	}

	/**
	 * 获得指定版本提交日志信息
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param startRevision
	 *            开始版本号
	 * @param endRevision
	 *            结束版本号
	 * @param limit
	 *            展示数
	 * @return 日志实体集合
	 * @throws SVNException
	 */
	public static List<SVNCommitLogDTO> getCommitLog(String svnPath, int startRevision, int endRevision, int limit)
			throws SVNException {
		return getCommitLog(svnPath, new String[] {}, -1, startRevision, endRevision, limit);
	}

	/**
	 * 获得指定版本提交日志信息
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param paths
	 *            文件路径
	 * @param pegRevision
	 *            文件版本号
	 * @param startRevision
	 *            开始版本号
	 * @param endRevision
	 *            结束版本号
	 * @param limit
	 *            展示数
	 * @return 日志实体集合
	 * @throws SVNException
	 */
	public static List<SVNCommitLogDTO> getCommitLog(String svnPath, String[] paths, int pegRevision, int startRevision,
			int endRevision, int limit) throws SVNException {
		return getCommitLog(svnPath, "admin", "admin", paths, pegRevision, startRevision, endRevision, limit);
	}

	/**
	 * 获得指定版本提交日志信息
	 * 
	 * @param svnPath
	 *            SVN路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            密码
	 * @param paths
	 *            文件路径
	 * @param pegRevision
	 *            文件版本号
	 * @param startRevision
	 *            开始版本号
	 * @param endRevision
	 *            结束版本号
	 * @param limit
	 *            展示数
	 * @return 日志实体集合
	 * @throws SVNException
	 */
	public static List<SVNCommitLogDTO> getCommitLog(String svnPath, String userName, String passWord, String[] paths,
			int pegRevision, int startRevision, int endRevision, int limit) throws SVNException {

		// 3.初始化权限
		ISVNAuthenticationManager isvnAuthenticationManager = SVNWCUtil.createDefaultAuthenticationManager(userName,
				passWord);
		// 4.创建SVNClientManager的实例
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		// 实例化客户端管理类
		SVNClientManager svnClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, "admin", "admin");
		SVNLogClient svnLogClient = svnClientManager.getLogClient();
		ArrayList<SVNCommitLogDTO> logList = new ArrayList<>();
		try {
			svnLogClient.doLog(SVNURL.parseURIEncoded(svnPath), paths, SVNRevision.create(pegRevision),
					SVNRevision.create(startRevision), SVNRevision.create(endRevision), false, true, false, limit, null,
					svnLogEntry -> {
						SVNCommitLogDTO svnCommitLogDTO = new SVNCommitLogDTO();
						svnCommitLogDTO.setAuthor(svnLogEntry.getAuthor());
						svnCommitLogDTO.setMessage(svnLogEntry.getMessage());
						svnCommitLogDTO.setRevision(svnLogEntry.getRevision());
						svnCommitLogDTO.setCommitDate(svnLogEntry.getDate());

						Collection<SVNLogEntryPath> svnLogEntryPathCollection = svnLogEntry.getChangedPaths().values();
						List<SVNFileEntryDTO> fileEntryDTOList = new ArrayList<>();
						for (SVNLogEntryPath svnLogEntryPath : svnLogEntryPathCollection) {
							int i = svnLogEntryPath.getPath().lastIndexOf("/");
							String substring = svnLogEntryPath.getPath().substring(0, i);
							SVNClientManager svnClientManager2 = SVNClientManager.newInstance(options,
									isvnAuthenticationManager);
							SVNRepository repository = svnClientManager2
									.createRepository(SVNURL.parseURIEncoded(svnPath), true);
							List<SVNFileEntryDTO> svnFileEntryDTOList = new ArrayList<>();
							listEntries(repository, substring, svnLogEntry.getRevision(), svnFileEntryDTOList);
							for (SVNFileEntryDTO svnFileEntryDTO : svnFileEntryDTOList) {
								svnFileEntryDTO.setSubmitType(String.valueOf(svnLogEntryPath.getType()));
								svnFileEntryDTO.setPath(svnFileEntryDTO.getPath());
								if (svnFileEntryDTO.getPath().equals(svnLogEntryPath.getPath())) {
									fileEntryDTOList.add(svnFileEntryDTO);
								}
							}
						}
						svnCommitLogDTO.setFileList(fileEntryDTOList);
						logList.add(svnCommitLogDTO);
					});
		} catch (Exception e) {
			e.printStackTrace();
		}
		return logList;
	}

	/**
	 * 获取文件详情信息
	 * 
	 * @param repository
	 *            镜像
	 * @param path
	 *            路径
	 * @param revision
	 *            版本
	 * @param svnFileEntryDTOList
	 *            文件实体集合
	 * @throws SVNException
	 */
	private static void listEntries(SVNRepository repository, String path, Long revision,
			List<SVNFileEntryDTO> svnFileEntryDTOList) throws SVNException {
		// 获取版本库的path目录下的所有条目。参数-1表示是最新版本。
		Collection entries = null;
		try {
			entries = repository.getDir(path, revision, null, (Collection) null);
		} catch (Exception e) {
			return;
		}
		Iterator iterator = entries.iterator();
		while (iterator.hasNext()) {
			SVNDirEntry entry = (SVNDirEntry) iterator.next();
			// 创建文件对象
			SVNFileEntryDTO svnFileEntryDTO = new SVNFileEntryDTO();
			svnFileEntryDTO.setName(entry.getName());
			svnFileEntryDTO.setRevision(entry.getRevision());
			svnFileEntryDTO.setPath("/" + ("".equals(path) ? "" : path + "/") + entry.getName());
			svnFileEntryDTO.setPath(svnFileEntryDTO.getPath().replace("//", "/"));
			svnFileEntryDTO.setKind(entry.getKind().toString());
			svnFileEntryDTOList.add(svnFileEntryDTO);
			if (entry.getKind() == SVNNodeKind.DIR) {
				listEntries(repository, (path.equals("")) ? entry.getName() : ToolUtils.endDir(path) + entry.getName(),
						revision, svnFileEntryDTOList);
			}
		}
	}

	/**
	 * 获取指定版本的文件并转换为字符串
	 * 
	 * @param url
	 *            SVN路径
	 * @param version
	 *            版本
	 * @return
	 * @throws Exception
	 */
	public static String getRevisionFileContent(String url, int version) throws Exception {
		return getRevisionFileContent(url, "admin", "admin", version);
	}

	/**
	 * 获取指定版本的文件并转换为字符串
	 * 
	 * @param url
	 *            SVN路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            密码
	 * @param version
	 *            版本
	 * @return
	 * @throws Exception
	 */
	public static String getRevisionFileContent(String url, String userName, String passWord, int version)
			throws Exception {

		// create clientManager
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, userName, passWord);

		// generate client
		SVNWCClient wcClient = ourClientManager.getWCClient();

		SVNURL repositoryUrl = SVNURL.parseURIEncoded(url);
		OutputStream contentStream = new ByteArrayOutputStream();
		wcClient.doGetFileContents(repositoryUrl, SVNRevision.HEAD, SVNRevision.create(version), false, contentStream);
		return contentStream.toString();
	}

	/**
	 * 获取指定版本的文件并转换为字符串
	 * 
	 * @param url
	 *            SVN路径
	 * @param userName
	 *            用户名
	 * @param passWord
	 *            密码
	 * @param version
	 *            版本
	 * @return 文件
	 * @throws Exception
	 */
	public File getRevisionFile(String url, String userName, String passWord, String version) throws Exception {

		// create clientManager
		ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
		ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions) options, userName, passWord);

		// generate client
		SVNWCClient wcClient = ourClientManager.getWCClient();

		SVNURL repositoryUrl = SVNURL.parseURIEncoded(url);

		SVNRevision revision = SVNRevision.create(Long.parseLong(version));
		File file = File.createTempFile("patch-", ".tmp");
		OutputStream contentStream = new FileOutputStream(file);
		wcClient.doGetFileContents(repositoryUrl, SVNRevision.HEAD, revision, false, contentStream);
		return file;
	}

	/**
	 * 扫描仓库
	 * 
	 * @param path
	 *            扫描的地址
	 * @return
	 */
	public static HashMap<String, String> scanRepository(String path) {
		HashMap<String, String> paths = new HashMap<>();
		File dir = new File(path + "repo" + File.separator);
		for (File file : dir.listFiles()) {
			if (FileUtil.isDirectory(file) //
					&& FileUtil.exist(file.getPath() + File.separator + "conf") //
					&& FileUtil.exist(file.getPath() + File.separator + "db") //
					&& FileUtil.exist(file.getPath() + File.separator + "hooks") //
					&& FileUtil.exist(file.getPath() + File.separator + "locks")) {
				paths.put(file.getName(), path);
			}
		}
		return paths;
	}

}

4、SvnServiceUtil.java

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RuntimeUtil;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

/**
 * @author: hanchunyu
 * @since 2022/11/2 上午10:58
 *        <p>
 *        Description: SVN服务器服务
 */
public class SvnServiceUtil {

	/**
	 * 创建SVN目录
	 * 
	 * @param path
	 *            服务器路径
	 */
	public static void createSvnDir(String path) {
		// 创建仓库目录
		FileUtil.mkdir(path + "repo");
	}

	/**
	 * 停止服务器
	 */
	public static void stopSvnServer() {
		if (SystemUtil.isWindows()) {
			RuntimeUtil.execForStr("taskkill /f /im svnserve.exe");
		} else {
			RuntimeUtil.execForStr("killall svnserve");
		}
	}

	/**
	 * 开启服务器
	 * 
	 * @param path
	 *            服务器路径
	 * @param port
	 *            端口号
	 * @return
	 */
	public static String startSvnServer(String path, String port) {
		String rs = null;
		if (SystemUtil.isWindows()) {
			// 使用vbs后台运行
			String cmd = "svnserve.exe -d -r " + (path + "repo").replace("/", "\\") + " --listen-port " + port;
			List<String> vbs = new ArrayList<>();
			vbs.add("set ws=WScript.CreateObject(\"WScript.Shell\")");
			vbs.add("ws.Run \"" + cmd + " \",0");
			FileUtil.writeLines(vbs, path + "run.vbs", Charset.forName("UTF-8"));

			rs = RuntimeUtil.execForStr("wscript " + path + "run.vbs");
		} else {
			rs = RuntimeUtil.execForStr("svnserve -d -r " + path + "repo --listen-port " + port);
		}
		return rs;
	}

	public static Boolean getStatus(SvnServerBean svnServerBean) {
		Boolean isRun = false;
		String status = "";

		SvnProtocolEnum serverProtocol = svnServerBean.getServerProtocol();
		if (SvnProtocolEnum.HTTP.equals(serverProtocol) || SvnProtocolEnum.HTTPS.equals(serverProtocol)) {
			String[] command = { "/bin/sh", "-c", "ps -ef|grep httpd" };
			String rs = RuntimeUtil.execForStr(command);
			isRun = rs.contains("httpd -k start");
		} else {
			if (Boolean.TRUE.equals(SystemUtil.isWindows())) {
				String[] command = { "tasklist" };
				String rs = RuntimeUtil.execForStr(command);
				isRun = rs.toLowerCase().contains("svnserve");
			} else {
				String[] command = { "/bin/sh", "-c", "ps -ef|grep svnserve" };
				String rs = RuntimeUtil.execForStr(command);
				isRun = rs.contains("svnserve -d -r");
			}
		}
		return isRun;
	}
}

5、SvnUserUtil.java

import org.ini4j.Ini;
import org.ini4j.Profile;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: hanchunyu
 * @since 2022/11/9 下午3:20
 *        <p>
 *        Description: SVN用户权限操作类
 */
public class SvnUserUtil {


	/**
	 * 文件删除用户
	 *
	 * @param repositoryBean
	 *            SVN仓库实体
	 * @param svnUserAuthBeans
	 *            用户权限实体集合
	 * @throws IOException
	 */
	public static void deleteUserToFile()
			throws IOException {
		String passwdPath = getPasswdPath(getServerPath(),getRepositoryName());
		File file = new File(passwdPath);
		Ini ini = new Ini();
		ini.load(file);

		Profile.Section users = ini.get("users");
        
		users.remove(getUserName())

		ini.store(file);
	}


	/**
	 * 从文件删除用户组
	 *
	 * @param repositoryBean
	 *            SVN仓库实体
	 * @param svnGroupAuthBeans
	 *            用户组权限实体集合
	 * @throws IOException
	 */
	public static void deleteGroupToFile()
			throws IOException {
		String authPath = getAuthzPath(getServerPath(),getRepositoryName());
		File file = new File(authPath);
		Ini ini = new Ini();
		ini.load(file);

		Profile.Section groups = ini.get("groups");
		groups.remove(getGroupName())
		ini.store(file);
	}


	/**
	 * 删除权限
	 *
	 * @param repositoryBean
	 *            SVN仓库实体
	 * @param svnUserAuthBeans
	 *            用户权限实体集合
	 * @param svnGroupAuthBeans
	 *            用户组权限实体集合
	 * @throws IOException
	 */
	public static void deleteAuth() throws IOException {
		String authPath = getAuthzPath(getServerPath(),getRepositoryName());
		File file = new File(authPath);
		Ini ini = new Ini();
		ini.load(file);

		Profile.Section users = ini.get(repositoryBean.getSvnAddress());
        
		users.remove("@" + getGroupName());
            
		ini.store(file);
	}

	/**
	 * 创建用户(刷新) 将数据库中的全部用户进行刷新写入
	 * 
	 * @param repositoryBean
	 *            SVN仓库实体
	 * @throws IOException
	 */
	public static void createUser() throws IOException {

		String passwdPath = getPasswdPath(getServerPath(),getRepositoryName());
		File file = new File(passwdPath);
		Ini ini = new Ini();
		ini.load(file);
		Map<String, Map<String, String>> updateData = new HashMap<>();

		Map<String, String> userMap = new HashMap<>();
		
		userMap.put(getUserName(),getPassword());

		updateData.put("users", userMap);

		Profile.Section section = null;
		Map<String, String> dataMap = null;
		for (String sect : updateData.keySet()) {
			section = ini.get(sect);
			dataMap = updateData.get(sect);
			if (section == null) {
				for (String key : dataMap.keySet()) {
					ini.add(sect, key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			} else {
				for (String key : dataMap.keySet()) {
					section.put(key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			}
		}
		ini.store(file);

	}

	/**
	 * 更新用户
	 * 
	 * @param svnUserAuthBean
	 *            用户权限实体
	 * @param repositoryBean
	 *            SVN仓库镜像
	 * @throws IOException
	 */
	public static void updateUser() throws IOException {

		String passwdPath = getPasswdPath(getServerPath(),getRepositoryName());
		File file = new File(passwdPath);
		Ini ini = new Ini();
		ini.load(file);

		Profile.Section section = ini.get("users");
		if (section != null) {
			section.put(getUserName(),getPassword() == null ? "":getPassword());
		} else {
			ini.add("users", getUserName(),getPassword() == null ? "":getPassword());
		}
		ini.store(file);
	}

	/**
	 * 更新用户权限
	 * 
	 * @param svnUserAuthBean
	 *            用户权限实体
	 * @param repositoryBean
	 *            SVN仓库镜像
	 * @throws IOException
	 */
	public static void updateUserAuth()
			throws IOException {
		
		String authPath = getAuthzPath(getServerPath(),getRepositoryName());
		File file = new File(authPath);
		Ini ini = new Ini();
		ini.load(file);

		Profile.Section section = ini.get(getSvnAddress());
		if (section != null) {
			section.put(userName(),typeName());
		} else {
			ini.add(getSvnAddress() != null ? getSvnAddress() : "/",
					getUserName(),typeName());
		}
		ini.store(file);
	}

	/**
	 * 更新用户组权限
	 * 
	 * @param svnGroupAuthBean
	 *            用户组权限实体
	 * @param repositoryBean
	 *            SVN仓库镜像
	 * @throws IOException
	 */
	public static void updateGroupAuth()
			throws IOException {
		
		String authPath = getAuthzPath(getServerPath(),getRepositoryName());
		File file = new File(authPath);
		Ini ini = new Ini();
		ini.load(file);

		Map<String, String> userGroupMap = new HashMap<>();
		Map<String, String> authMap = new HashMap<>();
		Map<String, Map<String, String>> updateData = new HashMap<>();
		
		userGroupMap.put(getGroupName(), userName);
		authMap.put("@" + getName(), typeName());

		updateData.put("groups", userGroupMap);

		updateData.put(
				repositoryBean.getSvnAddress() == null ? "/" : ToolUtils.startDir(repositoryBean.getSvnAddress()),
				authMap);

		Profile.Section section = null;
		Map<String, String> dataMap = null;
		for (String sect : updateData.keySet()) {
			section = ini.get(sect);
			dataMap = updateData.get(sect);
			if (section != null) {
				for (String key : dataMap.keySet()) {
					section.put(key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			} else {
				for (String key : dataMap.keySet()) {
					ini.add(sect, key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			}

		}
		ini.store(file);
	}

	/**
	 * 更新用户组
	 * 
	 * @param svnGroupAuthBean
	 *            用户组权限实体
	 * @param repositoryBean
	 *            SVN仓库镜像
	 * @throws IOException
	 */
	public static void updateGroup()
			throws IOException {
		
		String passwdPath = getPasswdPath(getServerPath(),getRepositoryName());
		File file = new File(passwdPath);
		Ini ini = new Ini();
		ini.load(file);
		Map<String, Map<String, String>> updateData = new HashMap<>();

		Map<String, String> userMap = new HashMap<>();

		
		userMap.put(userName,password);

		updateData.put("users", userMap);

		Profile.Section section = null;
		Map<String, String> dataMap = null;
		for (String sect : updateData.keySet()) {
			section = ini.get(sect);
			dataMap = updateData.get(sect);
			if (section != null) {
				for (String key : dataMap.keySet()) {
					section.put(key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			} else {
				for (String key : dataMap.keySet()) {
					ini.add(sect, key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			}
		}
		ini.store(file);
	}

	/**
	 * 创建权限以及用户组(刷新) 将数据库中的全部进行刷新写入
	 * 
	 * @param repositoryBean
	 *            SVN仓库实体
	 * @throws IOException
	 */
	public static void createAuth() throws IOException {
		String authPath = getAuthzPath(getServerPath(),getRepositoryName());
		File file = new File(authPath);
		Ini ini = new Ini();
		ini.load(file);
		Map<String, Map<String, String>> updateData = new HashMap<>();

		DBUtils t = DBUtils.t(WebContext.getTenantIdentifier());
		Map<String, String> userGroupMap = new HashMap<>();
		Map<String, String> authMap = new HashMap<>();
        
		authMap.put("@" + groupName,typeName);

		updateData.put("groups", userGroupMap);

		updateData.put(
				repositoryBean.getSvnAddress() == null ? "/" : ToolUtils.startDir(repositoryBean.getSvnAddress()),
				authMap);

		Profile.Section section = null;
		Map<String, String> dataMap = null;
		for (String sect : updateData.keySet()) {
			section = ini.get(sect);
			dataMap = updateData.get(sect);
			if (section != null) {
				for (String key : dataMap.keySet()) {
					section.put(key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			} else {
				for (String key : dataMap.keySet()) {
					ini.add(sect, key, dataMap.get(key) == null ? "" : dataMap.get(key));
				}
			}

		}
		ini.store(file);

	}

	/**
	 * 创建全部人权限
	 * 
	 * @param repositoryBean
	 *            仓库实体
	 * @param svnAuthEnum
	 *            权限枚举
	 * @throws IOException
	 */
	public static void updateAdminAuth() throws IOException {
	
		String authPath = getAuthzPath(getServerPath(),getRepositoryName());
		File file = new File(authPath);
		Ini ini = new Ini();
		ini.load(file);

		Profile.Section section = ini.get(getSvnAddress());
		if (section != null) {
			section.put("*", svnAuthEnum);
		} else {
			ini.add(repositoryBean.getSvnAddress(), "*", svnAuthEnum);
		}
		ini.store(file);

	}

	/**
	 * 获取用户名密码文件路径
	 * 
	 * @param path
	 *            SVN仓库路径
	 * @param name
	 *            仓库文件路径
	 * @return
	 */
	private static String getPasswdPath(String path, String name) {
		return ToolUtils.handlePath(
				ToolUtils.endDir(path) + "repo/" + ToolUtils.endDir(ToolUtils.startDir(name)) + "/conf/passwd");
	}

	/**
	 * 获取权限文件路径
	 * 
	 * @param path
	 *            SVN仓库路径
	 * @param name
	 *            仓库文件路径
	 * @return
	 */
	private static String getAuthzPath(String path, String name) {
		return ToolUtils.handlePath(
				ToolUtils.endDir(path) + "repo/" + ToolUtils.endDir(ToolUtils.startDir(name)) + "/conf/authz");
	}

}

6、SystemUtil.java

import cn.hutool.core.io.FileUtil;

/**
 * @author: hanchunyu
 * @since 2022/11/2 上午11:02
 *        <p>
 *        Description: 系统工具类
 */
public class SystemUtil {

	/**
	 * 判断系统
	 * 
	 * @return 字符串
	 */
	public static String getSystem() {

		if (cn.hutool.system.SystemUtil.get(cn.hutool.system.SystemUtil.OS_NAME).toLowerCase().contains("windows")) {
			return "Windows";
		} else if (cn.hutool.system.SystemUtil.get(cn.hutool.system.SystemUtil.OS_NAME).toLowerCase()
				.contains("mac os")) {
			return "Mac OS";
		} else {
			return "Linux";
		}

	}

	/**
	 * 判断是否是Windows系统
	 * 
	 * @return
	 */
	public static Boolean isWindows() {
		return getSystem().equals("Windows");
	}

	/**
	 * 判断是否是Mac系统
	 * 
	 * @return
	 */
	public static Boolean isMacOS() {
		return getSystem().equals("Mac OS");
	}

	/**
	 * 判断是否是Linux系统
	 * 
	 * @return
	 */
	public static Boolean isLinux() {
		return getSystem().equals("Linux");
	}

	/**
	 * 判断是否是root、用户
	 * 
	 * @return
	 */
	public static boolean hasRoot() {
		if (SystemUtil.isLinux()) {
			String user = System.getProperties().getProperty(cn.hutool.system.SystemUtil.USER_NAME);
			if ("root".equals(user)) {
				return true;
			} else {
				return false;
			}
		}
		return true;
	}

}

7、ToolUtils.java

public class ToolUtils {

	/**
	 * 处理路径的斜杠
	 * 
	 * @param path
	 *            路径
	 * @return
	 */
	public static String handlePath(String path) {
		return path.replace("\\", "/").replace("//", "/");
	}

	/**
	 * 处理目录最后的斜杠
	 * 
	 * @param path
	 *            路径
	 * @return
	 */
	public static String endDir(String path) {
		if (!path.endsWith("/")) {
			path += "/";
		}

		return path;
	}

	/**
	 * 处理目录开始的斜杠
	 *
	 * @param path
	 *            路径
	 * @return
	 */
	public static String startDir(String path) {
		if (!path.startsWith("/")) {
			path += "/";
		}

		return path;
	}
}

相关的实体

1、DirNodeDTO.java

public class DirNodeDTO {
	private String path;
	private String name;

	private Long size;

	private Long revision;

	private String author;

	private Date updateDate;

	private String message;

	private boolean isDir;

	private DirNodeDTO parent;
}

2、RepositoryFileContentDTO.java

public class RepositoryFileContentDTO implements Serializable {
	private boolean isText;
	private ByteArrayOutputStream baos;
}

3、SVNCommitLogDTO.java

public class SVNCommitLogDTO {

	/**
	 * 版本号
	 */
	private Long revision;
	/**
	 * 提交人信息
	 */
	private String author;
	/**
	 * 提交时间
	 */
	private Date commitDate;
	/**
	 * 提交信息
	 */
	private String message;
	/**
	 * 仓库前缀
	 */
	private String repoPrefix;
	/**
	 * 文件列表
	 */
	private List<SVNFileEntryDTO> fileList;
}

4、SVNFileEntryDTO.java

public class SVNFileEntryDTO {
	/**
	 * 文件名
	 */
	private String name;

	/**
	 * 文件类别,文件file,文件夹dir
	 */
	private String kind;
	/**
	 * 版本号
	 */
	private Long revision;
	/**
	 * 操作文件类型:A添加,D删除,U更新
	 */
	private String submitType;
	/**
	 * 文件路径 :如 /测试项目/112/中文.ppt
	 */
	private String path;
}

posted on 2022-12-22 15:24  Chase_Hanky  阅读(151)  评论(0编辑  收藏  举报