-
Notifications
You must be signed in to change notification settings - Fork 1
/
git-bpf
executable file
·167 lines (144 loc) · 5.28 KB
/
git-bpf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env python
#
# $ git bpf pull branch-integration
# $ git bpf push branch-integration
# $ git bpf rebuild branch-integration
#
# This script does not push or pull the rr_cache.
#
from commands import getoutput
import json
import os
import sys
import subprocess as subp
bpfpath = os.path.split(os.path.abspath(os.path.realpath(__file__)))[-2]
config_path = os.path.join(bpfpath, "bpf.json")
try:
f = open(config_path)
except:
print("%s not found" % config_path)
sys.exit()
try:
config = json.loads(f.read())
except:
print("%s invalid" % config_path)
sys.exit()
local_repo = os.getcwd().split("/")[-1]
local_branch = getoutput('git branch').split("* ")[-1].split("\n")[0]
def silent_call(cmd_list):
return subp.call(cmd_list, stdout=subp.PIPE, stderr=subp.PIPE)
def call(cmd_str):
cmd = cmd_str.split()
proc = subp.Popen(cmd, stdout=subp.PIPE, stderr=subp.PIPE)
out = proc.communicate()[0]
rc = proc.returncode
lines = out.rstrip().split('\n')
print(">>> {0} ({1})".format(cmd_str, rc))
# print("\n".join(lines))
# print
return (rc, lines)
def rebuild(remote, int_branch):
rc, out = call("git checkout " + int_root_name)
rc, out = call("git checkout -B " + int_branch_name)
for feature in int_branch['features']:
rc, out = call("git merge --no-ff --no-commit " + feature)
rc, out = call("git add .")
rc, out = call("git commit -a --no-edit")
if rc != 0:
sys.exit("Commit failed; run mergetool and commit to update rerere cache")
def pull(remote, int_branch):
# pull start-point
rc, out = call("git checkout " + int_root_name)
rc, out = call("git pull {0} {1}:{2}".format(remote, int_root_name, int_root_name))
# pull all features
for feature in int_branch['features']:
rc, out = call("git checkout " + feature)
rc, out = call("git pull {0} {1}:{2}".format(remote, feature, feature))
def push(remote, int_branch):
# push start-point
rc, out = call("git checkout " + int_root_name)
rc, out = call("git push {0} {1}:{2}".format(remote, int_root_name, int_root_name))
# push all features
for feature in int_branch['features']:
rc, out = call("git checkout " + feature)
rc, out = call("git push {0} {1}:{2}".format(remote, feature, feature))
def update(branch):
"""git bpf update <feature-branch>
Move all commits from the current xxx-integration branch into <feature-branch>.
Then, rebuild the current xxx-integration.
"""
def sync_bpf():
cur_path = os.getcwd()
os.chdir(bpfpath)
print(">>> Update " + bpfpath)
rc, out = call("git status")
rc, out = call("git add .")
rc, out = call("git commit -a -m 'update cache'")
rc, out = call("git pull")
rc, out = call("git push")
os.chdir(cur_path)
action = sys.argv[1]
# This is set in two possible places
int_branch_name = ""
if action == "update":
# must be on *-integration branch
if not local_branch.endswith("-integration"):
sys.exit("git bpf update: you must have an -integration branch \n"
"(with local commits) checked out when you run this command.")
# must specify feature branch argument
try:
feature_branch = sys.argv[2]
except:
sys.exit("git bpf update <feature-branch>: move all commits from the \n"
"current -integration branch into <feature-branch>, and rebuild \n"
"the -integration branch.")
# get commits from current -integration branch
integration_base = local_branch.split("-")[0]
commits = []
cmd = "git log --oneline {0}..HEAD".format(integration_base)
lines = getoutput(cmd).splitlines()
for commit in lines:
if commit.find("Merge branch") > -1:
# the first time we see this string,
# we know we've reached the end of commits made directly in
# -integration.
break
commits.append(commit)
if commits:
print "\n".join(commits)
print("Cancel now if you do not want these %s commits to be merged into %s"%(len(commits), feature_branch))
raw_input()
rc, out = call("git checkout {0}".format(feature_branch))
commits.reverse()
for commit in commits:
commit_hash, commit_subject = commit.split(" ", 1)
cmd = "git cherry-pick %s" % commit_hash
rc, out = call(cmd)
print(">>> Added %s commits to branch %s." % (len(commits), feature_branch))
action = "rebuild"
int_branch_name = local_branch
else:
sys.exit("No commits found in current integration branch.")
if not int_branch_name:
int_branch_name = sys.argv[2]
remote = config.get("remote", "origin")
int_root_name = int_branch_name.split("-")[0]
int_branch = config['integration_branches'].get(int_branch_name, "")
if not int_branch:
sys.exit("%s does not exist in bpf.json" % int_branch_name)
if action == "sync":
sync_bpf()
pull(remote, int_branch)
push(remote, int_branch)
elif action == "pull":
sync_bpf()
pull(remote, int_branch)
elif action == "push":
sync_bpf()
push(remote, int_branch)
elif action == "rebuild":
rebuild(remote, int_branch)
else:
sys.exit("invalid action " + action)
# rc, out = call("git checkout " + local_branch)
rc, out = call("git clean -xfd")