在做一个项目时,需要分析git上代码有效提交行数,即:添加的行数 - 空行 - 注释行,网上未找到支持多种语言的分析代码,自己写了段代码分享出来。
该代码接收两个参数。filepath变更的文件名称, 文件的变化内容(可以通过git diff {commit_id} 查看)

该段代码特点:

  1. 通过filepath的后缀,判断文件里包含的语言
  2. 获取该次提交的代码,里面注释和空行的增加数和删除数
  3. 支持文件类型,py,sh,java,rb,vue,html,js,xml,sql,css等
  4. 如果需要支持更多的语言代码分析,在luanges里加入对应的key即可,single代表单行注释,multi代表多行注释。
def get_commit_diff_comment_rows(filepath,diff):
        endfix = filepath.split("/")[-1].split('.')[-1]
        diff_rows = diff.split("\n")
        if len(diff_rows) < 3:
                return {}
        luanges={
                'py':{
                        'single':'#',
                        'multi_start':["'''",'"""'],
                        'multi_end':["'''",'"""']
                },
                'java':{
                        'single':'//',
                        'multi_start':["/*"],
                        'multi_end':["*/"],        
                },
                'js':{
                        'single':'//',
                        'multi_start':["/*"],
                        'multi_end':["*/"],        
                },        
                'vue':{
                        'single':'//',
                        'multi_start':["<!--",'/*'],
                        'multi_end':["-->","*/"],        
                },        
                'html':{
                        'single':'//',
                        'multi_start':["<!--",'/*'],
                        'multi_end':["-->","*/"],     
                },
                'jsx':{
                        'multi_start':["/*","{/*"],
                        'multi_end':["*/","*/}"],        
                },  
                'less':{
                        'single':'//',
                        'multi_start':["/*"],
                        'multi_end':["*/"],        
                },  
                'rb':{
                        'single':'#',
                        'multi_start':["=begin"],
                        'multi_end':["=end"],        
                },  
                'yml':{
                        'single':'#',      
                },  

                'xml':{
                        'multi_start':["<!--"],
                        'multi_end':["-->"],      
                },  
                'sql':{
                        'single':'--',
                        'multi_start':["/*"],
                        'multi_end':["*/"],                     
                },  
                'sh':{
                        'single':'#',      
                }, 
                'css':{
                        'multi_start':["/*"],
                        'multi_end':["*/"],                     
                },  
        }
        luange = luanges.get(endfix)
        if not luange:
                return {}
        single_start = luange.get("single")
        multi_start = luange.get("multi_start")
        multi_end = luange.get("multi_end")    
        comment_add = 0 
        comment_del = 0 
        empty_add = 0 
        empty_del = 0 
        block_comment_flag=False  #块注释默认为空
        for row in diff_rows:
                if row.startswith("---") or row.startswith("+++") or row.startswith("@@"):
                        continue
                if row.startswith("+"):
                        node_type = '+'
                elif row.startswith("-"):
                        node_type = '-'
                else:
                        continue
                row = row[1:].strip()
                if row == '':
                        if node_type == '+':
                                empty_add += 1
                        elif node_type == '-':
                                empty_del += 1
                else:        
                        add_number = 0 
                        if single_start:    
                                if row.startswith(single_start):
                                        add_number = 1 
                        if multi_start:
                                for i in multi_start:
                                        if row.startswith(i):
                                                add_number = 1 
                                                block_comment_flag=True
                        if multi_end:
                                for i in multi_end:
                                        if row.endswith(i):
                                                add_number = 1 
                                                block_comment_flag=False
                        if block_comment_flag:
                                add_number = 1 

                        if node_type == '+':
                                comment_add += add_number  
                        elif node_type == '-':
                                comment_del += add_number 

        return {"comment_add":comment_add, 
                        "comment_del":comment_del,
                        "empty_add":empty_add,
                        "empty_del":empty_del
                        }