## git生成编译的增量包说明

### 一、环境安装

#### Windows

1. 安装git-bash

   [下载](https://git-scm.com/downloads)git-bash并安装.

2. 安装python

   到[官网](https://www.python.org/downloads/windows/)下载python并安装.

3. 配置环境变量

   在高级系统设置里选择环境变量设置,然后点开系统变量的配置,修改PATH变量,把python的安装目录添加进去即可,例如C:\Python27.

#### MacOS

1. 安装homebrew

   打开终端,输入如下命令:

   ```shell
   $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
   ```

2. 安装python

   终端输入如下命令:

   ```shell
   $ brew install python3
   #也可安装python2,MacOS应该自带
   # $ brew install python 
   ```

### 二、拷贝脚本

到融租易(hel-leasing)项目下把archives.py和gen_patch.sh两个文件拷贝到需要生成增量包的项目的根目录下,或者直接复制如下代码为gen_patch.sh和archives.py两个文件放到项目的根目录下:

* gen_patch.sh

```shell
#!/bin/sh
#
# Generate compiled patch file automatically
#
################################################
#
# Set Script Variables
#
GENERATE_FOLDER=/Users/weck/Downloads/patch/    #生成差异包的目录

GIT_BRANCH=HLS-DEV          #分支

SINCE_DATE="2018-04-02 00:00:00"     #时间

AUTHOR=gaoyang        #提交人

git checkout "$GIT_BRANCH" &&

git pull

#if [ -n "$AUTHOR" ]; then
#    COMMIT_IDS=`git rev-list --author="$AUTHOR" --since="$SINCE_DATE" "$GIT_BRANCH"`
#else
#    COMMIT_IDS=`git rev-list --since="$SINCE_DATE" "$GIT_BRANCH"`
#fi

if [ -n "$AUTHOR" ]; then
    COMMIT_IDS=`git rev-list --author="$AUTHOR" --before="$SINCE_DATE" "$GIT_BRANCH"`
else
    COMMIT_IDS=`git rev-list --before="$SINCE_DATE" "$GIT_BRANCH"`
fi

COMMIT_IDS_ARRAY=($COMMIT_IDS)

COMMIT_ID_NUM=${#COMMIT_IDS_ARRAY}
if [ $COMMIT_ID_NUM -gt 0 ]; then
#    OLD_COMMIT_ID=${COMMIT_IDS_ARRAY[i-1]}
    OLD_COMMIT_ID=${COMMIT_IDS_ARRAY[0]}
else
    OLD_COMMIT_ID=
fi

LATEST_COMMIT_ID=$(git rev-parse HEAD)

echo "********************* Old Commit ID is "$OLD_COMMIT_ID "***********************"

echo "********************* Latest Commit ID is "$LATEST_COMMIT_ID "***********************"

SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)

DATE=`date +%Y-%m-%d`

ZIP_FILE="$GENERATE_FOLDER$DATE"'.zip'

#echo $LATEST_COMMIT_ID $OLD_COMMIT_ID

#
#################################################
#
# Start to execute command
#
if [ -n "$OLD_COMMIT_ID" ]; then
    # delete files which not exists
    FILES=`git diff "$LATEST_COMMIT_ID" "$OLD_COMMIT_ID" --name-only`
    FILE_ARRAY=($FILES)
    j=0
    for y in ${FILE_ARRAY[@]}
    do
    filepath="$SHELL_FOLDER/"$y
    if [ ! -f "$filepath" ]; then
        unset FILE_ARRAY[j]
    fi
    j=$[j+1]
    done

    FILES_NUM=${#FILE_ARRAY}
    if [ $FILES_NUM -gt 0 ]; then
        # start to pack
        git archive -o "$ZIP_FILE" HEAD ${FILE_ARRAY[@]} &&
        echo "-----------------generate patch zip package complete, filename is $ZIP_FILE" &&
        echo "************************ start to uncompress zip file *********************" &&
        unzip "$ZIP_FILE" -d "$GENERATE_FOLDER" &&
        echo "************************ uncompress zip file complete *********************" &&
        echo "***************************************************************************" &&
        echo "************************ start to compile project *************************" &&
#        mvn clean install &&
        echo "************************ compile project complete *************************" &&
        echo "***************************************************************************" &&
        python archives.py "$ZIP_FILE" "$SHELL_FOLDER" &&
        echo "************************ generate patch file complete *********************" &&
        echo "***************************************************************************"
    else
        echo "%%%%%%%%%%%%%%%%%%%%% No File to Patch,Do Nothing %%%%%%%%%%%%%%%%%%%%%%%%"
    fi
else
    echo "%%%%%%%%%%%%%%%%%%%%% No Commit Record Found,Do Nothing %%%%%%%%%%%%%%%%%%%%%%%%"
fi
#################################################

```

* archives.py

```python
#!/usr/bin/python
#coding=utf-8
#weck

import zipfile
import pdb
import os
import time
import shutil
from sys import argv

py_cmd, zip_filepath, source_project_path = argv

def zip_dir(dirname, zipfilename):
    filelist = []
    if os.path.isfile(dirname):
        filelist.append(dirname)
    else :
        for root, dirs, files in os.walk(dirname):
            for name in files:
                filelist.append(os.path.join(root, name))

    zf = zipfile.ZipFile(zipfilename, "w", zipfile.zlib.DEFLATED)
    for tar in filelist:
        arcname = tar[len(dirname):]
        zf.write(tar, arcname)
    zf.close()

'''
通过git生成的增量zip文件，获取编译后的文件并压缩
'''
def kbsZipFile(filename):
    if zipfile.is_zipfile(filename):
        rootdir = filename[0 : filename.rfind('/')+1]
        maxLen = len(rootdir)
        ctx = rootdir[(rootdir.rfind('/', 0, (maxLen-1))+1):maxLen]
        target_dir = os.path.join(rootdir, ctx)
        zf = zipfile.ZipFile(filename)
        filepath_list = zf.namelist()

        #遍历zip中的文件名，并且将文件 copy 到 target_dir 中
        for filepath in filepath_list:
            if os.path.isfile(os.path.join(rootdir, filepath)):
                #遍历 class 文件
                if filepath.startswith('core/src/main/java/'):
                    filename = filepath[filepath.rfind('/')+1:filepath.rfind('.java')]
                    my_dir = filepath[(len('core/src/main/java/')) : filepath.rfind('/')+1]
                    my_target_dir = os.path.join(target_dir, 'WEB-INF/classes/', my_dir)
                    project_dir = source_project_path
                    my_source_dir = os.path.join(project_dir, 'core/target/core/WEB-INF/classes/', my_dir)
                    # pdb.set_trace()
                    for my_filename in os.listdir(my_source_dir):
                        if os.path.isfile(os.path.join(my_source_dir, my_filename)) and (my_filename==filename + '.class' or my_filename.startswith(filename + '$')):
                            try:
                                os.makedirs(my_target_dir)
                            except OSError:
                                pass
                            shutil.copyfile(os.path.join(my_source_dir, my_filename), os.path.join(my_target_dir, my_filename))
                #遍历 properties/xml 配置文件
                elif filepath.startswith('core/src/main/resources/') and not filepath.endswith('.properties'):
                    my_dir = filepath[(len('core/src/main/resources/')) : filepath.rfind('/')+1]
                    my_filename = filepath[filepath.rfind('/')+1 : len(filepath)]
                    my_target_dir = os.path.join(target_dir, 'WEB-INF/classes/', my_dir)
                    my_source_dir = os.path.join(source_project_path, 'core/target/core/WEB-INF/classes/', my_dir)
                    try:
                        os.makedirs(my_target_dir)
                    except OSError:
                        pass
                    shutil.copyfile(os.path.join(my_source_dir, my_filename), os.path.join(my_target_dir, my_filename))
                #遍历 webapp 下的文件
                elif filepath.startswith('core/src/main/webapp/'):
                    my_dir = filepath[(len('core/src/main/webapp/')) : filepath.rfind('/')+1]
                    my_filename = filepath[filepath.rfind('/')+1 : len(filepath)]
                    my_target_dir = os.path.join(target_dir, my_dir)
                    my_source_dir = os.path.join(source_project_path, 'core/target/core/', my_dir)
                    try:
                        os.makedirs(my_target_dir)
                    except OSError:
                        pass
                    shutil.copyfile(os.path.join(my_source_dir, my_filename), os.path.join(my_target_dir, my_filename))

        #增加增量包记录 META-INF 下加上时间戳
        # update_dir_path = os.path.join(target_dir, 'META-INF');
        # try:
        #     os.makedirs(update_dir_path)
        # except OSError:
        #     pass
        # update_file_path = os.path.join(update_dir_path, time.strftime('%Y%m%d%H%M', time.localtime()) + '.txt')
        # with open(update_file_path, 'w') as update_file:
        #     update_file.write('update at ' + time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
        #     update_file.write('\n')

        #将 target_dir 压缩
        zip_dir(target_dir, rootdir + 'patch-' + time.strftime('%Y%m%d%H%M', time.localtime()) + '.zip')

        #删除临时生成的文件夹
        shutil.rmtree(target_dir)
        try:
            os.remove(zip_filepath)
        except:
            print ("Error deleting temporary file, please delete it manually.")
        finally:
            if os.path.exists(os.path.join(rootdir,"core")):
                shutil.rmtree(os.path.join(rootdir,"core"))
            if os.path.exists(os.path.join(rootdir,"core-db")):
                shutil.rmtree(os.path.join(rootdir,"core-db"))


if __name__=='__main__':
    kbsZipFile(zip_filepath);

```

### 三、配置参数

打开gen_patch.sh文件,修改里面的四个参数配置:

```shell
#生成差异包的目录,需要已经存在的目录(最好新建一个),windows的目录格式按照D:/test/patch/这种形式,目录需要以‘/’结尾
GENERATE_FOLDER=/Users/weck/Downloads/patch/    

#分支
GIT_BRANCH=HLS-DEV          

#时间
SINCE_DATE="2018-04-02 00:00:00"     

#提交人
AUTHOR=gaoyang        
```

### 四、运行脚本

Windows的童鞋请在项目目录下打开git-bash,MacOS的童鞋请打开终端并切换到项目目录,执行以下命令即可:

 ```shell
$ sh gen_patch.sh
 ```

**注:在gen_patch.sh中有一个编译打包命令`mvn clean install`,如果已经更新到最新版本代码并且编译打包过了,可以把这个命令注释,不需要每次打包,加快速度.**