| #!/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) |