docs-update.py 7.8 KB

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