]>
git.proxmox.com Git - ceph.git/blob - ceph/src/fmt/support/manage.py
3 """Manage site and releases.
6 manage.py release [<branch>]
10 from __future__
import print_function
11 import datetime
, docopt
, errno
, fileinput
, json
, os
12 import re
, requests
, shutil
, sys
, tempfile
13 from contextlib
import contextmanager
14 from distutils
.version
import LooseVersion
15 from subprocess
import check_call
19 def __init__(self
, dir):
22 def call(self
, method
, args
, **kwargs
):
23 return check_call(['git', method
] + list(args
), **kwargs
)
26 return self
.call('add', args
, cwd
=self
.dir)
28 def checkout(self
, *args
):
29 return self
.call('checkout', args
, cwd
=self
.dir)
31 def clean(self
, *args
):
32 return self
.call('clean', args
, cwd
=self
.dir)
34 def clone(self
, *args
):
35 return self
.call('clone', list(args
) + [self
.dir])
37 def commit(self
, *args
):
38 return self
.call('commit', args
, cwd
=self
.dir)
40 def pull(self
, *args
):
41 return self
.call('pull', args
, cwd
=self
.dir)
43 def push(self
, *args
):
44 return self
.call('push', args
, cwd
=self
.dir)
46 def reset(self
, *args
):
47 return self
.call('reset', args
, cwd
=self
.dir)
49 def update(self
, *args
):
50 clone
= not os
.path
.exists(self
.dir)
56 def clean_checkout(repo
, branch
):
57 repo
.clean('-f', '-d')
63 def __init__(self
, cwd
):
66 def __call__(self
, *args
, **kwargs
):
67 kwargs
['cwd'] = kwargs
.get('cwd', self
.cwd
)
68 check_call(args
, **kwargs
)
71 def create_build_env():
72 """Create a build environment."""
77 # Import the documentation build module.
78 env
.fmt_dir
= os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
)))
79 sys
.path
.insert(0, os
.path
.join(env
.fmt_dir
, 'doc'))
82 env
.build_dir
= 'build'
83 env
.versions
= build
.versions
85 # Virtualenv and repos are cached to speed up builds.
86 build
.create_build_env(os
.path
.join(env
.build_dir
, 'virtualenv'))
88 env
.fmt_repo
= Git(os
.path
.join(env
.build_dir
, 'fmt'))
93 def rewrite(filename
):
97 if not os
.path
.exists(filename
):
101 with
open(filename
) as f
:
102 buffer.data
= f
.read()
104 with
open(filename
, 'w') as f
:
108 fmt_repo_url
= 'git@github.com:fmtlib/fmt'
111 def update_site(env
):
112 env
.fmt_repo
.update(fmt_repo_url
)
114 doc_repo
= Git(os
.path
.join(env
.build_dir
, 'fmtlib.github.io'))
115 doc_repo
.update('git@github.com:fmtlib/fmtlib.github.io')
117 for version
in env
.versions
:
118 clean_checkout(env
.fmt_repo
, version
)
119 target_doc_dir
= os
.path
.join(env
.fmt_repo
.dir, 'doc')
120 # Remove the old theme.
121 for entry
in os
.listdir(target_doc_dir
):
122 path
= os
.path
.join(target_doc_dir
, entry
)
123 if os
.path
.isdir(path
):
125 # Copy the new theme.
126 for entry
in ['_static', '_templates', 'basic-bootstrap', 'bootstrap',
127 'conf.py', 'fmt.less']:
128 src
= os
.path
.join(env
.fmt_dir
, 'doc', entry
)
129 dst
= os
.path
.join(target_doc_dir
, entry
)
130 copy
= shutil
.copytree
if os
.path
.isdir(src
) else shutil
.copyfile
132 # Rename index to contents.
133 contents
= os
.path
.join(target_doc_dir
, 'contents.rst')
134 if not os
.path
.exists(contents
):
135 os
.rename(os
.path
.join(target_doc_dir
, 'index.rst'), contents
)
136 # Fix issues in reference.rst/api.rst.
137 for filename
in ['reference.rst', 'api.rst']:
138 pattern
= re
.compile('doxygenfunction.. (bin|oct|hexu|hex)$', re
.M
)
139 with
rewrite(os
.path
.join(target_doc_dir
, filename
)) as b
:
140 b
.data
= b
.data
.replace('std::ostream &', 'std::ostream&')
141 b
.data
= re
.sub(pattern
, r
'doxygenfunction:: \1(int)', b
.data
)
142 b
.data
= b
.data
.replace('std::FILE*', 'std::FILE *')
143 b
.data
= b
.data
.replace('unsigned int', 'unsigned')
144 b
.data
= b
.data
.replace('operator""_', 'operator"" _')
145 # Fix a broken link in index.rst.
146 index
= os
.path
.join(target_doc_dir
, 'index.rst')
147 with
rewrite(index
) as b
:
148 b
.data
= b
.data
.replace(
149 'doc/latest/index.html#format-string-syntax', 'syntax.html')
151 html_dir
= os
.path
.join(env
.build_dir
, 'html')
152 if os
.path
.exists(html_dir
):
153 shutil
.rmtree(html_dir
)
154 include_dir
= env
.fmt_repo
.dir
155 if LooseVersion(version
) >= LooseVersion('5.0.0'):
156 include_dir
= os
.path
.join(include_dir
, 'include', 'fmt')
157 elif LooseVersion(version
) >= LooseVersion('3.0.0'):
158 include_dir
= os
.path
.join(include_dir
, 'fmt')
160 build
.build_docs(version
, doc_dir
=target_doc_dir
,
161 include_dir
=include_dir
, work_dir
=env
.build_dir
)
162 shutil
.rmtree(os
.path
.join(html_dir
, '.doctrees'))
163 # Create symlinks for older versions.
164 for link
, target
in {'index': 'contents', 'api': 'reference'}.items():
165 link
= os
.path
.join(html_dir
, link
) + '.html'
167 if os
.path
.exists(os
.path
.join(html_dir
, target
)) and \
168 not os
.path
.exists(link
):
169 os
.symlink(target
, link
)
170 # Copy docs to the website.
171 version_doc_dir
= os
.path
.join(doc_repo
.dir, version
)
173 shutil
.rmtree(version_doc_dir
)
175 if e
.errno
!= errno
.ENOENT
:
177 shutil
.move(html_dir
, version_doc_dir
)
181 env
= create_build_env()
182 fmt_repo
= env
.fmt_repo
184 branch
= args
.get('<branch>')
187 if not fmt_repo
.update('-b', branch
, fmt_repo_url
):
188 clean_checkout(fmt_repo
, branch
)
190 # Convert changelog from RST to GitHub-flavored Markdown and get the
192 changelog
= 'ChangeLog.rst'
193 changelog_path
= os
.path
.join(fmt_repo
.dir, changelog
)
195 changes
, version
= rst2md
.convert(changelog_path
)
196 cmakelists
= 'CMakeLists.txt'
197 for line
in fileinput
.input(os
.path
.join(fmt_repo
.dir, cmakelists
),
199 prefix
= 'set(FMT_VERSION '
200 if line
.startswith(prefix
):
201 line
= prefix
+ version
+ ')\n'
202 sys
.stdout
.write(line
)
204 # Update the version in the changelog.
206 for line
in fileinput
.input(changelog_path
, inplace
=True):
207 if line
.decode('utf-8').startswith(version
+ ' - TBD'):
208 line
= version
+ ' - ' + datetime
.date
.today().isoformat()
209 title_len
= len(line
)
212 line
= '-' * title_len
+ '\n'
214 sys
.stdout
.write(line
)
216 # Add the version to the build script.
217 script
= os
.path
.join('doc', 'build.py')
218 script_path
= os
.path
.join(fmt_repo
.dir, script
)
219 for line
in fileinput
.input(script_path
, inplace
=True):
220 m
= re
.match(r
'( *versions = )\[(.+)\]', line
)
222 line
= '{}[{}, \'{}\']\n'.format(m
.group(1), m
.group(2), version
)
223 sys
.stdout
.write(line
)
225 fmt_repo
.checkout('-B', 'release')
226 fmt_repo
.add(changelog
, cmakelists
, script
)
227 fmt_repo
.commit('-m', 'Update version')
229 # Build the docs and package.
230 run
= Runner(fmt_repo
.dir)
232 run('make', 'doc', 'package_source')
235 # Create a release on GitHub.
236 fmt_repo
.push('origin', 'release')
237 params
= {'access_token': os
.getenv('FMT_TOKEN')}
238 r
= requests
.post('https://api.github.com/repos/fmtlib/fmt/releases',
240 data
=json
.dumps({'tag_name': version
,
241 'target_commitish': 'release',
242 'body': changes
, 'draft': True}))
243 if r
.status_code
!= 201:
244 raise Exception('Failed to create a release ' + str(r
))
246 uploads_url
= 'https://uploads.github.com/repos/fmtlib/fmt/releases'
247 package
= 'fmt-{}.zip'.format(version
)
249 '{}/{}/assets?name={}'.format(uploads_url
, id, package
),
250 headers
={'Content-Type': 'application/zip'},
251 params
=params
, data
=open('build/fmt/' + package
, 'rb'))
252 if r
.status_code
!= 201:
253 raise Exception('Failed to upload an asset ' + str(r
))
256 if __name__
== '__main__':
257 args
= docopt
.docopt(__doc__
)
258 if args
.get('release'):
260 elif args
.get('site'):
261 update_site(create_build_env())