2014-06-30 22:58:04 -04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
#
|
|
|
|
# Sven's quick hack script to update the documentation
|
|
|
|
#
|
|
|
|
# call with:
|
|
|
|
# ./docs/update.py /usr/bin/docker
|
|
|
|
#
|
|
|
|
|
2014-07-22 22:40:10 -04:00
|
|
|
import datetime
|
2014-06-30 22:58:04 -04:00
|
|
|
import re
|
|
|
|
from sys import argv
|
|
|
|
import subprocess
|
|
|
|
import os
|
|
|
|
import os.path
|
|
|
|
|
|
|
|
script, docker_cmd = argv
|
|
|
|
|
2014-07-22 22:40:10 -04:00
|
|
|
date_string = datetime.date.today().strftime('%B %Y')
|
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
def print_usage(outtext, docker_cmd, command):
|
|
|
|
try:
|
2014-09-30 04:43:28 -04:00
|
|
|
help_string = subprocess.check_output(
|
|
|
|
"".join((docker_cmd, " ", command, " --help")),
|
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
shell=True
|
|
|
|
)
|
2014-06-30 22:58:04 -04:00
|
|
|
except subprocess.CalledProcessError, e:
|
2014-09-30 04:43:28 -04:00
|
|
|
help_string = e.output
|
|
|
|
for l in str(help_string).strip().split("\n"):
|
2014-06-30 22:58:04 -04:00
|
|
|
l = l.rstrip()
|
|
|
|
if l == '':
|
|
|
|
outtext.write("\n")
|
|
|
|
else:
|
|
|
|
# `docker --help` tells the user the path they called it with
|
|
|
|
l = re.sub(docker_cmd, "docker", l)
|
2014-09-30 04:43:28 -04:00
|
|
|
outtext.write(" {}\n".format(l))
|
2014-06-30 22:58:04 -04:00
|
|
|
outtext.write("\n")
|
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
# TODO: look for an complain about any missing commands
|
|
|
|
def update_cli_reference():
|
|
|
|
originalFile = "docs/sources/reference/commandline/cli.md"
|
|
|
|
os.rename(originalFile, originalFile+".bak")
|
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
intext = open("{}.bak".format(originalFile), "r")
|
2014-06-30 22:58:04 -04:00
|
|
|
outtext = open(originalFile, "w")
|
|
|
|
|
|
|
|
mode = 'p'
|
|
|
|
space = " "
|
|
|
|
command = ""
|
|
|
|
# 2 mode line-by line parser
|
|
|
|
for line in intext:
|
2014-09-30 04:43:28 -04:00
|
|
|
if mode == 'p':
|
2014-06-30 22:58:04 -04:00
|
|
|
# Prose
|
|
|
|
match = re.match("( \s*)Usage: docker ([a-z]+)", line)
|
|
|
|
if match:
|
2014-12-15 17:30:52 -05:00
|
|
|
# the beginning of a Docker command usage block
|
2014-06-30 22:58:04 -04:00
|
|
|
space = match.group(1)
|
|
|
|
command = match.group(2)
|
|
|
|
mode = 'c'
|
|
|
|
else:
|
|
|
|
match = re.match("( \s*)Usage of .*docker.*:", line)
|
|
|
|
if match:
|
2014-12-15 17:30:52 -05:00
|
|
|
# the beginning of the Docker --help usage block
|
2014-06-30 22:58:04 -04:00
|
|
|
space = match.group(1)
|
|
|
|
command = ""
|
|
|
|
mode = 'c'
|
|
|
|
else:
|
|
|
|
outtext.write(line)
|
|
|
|
else:
|
|
|
|
# command usage block
|
|
|
|
match = re.match("("+space+")(.*)|^$", line)
|
|
|
|
if not match:
|
2014-09-30 04:43:28 -04:00
|
|
|
# The end of the current usage block
|
|
|
|
# Shell out to run docker to see the new output
|
2014-06-30 22:58:04 -04:00
|
|
|
print_usage(outtext, docker_cmd, command)
|
|
|
|
outtext.write(line)
|
|
|
|
mode = 'p'
|
|
|
|
if mode == 'c':
|
|
|
|
print_usage(outtext, docker_cmd, command)
|
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
def update_man_pages():
|
|
|
|
cmds = []
|
|
|
|
try:
|
2014-09-30 04:43:28 -04:00
|
|
|
help_string = subprocess.check_output(
|
|
|
|
"".join((docker_cmd)),
|
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
shell=True
|
|
|
|
)
|
2014-06-30 22:58:04 -04:00
|
|
|
except subprocess.CalledProcessError, e:
|
2014-09-30 04:43:28 -04:00
|
|
|
help_string = e.output
|
|
|
|
for l in str(help_string).strip().split("\n"):
|
2014-06-30 22:58:04 -04:00
|
|
|
l = l.rstrip()
|
|
|
|
if l != "":
|
|
|
|
match = re.match(" (.*?) .*", l)
|
|
|
|
if match:
|
|
|
|
cmds.append(match.group(1))
|
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
desc_re = re.compile(
|
|
|
|
r".*# DESCRIPTION(.*?)# (OPTIONS|EXAMPLES?).*",
|
|
|
|
re.MULTILINE | re.DOTALL
|
|
|
|
)
|
|
|
|
|
2014-11-27 23:21:55 -05:00
|
|
|
options_re = re.compile(
|
|
|
|
r".*# OPTIONS(.*?)# (HISTORY|EXAMPLES?).*",
|
|
|
|
re.MULTILINE | re.DOTALL
|
|
|
|
)
|
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
example_re = re.compile(
|
|
|
|
r".*# EXAMPLES?(.*)# HISTORY.*",
|
|
|
|
re.MULTILINE | re.DOTALL
|
|
|
|
)
|
|
|
|
|
|
|
|
history_re = re.compile(
|
|
|
|
r".*# HISTORY(.*)",
|
|
|
|
re.MULTILINE | re.DOTALL
|
|
|
|
)
|
2014-06-30 22:58:04 -04:00
|
|
|
|
|
|
|
for command in cmds:
|
|
|
|
print "COMMAND: "+command
|
2014-11-27 23:21:55 -05:00
|
|
|
if command == "":
|
|
|
|
print "SKIPPING"
|
|
|
|
continue
|
2014-06-30 22:58:04 -04:00
|
|
|
history = ""
|
|
|
|
description = ""
|
2014-11-27 23:21:55 -05:00
|
|
|
original_options = ""
|
2014-06-30 22:58:04 -04:00
|
|
|
examples = ""
|
|
|
|
if os.path.isfile("docs/man/docker-"+command+".1.md"):
|
|
|
|
intext = open("docs/man/docker-"+command+".1.md", "r")
|
|
|
|
txt = intext.read()
|
|
|
|
intext.close()
|
|
|
|
match = desc_re.match(txt)
|
|
|
|
if match:
|
|
|
|
description = match.group(1)
|
2014-11-27 23:21:55 -05:00
|
|
|
match = options_re.match(txt)
|
|
|
|
if match:
|
|
|
|
original_options = match.group(1)
|
|
|
|
#print "MATCHED OPTIONS\n" + original_options
|
2014-06-30 22:58:04 -04:00
|
|
|
match = example_re.match(txt)
|
|
|
|
if match:
|
|
|
|
examples = match.group(1)
|
|
|
|
match = history_re.match(txt)
|
|
|
|
if match:
|
|
|
|
history = match.group(1).strip()
|
2014-09-30 04:43:28 -04:00
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
usage = ""
|
|
|
|
usage_description = ""
|
|
|
|
params = {}
|
|
|
|
key_params = {}
|
2014-09-30 04:43:28 -04:00
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
try:
|
2014-09-30 04:43:28 -04:00
|
|
|
help_string = subprocess.check_output(
|
|
|
|
"".join((docker_cmd, " ", command, " --help")),
|
|
|
|
stderr=subprocess.STDOUT,
|
|
|
|
shell=True
|
|
|
|
)
|
2014-06-30 22:58:04 -04:00
|
|
|
except subprocess.CalledProcessError, e:
|
2014-09-30 04:43:28 -04:00
|
|
|
help_string = e.output
|
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
last_key = ""
|
2014-11-28 07:36:27 -05:00
|
|
|
for l in str(help_string).split("\n"):
|
2014-06-30 22:58:04 -04:00
|
|
|
l = l.rstrip()
|
|
|
|
if l != "":
|
2014-09-30 04:43:28 -04:00
|
|
|
match = re.match("Usage: docker {}(.*)".format(command), l)
|
2014-06-30 22:58:04 -04:00
|
|
|
if match:
|
|
|
|
usage = match.group(1).strip()
|
|
|
|
else:
|
|
|
|
match = re.match(" (-+)(.*) \s+(.*)", l)
|
|
|
|
if match:
|
|
|
|
last_key = match.group(2).rstrip()
|
|
|
|
key_params[last_key] = match.group(1)+last_key
|
|
|
|
params[last_key] = match.group(3)
|
|
|
|
else:
|
|
|
|
if last_key != "":
|
2014-09-30 04:43:28 -04:00
|
|
|
params[last_key] = "{}\n{}".format(params[last_key], l)
|
2014-06-30 22:58:04 -04:00
|
|
|
else:
|
|
|
|
if usage_description != "":
|
|
|
|
usage_description = usage_description + "\n"
|
|
|
|
usage_description = usage_description + l
|
2014-09-30 04:43:28 -04:00
|
|
|
|
|
|
|
# replace [OPTIONS] with the list of params
|
2014-06-30 22:58:04 -04:00
|
|
|
options = ""
|
2014-11-27 23:21:55 -05:00
|
|
|
match = re.match("\[OPTIONS\]\s*(.*)", usage)
|
2014-06-30 22:58:04 -04:00
|
|
|
if match:
|
|
|
|
usage = match.group(1)
|
|
|
|
|
|
|
|
new_usage = ""
|
|
|
|
# TODO: sort without the `-`'s
|
|
|
|
for key in sorted(params.keys(), key=lambda s: s.lower()):
|
|
|
|
# split on commas, remove --?.*=.*, put in *'s mumble
|
2014-11-27 23:21:55 -05:00
|
|
|
flags = []
|
2014-06-30 22:58:04 -04:00
|
|
|
ps = []
|
|
|
|
opts = []
|
|
|
|
for k in key_params[key].split(","):
|
|
|
|
match = re.match("(-+)([A-Za-z-0-9]*)(?:=(.*))?", k.lstrip())
|
|
|
|
if match:
|
2014-11-27 23:21:55 -05:00
|
|
|
flags.append("{}{}".format(match.group(1), match.group(2)))
|
2014-09-30 04:43:28 -04:00
|
|
|
p = "**{}{}**".format(match.group(1), match.group(2))
|
|
|
|
o = "**{}{}**".format(match.group(1), match.group(2))
|
2014-06-30 22:58:04 -04:00
|
|
|
if match.group(3):
|
|
|
|
val = match.group(3)
|
|
|
|
if val == "\"\"":
|
|
|
|
val = match.group(2).upper()
|
2014-09-30 04:43:28 -04:00
|
|
|
p = "{}[=*{}*]".format(p, val)
|
2014-06-30 22:58:04 -04:00
|
|
|
val = match.group(3)
|
|
|
|
if val in ("true", "false"):
|
|
|
|
params[key] = params[key].rstrip()
|
|
|
|
if not params[key].endswith('.'):
|
|
|
|
params[key] = params[key]+ "."
|
2014-09-30 04:43:28 -04:00
|
|
|
params[key] = "{} The default is *{}*.".format(params[key], val)
|
2014-06-30 22:58:04 -04:00
|
|
|
val = "*true*|*false*"
|
2014-09-30 04:43:28 -04:00
|
|
|
o = "{}={}".format(o, val)
|
2014-06-30 22:58:04 -04:00
|
|
|
ps.append(p)
|
|
|
|
opts.append(o)
|
|
|
|
else:
|
2014-09-30 04:43:28 -04:00
|
|
|
print "nomatch:{}".format(k)
|
|
|
|
new_usage = "{}\n[{}]".format(new_usage, "|".join(ps))
|
2014-11-27 23:21:55 -05:00
|
|
|
|
2014-09-30 04:43:28 -04:00
|
|
|
options = "{}{}\n {}\n\n".format(options, ", ".join(opts), params[key])
|
2014-11-27 23:21:55 -05:00
|
|
|
|
|
|
|
# look at the original options documentation and if its hand written, add it too.
|
|
|
|
print "SVEN_re: "+flags[0]
|
|
|
|
singleoption_re = re.compile(
|
|
|
|
r".*[\r\n]\*\*"+flags[0]+"\*\*([^\r\n]*)[\r\n]+(.*?)[\r\n](\*\*-|# [A-Z]|\*\*[A-Z]+\*\*).*",
|
|
|
|
#r""+flags[0]+"(.*)(^\*\*-.*)?",
|
|
|
|
re.MULTILINE | re.DOTALL
|
|
|
|
)
|
|
|
|
match = singleoption_re.match(original_options)
|
|
|
|
if match:
|
|
|
|
info = match.group(2).strip()
|
|
|
|
print "MATCHED: " + match.group(1).strip()
|
|
|
|
if info != params[key].strip():
|
|
|
|
#info = re.sub(params[key].strip(), '', info, flags=re.MULTILINE)
|
|
|
|
print "INFO changed: " +info
|
|
|
|
options = "{} {}\n\n".format(options, info.strip())
|
|
|
|
|
2014-06-30 22:58:04 -04:00
|
|
|
if new_usage != "":
|
2014-09-30 04:43:28 -04:00
|
|
|
new_usage = "{}\n".format(new_usage.strip())
|
2014-06-30 22:58:04 -04:00
|
|
|
usage = new_usage + usage
|
2014-09-30 04:43:28 -04:00
|
|
|
|
|
|
|
outtext = open("docs/man/docker-{}.1.md".format(command), "w")
|
2014-06-30 22:58:04 -04:00
|
|
|
outtext.write("""% DOCKER(1) Docker User Manuals
|
|
|
|
% Docker Community
|
|
|
|
% JUNE 2014
|
|
|
|
# NAME
|
|
|
|
""")
|
2014-09-30 04:43:28 -04:00
|
|
|
outtext.write("docker-{} - {}\n\n".format(command, usage_description))
|
|
|
|
outtext.write("# SYNOPSIS\n**docker {}**\n{}\n\n".format(command, usage))
|
2014-06-30 22:58:04 -04:00
|
|
|
if description != "":
|
2014-09-30 04:43:28 -04:00
|
|
|
outtext.write("# DESCRIPTION{}".format(description))
|
2014-06-30 22:58:04 -04:00
|
|
|
if options == "":
|
|
|
|
options = "There are no available options.\n\n"
|
2014-09-30 04:43:28 -04:00
|
|
|
outtext.write("# OPTIONS\n{}".format(options))
|
2014-06-30 22:58:04 -04:00
|
|
|
if examples != "":
|
2014-09-30 04:43:28 -04:00
|
|
|
outtext.write("# EXAMPLES{}".format(examples))
|
2014-06-30 22:58:04 -04:00
|
|
|
outtext.write("# HISTORY\n")
|
|
|
|
if history != "":
|
2014-09-30 04:43:28 -04:00
|
|
|
outtext.write("{}\n".format(history))
|
|
|
|
recent_history_re = re.compile(
|
|
|
|
".*{}.*".format(date_string),
|
|
|
|
re.MULTILINE | re.DOTALL
|
|
|
|
)
|
2014-11-27 23:21:55 -05:00
|
|
|
# if not recent_history_re.match(history):
|
|
|
|
# outtext.write("{}, updated by Sven Dowideit <SvenDowideit@home.org.au>\n".format(date_string))
|
2014-06-30 22:58:04 -04:00
|
|
|
outtext.close()
|
|
|
|
|
|
|
|
# main
|
|
|
|
update_cli_reference()
|
|
|
|
update_man_pages()
|