class GitThin::Hook

Public Class Methods

arguments() click to toggle source
# File lib/git-thin/command/hook.rb, line 13
def self.arguments
    [
      CLAide::Argument.new('install|unstall', false )
    ]
end
new(argv) click to toggle source
Calls superclass method GitThin::Thin::new
# File lib/git-thin/command/hook.rb, line 162
def initialize(argv)
    super
    @pwd = Dir.pwd
    if argv.arguments.length > 0 &&( argv.arguments[0] == 'install' || argv.arguments[0] == 'uninstall')
        @action = argv.shift_argument
    end
    @source_root = argv.option('source_root')
    @file_size_limit = argv.option('file_size_limit','2048')
    @commit_limit = argv.option('commit_limit','5000')
    @master_name = argv.option('master_name','develop')
    @names = argv.option('names','commands')
    @names = @names.split('|')
    @names = @names.map { |item|item.downcase }
    @support_names = ['push_count_checker','commit_lfs_checker','commands']
    if @names.include? 'all'
        @names = @support_names
    end
    check_name

    if not @source_root
        run_shell 'git rev-parse --show-toplevel',false ,LOGNone do |out,err,status|
            if status == 0
                @source_root = out[0].strip
            end
        end

        if not File.exist? @source_root+'/.git'
            UI.puts "git repository not found"
            exit 1
        end
    else
        if @source_root[-1] == '/'
            @source_root = @source_root[0..-2 ]
        end
    end
    if not Dir.exist? @source_root
        @source_root = nil
        return
    end
    @hook_path = "#{@source_root}/.git/hooks"
    if not Dir.exist? @hook_path
        FileUtils.mkdir_p @hook_path
    end
    @start_flag = '>>>>>>>>>>>>>>>>>>>'
    @end_flag   = '<<<<<<<<<<<<<<<<<<<'
end
options() click to toggle source
Calls superclass method
# File lib/git-thin/command/hook.rb, line 21
def self.options
    [
      ['--source_root', 'Specify the warehouse address manually if necessary.'],
      ['--names', 'set hook name,include "push_count_checker|commit_lfs_checker|commands|all",defaule commands'],
      ['--commit_limit', 'Upper count limit checked in the prepush hook. default 5000'],
      ['--master_name', 'The name of the repository main branch,defalut is develop'],
      ['--file_size_limit', 'Upper file size limit checked in the prepush hook.default 2097152B (2MB)'],
    ].concat(super)
end

Public Instance Methods

append_hook(name,content,hook) click to toggle source
# File lib/git-thin/command/hook.rb, line 242
def append_hook(name,content,hook)
    start_flag = '# '+@start_flag+' git thin '+name+@start_flag+"\n"
    end_flag = '# '+@end_flag+' git thin '+name+@end_flag+"\n"
    content += "\n\n #{start_flag}\n"
    content += hook
    content += "\n #{end_flag}"

end
check_name() click to toggle source
# File lib/git-thin/command/hook.rb, line 148
def check_name
    pass = true
    for name in @names
        name = name.downcase
        if !@support_names.include?(name) && name.downcase != 'all'
            logE "name [#{name}] is not supported"
            pass = false
        end
    end
    if false
        @names = []
    end
end
commands_hook() click to toggle source
# File lib/git-thin/command/hook.rb, line 31
        def commands_hook
            <<-DESC
                function git(){
                    o_git=`whereis git`
                    
                    if [ -z "$o_git" ] || ! command -v git-thin >/dev/null 2>&1;then
                        echo 'git or git-thin command failed, finish hook'
                        unset -f git
                        git "$@"
                    else
                        if [[ "$1" == "checkout" ]] || [[ "$1" == "pull" ]] || [[ "$1" == "fetch" ]];then
                           git-thin "$@"
                           ret=$?
                           if [ $ret -gt 100 ];then
                                return $ret-100
                           elif [ $ret -ne 0 ];then
                                echo 'git-thin command error,retry with git'
                                $o_git "$@"
                           else
                                return $ret
                           fi
                        else
                            $o_git "$@"
                        fi
                    fi
                    return $?
                }
                export -f git > /dev/null
            DESC
        end
commit_msg_hook() click to toggle source
# File lib/git-thin/command/hook.rb, line 72
def commit_msg_hook
    %Q{
        echo ''
        echo '======start lfs check========'
        root=`git rev-parse --show-toplevel`
        START_LINE=`head -n1 $1`
        if [[ -f $root/.git/MERGE_MSG ]] || [[ $START_LINE == "Merge"* ]];then
            echo "Current in merging,skip lfs check"
            exit 0
        fi
        map(){
            function_name=$1
            shift
            while read line
            do
                $function_name "$line" "$@"
            done
        }
        
        white_list=(mm m cpp c cc h hpp java cs cjs js css txt doc docx pdf ppt pptx xls htm html shtm shtml jsp xjsp jspf jsf jsx jspx md pl pm sass sh zsh bash rb json xml yml yaml cjsx uml es6 mjs ejs bat cgi cmd csv jam log opts mpmrc nvmrc vue xhtml xsl xslt elt)
        OLDIFS=$IFS
        IFS=$'\n'
        lfs_files=`git lfs ls-files`
        lfs_files=($lfs_files)
        IFS='*'
        for (( i = 0; i < ${#lfs_files[@]}; i++ )); do
            file_item=(${lfs_files[i]})
            lfs_files[i]=${file_item[1]}
        done
        export has_gitattributes=0
        check_file(){
            echo $1
           if [[ $1 =~ 'gitattributes' ]];then
                export has_gitattributes=1
                echo "has_gitattributes:$has_gitattributes"
           fi
           file_name=$1
           file_ext=${file_name##*.}
           file_ext=$(echo "$file_ext" | tr [A-Z] [a-z])
           for item in ${white_list[@]};do
              if [ "$file_ext" = "$item" ];then
                  return
              fi
           done
            
            for (( i = 0; i < ${#lfs_files[@]}; i++ )); do
                if [[ "${lfs_files[i]}" == " $file_name" ]];then
                     echo "file ${file_name} already in lfs, pass"
                     return
                fi
            done
            
            if [ -f "$file_name" ];then
                size=`ls -l $file_name | awk '{ print $5 }'`
                if [ "$size" -gt #{@file_size_limit} ];then
                    echo "修改的非代码文件超过#{@file_size_limit}KB,请使用git lfs管理,文件名称:$file_name"
                    exit 1
                fi
            fi
        }
        
        git diff --name-only --staged | map check_file
        if [ $? -ne 0 ];then
            echo "lfs check failed"
            exit 1
        fi
        IFS=$OLDIFS
        if [ `git diff --name-only | grep '.gitattributes' -c` -gt 0 ];then
            echo '存在未提交的.gitattributes文件,请主动add改文件。如果确认不需要则请重置该文件'
            echo "lfs check failed"
            exit 1
        fi
        echo "lfs check pass"
        echo ""
   }
end
install() click to toggle source
# File lib/git-thin/command/hook.rb, line 283
def install
    if @names.include? 'push_count_checker'
        Dir.chdir @source_root
        find_branch = false
        run_shell 'git branch -r',true ,true do |outs,errs,status|
            if status == 0
                for out in outs
                    items = out.strip.split '/'
                    if items.length == 2 && items[1] == @master_name
                        find_branch = true
                        break
                    end
                end
            end
        end

        run_shell 'git remote',true ,true do |outs,errs,status|
            if status == 0 && outs.length > 0
                @origin = outs[0]
            else
                @origin = 'origin'
            end
        end
        if !find_branch
            logE "install push_count_checker hook error:the main branch [#{@master_name}] is not exist,please specify an appropriate parameter for master_name"
            exit 1
        end

        install_hook @hook_path+'/pre-push','push_count_checker',pre_push_hook
    end
    if @names.include? 'commit_lfs_checker'
        install_hook @hook_path+'/commit-msg','commit_lfs_checker',commit_msg_hook
    end

    if @names.include? 'commands'
        profile = Dir.home+"/.bash_profile"
        install_hook profile,'commands_hook',commands_hook
        run_shell"cat #{profile}>tmp &&  source tmp && rm tmp",true ,LOGPRUNE
        logN 'This will take effect after restarting the computer'
    end

end
install_hook(path,name,hook) click to toggle source
# File lib/git-thin/command/hook.rb, line 267
def install_hook(path,name,hook)
    origin = []
    if File.exist? path
        File.open(path, "r") do |aFile|
            origin = aFile.readlines
        end
    end

    prune = prune_hook(name,origin).join("")
    content = append_hook name,prune,hook
    File.open(path, "w+") do |aFile|
        aFile.write content
    end
    logN 'success install hook:'+name+' to path:'+path
end
pre_push_hook() click to toggle source
# File lib/git-thin/command/hook.rb, line 62
        def pre_push_hook
            <<-DESC
                count=`git log --oneline #{@origin}/#{@master_name}..HEAD | wc -l`
                if [ $count -gt #{@commit_limit} ];then
                    echo "commit count:${count} is greater than #{@commit_limit} (base #{@master_name}), please contact kyle.zhou"
                    exit 1
                fi
            DESC
        end
prune_hook(name,content) click to toggle source
# File lib/git-thin/command/hook.rb, line 217
def prune_hook(name,content)
    start_flag = '# '+@start_flag+' git thin '+name+@start_flag
    end_flag = '# '+@end_flag+' git thin '+name+@end_flag
    find_start = false
    find_end = false
    lines = []
    content.each do |line|
        if line.index(start_flag)
            find_start = true
        end
        if line.index(end_flag) && find_start
            find_end = true
        end

        if !find_start && !find_end
            lines.push line
        end

        if find_start && find_end
            find_start = find_end = false
        end
    end
    return lines
end
run() click to toggle source
# File lib/git-thin/command/hook.rb, line 348
def run
    Dir.chdir @source_root
    if @action == 'install'
        install
    elsif @action =='uninstall'
        uninstall
    end
end
run_config() click to toggle source
# File lib/git-thin/command/hook.rb, line 342
def run_config
    values=[]

    return values
end
uninstall() click to toggle source
# File lib/git-thin/command/hook.rb, line 326
def uninstall
    if @names.include? 'push_count_checker'
        uninstall_hook @hook_path+'/pre-push','push_count_checker'
    end
    if @names.include? 'commit_lfs_checker'
        uninstall_hook @hook_path+'/commit-msg','commit_lfs_checker'
    end
    if @names.include? 'commands'
        profile = Dir.home+"/.bash_profile"
        uninstall_hook profile,'commands_hook'
        run_shell'echo "unset -f git" >tmp &&  source tmp && rm tmp',true ,LOGPRUNE
        logN 'This will take effect after restarting the computer'
    end
    logN 'finish uninstall'
end
uninstall_hook(path,name) click to toggle source
# File lib/git-thin/command/hook.rb, line 250
def uninstall_hook(path,name)
    origin = []
    if File.exist? path
        File.open(path, "r") do |aFile|
            origin = aFile.readlines
        end
    end

    prune = prune_hook(name,origin)
    content = prune.join("")
    File.open(path, "w+") do |aFile|
        aFile.write content
    end
    if prune.length != origin.length
        logN 'success uninstall hook:'+name+' to path:'+path
    end
end
validate!() click to toggle source
Calls superclass method
# File lib/git-thin/command/hook.rb, line 209
def validate!
    super
    help! 'validate SOURCE_ROOT is required' unless @source_root
    help! 'action must install/uninstall' unless @action
    help! 'validate names is required' unless @names.length

end