依据SVN日志自动生成补丁包[基于Tomcat的JavaEE项目]
根据SVN日志自动生成补丁包[基于Tomcat的JavaEE项目]
项目开发过程中代码变化很频繁,需要更新文件时,每次都需要手动制作补丁包,打包成Zip包后更新到生产环境,相当麻烦。
考虑是否可以根据SVN日志,自动生成补丁包。同时生成的输出可以当作更新日志使用。
原理就是自动去复制tomcat下的文件,包括根据src下的java文件去tomcat下查找编译类文件,包括内部类。
支持新增和修改的文件,不支持删除哦~~
于是产生了下面这个工具类。。用到了第三方库Svnkit 请自行导入。
package svnpatch; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNLogEntry; import org.tmatesoft.svn.core.SVNLogEntryPath; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.BasicAuthenticationManager; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc2.ISvnObjectReceiver; import org.tmatesoft.svn.core.wc2.SvnLog; import org.tmatesoft.svn.core.wc2.SvnOperationFactory; import org.tmatesoft.svn.core.wc2.SvnRevisionRange; import org.tmatesoft.svn.core.wc2.SvnTarget; public class PatchMaker_hello { /** * 设置一下 */ public static String destPath = "E:\\update1120\\hello\\"; //输出路径 ,可以自动建立 public static String tomcatPath = "E:\\tomcat\\webapps\\hello\\"; //tomcat的路径,需要包含最新的二进制文件哦 public static String start_date = "20141118000000";//上次更新时间 yyyyMMddHHmmss public static String end_date = "20141120234500";//截至时间 yyyyMMddHHmmss private static Map<String,String> typeDic = new HashMap<String,String>(); static { typeDic.put("M", "修改"); typeDic.put("A", "新增"); } public static void main(String[] args) { final SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); final SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); final SvnOperationFactory svnOperationFactory = new SvnOperationFactory(); try { //svn的 url final SVNURL url = SVNURL.parseURIEncoded("https://xxx/svn/xxx/hello"); svnOperationFactory.setAuthenticationManager(new BasicAuthenticationManager( "username", "password"));//svn用户名密码 final SvnLog log = svnOperationFactory.createLog(); Date date1 = sdf.parse(start_date); Date date2 = sdf.parse(end_date); log.addRange(SvnRevisionRange.create(SVNRevision.create(date1),SVNRevision.create(date2))); log.setDiscoverChangedPaths(true); log.setSingleTarget(SvnTarget.fromURL(url)); log.setReceiver(new ISvnObjectReceiver<SVNLogEntry>() { public void receive(SvnTarget arg0, SVNLogEntry arg1) throws SVNException { //每个版本执行一次 System.out.println("版本:"+arg1.getRevision()+"===========作者:"+arg1.getAuthor()+"======时间:"+sdf2.format(arg1.getDate())); System.out.println("===修改内容:"+arg1.getMessage()); Map<String,SVNLogEntryPath> map = arg1.getChangedPaths(); if(map.size()>0){ Set set = map.keySet(); for (Iterator iterator = set.iterator(); iterator .hasNext();) { String key = (String) iterator.next(); SVNLogEntryPath path = map.get(key); System.out.println(typeDic.get(path.getType()+"")+":"+key); handleFile(key); } } System.out.println("\n"); } }); log.run(); }catch(Exception ex){ ex.printStackTrace(); } finally { svnOperationFactory.dispose(); } } /** * 缓存 处理重复文件 */ private static Map<String,String> cache = new HashMap<String,String>(); /** * 处理文件 * 方法描述 * @param path */ public static void handleFile(String path){ if(cache.get("path")==null){ if(path.indexOf("/WebRoot/")>-1){ String purePath = path.substring(path.indexOf("/WebRoot/")+9); String srcPath = tomcatPath+purePath.replace("/", "\\"); String desPath = destPath+purePath.replace("/", "\\"); copyFile(srcPath,desPath); }else if(path.indexOf("/src/")>-1){ if(path.toLowerCase().endsWith("java")){ String purePath = path.substring(path.indexOf("/src/")+5); String className = purePath.substring(purePath.lastIndexOf("/")+1).replace(".java", ""); String classPath = purePath.substring(0,purePath.lastIndexOf("/")+1).replace("/", "\\"); String srcPath = tomcatPath+"WEB-INF\\classes\\"+classPath; String desPath = destPath+"WEB-INF\\classes\\"+classPath; copyJava(srcPath,desPath,className); }else{ String purePath = path.substring(path.indexOf("/src/")+5); String srcPath = tomcatPath+"WEB-INF\\classes\\"+purePath.replace("/", "\\"); String desPath = destPath+"WEB-INF\\classes\\"+purePath.replace("/", "\\"); copyFile(srcPath,desPath); } } cache.put(path, "1");//放到缓存 }else{ //处理过了 跳过 } } /** * 复制普通文件 * 方法描述 * @param src * @param dest */ public static void copyFile(String src,String dest){ File destF = new File(dest); if(!destF.getParentFile().exists()){ destF.getParentFile().mkdirs(); } try { File fsrc = new File(src); File fdest = new File(dest); if(fsrc.isDirectory()){ if(!fdest.exists()){ fdest.mkdirs(); } }else{ copyFile(fsrc,fdest); } } catch (IOException e) { e.printStackTrace(); } } /** * 主要是考虑 含有内部类的 java文件 * 方法描述 * @param src * @param dest */ public static void copyJava(String src,String dest,String cname){ File destF = new File(dest); if(!destF.exists()){ destF.mkdirs(); } File srcF = new File(src); File [] files = srcF.listFiles(); for (int i = 0; i < files.length; i++) { if(files[i].getName().startsWith(cname)){ //包含了内部类了吧 String destPath1 = dest+files[i].getName(); try { copyFile(files[i],new File(destPath1)); } catch (IOException e) { e.printStackTrace(); } } } } /** * 复制文件 * 方法描述 * @param sourceFile * @param targetFile * @throws IOException */ public static void copyFile(File sourceFile, File targetFile) throws IOException { BufferedInputStream inBuff = null; BufferedOutputStream outBuff = null; try { // 新建文件输入流并对它进行缓冲 inBuff = new BufferedInputStream(new FileInputStream(sourceFile)); // 新建文件输出流并对它进行缓冲 outBuff = new BufferedOutputStream(new FileOutputStream(targetFile)); // 缓冲数组 byte[] b = new byte[1024 * 5]; int len; while ((len = inBuff.read(b)) != -1) { outBuff.write(b, 0, len); } // 刷新此缓冲的输出流 outBuff.flush(); } finally { // 关闭流 if (inBuff != null) inBuff.close(); if (outBuff != null) outBuff.close(); } } }