-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsync.py
More file actions
104 lines (83 loc) · 3.98 KB
/
Copy pathsync.py
File metadata and controls
104 lines (83 loc) · 3.98 KB
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
# Script to sync with upstream.
#
# Meant to be called via CI
import sys
import configargparse
from git import Repo
from git.exc import GitError
REMOTE_URL = "https://github.com/{}/{}.git"
class SyncException(Exception):
def __init__(self, message):
super().__init__(self)
self.message = message
if __name__ == "__main__":
config = configargparse.ArgParser()
# Get our required arguments, they can be specified by environment variables
config.add('--upstream-org', env_var='UPSTREAM_ORG', help='The upstream github organization', required=True)
config.add('--upstream-repo', env_var='UPSTREAM_REPO', help='The upstream repository', required=True)
config.add('--upstream-branch', env_var='UPSTREAM_BRANCH', help='The upstream branch', required=True)
config.add('--origin-branch', env_var='ORIGIN_BRANCH', help='The downstream branch that will be pushed to the '
'origin remote', required=True)
config.add('path', help='Path to local repository')
options = config.parse_args()
repo = Repo(options.path)
# Fail if upstream remote is already defined
if 'upstream' in repo.remotes:
print('There is already an "upstream" remote. Exiting.')
sys.exit(-1)
try:
# Fail if origin remote is not defined
if 'origin' not in repo.remotes:
raise SyncException('There is no "origin" remote to push to.')
# Fetch the upstream remote
upstream_url = REMOTE_URL.format(options.upstream_org, options.upstream_repo)
print("Fetching upstream: {}.".format(upstream_url))
upstream = repo.create_remote('upstream', upstream_url)
fetch_info = upstream.fetch(prune=True)
for info in fetch_info:
if info.flags & info.ERROR:
raise SyncException(info.note)
# Fetch the origin remote
origin = repo.remotes.origin
print("Fetching origin: {}.".format(origin.url))
fetch_info = origin.fetch(prune=True)
for info in fetch_info:
if info.flags & info.ERROR:
raise SyncException(info.note)
# Fail if the upstream branch does not exist
if options.upstream_branch not in upstream.refs:
raise SyncException('Upstream branch ({}) does not exist.'.format(options.upstream_branch))
# Origin branch does not exist in local repo
if options.origin_branch not in repo.heads:
repo.create_head(options.origin_branch, upstream.refs[options.upstream_branch])
if options.origin_branch in origin.refs:
print("Origin branch ({}) exists on remote.".format(options.origin_branch))
origin_commit = origin.refs[options.origin_branch].commit
print("Origin commit: {}".format(origin_commit))
else:
origin_commit = None
print("Origin branch ({}) does not exist on remote, creating it.".format(options.origin_branch))
upstream_commit = upstream.refs[options.upstream_branch].commit
print("Upstream commit: {}".format(upstream_commit))
if upstream_commit == origin_commit:
print("Already up to date. Exiting without update.")
else:
repo.heads[options.origin_branch].reference = upstream.refs[options.upstream_branch].commit
print("Pushing to origin ({})".format(repo.heads[options.origin_branch]))
push_info = origin.push(repo.heads[options.origin_branch], force=True)
for info in push_info:
if info.flags & info.ERROR:
raise SyncException(info.summary)
print("Updated!")
except SyncException as e:
error = "\n".join([e.message.strip(), "Exiting."])
print(error)
sys.exit(-1)
except GitError as e:
print("Git Error!")
print(e)
sys.exit(-2)
finally:
# clean up remotes
if 'upstream' in repo.remotes:
repo.delete_remote(repo.remotes.upstream)