工欲善其事,必先利其器。
脚本可解放劳动力,自觉学习一门脚本开发很是重要。以下是为工作过程中通过 Python 脚本减少手动工作量的场景以及工具实现代码。后续还会继续更新。
批量clone项目以及更新远程项目地址
场景:因为项目中用到了模块化开发(安卓),整个项目分成了十几个子模块,然后前端时间公司 git 要进行迁移,这么多模块手动一个个更新、切换分支以及更换远程地址肯定是很麻烦,使用脚本批量操作就是一件很方便的事,还可以将脚本分享给其他同事使用。当然 shell 脚本更容易,选择 python 主要是熟并且我司电脑均是自带 python 环境。比较废话,以下是为实现代码:
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 一键clone所有模块工程、批量修改仓库地址
# 使用说明:
# 1)配置 REPO_CONFIGS 包括项目路径,老仓库地址(可不进行配置),新仓库地址(注意配置项一一对应);
# 2)将本脚本放到项目同级目录下;
# 3)执行脚本:python git_repo.py ;
# 4) 也可用 shell 脚本,更方便。
# 5) python 2.7 或 3 均可使用。
# 6) 最好所有的模块都放在同一目录,不在同一目录,dir 配置则需使用相对或绝对路径。
# 7) 执行脚本前,先 stash 或 commit 当前分支修改。因为脚本会直接先切到 develop 进行操作。
import re
import os
# Python通过prettytable模块将输出内容如表格方式整齐输出,python本身并不内置,需要独立安装该第三方库。
from prettytable import PrettyTable
OLD_REPO = 'gitAddr:gitGroup/%s.git' # 这里修改为旧的 gitAddr 和 gitGroup 名
NEW_REPO = 'gitAddr:gitGroup/%s.git' # 这里修改为新的 gitAddr 和 gitGroup 名
PROJECT_DIRS = [
'module1', 'module2', 'module3'
] # 这里修改为自己的模块名列表
# 通过 prettytable 模块按表格样式输出内容。安装第三方库:pip3 install PrettyTable
def printProjectDir(projectDirs):
x = PrettyTable(["olderRepo", "projectName", "newerRepo"])
x.align["projectName"] = "1"
x.padding_width = 1 # 填充宽度
for projectDir in projectDirs:
oldRepo = NAPOS_OLD_REPO % (projectDir)
newRepo = NAPOS_NEW_REPO % (projectDir)
x.add_row([oldRepo, projectDir, newRepo])
# print(projectDir, oldRepo, newRepo)
print(x)
def addNewBranch(branchName, projectDirs):
for projectDir in projectDirs:
existed = os.path.exists(projectDir)
print(projectDir, existed)
if (existed):
os.chdir(projectDir)
executeCmd('git checkout -b %s' % (branchName))
executeCmd('git push origin %s' % (branchName))
os.chdir('..')
def executeCmd(cmd):
return os.system(cmd) # 返回值为0,执行命令成功
# clone 所有模块项目
def batchCloneRepo(repoAddr, projectDirs):
for projectDir in projectDirs:
# 当前目录不存在才clone
if (os.path.exists(projectDir)):
print('%s project has existed !' % (projectDir))
else:
repo = repoAddr % (projectDir)
clone_res = executeCmd('git clone ' + repo)
if (clone_res != 0):
print('%s clone failed !' % (projectDir))
else:
print('%s clone successed !' % (projectDir))
# 批量修改所有模块仓库地址(适用于不同group下的仓库迁移,需配置dir, newRepo字典数据)
# def batchSetRemoteUrl(configs):
# for repoDict in configs:
# setRemoteUrl(repoDict['dir'], repoDict['newRepo'])
# 批量更新所有模块 develop 分支代码
def batchFetch(repoAddr, projectDirs):
for projectDir in projectDirs:
existed = os.path.exists(projectDir)
# print(projectDir, existed)
if (existed):
newRepo = repoAddr % (projectDir)
print(newRepo)
os.chdir(projectDir)
executeCmd('git checkout develop')
executeCmd('git fetch')
executeCmd('git merge')
executeCmd('git branch --set-upstream-to origin/develop develop')
os.chdir('..')
else:
print('%s project not existed !' % (projectDir))
# 批量修改所有模块仓库地址(适用于属于同一个group下的仓库迁移,只需配置 NEW_GROUP)
def batchSetSameGroupRemoteUrl(repoAddr, projectDirs):
for projectDir in projectDirs:
existed = os.path.exists(projectDir)
# print(projectDir, existed)
if (existed):
newRepo = repoAddr % (projectDir)
print(newRepo)
setRemoteUrl(projectDir, newRepo)
else:
print('%s project not existed !' % (projectDir))
def setRemoteUrl(projectDir, newRepo):
if (newRepo != ''):
# 进入到指定目录,执行cd命令无法改变命令行当前目录
os.chdir(projectDir)
# 先暂存当前分支修改,再执行切分支等命令
# 恢复暂存,切换到之前的分支,执行命名:
# 1)git stash list 查看所有暂存;2)git stash apply stash@{pos} 运用第pos条暂存内容,pos为你之前暂存的内容。
stash_res = executeCmd('git stash')
if (stash_res != 0):
print('%s stash failed !' % (projectDir))
checkout_res = executeCmd('git checkout develop')
if (checkout_res != 0):
print('%s checkout develop failed !' % (projectDir))
executeCmd('git remote remove origin')
executeCmd('git remote add origin %s' % (newRepo))
# 查看远程仓库地址
# executeCmd('git remote -v')
executeCmd('git fetch')
upstream_res = executeCmd('git branch --set-upstream-to origin/develop develop')
if (upstream_res != 0):
print('%s set-upstream failed !' % (projectDir))
# 回到上级目录
os.chdir('..')
def printRemoteUrl(projectDirs):
for projectDir in projectDirs:
existed = os.path.exists(projectDir)
if (existed):
os.chdir(projectDir)
executeCmd('git remote -v')
os.chdir('..')
if __name__ == '__main__':
# 批量克隆项目
# batchCloneRepo(REPO_ADDR, PROJECT_DIRS)
# 拉老版本的功能代码
# batchFetch(OLD_REPO, PROJECT_DIRS)
# 设置老远程仓库地址
# batchSetSameGroupRemoteUrl(NEW_REPO, MY_DIRS)
# 设置新仓库地址
# batchSetSameGroupRemoteUrl(NEW_REPO, PROJECT_DIRS)
# addNewBranch('testBranch', MY_DIRS)
# 打印远程仓库地址
# printRemoteUrl(PROJECT_DIRS)
batchSetSameGroupRemoteUrl(repo, dirs)
查找某个目录下给定的后缀名文件名
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import re
import os
def findFileNamesWithSuffix(myDir, suffix):
os.chdir(myDir)
arr = [x for x in os.listdir(myDir) if os.path.isfile(x)
and os.path.splitext(x)[1] == suffix]
new_arr = []
for filename in arr:
name = os.path.splitext(filename)
new_arr.append(name[0])
print(new_arr)
findFileNamesWithSuffix('.', '.podSpec')
筛选json文件中多余键值
场景:一般随着迭代的更新换代,后台肯定保留了很多冗余字段或者兼容字段当前版本没有用到,若后台返回的json串过大,而客户端并不需要这么多字段,造成多余的Json解析时间,有些不好了。以下是为以客户端用到的对象字段生成的 json 串和后台返回的大 json 串对比,筛选出后台多余的字段。
# encoding:utf-8
import json
def readFile(file_path):
f = open(file_path, 'r')
content = f.read()
f.close()
return content
def readJsonFromFile(filename):
jsonStr = readFile(filename)
return json.loads(jsonStr)
def excludeAFromB(list_a, list_b):
return list(set(list_b).difference(set(list_a))) # b中有而a中没有的
def excludeDictAFromB(dict_a, dict_b):
a_keys = list(dict_a.keys())
b_keys = list(dict_b.keys())
return list(set(b_keys).difference(set(a_keys))) # b中有而a中没有的
def unionList(list_a, list_b):
return list(set(list_a).union(set(list_b)))
def unionDictKeys(dict_a, dict_b, dict_c):
a_keys = list(dict_a.keys())
b_keys = list(dict_b.keys())
c_keys = list(dict_c.keys())
return unionList(a_keys, unionList(b_keys, c_keys))
def getResult():
s_json = readJsonFromFile('./server.json') # 同级目录服务端json文件
a_json = readJsonFromFile('./android.json') # 同级目录安卓本地json文件
# i_json = readJsonFromFile('./ios.json')
# p_json = readJsonFromFile('./pc.json')
# 求服务器中存在各段不存在的字段
s_exc_a = excludeDictAFromB(a_json, s_json)
# s_exc_i = excludeDictAFromB(i_json, s_json)
# s_exc_p = excludeDictAFromB(p_json, s_json)
print('server exclude android: ', s_exc_a)
# print('server exclude ios: ', s_exc_i)
# print('server exclude pc: ', s_exc_p)
# 方案二:取三段使用字段取并集对比,缩小范围
# # 1. 求三段本地json数据并集
# union_list = unionDictKeys(a_json, i_json, p_json)
# print('Union client datas: ', union_list)
# # 2. 从server json串中排除三端并集数据,为服务器参考字段
# exclude_list = excludeAFromB(union_list, s_json.keys())
# print('Server datas: ', exclude_list)
output = open('./diff.txt', 'w')
for data in s_exc_a:
print(data)
output.write(data + '\n')
getResult()
未完待续。