-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfcav
executable file
·234 lines (215 loc) · 8.24 KB
/
fcav
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#! /usr/bin/python
import re, os, sys, subprocess
import pystache as p
def usage():
# Print a short usage message for this script
print "usage: fcav COMMAND [ARG ...]"
print " where COMMAND is one of: 'list', 'create', 'delete', 'deploy'"
exit(-1)
def standardize_version_tag(tag):
# Return a copy of the string `tag` with the prefix `fcav-` prepended to it,
# unless `tag` already starts with that prefix, in which case it is returned
# unaltered.
if tag.startswith("fcav-"):
return tag
else:
return "fcav-" + tag
def system(cmd):
# Convenience wrapper for os.system that lets us print the command being
# executed, for debugging.
#print cmd
return os.system(cmd)
def compare_versions(a,b):
# Sorting comparison function for tags of the form N.M
try:
[amajor,aminor] = [int(x) for x in a.split('.')]
[bmajor,bminor] = [int(x) for x in b.split('.')]
except:
if a < b:
return -1
elif a > b:
return 1
else:
return 0
if amajor < bmajor:
return -1
elif amajor > bmajor:
return 1
else:
if aminor < bminor:
return -1
elif aminor > bminor:
return 1
return 0
def tag_list():
# Return a list of all tags of the form 'fcav-*'
return sorted([re.sub(r'^fcav-(.*)$',r'\1',x) for x in
subprocess.Popen(['git', 'tag'], stdout=subprocess.PIPE).communicate()[0].split('\n') if x != ''], cmp=compare_versions)
def tag_exists(tag):
# Return True if and only if the named tag exists
tag = re.sub(r'^fcav-', '', tag)
for t in tag_list():
if t == tag:
return True
return False
def dist(tag):
# This function creates a gzipped tar file in the top level
# directory, containing a deployable copy of fcav corresponding to
# the named tag. The name of the tar file will be the tag
# followed by the suffix ".tgz".
#
# This function works by exporting the named tag from the current project's repository
# in ./.git. Therefore, the named tag must already exist in that repo.
try:
system("/bin/rm -rf .stage")
stagedir = p.render('.stage/{{{tag}}}', {'tag' : tag})
unpackdir = p.render('.stage/unpack', {'tag' : tag})
os.makedirs(stagedir)
os.makedirs(unpackdir)
status = system(p.render("(git archive --format=tar {{{tag}}} | (cd {{{unpackdir}}} ; tar xf -)) > /dev/null 2>&1", {
'tag' : tag,
'unpackdir' : unpackdir}))
if status != 0:
raise Exception("Cannot export tag '%s'" % tag)
if not os.path.exists(unpackdir + "/bin-release"):
raise Exception("tag '%s' does not contain a bin-release/ subdirectory" % tag)
if not os.path.exists(unpackdir + "/bin-deploy"):
raise Exception("tag '%s' does not contain a bin-deploy/ subdirectory" % tag)
system(p.render("(cd {{{unpackdir}}}/bin-release ; tar cf - .) | (cd {{{stagedir}}} ; tar xf -)", {
'unpackdir' : unpackdir,
'stagedir' : stagedir
}))
system(p.render("(cd {{{unpackdir}}}/bin-deploy ; tar cf - .) | (cd {{{stagedir}}} ; tar xf -)", {
'unpackdir' : unpackdir,
'stagedir' : stagedir
}))
f = open(stagedir + "/VERSION", "w")
f.write(tag + "\n")
f.close()
distfile = tag + ".tgz"
system(p.render("(cd .stage ; tar cfz - {{{tag}}}) > {{{distfile}}}", {
'tag' : tag,
'distfile' : distfile}))
system("/bin/rm -rf .stage")
return distfile
except Exception as e:
print "Error: ", e.message
#system("/bin/rm -rf .stage")
sys.exit(-1)
def validate_deploy_dst(dst):
# Return True or False, depending on whether the given dst directory is a valid
# deployment destination for fcav.
# make sure dst exists:
if not os.path.exists(dst):
return False
# Nothing else to check...
# ...if we got this far, all is well
return True
def deploy(tag, dst, configFile):
###
### Deploy the named tag to the named dst dir
###
# make sure deploy dst is valid
if not validate_deploy_dst(dst):
print "Directory `%s` does not appear to be a valid fcav deployment destination" % dst
sys.exit(-1)
print "extracting %s..." % tag
tgzfile = dist(tag)
# make sure tgzfile is really there
if not os.path.exists(tgzfile):
print "Archive file %s does not exist." % tgzfile
sys.exit(-1)
# unpack tgzfile into staging dir:
system("/bin/rm -rf .stage")
os.mkdir(".stage")
system(p.render("cat {{{tgzfile}}} | ( cd .stage ; tar xfz - )", { 'tgzfile' : tgzfile }))
# remove all files from dst
print "cleaning old files from %s..." % dst
for f in [f for f in os.listdir(dst)]:
system(p.render("/bin/rm -rf {{{dst}}}/{{{f}}}",
{ 'dst' : dst,
'f' : f }))
# copy everything from the staging directory to the dst:
print "copying %s files to %s..." % (tag, dst)
system(p.render("(cd .stage/{{{tag}}} ; tar cf - .) | (cd {{{dst}}} ; tar xf -)",
{ 'tag' : tag,
'dst' : dst }))
# edit the deployed index.html to change the configFile setting
print "editing configFile setting in deployed index.html..."
content = ""
f = open(dst + "/index.html", "r")
for line in f:
content = content + re.sub(r'configFile\s*=\s*[^\'\"]*', 'configFile='+configFile, line)
f.close()
f = open(dst + "/index.html", "w")
f.write(content)
f.close()
# remove other-write and group-write permission on the dst dir:
system(p.render("chmod -R g-w,o-w {{{dst}}}", { 'dst' : dst }))
# clean up staging dir
print "cleaning up..."
os.unlink(tgzfile)
system("/bin/rm -rf .stage")
print "finished deploying %s to %s" % (tag, dst)
if __name__ == "__main__":
try:
command = sys.argv[1]
except:
usage()
if command == "list":
print ("The versions of fcav currently defined in the git repository are: %s" % ", ".join(tag_list()))
sys.exit(0)
if command == "dist":
try:
tag = standardize_version_tag(sys.argv[2])
except:
print "usage: fcav dist TAG"
sys.exit(-1)
tag = standardize_version_tag(sys.argv[2])
system("git checkout master")
system("git pull origin master")
distfile = dist(tag)
print "Wrote `" + distfile + "`"
sys.exit(0)
if command == "deploy":
try:
tag = standardize_version_tag(sys.argv[2])
dst = re.sub(r'/$', '', sys.argv[3]) # be sure to remove any trailing '/' from dst dir
configFile = sys.argv[4]
except:
print "usage: fcav deploy TAG DESTINATION-DIRECTORY CONFIG_FILE_URL"
sys.exit(-1)
deploy(tag, dst, configFile)
sys.exit(0)
if command == "create":
try:
tag = standardize_version_tag(sys.argv[2])
except:
print "usage: fcav create TAG"
sys.exit(-1)
if tag_exists(tag):
print "Error: The tag '%s' already exists." % tag
sys.exit(-1)
system("git checkout master")
system("git pull origin master")
system(p.render("git tag -a -m 'create tag {{{tag}}}' {{{tag}}}", { 'tag' : tag }))
system("git push origin master")
system("git push origin %s" % tag)
print "created %s " % (tag)
sys.exit(-1)
if command == "delete":
try:
tag = standardize_version_tag(sys.argv[2])
except:
print "usage: fcav delete TAG"
sys.exit(-1)
if not tag_exists(tag):
print "Error: The tag '%s' does not exist." % tag
sys.exit(-1)
system("git checkout master")
system("git pull origin master")
system(p.render("git tag -d {{{tag}}}", { 'tag' : tag }))
system(p.render("git push origin :refs/tags/{{{tag}}}", { 'tag' : tag }))
print "deleted %s " % (tag)
sys.exit(-1)
usage()