-
Notifications
You must be signed in to change notification settings - Fork 346
/
Copy pathsubmodules.py
executable file
·136 lines (110 loc) · 4.32 KB
/
submodules.py
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
#!/usr/bin/python2
############################################################
# <bsn.cl fy=2013 v=none>
#
# Copyright 2013, 2014 BigSwitch Networks, Inc.
#
#
#
# </bsn.cl>
############################################################
#
# Submodule management.
#
############################################################
import os
import sys
import subprocess
import shutil
import logging
logging.basicConfig()
logger = logging.getLogger("submodules")
logger.setLevel(logging.INFO)
def check_call(cmd, *args, **kwargs):
if type(cmd) == str:
logger.debug("+ " + cmd)
else:
logger.debug("+ " + " ".join(cmd))
return subprocess.check_call(cmd, *args, **kwargs)
def check_output(cmd, *args, **kwargs):
if type(cmd) == str:
logger.debug("+ " + cmd)
else:
logger.debug("+ " + " ".join(cmd))
return subprocess.check_output(cmd, *args, **kwargs)
class OnlSubmoduleError(Exception):
"""General Package Error Exception"""
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
class OnlSubmoduleManager(object):
def __init__(self, root):
if not os.path.exists(os.path.join(root, ".git")):
raise OnlSubmoduleError("%s is not a git repository." % root)
if not os.path.exists(os.path.join(root, ".gitmodules")):
raise OnlSubmoduleError("The git repository %s does not contain any submodules." % root)
self.root = root
self.get_status()
def get_status(self):
self.status = {}
try:
for entry in check_output(['git', 'submodule', 'status'], cwd=self.root).split("\n"):
data = entry.split()
if len(data) >= 2:
self.status[data[1]] = data[0]
except subprocess.CalledProcessError:
raise OnlSubmoduleError("git command(s) failed")
def validate(self, path):
if not path in self.status:
raise OnlSubmoduleError("Submodule %s does not exist in repository %s" % (path, self.root))
def update(self, path, depth=None, recursive=False):
self.validate(path)
if depth:
logger.debug("shallow clone depth=%d", int(depth))
# Shallow clone first
url = check_output(['git', 'config', '-f', '.gitmodules', '--get',
'submodule.' + path + '.url' ], cwd=self.root)
url = url.rstrip('\n')
args = [ 'git', 'clone', '--depth', depth, url, path ]
try:
check_call(args, cwd=self.root)
except subprocess.CalledProcessError:
raise OnlSubmoduleError("git error cloning module %s" % path)
# full or partial update
args = [ 'git', 'submodule', 'update', '--init' ]
if recursive:
args.append("--recursive")
args.append(path)
try:
check_call(args, cwd=self.root)
except subprocess.CalledProcessError:
raise OnlSubmoduleError("git error updating module %s" % path)
#
# Run any repository-specific post-submodule-init scripts.
#
for script in os.getenv("ONL_SUBMODULE_UPDATED_SCRIPTS", "").split(':'):
if os.path.exists(script):
try:
print "Calling %s..." % script
check_call([script, path], cwd=self.root)
except subprocess.CalledProcessError:
raise OnlSubmoduleError("The repository post-init script %s failed." % script)
def require(self, path, depth=None, recursive=False):
self.get_status()
self.validate(path)
if self.status[path][0] == '-':
self.update(path, depth=depth, recursive=recursive)
if __name__ == '__main__':
import argparse
ap = argparse.ArgumentParser(description='Submodule Manager')
ap.add_argument("root", help="The root of the git repository in which to operate.")
ap.add_argument("path", help="The submodule path to initialize.")
ap.add_argument("--depth", help="Shallow submodule clone to given depth.")
ap.add_argument("--recursive", help="Recursive update.", action='store_true')
ops = ap.parse_args()
try:
sm = OnlSubmoduleManager(ops.root)
sm.require(ops.path)
except OnlSubmoduleError, e:
logger.error("%s" % e.value)