Android repo代码仓库上传到公司的git服务器修改记录
参考地址
0x00 首先从供应商那里拿到了一份AOSP的源码,比如我拿到的是Android8.1的源代码。
比如我的拿到的部分代码,只有一个.repo文件夹,文件夹大小为39G(Android8.1)的代码。
0x01 然后同步供应商的代码。
使用repo sync -l 同步供应商的代码,如图同步完成相关的代码。(repo 命令应之前已经安装好,不懂的自己百度哈)
0x02 获取项目源码中每个代码仓的位置
使用命令获取代码整个项目的每个git的代码仓库,然后把他生成到文档中。
#使用命令如下,把qcom_source源码仓中所有的.git 项目路径都写到git_pro.txt文件中
find qcom_source/ -type d -name '.git' > git_pro.txt
1、如图所示,我的项目中一共有五百多个git项目。
2、然后使用命令把项目的头尾去掉,然后只留下项目的相对路径。
#命令,其中13是每行开头到相对路径的字符个数,根据自己的路径进行修改
cat git_pro.txt | cut -c 13- | sed 's/.....$//' > path.txt
结果如图所示
0x03 repo使用的是manifest.xml来管理整个repo的代码仓的,所以需要我们生成自己的manifest.xml文件,当然使用供应商提供的manifest.xml来使用也是一样的,需要修改部分代码,我自己生成自己的xml文件;
1、上面使用相关的步骤后,就生成了一个path.txt文件了,然后我们使用这个path.txt文件生成default.xml文件。repo会把这个default.xml文件后面和manifest.xml关联起来,不用我们手动关联。
使用刚刚的path.txt文件和shell脚本来生成default.xml文件,暂时文件名定为gen_xml.sh,如下:
#!/bin/bash
echo -e "
<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<manifest>
<remote name=\"origin\" fetch=\".\"/>
<default remote=\"origin\" sync-j=\"4\" revision=\"main\" />" >>$1
while read line; do
echo " <project path=\"$line\" name=\"$line\" />" >>$1
done
echo -e "\n</manifest>" >>$1
#使用shell脚本生成xml文件
cat path.txt | sh gen_xml.sh default.xml
执行后生成的xml文件如图:
0x04 default.xml文件概述
<?xml version="1.0" encoding="UTF-8"?>
<manifest>
<remote name="origin" fetch="."/>
<default remote="origin" sync-j="4" revision="main" />
<project path="cts" name="cts" /> #往下是相关项目的信息
<project path="kernel/msm-3.18" name="kernel/msm-3.18" />
<project path="packages/services/Telephony" name="packages/services/Telephony" />
<project path="packages/services/BuiltInPrintService" name="packages/services/BuiltInPrintService" />
<project path="packages/services/Car" name="packages/services/Car" />
<project path="packages/services/NetworkRecommendation" name="packages/services/NetworkRecommendation" />
<project path="packages/services/Telecomm" name="packages/services/Telecomm" />
<project path="packages/services/Mms" name="packages/services/Mms" />
<project path="packages/apps/SnapdragonMusic" name="packages/apps/SnapdragonMusic" />
<project path="packages/apps/TV" name="packages/apps/TV" />
<project path="packages/apps/Launcher3" name="packages/apps/Launcher3" />
<project path="packages/apps/QuickSearchBox" name="packages/apps/QuickSearchBox" />
<project path="packages/apps/Nfc" name="packages/apps/Nfc" />
<project path="packages/apps/HTMLViewer" name="packages/apps/HTMLViewer" />
<project path="packages/apps/StorageManager" name="packages/apps/StorageManager" />
<project path="packages/apps/BasicSmsReceiver" name="packages/apps/BasicSmsReceiver" />
<project path="packages/apps/Phone" name="packages/apps/Phone" />
<project path="packages/apps/Exchange" name="packages/apps/Exchange" />
<project path="packages/apps/EmergencyInfo" name="packages/apps/EmergencyInfo" />
<project path="packages/apps/SnapdragonGallery" name="packages/apps/SnapdragonGallery" />
<project path="packages/apps/Launcher2" name="packages/apps/Launcher2" />
<project path="packages/apps/PackageInstaller" name="packages/apps/PackageInstaller" />
<project path="packages/apps/SmartCardService" name="packages/apps/SmartCardService" />
<project path="packages/apps/OneTimeInitializer" name="packages/apps/OneTimeInitializer" />
<project path="packages/apps/Car/Media" name="packages/apps/Car/Media" />
<project path="packages/apps/Car/Messenger" name="packages/apps/Car/Messenger" />
<project path="packages/apps/Car/Hvac" name="packages/apps/Car/Hvac" />
<project path="packages/apps/Car/SystemUpdater" name="packages/apps/Car/SystemUpdater" />
<project path="packages/apps/Car/Settings" name="packages/apps/Car/Settings" />
<project path="packages/apps/Car/LatinIME" name="packages/apps/Car/LatinIME" />
# 不止这些
0x05 由于不只是一个git代码仓库,所以不可能手动来创建仓库,所以我们只能使用脚本来创建远程的代码仓库。
1、通过shell和生成的default.xml文件来创建git远程厂库。(注,一定要在主组下面创建,我不是在主组下创建会失败,有些项目无法完成,可能是因为权限的问题)
需要用的工具和build-git.py脚本
工具:python3 python-gitlab库
脚本:
#!/usr/bin/python3
import gitlab
import os
import re
import time
import sys
MANIFEST_XML = "default.xml"#其中这个是我们刚刚生成的default.xml文件
ROOT = os.getcwd()
ROOT_GROUP = "qcom-android"#这个是我们的主组
MANIFEST_XML_PATH_NAME_RE = re.compile(r"<project\s+path=\"(?P<path>[^\"]+)\"\s+name=\"(?P<name>[^\"]+)\"\s+/>",
re.DOTALL)
gl = gitlab.Gitlab('http://ip/', private_token='xxxxxxxxxxxxxxxxxxx')#token是我的用户token 下面介绍
manifest_xml_project_paths = []
def parse_repo_manifest():
with open(os.path.join(ROOT, MANIFEST_XML), "rb") as strReader:
for line in strReader:
if line is not None and len(line) != 0:
this_temp_line = line.decode()
#print(this_temp_line)
if line.find("path".encode(encoding="utf-8")):
s = MANIFEST_XML_PATH_NAME_RE.search(this_temp_line)
#print(s)
if s is not None:
manifest_xml_project_paths.append(s.group("path"))
print("manifest_xml_project_paths=" + str(manifest_xml_project_paths))
print("manifest_xml_project_paths len=" + str(len(manifest_xml_project_paths)))
def create_group_and_project():
all_groups = gl.groups.list(all=True)
print("all_groups=" + str(all_groups))
group_parent = None
for g in all_groups:
if g.name == ROOT_GROUP:
group_parent = g
break
# print("**** get group parent=" + str(group_parent)) #查找父组
for path in manifest_xml_project_paths: #解析文件夹
print("path=" + path)
paths = path.split("/")
print("paths=" + str(paths))
last_path_index = len(paths) - 1
group = group_parent
for index in range(0, last_path_index):
p = paths[index] #取出每个文件夹
print("ex p=" + p)
# is the group exist
print("build parent group=" + group.name)
try:
all_groups = group.subgroups.list(all=True)
except AttributeError:
all_groups = []
print("AttributeError: clear all subgroups")
is_group_exist = False
for g in all_groups:
if g.name == p:
is_group_exist = True
group = g
print("group exist=" + g.name)
break
if is_group_exist:
continue
# create subgroup
data = {
"name": p,
"path": p,
"parent_id": group.id
}
#print("-------------->data:{}, name:{}".format(data, group.name))
try:
group = gl.groups.create(data)
print("group create success name=" + p)
time.sleep(1)
except gitlab.exceptions.GitlabCreateError as e:
if e.response_code == 400:
#print("=============> group name :" + p + " has already been created")
query_groups = gl.groups.list(all=True)
#print("-------------> query_groups:" + str(query_groups))
for query_group in query_groups:
if query_group.name == p and query_group.parent_id == group.id:
group = query_group
print("update exit group:" + group.name)
break
# '''
project = paths[last_path_index]
print("group project list group=" + group.name)
real_group = gl.groups.get(group.id, lazy=True)
all_projects = real_group.projects.list(all=True)
print("group all projects=" + str(all_projects))
is_project_exist = False
for p in all_projects:
if p.name == project:
is_project_exist = True
print("project exist=" + p.name)
break
if not is_project_exist:
print("create project=" + project)
gl.projects.create({'name': project, 'path': project, 'namespace_id': group.id})
print("project create success name=" + project)
time.sleep(1)
# '''
def test_create_project_with_dot_name():
# need use path field, if don't use path, GitLab url will replace "." to "_"
gl.projects.create({
'name': "xxx.yy.xy", 'path': "xxx.yy.xy"})
if __name__ == '__main__':
parse_repo_manifest()
create_group_and_project()
1、首先登陆我们的git web,新建一个主组结构。
2、创建一个叫qcom-android的主组
3、由于脚本内写死了父组名(qcom-android),这个组需要在 GitLab 网页中自行创建。同样 url 和 token 需要更换为你自己的,生成 token 是在 GitLab Settings -> Access Tokens -> Add a personal access token。如图,在名称中随便加一个名字,然后生成token。然后复制放到上面的脚本中。
使用上面的build-git.py脚本,然后通过正则表达式解析 default.xml 中的 project 标签拿到 path,根据 path 创建 group (包括 subgroup),最后再创建 project。
4、执行完build-git.py脚本的结果如图
我只拿了三个项目来做测试,如图是创建完成后的代码仓库。
0x06 给git服务器新建一个manifest的git仓库,然后把default.xml上传上去
1、比如我在qcom-android组下面新建一个manifest项目
2、然后把default.xml文件上传到服务器
使用如下命令在上面生成的default.xml文件夹下面执行如下命令(根据你的项目路径使用不同的命令,我这个是新建项目的时候在项目里生成的相关命令,你的根据需要就行修改)
3、添加完成
0x07 push本地已经有的代码到远程代码仓中
一、使用的工具有,python3、python-gitlab、push_git.py
二、首先需要确定的事你的ssh已经生成相关的公共密钥,并且已经绑定到git服务器。不然你执行下一步的脚本会出错。
1、先在Ubuntu上安装 Git
sudo apt-get install git
2、安装成功后键入命令可以查看 Git 版本,有版本提示说明已经安装成功。
git --version
3、配置全局git的用户名和邮箱
git config --global user.name "xxx" # xxx 是你的用户名
git config --global user.email "user email address" # 后面这个是你的邮箱名字
4、使用生成 SSH key
ssh-keygen -t rsa -C "user email address" # 是你的邮箱
5、然后再用户目录下会生成一个.ssh,然后里面有两个问文件
6、打开id_rsa.pub文件,复制里面的内容然后填写到git webview面别的
三、push_git.py脚本
这需要开发一个脚本执行,这里还是用 python 实现。
#!/usr/bin/python3
import time
import os
import re
MANIFEST_XML = "default.xml" #我们生成的defualt.xml文件
ROOT = os.getcwd()
LOG_FILE_PATH = os.path.join(ROOT, "log-push.log")
MANIFEST_XML_PATH_NAME_RE = re.compile(r"<project\s+path=\"(?P<path>[^\"]+)\"\s+name=\"(?P<name>[^\"]+)\"\s+/>",
re.DOTALL)
SOURCE_CODE_ROOT = "/work/qcom_source/" #你源代码路径,这个是供应商提供的代码
REMOTE = "git@192.168.1.100:qcom-android/" #你的git服务器地址和主目录路径
manifest_xml_project_paths = []
def parse_repo_manifest():
with open(os.path.join(ROOT, MANIFEST_XML), "rb") as strReader:
for line in strReader:
if line is not None and len(line) != 0:
this_temp_line = line.decode()
if line.find("path".encode(encoding="utf-8")):
s = MANIFEST_XML_PATH_NAME_RE.search(this_temp_line)
if s is not None:
manifest_xml_project_paths.append(s.group("path"))
print("manifest_xml_project_paths=" + str(manifest_xml_project_paths))
print("manifest_xml_project_paths len=" + str(len(manifest_xml_project_paths)))
def push_source_code_by_folder(str_writer):
for path in manifest_xml_project_paths:
print("path=" + path)
abs_path = SOURCE_CODE_ROOT + path
print("abs_path:", abs_path)
if os.path.exists(abs_path):
# change current work dir
os.chdir(abs_path + "/")
dir_data = os.listdir(os.getcwd())
cmd_list = []
if len(dir_data) == 0:
echo_cmd = "echo \"This is a empty repository.\" > ReadMe.md"
str_writer.write("empty repository:" + abs_path)
str_writer.write("\r\n")
cmd_list.append(echo_cmd)
git_init_cmd = "git init"
cmd_list.append(git_init_cmd)
#git_rename_origin_cmd = "git remote rename origin origin-old"
#cmd_list.append(git_rename_origin_cmd)
git_remote_cmd = "git remote add origin " + REMOTE + path + ".git"
print("******************************remote path:", git_remote_cmd)
cmd_list.append(git_remote_cmd)
git_push_cmd = 'git push -u origin --all'
cmd_list.append(git_push_cmd)
git_push_cmd = 'git push -u origin --tags'
cmd_list.append(git_push_cmd)
for cmd in cmd_list:
print("--------------------->begin exec cmd:" + cmd)
os.popen(cmd)
time.sleep(1)
print("====================>end exec cmd:" + cmd)
else:
print("abs_path=" + abs_path + " is not exist.")
str_writer.write("folder not exist:" + abs_path)
str_writer.write("\r\n")
def wrapper_push_source_code_write_log():
with open(LOG_FILE_PATH, 'wb+') as strWriter:
push_source_code_by_folder(strWriter)
strWriter.close()
def test_only_dot_git_folder():
subdir_and_file = os.listdir(os.getcwd())
print("subdir_and_file=" + str(subdir_and_file))
with open(LOG_FILE_PATH, 'wb+') as strWriter:
strWriter.write(str(subdir_and_file))
strWriter.write("\r\n")
strWriter.write(str(subdir_and_file))
strWriter.close()
if __name__ == '__main__':
parse_repo_manifest()
wrapper_push_source_code_write_log()
执行完脚本后嘚结果
至此,代码已经从供应商的git 地址推送到我们自己的git 服务器中了。接下来继续
0x08 repo 部署到服务器,这个 是必须的用于同步git的代码
1、把代码clone下来
git clone https://github.com/GerritCodeReview/git-repo.git
然后把项目里面的.git文件夹删除掉
2、在git webview上新建一个repo仓库,如图我的是这么做的。
3、把刚刚下载好的repo代码上传到新建的仓库中。
执行的命令如下
上传成功
0x09 客户端 repo 同步代码
执行命令:
1、同步服务器的代码
repo-admin init -u git@192.168.2.111:qcom-android/manifest.git --repo-url=git@192.168.2.111:qcom-android/repo.git --no-repo-verify
这时候执行repo sync可能会出现错误,可能是因为python版本或者是repo版本不对,需要最新的repo命令。(这个需要自己同步最新的repo应用,我服务器中存在两个repo ,一个命名成repo-admin 这个是最新版本的,另一个是repo 是比较旧的版本)
结果:
2、同步代码命令
repo-admin sync
同步完成后,就生成相关的项目文件了
由于我只测试了几个项目,所以才有三个项目被同步了过来。
错误
1、出现如下错误
如果错误,是因为repo脚本需要修改。
解决:一,我们打开我们的repo脚本
命令:sudo vi /user/repo-admin (其中repo-admin是我最新的repo版本,是通过repo重新命名成repo-admin的,你们看你们的应用名字)
修改 把REPO_REV修改成master
2 出现如图所示问题可能是因为你git远程仓库没用master分支,需要切换到对应分支
解决:
在执行完上面的第0x09步骤操作后,打开vi .repo/manifests/default.xml,把revision=master修改成你对应的分支名字,然后在执行repo sync操作。
至此完成了repo工程的创建和代码管理。有不足和写得不对的地方望大家留言指出,大家一起学习成长。谢谢~