自动拉取svn更改日志列表,并编译

项目太老了,发版需要一个文件一个文件编译打包,再整合发版,太麻烦了,所以写了个自动编译

1.在项目中手动更新代码
2.加入依赖jar包

        <!--svn包-->
        <dependency>
            <groupId>org.tmatesoft.svnkit</groupId>
            <artifactId>svnkit</artifactId>
            <version>1.9.2</version>
        </dependency>

3.在项目中建一个test包,复制下面代码执行

package test;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNWCUtil;

import edu.emory.mathcs.backport.java.util.Collections;


public class CopyFile {

	//=================================================================================================//
	//==																						     ==//
	//==								     以下成员变量可作调整										     ==//
	//==																						     ==//
	//=================================================================================================//
	
   //svn路径
	private static String url = "svn://xxx"
   //svn用户名
	private static String username = "xxx"
   //svn密码
	private static String password = "xxx";
	private static String startData = "2018-10-03 00:00:00"; //指定的日期戳之前或之间最接近的版本号
	
	
	/**
	 * 是否校验文件最后修改时间,开启校验后,不满足的会警告,无论是否满足都会处理/编译
	 */
	private static boolean isCheckFileLastModifyDate = true;
	
	/**
	 * 开启校验文件最后修改时间后,文件的最后修改时间小于此时间则会警告
	 */
	private static String fileLastModifyDateString = "2018-12-19 08:30:11";
	
	/**
	 * 处理后的文件目录,以运行时的年与日时分秒为文件名,以防文件名重复
	 */
	private static String newPath = "D:/backups/"+new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss").format(new Date())+"/";
	
	
	/**
	 * 去除文件路径的前缀(svn路径修改之后则需要修改)
	 */
	private static String filePrefix = "/FTMSN/ftmsn";
	
	/**
	 * 源文件目录
	 */
	private static String sourcePath = "D:/FTMSN/";
	
	/**
	 * jdk安装目录
	 */
	private static String JDKPath = "D:/mocrisoft/java/JDK/jdk1.6.0_45";
	
	//=================================================================================================//
	//==																						     ==//
	//==								     以下成员变量不需修改										     ==//
	//==																						     ==//
	//=================================================================================================//
	
	/**
	 * 需要处理的文件列表路径  ,文件的编码要求是GBK
	 */
	private static String fileListPath = newPath +"fileList.txt";
	
	/**
	 * 需要处理的文件列表
	 */
	private static List<String> fileList = new ArrayList<String>();
	
	/**
	 * 删除的文件列表(删除的文件,svn上的操作是删除)
	 */
	private static List<String> deleteFileList = new ArrayList<String>();
	
	/**
	 * 处理失败(编译失败或者文件复制失败)
	 */
	private static List<String> compileFailList = new ArrayList<String>();
	
	/**
	 * 日志文件路径
	 */
	private static String logFilePath = newPath +"log.log";
	
	private static String svnFileList = newPath +"svnFileList.txt";
	/**
	 * 日志输出流
	 */
	private static MyPrintStream log = null;
	
	/**
	 * 不处理的文件集合(ftmerge项目下的Java文件不处理)
	 */
	private static List<String> untreatedList = new ArrayList<String>();
	
	/**
	 * 警告的文件集合(涉及到配置文件)
	 */
	private static List<String> warningList = new ArrayList<String>();
	
	/**
	 * 文件最后修改日期不符合的文件集合
	 */
	private static List<String> fileLastModifyDateWarningList = new ArrayList<String>();
	
	/**
	 * 此时间由 fileLastModifyDateString 转化而来
	 */
	private static Date fileLastModifyDate = null;
	
	//初始化操作
	static{
		//创建文件列表
		try {
			File file = new File(newPath);
			if (!file.exists()) {
				file.mkdirs();
			}
			log = new MyPrintStream(new FileOutputStream(fileListPath, true),true);
		} catch (IOException e) {
			e.printStackTrace(log);
			log.println("文件列表输出流创建失败,程序退出");
			//日志输出流创建失败,退出程序
			System.exit(0); 
		}
		
		
		//转化时间
		try {
			fileLastModifyDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(fileLastModifyDateString);
		} catch (ParseException e) {
			e.printStackTrace(log);
			fileLastModifyDate = new Date();
		}
		
	}
	
	
	
	public static void main(String[] args) {

       //从svn获取更改文件列表,并写进文本中
		getSVNLogs()
		
		//创建日志文件
		try {
			log = new MyPrintStream(new FileOutputStream(logFilePath, true), true);
		} catch (IOException e) {
			e.printStackTrace(log);
			log.println("日志输出流创建失败,程序退出");
			// 日志输出流创建失败,退出程序
			System.exit(0);
		}
	
		//读取文件列表
		log.println("=====================读取文件列表中=====================");
		
		rederFileListPath();
		log.println("=====================读取文件列表完成=====================");
		log.println("=====================总文件数:"+fileList.size());
		
		
		for (String filePath : fileList) {

			//读取原文件
			File sourceFile = new File(sourcePath+filePath);
			if (!sourceFile.exists()) {
				log.println("源文件或文件夹:"+sourcePath+filePath+" 不存在");
				compileFailList.add("源文件或文件夹不存在:"+sourcePath+filePath);
				continue;
			}
			//判断是否是文件
			if (!sourceFile.isFile()) {
				log.println("不是文件:"+sourcePath+filePath);
				compileFailList.add("不是文件:"+sourcePath+filePath);
				continue;
			}
			Date lastModified = new Date(sourceFile.lastModified());
			log.println("原文件最后修改时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(lastModified));
			if (isCheckFileLastModifyDate && lastModified.before(fileLastModifyDate)) {
				fileLastModifyDateWarningList.add(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(lastModified)+":"+sourcePath+filePath);
			}
			
			//不是Java文件不需要编译
			if (filePath.endsWith(".java")) {
				compileFile(filePath);
			}else {
				copyFile(filePath);
			}
			
		} //for循环结束
		
		log.println("=====================编译结束==========================================" );
		log.println("\r\n" );
		log.println("\r\n" );
		
		log.println("=====================总文件数:"+fileList.size());
		log.println("=====================处理失败数量:" + compileFailList.size());
		if (compileFailList.size() >0) {
			log.println("=====================文件如下:");
			for (String string : compileFailList) {
				log.println(string);
			}
			log.println("================处理失败文件结束===================");
		}
		log.println("\r\n" );
		log.println("\r\n" );
		
		log.println("=====================未处理的文件数量:" + untreatedList.size());
		if (untreatedList.size() >0) {
			log.println("=====================文件如下:");
			for (String string : untreatedList) {
				log.println(string);
			}
			log.println("================未处理的文件结束===================");
		}
		log.println("\r\n" );
		log.println("\r\n" );
		
		
		log.println("=====================注意,以下文件的操作是删除,删除的文件数量" + deleteFileList.size());
		if (deleteFileList.size() >0) {
			log.println("=====================文件如下:");
			for (String string : deleteFileList) {
				log.println(string);
			}
			log.println("================删除的文件结束===================");
		}
		log.println("\r\n" );
		log.println("\r\n" );
		
		
		if (warningList.size() >0) {
			log.println("=====================警告,本次提交了以下配置文件或toftmerge项目文件,文件数量" + warningList.size());
			log.println("=====================文件如下:");
			for (String string : warningList) {
				log.println(string);
			}
			log.println("================警告的文件结束===================");
		}
		
		if (isCheckFileLastModifyDate && fileLastModifyDateWarningList.size() >0) {
			log.println("=====================警告,以下文件不符合时间要求,文件数量" + fileLastModifyDateWarningList.size());
			log.println("=====================要求时间不得小于:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(fileLastModifyDate)+";文件如下:");
			for (String string : fileLastModifyDateWarningList) {
				log.println(string);
			}
			log.println("================警告的文件结束===================");
		}
		
		log.close();
		
	}
	
	/**
	 * 从svn获取更改文件的路径,并写入文本中
	 */
	public static void getSVNLogs() { 
		// 版本库初始化
        DAVRepositoryFactory.setup(); 
        // 资源库相关登录配置信息
        long startRevision = 0;// 最初版本
        long endRevision = SVNRepository.INVALID_REVISION;// 最新版本
        SVNRepository repository = null;
        List<SvnLogModel> svns = new ArrayList<SvnLogModel>();
        try {
            // 建立一个新的资源库
            repository = DAVRepositoryFactory.create(SVNURL.parseURIEncoded(url)); // 登录确认信息
            @SuppressWarnings("deprecation")
			ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(username, password);
            repository.setAuthenticationManager(authManager);

            //获取日期最近的版本号
            startRevision = repository.getDatedRevision(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(startData));
            log.print("起始版本号:"+startRevision +"\n");

            // 存放结果
            final List<SVNLogEntry> logEntries = new ArrayList<SVNLogEntry>();
            //查询版本startRevision到版本endRevision的更新日志列表,列表结果logEntries
            repository.log(new String[]{""}, logEntries, startRevision, endRevision, true, true);

            log.println("     总共"+logEntries.size()+"条记录" +"\r\n");
            // 遍历
            for (Iterator<SVNLogEntry> entries = logEntries.iterator(); entries.hasNext(); ) {
                SVNLogEntry logEntry = (SVNLogEntry) entries.next();
                SvnLogModel svn = new SvnLogModel();
                svn.setMessage(logEntry.getMessage());
                svn.setAuthor(logEntry.getAuthor());
                svn.setDate(logEntry.getDate());
                svn.setRevision(logEntry.getRevision());
                List<String> changedPathsList = new ArrayList<String>();

                //遍历变更的文件列表
                if (logEntry.getChangedPaths().size() > 0) {
                    Set<String> changedPathsSet = logEntry.getChangedPaths().keySet();
                    for (Iterator<String> changedPaths = changedPathsSet.iterator(); changedPaths.hasNext(); ) {
                        SVNLogEntryPath entryPath = logEntry.getChangedPaths().get(changedPaths.next());
                        char entrytype = entryPath.getType();
                        String typeCN = "";
                        if ("M".equals(String.valueOf(entrytype))) {
                            typeCN = "已修改 : ";
                        } else if ("A".equals(String.valueOf(entrytype))) {
                            typeCN = "已增加 : ";
                        } else if ("D".equals(String.valueOf(entrytype))) {
                            typeCN = "已删除 : ";
                        }
                        changedPathsList.add(typeCN+entryPath.getPath());
                    }
                }

                svn.setLogEntry(changedPathsList);
                svns.add(svn);
            }
        } catch (Exception ex) {
            ex.printStackTrace(log);
        }
        Collections.reverse(svns);
        for (SvnLogModel svnLogModel : svns) {
        	log.println(svnLogModel);
        }
        log.flush();
        log.close();
        log = null;
		// 创建svn日志文件
		try {

			log = new MyPrintStream(new FileOutputStream(svnFileList, true), true);
		} catch (IOException e) {
			e.printStackTrace(log);
			log.println("svn日志输出流创建失败,程序退出");
			// 日志输出流创建失败,退出程序
			System.exit(0);
		}
		long count = 0L;
		for (SvnLogModel svnLogModel : svns) {
			if (svnLogModel.getLogEntry() != null) {
				for (String fileList : svnLogModel.getLogEntry()) {
					fileList = fileList.replace("已修改 : ", "");
					fileList = fileList.replace("已增加 : ", "");
					fileList = fileList.replace("已删除 : ", "");
					log.println("svn://xxx"+fileList);
					count++;
				}
			}
        }
		log.println("总文件数:"+count+"个");
		log.flush();
        log.close();
        log = null;
		
    }



	/**
	 * 编译Java文件
	 * @param filePath
	 */
	private static void compileFile(String filePath) {
		
		//web  web的编译环境包括了ejb编译环境
		String webCP = sourcePath+"WEB/webapp/WEB-INF/classes;"+sourcePath+"EJB/classes";
		String webLib =sourcePath+"WEB/webapp/WEB-INF/lib;"+sourcePath+"lib";
		String webSourcepath = sourcePath+"WEB/src/";
		
		//ejb  ejb的编译环境
		String ejbCP = sourcePath+"EJB/classes";
		String ejbLib =sourcePath+"lib";
		String ejbSourcepath = sourcePath+"EJB/src/";
		
		//bankP  bankP的编译环境
		String bankPCP = sourcePath+"BankP/WebRoot/WEB-INF/classes;"+sourcePath+"EJB/classes";
		String bankPLib =sourcePath+"lib;"+sourcePath+"BankP/lib/";
		String bankPSourcepath = sourcePath+"BankP/src/";
		
		//ftmerge  ftmerge的编译环境
		String ftmergeCP = sourcePath+"ftmerge/WebContent/WEB-INF/classes;"+sourcePath+"EJB/classes";
		String ftmergeLib =sourcePath+"ftmerge/WebContent/WEB-INF/lib";
		String ftmergeSourcepath = sourcePath+"ftmerge/src/";
		
		String tmpCP = "";
		String tmpLib = "";
		String tmpSourcepath = "";
		
		String targetPath = "";
		//创建目标文件夹
		if(filePath.startsWith("/WEB/src/")){
			
			targetPath = "WEB/WEB-INF/classes/";
			tmpCP = webCP;
			tmpLib = webLib;
			tmpSourcepath = webSourcepath;
			
		
		}else if (filePath.toLowerCase().startsWith("/EJB/src/".toLowerCase())) {
			
			targetPath = "EJB/";
			tmpCP = ejbCP;
			tmpLib = ejbLib;
			tmpSourcepath = ejbSourcepath;
					
		}
	
		else if (filePath.toLowerCase().startsWith("/bankp/src/".toLowerCase())) {
			
			targetPath = "BankP/WEB-INF/classes/";
			tmpCP = bankPCP;
			tmpLib = bankPLib;
			tmpSourcepath = bankPSourcepath;
					
		}else if (filePath.toLowerCase().startsWith("/ftmerge/src/".toLowerCase())) {
			targetPath = "ftmerge/WEB-INF/classes/";
			tmpCP = ftmergeCP;
			tmpLib = ftmergeLib;
			tmpSourcepath = ftmergeSourcepath;
					
			warningList.add("有ftmerge项目的文件,请注意文件对应的位置"+sourcePath+filePath);
		}else {
			log.println("文件未处理:"+sourcePath+filePath);
			untreatedList.add(sourcePath+filePath);
			return;
		}
		File targetdir = new File(newPath + targetPath);
		log.println("正在编译:"+sourcePath+filePath);
		log.println("编译目标路径:"+targetdir.getAbsolutePath());
		if (!targetdir.exists()) {
			targetdir.mkdirs();
		}
		
		//编译
		int result = -1;
		
		log.println("编译环境:"+ tmpCP +"\n "+ tmpLib +"\n"+tmpSourcepath);
		
		String[] args1 = {
				"-g",  //生成所有调试信息
				"-implicit:none", //不生成依赖文件的class文件
				"-nowarn",  //不生成警告
				"-classpath",tmpCP,
				"-Djava.ext.dirs="+JDKPath+"/jre/lib/ext;"+tmpLib,
				//加上这个,如果有包路径和类名都相同的情况下,优先使用sourcepath下的类
				"-sourcepath",tmpSourcepath,
				"-version", //输出编译版本  (默认与项目设置的版本一样)
//				"-verbose", //输出解析详情
//				"-encoding","GBK", //指定源文件使用的字符编码
//				"-source","1.6.0", //提供与指定发行版的源兼容性
//				"-target","1.6", //生成特定 VM 版本的类文件
				"-d" , newPath+targetPath , //编译后的目标目录
				sourcePath+filePath}; //原文件路径
		
//				result = Main.compile(args1);  //另一种编译方式,暂时不用
		
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		
		result = compiler.run(null, log, log, args1);
		
		log.println("执行结果:"+result+(result==0?" 编译成功":" 编译失败"));
		if (result != 0) {
			compileFailList.add("编译失败:"+sourcePath+filePath);
		}
	}

	/**
	 * 复制文件
	 * @param filePath
	 */
	private static void copyFile(String filePath) {
		BufferedInputStream in = null;
		BufferedOutputStream out = null;
		try {
			
			//检查是否为配置文件
			if (filePath.toLowerCase().endsWith(".xml")||filePath.toLowerCase().endsWith(".properties")) {
				warningList.add(sourcePath+filePath);
			}
			
			in = new BufferedInputStream(new FileInputStream(sourcePath+filePath));
			
			filePath = filePath.replace("/WEB/src/", "/WEB/WEB-INF/classes/");
			filePath = filePath.replace("/EJB/src/", "/EJB/");
			filePath = filePath.replace("/BankP/src/", "/BankP/WEB-INF/classes/");
			filePath = filePath.replace("/ftmerge/src/", "/ftmerge/WEB-INF/classes/");
			
			filePath = filePath.replace("/BankP/WebRoot/", "/BankP/");
			filePath = filePath.replace("/bankp/WebRoot/", "/BankP/");
			filePath = filePath.replace("/WEB/webapp/", "/WEB/");
			filePath = filePath.replace("/ftmerge/WebContent/", "/ftmerge/");
			
			//目标文件夹
			File file = new File(newPath+filePath.substring(0, filePath.lastIndexOf("/")));
			//创建文件夹
			if (!file.exists()) {
				file.mkdirs();
			}
			log.println("正在复制文件:"+sourcePath+filePath);
			log.println("目标路径:"+file.getAbsolutePath());
			file = new File(file, filePath.substring(filePath.lastIndexOf("/")));
			out = new BufferedOutputStream(new FileOutputStream(file));
			int tmp = -1;
			while((tmp = in.read())!= -1){
				out.write(tmp);
				out.flush();
			}
			
		} catch (FileNotFoundException e) {
			log.println("文件:"+sourcePath+filePath+" 不存在! 或  目标文件"+newPath+filePath+"创建失败,请检查!");
			compileFailList.add("文件不存在:"+sourcePath+filePath);
		} catch (IOException e) {
			e.printStackTrace(log);
			log.println("复制文件出错:"+sourcePath+filePath);
			compileFailList.add("复制文件出错:"+sourcePath+filePath);
		}finally{
			try {
				if (in != null) {
					in.close();
				}
				if (out != null) {
					out.close();
				}
			} catch (IOException e) {
				e.printStackTrace(log);
			}
		}
	}

	/**
	 * 读取文件列表
	 * @param fileList 接收文件列表的集合
	 * @param fileListPath 需读取的文件列表路径
	 * @param filePrefix 需去除的文件名前缀
	 */
	private static void rederFileListPath() {
		try {
			//读取文件列表
			Reader in = new FileReader(fileListPath);
			BufferedReader bufferedReader = new BufferedReader(in);
			String tmp = null;
			while ((tmp = bufferedReader.readLine())!= null) {
				//只读取文件路径
				String tmpFilePrefix = "";
				if (tmp.startsWith("已修改 : ")) {
					tmpFilePrefix = "已修改 : ";
					
				}else if (tmp.startsWith("已增加 : ")) {
					tmpFilePrefix = "已增加 : ";
					
				}else if (tmp.startsWith("已删除 : ")) {
					tmpFilePrefix = "已删除 : ";
					tmp = tmp.replace(tmpFilePrefix +filePrefix, "");
					log.println("已删除 : "+tmp);
					deleteFileList.add(tmp);
					continue; 
					
				}else if (tmp.toLowerCase().startsWith("/web") || 
						  tmp.toLowerCase().startsWith("/ejb")||
						  tmp.toLowerCase().startsWith("/bankp") || 
						  tmp.toLowerCase().startsWith("/lib")||
						  tmp.toLowerCase().startsWith("/ftmerge") || 
						  tmp.toLowerCase().startsWith("/webdoc")) {
					//此类型没有前缀,不用做任何处理
					//此IF判断处理的是:在项目中右键复制限定名,限定名的路径是以下形式
					// /EJB/src/com/iss/closesystem/basebean/FunctionBaseBean.java
				}else {
					continue;
				}
				//去除前缀
				tmp = tmp.replace(tmpFilePrefix +filePrefix, "");
				
				fileList.add(tmp);
				log.println(tmp);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace(log);
			log.println("文件:"+fileListPath+" 不存在!");
		} catch (IOException e) {
			e.printStackTrace(log);
		}
	}

}

/**
 * 为了在控制台输出信息,重写write方法
 * @author dong
 *
 */
class MyPrintStream extends PrintStream{

	public MyPrintStream(OutputStream out, boolean autoFlush) {
		super(out, autoFlush);
	}

	@Override
	public void write(byte[] buf, int off, int len) {
		System.out.write(buf, off, len);
		super.write(buf, off, len);
	}
	
}

class SvnLogModel {
    private String message; //提交svn时写的信息
    private String author;//作者
    private Date date; //日期
    private long revision; //版本
    private List<String> logEntry;//更改的文件列表

    public SvnLogModel() {
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public Date getDate() {
        return date;
    }

    public String getDateToString() {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public long getRevision() {
        return revision;
    }

    public void setRevision(long revision) {
        this.revision = revision;
    }

    public List<String> getLogEntry() {
        return logEntry;
    }

    public void setLogEntry(List<String> logEntry) {
        this.logEntry = logEntry;
    }

    public SvnLogModel(String message, String author, Date date, long revision, List<String> logEntry) {
        this.message = message;
        this.author = author;
        this.date = date;
        this.revision = revision;
        this.logEntry = logEntry;
    }

    @Override
    public String toString() {
        String log =  "版本:" + revision + "\r\n" +
                "作者: " + author + "\r\n" +
                "日期: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date) + "\r\n" +
                "信息:" + message + "\r\n"+
                "----"+ "\r\n";

        for (String path : logEntry) {
            log = log+path+"\r\n";
        }
        return log +"\r\n";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现自动运行某一SVN路径下的bat脚本,需要用到以下几个步骤: 1. 首先需要安装SVN命令行工具,可以从SVN官网下载安装包进行安装。 2. 在SVN路径下创建一个批处理文件,比如run.bat,包含以下命令: ``` cd /d C:\SVN\project call build.bat ``` 其中,cd命令切换到SVN路径下,call命令调用项目中的build.bat脚本来进行编译。 3. 使用Windows计划任务定时运行run.bat脚本,可以设置每天凌晨自动运行。 实现自动拉取SVN tag,需要用到以下几个步骤: 1. 在SVN路径下创建一个批处理文件,比如update.bat,包含以下命令: ``` cd /d C:\SVN\project svn update svn switch ^/tags/1.0 ``` 其中,cd命令切换到SVN路径下,svn update命令更新最新的代码,svn switch命令切换到指定的tag版本。 2. 使用Windows计划任务定时运行update.bat脚本,可以设置每天凌晨自动运行。 实现将编译后的文件重命名自动上传SVN,需要用到以下几个步骤: 1. 在SVN路径下创建一个批处理文件,比如upload.bat,包含以下命令: ``` cd /d C:\SVN\project\build ren app.exe app_%date:~0,4%%date:~5,2%%date:~8,2%.exe svn add app_%date:~0,4%%date:~5,2%%date:~8,2%.exe svn commit -m "upload app_%date:~0,4%%date:~5,2%%date:~8,2%.exe" ``` 其中,cd命令切换到编译后的文件所在的目录,ren命令将文件重命名为app_yyyyMMdd.exe的格式,svn add命令将新文件添加到SVN仓库,svn commit命令提交修改。 2. 使用Windows计划任务定时运行upload.bat脚本,可以设置每天凌晨自动运行。 综合起来,可以创建一个批处理文件run_upload.bat,包含以上三个步骤,使用Windows计划任务定时运行run_upload.bat脚本即可实现自动运行某一SVN路径下的bat脚本,同时自动拉取SVN tag ,并将编译后的文件重命名自动上传SVN
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值