Android source deployed to the server, a total of seven parts.
- Software environment
- GitLab server deployment
- Repo Manifest. XML is generated
- GitLab position
- Git Push source code to the server
- Repo synchronizes source code
- Commit the modified code
First, software environment
Server system: Ubuntu 16.04
GitLab Software: GitLab Community Edition
Client system: Ubuntu 14.04
Git: Git 2.27.0
Second, GitLab server deployment
- Installation of Required Components
sudo apt-get update
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix
Copy the code
When installing Postfix, use the left and right keys and Enter keys, and select an Internet Site from the drop-down list.
- Trust GitLab’s GPG public key
curl https://packages.gitlab.com/gpg.key 2> /dev/null | sudo apt-key add - &>/dev/null
Copy the code
- Configuring a Mirror Path
If vim is not installed, install it first
vim /etc/apt/sources.list.d/gitlab-ce.list
Copy the code
Gitlab-ce. List:
deb https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/ubuntu xenial main
Copy the code
If the gitlab-ce. List file does not exist, create it and grant permission to the root file.
touch /etc/apt/sources.list.d/gitlab-ce.list
chmod 777 /etc/apt/sources.list.d/gitlab-ce.list
Copy the code
- Install gitlab – ce
sudo apt-get update
sudo apt-get install gitlab-ce
Copy the code
- Perform the configuration
sudo gitlab-ctl reconfigure
Copy the code
- Start the GitLab
sudo gitlab-ctl start
Copy the code
- Modify external_url
sudo gedit /etc/gitlab/gitlab.rb
Copy the code
Change the following path:
external_url 'http://gitlab.example.com'
Copy the code
The specific IP address should be changed to your server, for example, I use 192.168.50.10
External_url 'http://192.168.50.10'Copy the code
Be sure to reconfigure and run the configuration command again
sudo gitlab-ctl reconfigure
Copy the code
- Visit your GitLab service
Open the browser on any computer in the same network segment only when the computers can communicate with each other. If VMS are used, set the network type to Bridge and configure VMS in the same network segment to communicate with each other.
Enter http://192.168.50.10 in the browser address bar (use your own URL instead).
You can then create user root, enter the password and confirm. Register other users and so on.
Repo manifest.xml generation
Why do I need to generate manifest.xml myself? If you have code that has been synchronized from unknown sources, or is provided by a solution vendor, or is not managed using a Repo, you may have changed the part of your code as a separate Git repository. So we need to generate manifest.xml from the existing source code.
Manifest.xml needs to be modified to keep the source repository equivalent to the manifest.xml repository.
Since.git is present in every repository in the source code, we need to count all.git. This is to find all the repositories and write them to manifest.xml so that we can manage them using the Repo.
- Find all Git repositories
find myandroid/ -type d -name '.git' > git_pro.txt
Copy the code
Open git_pro.txt and you’ll see the following line
. /home/snake/Share/art/.git ......Copy the code
Use the bash command to “nip things in the bud” (delete the prefix path /home/snake/Share/ and the suffix.git)
cat git_pro.txt | cut -c 18- | sed 's/..... $//' > path.txtCopy the code
The following path is obtained:
art
Copy the code
You then need to generate the manifest file.
gen_xml.sh
#! /bin/bashecho -e " <? The XML version = \ \ "1.0" encoding = \ "utf-8 \"? > <manifest> <remote name=\"aosp\" fetch=\".. \"/> <default revision=\"master\" remote=\"aosp\" sync-j=\"4\" />" >>$1 while read line; do echo " <project path=\"$line\" name=\"$line\" />" >>$1 done echo -e "\n</manifest>" >>$1Copy the code
Run the script gen_xml.sh.
cat path.txt | ./gen_xml.sh default.xml
Copy the code
Default. XML reads as follows. This is the manifest.xml file we want.
<manifest>
<remote name="aosp"
fetch=".."/>
<default revision="master"
remote="aosp"
sync-j="4" />
<project path="art" name="art" />
<project path="abi/cpp" name="abi/cpp" />.</manifest>
Copy the code
The fetch is “…” I have placed the manifest repository under the android6newc group, as described below.
Revision master represents the trunk branch, which corresponds to the repository branch under the Android6Newc group.
The two are not configured correctly, and the REPO cannot synchronize the repository properly.
Fourth, GitLab warehouse construction
There are too many repositories in the source code to create one by one in the browser, so you need to automate this with the python-Gitlab library. Place default.xml in the same directory as the script and run it. Waiting for the completion of the warehouse, a bit time-consuming, maybe half an hour. If python-Gitlab is not installed, it can be installed with PIP.
The script contains the name of the parent group (Android6NewC), which needs to be created in the GitLab web page. To generate Tokens, go to GitLab Settings -> Access Tokens -> Add a Personal Access token.
AndroidSourceCodeGitlabManager.py
#! /usr/bin/python3
import gitlab
import os
import re
import time
MANIFEST_XML = "default.xml"
ROOT = os.getcwd()
ROOT_GROUP = "Android6NewC"
MANIFEST_XML_PATH_NAME_RE = re.compile(r"
[^\"]+)\"\s+name=\"(? P
[^\"]+)\"\s+/>"
\s+path=\"(?>,
re.DOTALL)
gl = gitlab.Gitlab('http://192.168.50.10/', private_token='xxxxxxx')
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 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("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("p=" + p)
# is the group exist
print("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
}
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:" + 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()
Copy the code
The basic working principle of the script is relatively simple. It parses the project tag in default. XML to get path through regular expression, creates groups (including subgroups) according to path, and finally creates project.
When the script runs correctly, output looks like the following:
. path=external/mtd-utils paths=['external', 'mtd-utils'] p=external parent group=Android6NewC group exist=external group project list group=external group all projects=[...] create project=mtd-utils project create success name=mtd-utils ...... Process finished with exit code 0Copy the code
After the script runs, take a look at the GitLab group page and generate the directory structure we need.
Git Push source code to server
Install Git first, then write an automatic commit script to commit the source code to the repository.
1. Install Git
Use the following command to install Git on Ubuntu 14.04 LTS
apt-get install git
Copy the code
If Git version 2.7.4 is displayed, the installation is successful.
git --version
Copy the code
Git globally configures the user name and mailbox
git config --global user.name "xxx"
git config --global user.email "xxx email address"
Copy the code
Generate the SSH key
ssh-keygen -t ed25519 -C "xxx email address"
Copy the code
The generated message is as follows. Sensitive information has been removed from the generated message. Your generated message will change.
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/captain/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/captain/.ssh/id_ed25519.
Your public key has been saved in /home/captain/.ssh/id_ed25519.pub.
The key fingerprint is:
xxxxxx xxx email address
The key's randomart image is:
+--[ED25519 256--+
| = |
| x * |
| . x x |
| xo |
| * o = S o |
| o = x o x |
| x o.4 . |
| x+ |
| xx |
+-----------------+
Copy the code
See the SSH key
cat /home/captain/.ssh/id_ed25519.pub
Copy the code
The following information is displayed
ssh-ed25519 AAAAC3NzaC1lZXXXXXXXXXXXXXXsULA48NC2f+oOLf5EoFSpn4 xxx email address
Copy the code
Add SSH key in GitLab. Paste the above key into Settings -> SSH Keys -> Add an SSH key.
Push is stored in the source folder project to the repository. Here is an example where the script actually wraps these commands.
CD existing_folder git init git remote add origin [email protected]: android6newc/build git git add. The git commit -m "Initial commit" git push -u origin masterCopy the code
Of course, because the code has been synchronized with Git before, so you need to delete. Git, use the rm command to delete.
rm -rf .git
Copy the code
2. Push the Manifest file to the GitLab server
Create the manifest Project under the Android6Newc group (android6newc). And push the client default.xml.
CD existing_folder git init git remote add origin [email protected]: android6newc/manifest git git add. The git commit -m "Initial commit" git push -u origin masterCopy the code
3. Automatically Push code to GitLab server
This requires the development of a script to execute, again in Python implementation, must be careful to switch to the working path, otherwise the pit, of course, the script has fixed the bug.
PushAndroidSourceCode2GitLab.py
#! /usr/bin/python3
import os
import re
MANIFEST_XML = "default.xml"
ROOT = os.getcwd()
LOG_FILE_PATH = os.path.join(ROOT, "push.log")
MANIFEST_XML_PATH_NAME_RE = re.compile(r"
[^\"]+)\"\s+name=\"(? P
[^\"]+)\"\s+/>"
\s+path=\"(?>,
re.DOTALL)
SOURCE_CODE_ROOT = "/home/captain/myandroid/"
REMOTE = [email protected]: android6newc "/"
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
if os.path.exists(abs_path):
# change current work dir
os.chdir(abs_path + "/")
# 1. delete .git & .gitignore folder
rm_git_cmd = "rm -rf .git"
rm_gitignore_cmd = "rm -rf .gitignore"
os.popen(rm_git_cmd)
os.popen(rm_gitignore_cmd)
# 2. list dir
dir_data = os.listdir(os.getcwd())
cmd_list = []
print("changed cwd=" + os.getcwd())
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_remote_cmd = "git remote add origin " + REMOTE + path + ".git"
cmd_list.append(git_remote_cmd)
git_add_dot_cmd = "git add ."
cmd_list.append(git_add_dot_cmd)
git_commit_cmd = "git commit -m \"Initial commit\""
cmd_list.append(git_commit_cmd)
git_push_cmd = "git push -u origin master"
cmd_list.append(git_push_cmd)
for cmd in cmd_list:
print("begin exec cmd=" + cmd)
os.popen(cmd)
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()
# test_only_dot_git_folder()
Copy the code
Place default.xml in the same directory as the script and run it. At the end of the run, all the source code is synchronized to GitLab.
Repo synchronous source code
Since the source is deployed on a LAN, the LAN cannot access the Internet. So you also need to deploy the REPO to the server.
1. The REPO is deployed on the server
Clone a copy of the REPo to a computer with Internet access.
git clone https://github.com/GerritCodeReview/git-repo.git
Copy the code
Then wrap it up
tar cvf git-repo.tar git-repo/
Copy the code
Copy git-repo.tar to the Intranet PC and decompress it.
tar xvf git-repo.tar
Copy the code
Delete.git from git-repo/.
Create a Git-repo project under the Android-tools group. And push git-repo there.
CD existing_folder git init git remote add Origin [email protected]:android-tools/git-repo.git git add. git commit -m "add repo tool" git push -u origin masterCopy the code
2. Client repO synchronizes code
Locate the repo file in the git-repo path in the previous step. Place it under ~/bin, give execution permission, and add it to the environment variable PATH. This file can also be deployed on an HTTPD server to install the apache2 service.
sudo apt-get install apache2
Copy the code
Check whether the installation is successful.
sudo systemctl status apache2
Copy the code
Change the listening port, I changed it to 10086. We know that HTTP is on port 80 by default, but this port is already used by GitLab, so make room.
sudo vim /etc/apache2/ports.conf
Copy the code
Copy repo to the /var/www/html directory.
Restart the Apache2 service.
sudo service apache2 restart
Copy the code
Download the repo from the ~/bin/ directory.
The curl http://192.168.50.10:10086/repo > repoCopy the code
Modify permissions and add environment variables.
chmod a+x ~/bin/repo
export PATH=$PATH:~/bin
Copy the code
Now you can create a new folder to store the source code. Repo init first, then repo sync.
Repo init -u [email protected]: android6newc/manifest. Git - '08 - url = [email protected]: android - the tools/git - repo. The git --no-repo-verifyCopy the code
The.repo folder will be created in the current folder after init is successful. You can now run repo Sync to start synchronizing your code.
repo sync
Copy the code
To prevent it from popping up in the download, we use the following script, created first.
vim down.sh
Copy the code
Write the following:
#! /bin/sh repo sync while [ $? -ne 0 ] do repo sync doneCopy the code
Replace the repo sync command with this script.
chmod a+x down.sh
./down.sh
Copy the code
Make command can not be used when compiling because there is no Makefile. Copy the Makefile from the source directory. This file is very simple and includes build/core/main.mk.
### DO NOT EDIT THIS FILE ###
include build/core/main.mk
### DO NOT EDIT THIS FILE ###
Copy the code
Submit the modified code
Create a local branch for all repositories with an arbitrary branch name dev.
repo start dev --all
Copy the code
Submit code to remote.
git add .
git commit -m "xxx"
git push aosp dev
Copy the code
Git push < remote host name > < local branch name > will create a dev branch at the remote creation and request merge.
Git branch -a is the name of the remote repository.
Repo upload. (note the dot at the end) is not available because we have not configured the Gerrit server.
Alternatively, the code can be synchronized using the pull command.
git pull --rebase
Copy the code
Advanced usage
Repo forall -c XXX executes the commands specified by -c on all warehouses
repo forall -c git add .
repo forall -c git commit -m "xxx"
repo forall -c git pull --rebase
repo forall -c git push aosp dev
Copy the code
8. Records of errors encountered
1. The default. XML FETCH configuration is incorrect
The following figure is the result of a default.xml FETCH configuration error.
2. Short position and unsubmitted content
Fatal: Couldn’t find remote ref refs/heads/master fatal: Couldn’t find remote ref refs/heads/master fatal: Couldn’t find remote ref refs/heads/master
3. The Git version is old
git commit
Git: ‘Interpret – Trailers’ is not a Git command. See’ git –help ‘.
cannot insert change-id line in .git/COMMIT_EDITMSG
Update with the following command
sudo add-apt-repository ppa:git-core/ppa
sudo apt-get update
sudo apt-get install git
Copy the code
4. The compilation file is missing
This is because some files were added to the.gitignore while git push was in the repository, but the problem is caused by ignoring that the configuration files don’t exactly match the files needed for the actual compilation. Delete this file directly from the script, corrected.
If you still fail to compile, it must be on the library, source repository some subfolders under the.gitignore, can be based on the error message will be the corresponding file on the library.
For example, the netlink/version.h header is missing.
external/libnl/include/netlink/netlink.h:29:29: fatal error: netlink/version.h: No such file or directory
#include <netlink/version.h>
Copy the code
References: