blob: 7feb72e05befd458dc21ea2b22b3a2817a9adc9d [file] [log] [blame]
#!/usr/bin/env python
#
# Copyright 2008 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
"""drtool is for moving your wiki documents between googlecode projects.
drtool actually does three things:
- copy all of your wiki documentation between googlecode projects. This is
done via the "copy" command. References to a project will be changed during
the move.
- tell you what wiki pages are not referenced by your docreader-enabled
TableOfContents page. Use "nothave" or "orphans" or "list-orphans" for
this.
- find all of the http references to your subversion repository in your wiki
docs. "references" or "refs".
It's assumed that you have svn checkouts of both projects.
"""
import sys
import shutil
import re
import os.path
import glob
import TOCNode
from BuildGlobalTOC import BuildTOC
NOTHAVE = ["nothave", "orphans", "list-orphans"]
REFERENCES = ["references", "refs"]
COPY = ["copy"]
wikipatterns = {}
svnpatterns = {}
def getpattern(table, template, projectname):
if table.has_key(projectname):
return table[projectname]
else:
pattern = (template % projectname)
compiled = re.compile(pattern)
table[projectname] = compiled
return compiled
def wikipattern(projectname):
return getpattern(wikipatterns,
"http://code.google.com/p/(%s)/wiki/([^\s\]]+)",
projectname)
def svnpattern(projectname):
return getpattern(svnpatterns,
"http://(%s).googlecode.com([^\s\]]+)",
projectname)
def change_ref(link, oldproject, newproject):
return link.replace(oldproject, newproject)
def change_references(bytes, oldprojectname, newprojectname):
"""Returns the string that is the new text for the wiki page, with all
of the references changed to point to the new project."""
svn = svnpattern(oldprojectname)
wiki = wikipattern(oldprojectname)
postsvn = ""
postwiki = ""
## step one, do all the svn references.
svnreferences = re.finditer(svn, bytes)
append_start = 0
for match in svnreferences:
matchstart, matchend = match.span()
## take all of the stuff from the end of the last match to the beginning
## of this one and append it to the output.
postsvn += bytes[append_start:matchstart]
## append the version of this match with the project names replaced
postsvn += change_ref(match.group(0), oldprojectname, newprojectname)
append_start = matchend
postsvn += bytes[append_start:]
## step two, do all the wiki references (should be rarer?)
wikireferences = re.finditer(wiki, postsvn)
append_start = 0
for match in wikireferences:
matchstart, matchend = match.span()
## take all of the stuff from the end of the last match to the beginning
## of this one and append it to the output.
postwiki += postsvn[append_start:matchstart]
## append the version of this match with the project names replaced
postwiki += change_ref(match.group(0),
oldprojectname,
newprojectname)
append_start = matchend
postwiki += postsvn[append_start:]
return postwiki
def find_references(bytes, projectname, fn):
"""Return a list of all the references to a given project in this string"""
def find_refs(pattern):
compiled = re.compile(pattern)
refs = re.findall(compiled, bytes)
return refs
svn = svnpattern(projectname)
wiki = wikipattern(projectname)
return find_refs(svn) + find_refs(wiki)
def print_references(bytes, projectname, fn):
refs = find_references(bytes, projectname, fn)
if refs:
print ("** %s" % fn)
for ref in refs:
print ":::", ref
def usage():
commands = (", ").join(NOTHAVE + REFERENCES + COPY)
print ("usage: %s <cmd> prj1 [prj2]" % sys.argv[0])
print "\tcmd is one of: ", commands
print "\tprj2 is required for 'copy' command"
def copy_into_target(source_project, target_project, source_path,
relative_filename, target_dir):
"""Copy one file into the target directory."""
target_path = os.path.join(target_dir, relative_filename)
if relative_filename.endswith(".wiki"):
infile = open(source_path)
bytes = infile.read()
changed = change_references(bytes, source_project, target_project)
head,tail = os.path.split(target_path)
if not os.path.isdir(head):
os.makedirs(head)
outfile = open(target_path, "w")
outfile.write(changed)
outfile.close()
# print ("%s: changed references, wrote into %s." %
# (relative_filename, target_project) )
else:
shutil.copyfile(source_path, target_path)
# print ("%s: not a wiki file, copied into the new %s" %
# (relative_filename, target_project))
pass
def find_wikipath(target):
normalized = os.path.normpath(target)
if not normalized.endswith("/wiki"):
normalized += "/wiki"
return normalized
def all_wiki_docs(wikipath):
"""All of the .wiki files in our wiki directory, with paths, recursively."""
out = []
for root, dirs, fileshere in os.walk(wikipath):
path_elements = root.split(os.sep)
if ".svn" in path_elements:
continue
for fn in fileshere:
if fn.endswith(".wiki"):
whole_pathname = os.path.join(root, fn)
out.append(whole_pathname)
return out
def nothave(wikipath, projectname):
toc_path = wikipath + os.path.sep + "TableOfContents.wiki"
if not os.path.exists(toc_path):
print "Could not find TableOfContents.wiki for that project."
return
listed = BuildTOC(toc_path, projectname)
all_wiki_pages = all_wiki_docs(wikipath)
## run through every .wiki file (recursively under the wiki directory, and if
## it's not mentioned in the TOC, print it out.
for wikipage in all_wiki_pages:
basename = os.path.basename(wikipage)
wikiword = basename[:-5]
node = TOCNode.lookup(wikiword)
if not node:
print " ", wikipage
def file_references(fn, projectname):
infile = open(fn)
bytes = infile.read()
print_references(bytes, projectname, fn)
def references(wikipath, projectname):
wikipaths = all_wiki_docs(wikipath)
for wikipath in wikipaths:
file_references(wikipath, projectname)
def wikicopy(source_dir, source_project, target_dir, target_project):
print "Copying from", source_project,
print "to", target_project, "and changing references...",
## Walk every file in source_dir. Skip .svn directories.
for root, dirs, fileshere in os.walk(source_dir):
path_elements = root.split(os.sep)
if ".svn" in path_elements:
continue
for filename in fileshere:
## Find the part of the path after source_dir
whole_pathname = os.path.join(root, filename)
after_source_dir = whole_pathname[len(source_dir):]
if after_source_dir.startswith("/"):
after_source_dir = after_source_dir[1:]
copy_into_target(source_project, target_project, whole_pathname,
after_source_dir, target_dir)
print "OK!"
## Warn about wiki pages that are not referenced by TOC.
print "Careful: these wiki pages aren't referenced in your TableOfContents:"
nothave(source_dir, source_project)
print "Done."
def main(argv):
if len(argv) < 3:
usage()
return
source_dir = find_wikipath(argv[2])
source_projectname = source_dir.split(os.path.sep)[-2]
if len(argv) > 3:
target_dir = find_wikipath(argv[3])
target_projectname = target_dir.split(os.path.sep)[-2]
if argv[1] in NOTHAVE:
nothave(source_dir, source_projectname)
elif argv[1] in REFERENCES:
references(source_dir, source_projectname)
elif argv[1] in COPY:
if not target_dir:
usage()
return
wikicopy(source_dir, source_projectname, target_dir, target_projectname)
if __name__ == '__main__':
main(sys.argv)