docs-update.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. #!/usr/bin/env python
  2. #
  3. # Sven's quick hack script to update the documentation
  4. #
  5. # call with:
  6. # ./docs/update.py /usr/bin/docker
  7. #
  8. import datetime
  9. import re
  10. from sys import argv
  11. import subprocess
  12. import os
  13. import os.path
  14. script, docker_cmd = argv
  15. # date "+%B %Y"
  16. date_string = datetime.date.today().strftime('%B %Y')
  17. def print_usage(outtext, docker_cmd, command):
  18. help = ""
  19. try:
  20. #print "RUN ", "".join((docker_cmd, " ", command, " --help"))
  21. help = subprocess.check_output("".join((docker_cmd, " ", command, " --help")), stderr=subprocess.STDOUT, shell=True)
  22. except subprocess.CalledProcessError, e:
  23. help = e.output
  24. for l in str(help).strip().split("\n"):
  25. l = l.rstrip()
  26. if l == '':
  27. outtext.write("\n")
  28. else:
  29. # `docker --help` tells the user the path they called it with
  30. l = re.sub(docker_cmd, "docker", l)
  31. outtext.write(" "+l+"\n")
  32. outtext.write("\n")
  33. # TODO: look for an complain about any missing commands
  34. def update_cli_reference():
  35. originalFile = "docs/sources/reference/commandline/cli.md"
  36. os.rename(originalFile, originalFile+".bak")
  37. intext = open(originalFile+".bak", "r")
  38. outtext = open(originalFile, "w")
  39. mode = 'p'
  40. space = " "
  41. command = ""
  42. # 2 mode line-by line parser
  43. for line in intext:
  44. if mode=='p':
  45. # Prose
  46. match = re.match("( \s*)Usage: docker ([a-z]+)", line)
  47. if match:
  48. # the begining of a Docker command usage block
  49. space = match.group(1)
  50. command = match.group(2)
  51. mode = 'c'
  52. else:
  53. match = re.match("( \s*)Usage of .*docker.*:", line)
  54. if match:
  55. # the begining of the Docker --help usage block
  56. space = match.group(1)
  57. command = ""
  58. mode = 'c'
  59. else:
  60. outtext.write(line)
  61. else:
  62. # command usage block
  63. match = re.match("("+space+")(.*)|^$", line)
  64. #print "CMD ", command
  65. if not match:
  66. # The end of the current usage block - Shell out to run docker to see the new output
  67. print_usage(outtext, docker_cmd, command)
  68. outtext.write(line)
  69. mode = 'p'
  70. if mode == 'c':
  71. print_usage(outtext, docker_cmd, command)
  72. def update_man_pages():
  73. cmds = []
  74. try:
  75. help = subprocess.check_output("".join((docker_cmd)), stderr=subprocess.STDOUT, shell=True)
  76. except subprocess.CalledProcessError, e:
  77. help = e.output
  78. for l in str(help).strip().split("\n"):
  79. l = l.rstrip()
  80. if l != "":
  81. match = re.match(" (.*?) .*", l)
  82. if match:
  83. cmds.append(match.group(1))
  84. desc_re = re.compile(r".*# DESCRIPTION(.*?)# (OPTIONS|EXAMPLES?).*", re.MULTILINE|re.DOTALL)
  85. example_re = re.compile(r".*# EXAMPLES?(.*)# HISTORY.*", re.MULTILINE|re.DOTALL)
  86. history_re = re.compile(r".*# HISTORY(.*)", re.MULTILINE|re.DOTALL)
  87. for command in cmds:
  88. print "COMMAND: "+command
  89. history = ""
  90. description = ""
  91. examples = ""
  92. if os.path.isfile("docs/man/docker-"+command+".1.md"):
  93. intext = open("docs/man/docker-"+command+".1.md", "r")
  94. txt = intext.read()
  95. intext.close()
  96. match = desc_re.match(txt)
  97. if match:
  98. description = match.group(1)
  99. match = example_re.match(txt)
  100. if match:
  101. examples = match.group(1)
  102. match = history_re.match(txt)
  103. if match:
  104. history = match.group(1).strip()
  105. usage = ""
  106. usage_description = ""
  107. params = {}
  108. key_params = {}
  109. help = ""
  110. try:
  111. help = subprocess.check_output("".join((docker_cmd, " ", command, " --help")), stderr=subprocess.STDOUT, shell=True)
  112. except subprocess.CalledProcessError, e:
  113. help = e.output
  114. last_key = ""
  115. for l in str(help).split("\n"):
  116. l = l.rstrip()
  117. if l != "":
  118. match = re.match("Usage: docker "+command+"(.*)", l)
  119. if match:
  120. usage = match.group(1).strip()
  121. else:
  122. #print ">>>>"+l
  123. match = re.match(" (-+)(.*) \s+(.*)", l)
  124. if match:
  125. last_key = match.group(2).rstrip()
  126. #print " found "+match.group(1)
  127. key_params[last_key] = match.group(1)+last_key
  128. params[last_key] = match.group(3)
  129. else:
  130. if last_key != "":
  131. params[last_key] = params[last_key] + "\n" + l
  132. else:
  133. if usage_description != "":
  134. usage_description = usage_description + "\n"
  135. usage_description = usage_description + l
  136. # replace [OPTIONS] with the list of params
  137. options = ""
  138. match = re.match("\[OPTIONS\](.*)", usage)
  139. if match:
  140. usage = match.group(1)
  141. new_usage = ""
  142. # TODO: sort without the `-`'s
  143. for key in sorted(params.keys(), key=lambda s: s.lower()):
  144. # split on commas, remove --?.*=.*, put in *'s mumble
  145. ps = []
  146. opts = []
  147. for k in key_params[key].split(","):
  148. #print "......"+k
  149. match = re.match("(-+)([A-Za-z-0-9]*)(?:=(.*))?", k.lstrip())
  150. if match:
  151. p = "**"+match.group(1)+match.group(2)+"**"
  152. o = "**"+match.group(1)+match.group(2)+"**"
  153. if match.group(3):
  154. # if ="" then use UPPERCASE(group(2))"
  155. val = match.group(3)
  156. if val == "\"\"":
  157. val = match.group(2).upper()
  158. p = p+"[=*"+val+"*]"
  159. val = match.group(3)
  160. if val in ("true", "false"):
  161. params[key] = params[key].rstrip()
  162. if not params[key].endswith('.'):
  163. params[key] = params[key]+ "."
  164. params[key] = params[key] + " The default is *"+val+"*."
  165. val = "*true*|*false*"
  166. o = o+"="+val
  167. ps.append(p)
  168. opts.append(o)
  169. else:
  170. print "nomatch:"+k
  171. new_usage = new_usage+ "\n["+"|".join(ps)+"]"
  172. options = options + ", ".join(opts) + "\n "+ params[key]+"\n\n"
  173. if new_usage != "":
  174. new_usage = new_usage.strip() + "\n"
  175. usage = new_usage + usage
  176. outtext = open("docs/man/docker-"+command+".1.md", "w")
  177. outtext.write("""% DOCKER(1) Docker User Manuals
  178. % Docker Community
  179. % JUNE 2014
  180. # NAME
  181. """)
  182. outtext.write("docker-"+command+" - "+usage_description+"\n\n")
  183. outtext.write("# SYNOPSIS\n**docker "+command+"**\n"+usage+"\n\n")
  184. if description != "":
  185. outtext.write("# DESCRIPTION"+description)
  186. if options == "":
  187. options = "There are no available options.\n\n"
  188. outtext.write("# OPTIONS\n"+options)
  189. if examples != "":
  190. outtext.write("# EXAMPLES"+examples)
  191. outtext.write("# HISTORY\n")
  192. if history != "":
  193. outtext.write(history+"\n")
  194. recent_history_re = re.compile(".*"+date_string+".*", re.MULTILINE|re.DOTALL)
  195. if not recent_history_re.match(history):
  196. outtext.write(date_string+", updated by Sven Dowideit <SvenDowideit@home.org.au>\n")
  197. outtext.close()
  198. # main
  199. update_cli_reference()
  200. update_man_pages()