小项目 GIT生成公司EXCEL周报(4)日志内容解析

Git操作与日志解析实践
本文详述了如何在项目中添加.gitignore文件,执行git命令处理日志,处理IDEA报错,创建多行日志和合并冲突的场景。通过解析Git日志,提取作者、时间等信息,将日志转换为Java对象。此外,展示了如何从日志中提取关键信息,生成符合格式的Java对象。

 项目任务4 日志内容解析

 添加 .gitignore 文件

突然发现没有加 忽略文件 ,所以此处重加了这个文件

路径:项目路径下一层

.gitignore

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

# maven ignore
target/
*.jar
!.mvn/wrapper/*
*.war
*.zip
*.tar
*.tar.gz

# eclipse ignore
.myeclipse/
.settings/
.project
.classpath

# idea ignore
.idea/
*.ipr
*.iml
*.iws
out/
/bin

# temp ignore
*.log
*.cache
*.diff
*.patch
*.tmp

# system ignore
.DS_Store
Thumbs.db
*.orig

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

然后在项目下执行以下命令:

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

IDEA执行后会有报错,处理如下:

全部操作后,选择 OK ,恢复正常(还不正常就重启一下项目)

 制作特殊情况 log

然后执行以下命令,新建分支:

 git checkout -b dev

新建分支后,在项目任意行末尾追加空行,然后进行提交,命令如下:

git status
git add -A
git commit -m "多行日志第一行
多行日志第二行
多行日志第三行"

把刚加的换行删掉,再加一个特殊日志,如下:

git status
git add -A
git commit -m "多个-m第一个" -m "多个-m第二个"

形成了两个多行日志

还有一种比较特殊,是合并冲突。先在master分支加个换行:

进行提交:

切换分支,在同样的位置加换行符,进行提交:

回到master,进行合并,制造冲突

删掉冲突行:

提交:

新日志产生了 merge行,如下:

一般这个Merge 行都是为了解决冲突的,一般不用考虑记录在周报中,是需要考虑的情况之一

 包装已有生成日志代码

下图的3、4部分,本质上就是读取git内容,然后把各个项目对应的文本内容读出来,事实上这个步骤我们不关心,把这两步独立处理到文件中,最终返回一组 项目名->内容映射:

GitDealUtil.java

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

import com.weekpaper.bean.ConfigData;
 
import java.io.File;
import java.io.InputStream;
import java.util.*;
 
public class GitDealUtil {
     
    public static Map<String,String> createLogTxt(ConfigData cd){
        //2. 生成 git 执行命令行(windows,linux的类似,进入盘符的几个步骤有差别)
        String commandFilePath = createGitCommandFile(cd);
     
        //3. 执行 git 生成限定时间段日志
        boolean result = executeGitCommand(commandFilePath);
     
        //4. 读取抓到的日志内容
        return readGitLog(cd,result);
    }
     
    private static Map<String,String> readGitLog(ConfigData cd, boolean result){
        if(cd == null || !result){
            LogUtil.severe("配置文件拿到空值或命令执行失败, 无法执行后续操作!");
            System.exit(0);
            return new LinkedHashMap<>();
             
        }
         
        Map<String,String> map = new LinkedHashMap<>();
        int n = cd.getProjectPaths().size();
        for(int i = 0; i < n; i++) {
            String path = cd.getProjectPaths().get(i);
            File f = new File(path);
           
            if(f.exists() && f.isDirectory()){
                String fullPath = FileUtil.getTmpFilePath(cd.getOutputPath(),f.getName()+".txt");
                String msg = FileUtil.getInputMsg(fullPath);
                System.out.println(msg);
                map.put(cd.getProjectNames().get(i),msg);
            }
        }
         
         
        return map;
    }
     
    private static boolean executeGitCommand(String path){
        if(path == null || path.length() == 0){
            LogUtil.severe("未生成可执行命令,无法进行后续流程!");
            System.exit(0);
            return false;
        }
        LogUtil.info("CMD /GIT命令开始执行...");
        Process p;
        boolean result = true;
        try {
            p = Runtime.getRuntime().exec(path);
            InputStream fis = p.getErrorStream();//p.getInputStream();
            String msg = FileUtil.getInputMsg(fis,false);
            p.waitFor();
            int i = p.exitValue();
            if (i != 0) {
                result = false;
                LogUtil.severe("CMD /GIT命令执行失败!请检查是否安装 git 环境,命令是否正确!提示信息为:"+msg);
            }else {
                LogUtil.info("CMD /GIT命令执行成功!");
            }
        } catch (Exception e) {
            result = false;
            LogUtil.severe("未知错误!"+e.getMessage());
        }
        return result;
    }
     
     
    private static String createGitCommandFile(ConfigData cd) {
        if(cd == null){
            LogUtil.severe("配置文件拿到空值,无法执行后续操作!");
            System.exit(0);
            return "";
        }
        LogUtil.info("开始生成"+DateUtil.toString(cd.getStartDate())+"到"+DateUtil.toString(cd.getEndDate())+"git 命令行,如下:");
//        盘符:
//        cd 【项目路径】
//        for /F %%i in ('git config --get user.name') do ( set name=%%i)
//        git log --author=%name% --since ==【开始时间】 --until=【结束时间】 > 【输出路径\tmp】\【项目名称英文】.txt
         
        if(cd.getProjectPaths()==null || cd.getProjectPaths().isEmpty()){
            LogUtil.severe("无可用项目!");
            System.exit(0);
        }
         
        int n = cd.getProjectPaths().size();
        if(cd.getProjectNames().size()<n){
            LogUtil.severe("项目中文名称和项目路径数目不匹配!");
            System.exit(0);
        }
         
        List<String> commands = new ArrayList<String>();
        for(int i = 0; i < n; i++){
            String path = cd.getProjectPaths().get(i);
            String name = cd.getProjectNames().get(i);
            LogUtil.info("开始创建项目"+name+"的 GIT 命令...");
            File f = new File(path);
            if(f.exists() && f.isDirectory()){
                //        盘符:[linux不用写这个]
                commands.add(path.split(":")[0]+":");
                //        cd 【项目路径】
                commands.add("cd "+path);
                //        for /F %%i in ('git config --get user.name') do ( set name=%%i)
                commands.add("for /F %%i in ('git config --get user.name') do ( set name=%%i)");
                //        git log --author=%name% --since ==【开始时间】 --until=【结束时间】 > D:\program\eclipse\work\DEST\config\【项目名称英文】.txt
                 
                File targetFilePath = FileUtil.reCreateFile(FileUtil.getTmpFilePath(cd.getOutputPath(),f.getName()+".txt"));
                //注意:不包含第一天,需要向前挪动1天
                commands.add("git log --author=%name% --since =="+DateUtil.getPreDayStr(cd.getStartDate())+" --until="+DateUtil.toString(cd.getEndDate())+" > "+
                        FileUtil.getShortPath(targetFilePath));
                LogUtil.info("创建项目"+name+"的 GIT 命令成功!");
            }else{
                LogUtil.info("创建项目"+name+"的 GIT 命令失败,找不到文件夹!");
            }
        }
         
        for(String command:commands){
            System.out.println(command);
        }
         
        if(!commands.isEmpty()){
            String commandPath = FileUtil.getTmpFilePath(cd.getOutputPath(),"cmd.bat");
            File commandFilePath = FileUtil.reCreateFile(commandPath);
            FileUtil.storeGitCommands(commands,FileUtil.getShortPath(commandFilePath));
            return commandPath;
        }
        return "";
         
    }
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

 读取日志转换为Java对象

综合格式如下,大致总结出以下规律:

commit 代表日志的开头,可用于作为上一条日志的标志

Merge 说明这条日志是用于解决冲突的,可以不要

Author 里面可以抓取到用户名和邮箱,需要使用空格分割处理

Date 是时间,去掉尾巴+0800 解析即可

剩余多行是日志实际内容,可能会有空行,空行全部忽略,前面的空格删掉,即可拿到真实日志内容

另外:时间是倒序的,需要反过来

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

commit 57eecf580915851dde6b780677690ce269a87683
Merge: 12047ba ab16970
Author: 【用户名】 <【邮箱名】>
Date:   Thu Jun 2 15:29:08 2022 +0800


    多行日志第一行

    多行日志第三行

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

规律弄懂,开始写:

WeekPaper.java

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

import com.weekpaper.bean.ConfigData;
import com.weekpaper.bean.LogContent;
import com.weekpaper.util.DateUtil;
import com.weekpaper.util.FileUtil;
import com.weekpaper.util.GitDealUtil;
import com.weekpaper.util.LogUtil;
 
import java.util.*;
 
public class WeekPaper {
     
    public static void main(String[] args) {
        if(args==null || args.length<1){
            LogUtil.severe("找不到配置文件!");
            System.exit(0);
        }
        //1.加载配置文件信息
        ConfigData cd = loadConfigFile(args[0]);
         
        //2. 创建Git日志文件读取日志内容
        Map<String,String> logMsgs = GitDealUtil.createLogTxt(cd);
         
        //3. 解析日志内容,读取为对象
        Map<String,List<LogContent>> projectLogs = getListObjects(logMsgs);
        for(String projectName:projectLogs.keySet()){
            System.out.println(projectName+projectLogs.get(projectName));
        }
    }
     
    private static Map<String, List<LogContent>> getListObjects(Map<String, String> logMsgs) {
        Map<String,List<LogContent>> logAns = new HashMap<>();
        for(Map.Entry<String,String> item:logMsgs.entrySet()){
            String name = item.getKey();
            String content = item.getValue();
            String[] lines = content.split("\n");
            //3.处理日志内容,抽象为对象
            List<LogContent> lcs = new ArrayList<>();
            LogContent lc = null;
            StringBuilder sb = new StringBuilder();
            boolean isMerge = false;
            for(String line:lines){
                if(line.startsWith("commit")){
                    if(lc!=null){
                        if(sb.length()>0){
                            sb.deleteCharAt(sb.length()-1);
                        }
                        lc.setContent(sb.toString());
                        sb.delete(0,sb.length());
                        if(!isMerge)
                            lcs.add(lc);
                        isMerge = false;
                    }
                    lc = new LogContent();
                    lc.setCommitVersion(line.substring("commit".length()+1).trim());
                }else if(line.startsWith("Author:")){
                    String authorAndEmail = line.substring("Author:".length()+1).trim();
                    lc.setAuthor(authorAndEmail.split(" ")[0]);
                    lc.setEmail(authorAndEmail.split(" ")[1]);
                    lc.setEmail(lc.getEmail().substring(1,lc.getEmail().length()-1));
                }else if(line.startsWith("Date:")){
                    lc.setDate(DateUtil.getUsDate(line.substring("Date:".length()+1).trim()));
                }else if(line.startsWith("Merge: ")){
                    isMerge = true;
                }else{
//                    commit 50ff270a2ba476db707df277d652t1234b732da8e
//                    Merge: 2677td2 1c873fe
//                    Author: xx <xx@xx.com>
//                    Date:   Wed Jun 1 13:55:26 2022 +0800
//
//                    Merge branch 'dev'
//                    Merge 合并分支格式的忽略
                    if(line.length()<"    ".length()) continue;
                    String str = line.substring("    ".length()).trim();
                     
                    if(str.length()>0){
                        sb.append(str);
                        sb.append("\n");
                    }
                }
            }
            if(lc!=null){
                if(sb.length()>0){
                    sb.deleteCharAt(sb.length()-1);
                }
                lc.setContent(sb.toString());
                sb.delete(0,sb.length());
                if(!isMerge)
                    lcs.add(lc);
            }
            //由于时间倒序,所以需要反过来
            Collections.reverse(lcs);
            if(!lcs.isEmpty()){
                logAns.put(name,lcs);
            }
             
        }
        return logAns;
         
    }
     
     
    private static ConfigData loadConfigFile(String path) {
        ConfigData cd = FileUtil.loadConfigData(path);
        if(cd == null){
            LogUtil.severe("配置内容有误!");
            System.exit(0);
        }else{
            LogUtil.info("获取配置文件"+ FileUtil.getFilePath(path)+"成功!");
//            LogUtil.info("获取配置文件"+ FileUtil.getFilePath(args[0])+"成功!信息如下:");
//            LogUtil.info(cd.toString());
        }
        return cd;
    }
     
     
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

LogContent.java

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

import com.weekpaper.util.DateUtil;
 
import java.util.Date;
 
public class LogContent {
    private String commitVersion;//提交版本号
    private String author;//作者
    private String email;//邮箱
    private Date date;//提交日期
    private String content;//提交日志内容
     
    public String getEmail() {
        return email;
    }
     
    public void setEmail(String email) {
        this.email = email;
    }
     
    public String getCommitVersion() {
        return commitVersion;
    }
     
    public void setCommitVersion(String commitVersion) {
        this.commitVersion = commitVersion;
    }
     
    public String getAuthor() {
        return author;
    }
     
    public void setAuthor(String author) {
        this.author = author;
    }
     
    public Date getDate() {
        return date;
    }
     
    public void setDate(Date date) {
        this.date = date;
    }
     
    public String getContent() {
        return content;
    }
     
    public void setContent(String content) {
        this.content = content;
    }
     
    @Override
    public String toString() {
        return "LogContent{" +
                "提交版本=" + commitVersion + '\n' +
                ", 作者=" + author + '\n' +
                ", Email=" + email + '\n' +
                ", 日期=" + DateUtil.toString(date) +'\n'+
                ", 工作内容=" + content + '\n' +
                "}\n";
    }
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

DateUtil.java

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

public class DateUtil {
    public static Date getDefaultStart() {
        Calendar cld = Calendar.getInstance(Locale.CHINA);
        cld.setFirstDayOfWeek(Calendar.MONDAY);//以周一为首日
        cld.setTimeInMillis(System.currentTimeMillis());//当前时间
         
        cld.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);//周一
        return cld.getTime();
    }
     
    public static String getPreDayStr(Date d){
        Calendar cld = Calendar.getInstance(Locale.CHINA);
        cld.setTime(d);
        cld.add(Calendar.DATE, -1);// 日期减1
        return toString(cld.getTime());
    }
     
    public static Date getUsDate(String dateStr){
        dateStr= dateStr.substring(0,dateStr.length()-" +0800".length());
        try {
            return new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy", Locale.US).parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }
     
     
    public static String toString(Date d){
        SimpleDateFormat sdfFormat = new SimpleDateFormat("yyyy-MM-dd");
        return sdfFormat.format(d);
    }
     
    public static Date toDate(String str){
        SimpleDateFormat sdfFormat = new SimpleDateFormat("yyyy-MM-dd");
        // 严格模式
        sdfFormat.setLenient(false);
        try {
            return sdfFormat.parse(str);
        } catch (ParseException e) {
            return null;
        }
    }
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

可以看到数据有写进来,多行日志也可正常读取

评论🌹点赞👍收藏✨关注👀,是送给作者最好的礼物,愿我们共同学习,一起进步

如果对作者发布的内容感兴趣,可点击下方关注公众号 钰娘娘知识汇总 查看更多作者文章哦!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值