Android Studioプロジェクトgradle+Git Hooks実装コミット時のコミットログとコードのチェック

25095 ワード

Android Studioプロジェクトgradle+Git Hooks実装コミット時のコミットログとコードのチェック
主にプロジェクトのログとコードの仕様制御を解決し、gitがコミットする前に、コミットログとコードのcheckStyeをチェックすることを実現する.
Git hooksの原理
フックはいずれもGitディレクトリの下のhooksサブディレクトリに格納される.つまり、ほとんどのプロジェクトの中で.git/hooks. git initで新しいバージョンライブラリを初期化すると、Gitはデフォルトでこのディレクトリにサンプルスクリプトを配置します.これらのスクリプトは、自身が呼び出すことができるほか、トリガされたときに入力されるパラメータも明らかにします.すべての例はshellスクリプトで、一部はPerlコードが混在していますが、正しい名前の実行可能なスクリプトは正常に使用できます.RubyやPython、または他の言語で作成できます.これらの例の名前はすべて.sampleの最後に、有効にするには、この接尾辞を削除する必要があります.Gitディレクトリの下にあるhooksサブディレクトリに正しい名前と実行可能なファイルを入れると、フックスクリプトがアクティブになります.これによりGitに呼び出されます.
以下では、コミットログ部とコードの検出の2つの部分に分けて説明します.
コミットログのチェック
要求
    ,Commit message        :Header,Body   Footer。

(): 
//    

//    
,Header ,Body Footer 。 , 72 ( 100 )。 。 Header , :type( )、scope( ) subject( )。 **type** commit , 7 。 - feat: (feature) - fix: bug - docs: (documentation) - style: ( ) - refactor: ( , bug ) - perf: (performance) - test: - chore: - revert: , commit commit, revert: , Commit Header。 revert: feat(pencil): add 'graphiteWidth' option **scope** commit , 、 、 , 。 **subject** commit 。 Body , This reverts commit <hash>., hash commit SHA 。
インプリメンテーション
shellスクリプトに詳しくないため、pythonで実現します.commit-msgファイルの上部のコードを変更すると
 #!/bin/sh
次のように変更
 #!/usr/bin/python2.6
pythonスクリプトが認識されない場合
  • 1、commit-msgに関するプロファイル(commit-msg-config.txt)を作成し、commit-msgの同じディレクトリの下に配置する.私たちはいくつかの正規表現、ヒント情報を中に入れて、後期の修正とメンテナンスを容易にします.
  • commitMessageRegex=.+(

    .){0,2} commitMessage= , :
    Header(72 )+ +Body(72 , )+ +Footer(72 , ); HeadLengthMessage=Header 72 HeadFormatMessage=Head (): type( )、scope( ) subject( ) **type** commit , 7 。
    **scope** commit , 、 、 , 。
    **subject** commit headTypeRegex=^(feat|fix|docs|style|refactor|perf|test|chore)(\(.*\)){0,1}$|^revert$ headTypeMessage=type : feat: (feature) fix: bug
    docs: (documentation) tyle: ( ) refactor: ( , bug ) perf: (performance) test: chore: revert: commit commit RevertCommitHeadMessage= type revert, revert: , Commit Header, Commit Header 。 RevertMessage= type revert, revert: , Commit Header。 :
    revert: feat(pencil): add 'graphiteWidth' option BodyLengthMessage=Body 72 FootLengthMessage=Body 72
  • 2、commit-msgファイルの修正
  • #!/usr/bin/python2.6
    #coding=utf-8
    #
    # An example hook script to check the commit log message.
    # Called by "git commit" with one argument, the name of the file
    # that has the commit message.  The hook should exit with non-zero
    # status after issuing an appropriate message if it wants to stop the
    # commit.  The hook is allowed to edit the commit message file.
    #
    # To enable this hook, rename this file to "commit-msg".
    
    # Uncomment the below to add a Signed-off-by line to the message.
    # Doing this in a hook is a bad idea in general, but the prepare-commit-msg
    # hook is more suited to it.
    #
    # SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
    # grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
    
    # This example catches duplicate Signed-off-by lines.
    
    # test "" = "$(grep '^Signed-off-by: ' "$1" |
    #    sort | uniq -c | sed -e '/^[   ]*1[    ]/d')" || {
    #   echo >&2 Duplicate Signed-off-by lines.
    #   exit 1
    # }
    import re
    import sys
    import os
    
    map = dict()
    configFile = open('.git/hooks/commit-msg-config.txt','r')
    
    for line in open('.git/hooks/commit-msg-config.txt'):  
        line = configFile.readline()  
        value = line.split('=',2)
        if len(value)==2:
            map[value[0]]=value[1]
    
    
    filePath    = sys.argv[1]
    file       = open(filePath)
    content    = file.read(os.path.getsize(filePath))
    machObject = re.match(map["commitMessageRegex"], content, flags=0)
    
    if not machObject:
        print map["commitMessage"]
        exit(1)
    
    
    splitArray = content.split('

    ',3) if len(splitArray[0].decode('utf-8')) > 73: print map["HeadLengthMessage"] exit(1) head = splitArray[0] splitHead = head.split(':',2) if len(splitHead) < 2 or len(splitHead)>3: print map["HeadFormatMessage"] exit(1) machHead=re.match(map["headTypeRegex"],splitHead[0],flags=0) if not machHead: print (map["headTypeMessage"]) exit(1) if splitHead[0]=="revert" and len(splitHead)==3: machRevertHead = re.match(headRegex,splitHead[1],flags=0) if not machRevertHead: print map["RevertCommitHeadMessage"] exit(1) else: print map["RevertMessage"] exit(1) if len(splitArray) > 1 and len(splitArray[1].decode('utf-8')) > 73: print map["BodyLengthMessage"] exit(1) if len(splitArray) > 2 and len(splitArray[2].decode('utf-8')) > 73: print map["FootLengthMessage"] exit(1) file.close()
    ここで、次のコードは、前に作成したプロファイルを読み込むために使用されます.
    map = dict()
    configFile = open('.git/hooks/commit-msg-config.txt','r')
    
    for line in open('.git/hooks/commit-msg-config.txt'):  
        line = configFile.readline()  
        value = line.split('=',2)
        if len(value)==2:
            map[value[0]]=value[1]
    
    このコードは、コミットしたログを読み取り、フォーマットが正しいかどうかを判断するために使用されます.
    filePath    = sys.argv[1]
    file       = open(filePath)
    content    = file.read(os.path.getsize(filePath))
    
    保存後、再びgitでコードをコミットすると、git hooksはログをチェックし、フォーマットに合わないとエラーを印刷し、コミット操作を終了します.覚えておいて、commit-msgの接尾辞名.sampleは削除する必要がありますが、それでも機能しない場合はchmod a+x commit-msg読み書き権限を与えることができます.
    コミットコードのチェック
    げんり
    AndroidのGradle Apiには元々checkStyleタイプのtaskがあり、checkstyle pluginを適用し、このようなtaskを実現すれば検査コードスタイルを実行し、検査レポートを生成することができます.コードは次のとおりです.
    allprojects {
        ...
        ...
        apply plugin: 'checkstyle'
    
        checkstyle {
            configFile rootProject.file('checkstyle.xml')
            toolVersion '6.19'
            ignoreFailures false
            showViolations true
        }
    
        task('checkstyle', type: Checkstyle) {
            source 'src/main/java'
            include '**/*.java'
            exclude '**/R.java'
            exclude '**/BuildConfig.java'
            classpath = files()
        }
    }
    
    このスクリプトはhook git commitで実行でき、チェック結果に基づいてcommitできるかどうかを決定します.
    インプリメンテーション
    私たちがまずしなければならないことは次のとおりです.
  • 1、checkstyleのxmlファイルを1部作成
  • 2、checkstyletaskのincludeexclude必要と不要のjavaクラスを追加します.
  • 3、git hookファイルを作成してcheckstyleを呼び出すtask
  • checkstyleのxmlファイルを貼って、みんなは自分の実際のプロジェクトの必要に応じて配置することができます
    
    
    
    
    
    
        
    
        
    
        
        
        
            
                
            
    
        
            
            
                
                
                
            
            
                
                
                
            
            
                
                
            
            
            
            
            
                
                
            
            
            
                
            
            
                
                
            
            
                
                
                
            
            
                
                
                
                
                
                 
            
            
            
            
            
            
            
            
            
                
            
            
                
                
                
            
            
                
                
                
            
            
                
                
            
            
                
            
            
                
                
            
            
                
                
            
            
            
                
                
                
            
            
                
                
            
            
                
                
            
            
                
                
            
            
            
                
                 
                 
                 
            
            
                
                
                
                
                
                
            
            
                
                
            
            
            
            
                
                
                
            
            
            
            
            
                
                
            
            
                
                
                
            
            
            
            
                
            
            
            
                
                
            
            
                
                
                
                
                
                
                
            
            
                
                
            
            
                
            
            
                
            
            
        
    
    
    gradleの中のexcludeファイルは書きやすいですがinclude修正したファイルだけをチェックする必要があります.そうしないと、全工程検査のたびに、多くの時間がかかります.git status -s修正したファイル文字列が得られることを知っているのでgradleでこのコマンドを呼び出し、修正したファイルリストを取得します.
     def getChangeFiles() {
        try {
            String changeInfo = 'git status -s'.execute(null, project.rootDir).text.trim()
            return changeInfo == null ? "" : changeInfo
        } catch (Exception e) {
            return ""
        }
    }
    
    その後、この文字列を解析すると、変更したjavaファイルクラス名の集合が得られます.実装関数は次のとおりです.
    def filterCommitter(String gitstatusinfo) {
        ArrayList filterList = new ArrayList();
        String[] lines = gitstatusinfo.split("\
    ") for (String line : lines) { if (line.contains(".java")) { String[] spliters = line.trim().split(" "); for (String str : spliters) { if (str.contains(".java")) { filterList.add(str) } } } } return filterList; }
    これによりgradleでは、上記のjavaファイルincludeを入れておけば、gradle taskで修正したjavaファイルのみcheckstyleを実現できます.次はgradleの完全なコードを貼ります
    // Top-level build file where you can add configuration options common to all sub-projects/modules.
    
    buildscript {
        repositories {
            jcenter()
        }
        dependencies {
            classpath 'com.android.tools.build:gradle:2.1.0'
    
            // NOTE: Do not place your application dependencies here; they belong
            // in the individual module build.gradle files
        }
    }
    
    allprojects {
        repositories {
            jcenter()
            mavenCentral()
        }
        apply plugin: 'checkstyle'
    
        checkstyle {
            toolVersion '6.13'
            ignoreFailures false
            showViolations true
        }
    
    
    }
    
    task clean(type: Delete) {
        delete rootProject.buildDir
    }
    
    
    task checkstyle(type: Checkstyle) {
        source 'app/src/main/java'
    
        exclude '**/gen/**'
        exclude '**/R.java'
        exclude '**/BuildConfig.java'
        if (project.hasProperty('checkCommit') && project.property("checkCommit")) {
            def ft = filterCommitter(getChangeFiles());
            def includeList = new ArrayList()
            for (int i = 0; i < ft.size(); i++) {
                String spliter = ft.getAt(i)
                String[] spliterlist = spliter.split("/")
                String fileName = spliterlist[spliterlist.length - 1]
                includeList.add("**/" + fileName)
            }
            if (includeList.size() == 0) {
                exclude '**/*.java'
            } else {
                println("includeList=="+includeList)
                include includeList
            }
        } else {
            include '**/*.java'
        }
        configFile rootProject.file('checkstyle.xml')
        classpath = files()
    }
    
    
    def getChangeFiles() {
        try {
            String changeInfo = 'git status -s'.execute(null, project.rootDir).text.trim()
            return changeInfo == null ? "" : changeInfo
        } catch (Exception e) {
            return ""
        }
    }
    
    def filterCommitter(String gitstatusinfo) {
        ArrayList filterList = new ArrayList();
        String[] lines = gitstatusinfo.split("\
    ") for (String line : lines) { if (line.contains(".java")) { String[] spliters = line.trim().split(" "); for (String str : spliters) { if (str.contains(".java")) { filterList.add(str) } } } } return filterList; }
    gradleファイルにcheckstyleのtaskを追加した後、git commit時に自動的にチェックする必要があります.git hookを変更する必要があります../git/hook/pre-commitファイルの接尾辞名を削除します.sampleは、gradle taskを呼び出し、taskの出力結果でcommitできるかどうかを判断します.コードは次のとおりです.
    #!/bin/sh
    #
    # An example hook script to verify what is about to be committed.
    # Called by "git commit" with no arguments.  The hook should
    # exit with non-zero status after issuing an appropriate message if
    # it wants to stop the commit.
    #
    # To enable this hook, rename this file to "pre-commit".
    
    if git rev-parse --verify HEAD >/dev/null 2>&1
    then
        against=HEAD
    else
        # Initial commit: diff against an empty tree object
        against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
    fi
    
    SCRIPT_DIR=$(dirname "$0")
    SCRIPT_ABS_PATH=`cd "$SCRIPT_DIR"; pwd`
    $SCRIPT_ABS_PATH/../../gradlew  -PcheckCommit="true" checkstyle 
    if [ $? -eq 0   ]; then
        echo "checkstyle OK"
    else
        exit [[ $ERROR_INFO =~ "checkstyle" ]] && exit 1  
    fi
    
    
    # If you want to allow non-ASCII filenames set this variable to true.
    allownonascii=$(git config --bool hooks.allownonascii)
    
    # Redirect output to stderr.
    exec 1>&2
    
    # Cross platform projects tend to avoid non-ASCII filenames; prevent
    # them from being added to the repository. We exploit the fact that the
    # printable range starts at the space character and ends with tilde.
    if [ "$allownonascii" != "true" ] &&
        # Note that the use of brackets around a tr range is ok here, (it's
        # even required, for portability to Solaris 10's /usr/bin/tr), since
        # the square bracket bytes happen to fall in the designated range.
        test $(git diff --cached --name-only --diff-filter=A -z $against |
          LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
    then
        cat <
    これによりgitでコードをコミットすると、修正したコードが私たちの規定のスタイルに合っているかどうかをチェックすることができます(checkstyle.xml)
    最後に以下の2人が私に提供してくれた考えに感謝します.
    Gitステップアップ:Hooksインスタンスが制御コードをコミットする際のコメント
    Androidプロジェクトgit+gradle commit実現時checkstyleチェック