release_docs.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2013 Google Inc. All Rights Reserved.
  4. #
  5. # Redistribution and use in source and binary forms, with or without
  6. # modification, are permitted provided that the following conditions are
  7. # met:
  8. #
  9. # * Redistributions of source code must retain the above copyright
  10. # notice, this list of conditions and the following disclaimer.
  11. # * Redistributions in binary form must reproduce the above
  12. # copyright notice, this list of conditions and the following disclaimer
  13. # in the documentation and/or other materials provided with the
  14. # distribution.
  15. # * Neither the name of Google Inc. nor the names of its
  16. # contributors may be used to endorse or promote products derived from
  17. # this software without specific prior written permission.
  18. #
  19. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. """Script for branching Google Test/Mock wiki pages for a new version.
  31. SYNOPSIS
  32. release_docs.py NEW_RELEASE_VERSION
  33. Google Test and Google Mock's external user documentation is in
  34. interlinked wiki files. When we release a new version of
  35. Google Test or Google Mock, we need to branch the wiki files
  36. such that users of a specific version of Google Test/Mock can
  37. look up documenation relevant for that version. This script
  38. automates that process by:
  39. - branching the current wiki pages (which document the
  40. behavior of the SVN trunk head) to pages for the specified
  41. version (e.g. branching FAQ.wiki to V2_6_FAQ.wiki when
  42. NEW_RELEASE_VERSION is 2.6);
  43. - updating the links in the branched files to point to the branched
  44. version (e.g. a link in V2_6_FAQ.wiki that pointed to
  45. Primer.wiki#Anchor will now point to V2_6_Primer.wiki#Anchor).
  46. NOTE: NEW_RELEASE_VERSION must be a NEW version number for
  47. which the wiki pages don't yet exist; otherwise you'll get SVN
  48. errors like "svn: Path 'V1_7_PumpManual.wiki' is not a
  49. directory" when running the script.
  50. EXAMPLE
  51. $ cd PATH/TO/GTEST_SVN_WORKSPACE/trunk
  52. $ scripts/release_docs.py 2.6 # create wiki pages for v2.6
  53. $ svn status # verify the file list
  54. $ svn diff # verify the file contents
  55. $ svn commit -m "release wiki pages for v2.6"
  56. """
  57. __author__ = 'wan@google.com (Zhanyong Wan)'
  58. import os
  59. import re
  60. import sys
  61. import common
  62. # Wiki pages that shouldn't be branched for every gtest/gmock release.
  63. GTEST_UNVERSIONED_WIKIS = ['DevGuide.wiki']
  64. GMOCK_UNVERSIONED_WIKIS = [
  65. 'DesignDoc.wiki',
  66. 'DevGuide.wiki',
  67. 'KnownIssues.wiki'
  68. ]
  69. def DropWikiSuffix(wiki_filename):
  70. """Removes the .wiki suffix (if any) from the given filename."""
  71. return (wiki_filename[:-len('.wiki')] if wiki_filename.endswith('.wiki')
  72. else wiki_filename)
  73. class WikiBrancher(object):
  74. """Branches ..."""
  75. def __init__(self, dot_version):
  76. self.project, svn_root_path = common.GetSvnInfo()
  77. if self.project not in ('googletest', 'googlemock'):
  78. sys.exit('This script must be run in a gtest or gmock SVN workspace.')
  79. self.wiki_dir = svn_root_path + '/wiki'
  80. # Turn '2.6' to 'V2_6_'.
  81. self.version_prefix = 'V' + dot_version.replace('.', '_') + '_'
  82. self.files_to_branch = self.GetFilesToBranch()
  83. page_names = [DropWikiSuffix(f) for f in self.files_to_branch]
  84. # A link to Foo.wiki is in one of the following forms:
  85. # [Foo words]
  86. # [Foo#Anchor words]
  87. # [http://code.google.com/.../wiki/Foo words]
  88. # [http://code.google.com/.../wiki/Foo#Anchor words]
  89. # We want to replace 'Foo' with 'V2_6_Foo' in the above cases.
  90. self.search_for_re = re.compile(
  91. # This regex matches either
  92. # [Foo
  93. # or
  94. # /wiki/Foo
  95. # followed by a space or a #, where Foo is the name of an
  96. # unversioned wiki page.
  97. r'(\[|/wiki/)(%s)([ #])' % '|'.join(page_names))
  98. self.replace_with = r'\1%s\2\3' % (self.version_prefix,)
  99. def GetFilesToBranch(self):
  100. """Returns a list of .wiki file names that need to be branched."""
  101. unversioned_wikis = (GTEST_UNVERSIONED_WIKIS if self.project == 'googletest'
  102. else GMOCK_UNVERSIONED_WIKIS)
  103. return [f for f in os.listdir(self.wiki_dir)
  104. if (f.endswith('.wiki') and
  105. not re.match(r'^V\d', f) and # Excluded versioned .wiki files.
  106. f not in unversioned_wikis)]
  107. def BranchFiles(self):
  108. """Branches the .wiki files needed to be branched."""
  109. print 'Branching %d .wiki files:' % (len(self.files_to_branch),)
  110. os.chdir(self.wiki_dir)
  111. for f in self.files_to_branch:
  112. command = 'svn cp %s %s%s' % (f, self.version_prefix, f)
  113. print command
  114. os.system(command)
  115. def UpdateLinksInBranchedFiles(self):
  116. for f in self.files_to_branch:
  117. source_file = os.path.join(self.wiki_dir, f)
  118. versioned_file = os.path.join(self.wiki_dir, self.version_prefix + f)
  119. print 'Updating links in %s.' % (versioned_file,)
  120. text = file(source_file, 'r').read()
  121. new_text = self.search_for_re.sub(self.replace_with, text)
  122. file(versioned_file, 'w').write(new_text)
  123. def main():
  124. if len(sys.argv) != 2:
  125. sys.exit(__doc__)
  126. brancher = WikiBrancher(sys.argv[1])
  127. brancher.BranchFiles()
  128. brancher.UpdateLinksInBranchedFiles()
  129. if __name__ == '__main__':
  130. main()