首页 > 编程语言 > 详细

通过 python 获取一个 git commit 的改动行信息

时间:2021-04-29 10:14:00      阅读:59      评论:0      收藏:0      [点我收藏+]

直接贴代码了,可以通过下面的 python 方法获取到(执行 prepareInfomation 方法,返回的):


import os
import re
from typing import *
import subprocess

class ChangedLineInfo:
    def __init__(self):
        self.changedLineNumbers = set()

    def addChangeInfo(self, startLine: int, lineCount: int):
        """
        补充改变的行号信息,
        startLine : 表示从该行起始有改变。
        lineCount : 表示从改行起,有多少行被改变了。
        """
        endLine = startLine + lineCount
        if (endLine < startLine):
            return
        for i in range(startLine, endLine):
            self.changedLineNumbers.add(i)

    def isLineChanged(self, line: int) -> bool:
        return line in self.changedLineNumbers

def getChangedLineInfoFromDiffLines(lines: List[str]) -> ChangedLineInfo:
    """
    该方法计算出 ,返回一个 ChangedLineInfo 对象
    参数 : lines , git-diff 命令输出的,对一个文件的描述
    返回 : 返回一个ChangedLineInfo, 表示从 lines 中解析出来的 改变了的行 的信息。
    """
    changedLineInfo = ChangedLineInfo()
    # 根据 "@@ @@" 获取改变行信息
    # 匹配到的 [0] : ","+从此处起始的删除行数; [1] : 从此处新增的行数起始行; [2] : ","+从此处新增的行数数量
    reg = re.compile("^@@ -[0-9]+(,[0-9]+)? \+([0-9]+)(,[0-9]+)? @@")
    for line in lines:
        r = reg.findall(line)
        if len(r) > 0:
            changedLineStart = int(r[0][1])
            caughtLineCountStr = r[0][2]
            if len(caughtLineCountStr) > 0:
                changedLineCount = int(caughtLineCountStr[1:])
            else:
                changedLineCount = 1
            changedLineInfo.addChangeInfo(changedLineStart, changedLineCount)
    return changedLineInfo



def prepareInfomation():
    """
    执行一些操作,准备好数据并且返回:
    :return: 一个 map, key 为本次 commit 导致的"非删除文件"的路径(相对于 git 仓库的路径); value 为 ChangedInfo 对象,表示该文件的改动行信息.
    """
    gitCmd = "git diff --unified=0 --diff-filter=d HEAD~1 HEAD"
    gitDiffOutputRaw = subprocess.check_output(gitCmd.split(" "))
    outputStr = gitDiffOutputRaw.decode(‘utf-8‘)
    diffOutputLines = outputStr.splitlines()

    map = {}
    # 匹配到这个的一行表示开始结果开始展示 一个新的文件的 diff 信息,匹配到的信息 [0] 表示文件名
    # !!!!!!!!!! 忽略带有空格的文件名的处理, 对于带有空格的文件名,该检测会出错.但是暂时忽略
    separateLineReg = re.compile("^diff --git a/\S+ b/(\S+)")
    currentCheckFileName = ""
    diffLinesForCurrentCheckFile = []
    for i in range(len(diffOutputLines)):
        l = diffOutputLines[i]
        # 如果当前匹配到了 separateLine ,则
        # 1. 解析 diffLinesForCurrentCheckFile,并且将 { currentCheckFileName : 解析后的信息} 加入到 map 中;
        # 2. 更新当前的 currentCheckFileName ; 清空 diffLinesForCurrentCheckFile
        # 如果未匹配到,加入 diffLinesForCurrentCheckFile , 继续下一行
        separateLineMatchResult = separateLineReg.findall(l)
        if len(separateLineMatchResult) > 0:
            if len(diffLinesForCurrentCheckFile) > 0:
                a = getChangedLineInfoFromDiffLines(diffLinesForCurrentCheckFile)
                map[currentCheckFileName] = a
                diffLinesForCurrentCheckFile.clear()
            # 只匹配了一个项,所以不需要使用 separateLineMatchResult[0][0]
            currentCheckFileName = separateLineMatchResult[0]
        else:
            diffLinesForCurrentCheckFile.append(l)
        # 已经是最后一行
        if i == len(diffOutputLines) - 1:
            a = getChangedLineInfoFromDiffLines(diffLinesForCurrentCheckFile)
            map[currentCheckFileName] = a
    return map


通过 python 获取一个 git commit 的改动行信息

原文:https://www.cnblogs.com/wkmcyz/p/14716288.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!