$search
00001 # Software License Agreement (BSD License) 00002 # 00003 # Copyright (c) 2010, Willow Garage, Inc. 00004 # All rights reserved. 00005 # 00006 # Redistribution and use in source and binary forms, with or without 00007 # modification, are permitted provided that the following conditions 00008 # are met: 00009 # 00010 # * Redistributions of source code must retain the above copyright 00011 # notice, this list of conditions and the following disclaimer. 00012 # * Redistributions in binary form must reproduce the above 00013 # copyright notice, this list of conditions and the following 00014 # disclaimer in the documentation and/or other materials provided 00015 # with the distribution. 00016 # * Neither the name of Willow Garage, Inc. nor the names of its 00017 # contributors may be used to endorse or promote products derived 00018 # from this software without specific prior written permission. 00019 # 00020 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00021 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00022 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 00023 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 00024 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 00025 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 00026 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 00027 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00028 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 00030 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00031 # POSSIBILITY OF SUCH DAMAGE. 00032 # 00033 # Revision $Id: generate_megamanifest.py 12303 2010-11-23 16:43:34Z kwc $ 00034 00035 import os 00036 import sys 00037 import traceback 00038 import yaml 00039 00040 import types 00041 00042 import rospkg 00043 00044 from subprocess import call, check_call, Popen 00045 from xml.dom.minidom import getDOMImplementation, parse, _write_data, Node 00046 00047 from .repo_util import guess_vcs_uri, get_svn_url 00048 00049 00050 # hack to attempt to hotpatch minidom bug http://www.velocityreviews.com/forums/t325107-minidom-questions.html 00051 def _override_write_data(writer, data): 00052 "Writes datachars to writer." 00053 if data is None: 00054 return 00055 data = data.replace("&", "&").replace("<", "<") 00056 data = data.replace("\"", """).replace(">", ">") 00057 writer.write(data) 00058 00059 #xml.dom.minidom._write_data = _override_write_data 00060 00061 #writexml from minidom Element 00062 def _Element__writexml(self, writer, indent="", addindent="", newl=""): 00063 # indent = current indentation 00064 # addindent = indentation to add to higher levels 00065 # newl = newline string 00066 writer.write(indent+"<" + self.tagName) 00067 00068 attrs = self._get_attributes() 00069 a_names = attrs.keys() 00070 a_names.sort() 00071 00072 for a_name in a_names: 00073 writer.write(" %s=\"" % a_name) 00074 v = attrs[a_name].value 00075 if v is None: 00076 v = "" 00077 _write_data(writer, v) 00078 writer.write("\"") 00079 if self.childNodes: 00080 writer.write(">%s"%(newl)) 00081 for node in self.childNodes: 00082 #hotpatch recursively with this method 00083 if node.nodeType == Node.ELEMENT_NODE: 00084 node.writexml = types.MethodType(_Element__writexml, node) 00085 #if node.nodeType == Node.TEXT_NODE: 00086 node.writexml(writer,indent+addindent,addindent,newl) 00087 writer.write("%s</%s>%s" % (indent,self.tagName,newl)) 00088 else: 00089 writer.write("/>%s"%(newl)) 00090 00091 00092 def generate_megamanifest(ctx, repos, checkouts_dir): 00093 all_pkgs = { } 00094 for repo_name, repo in repos: 00095 name = repo_name 00096 vcs = repo.type 00097 uri = repo.uri 00098 00099 assert uri, "repo [%s] has invalid uri [%s]"%(repo_name, uri) 00100 00101 print "snarfing manifests in local copy of %s"%name 00102 # workaround for ros aliasing 00103 if repo_name == 'ros': 00104 rel_path = os.path.join(checkouts_dir, 'ros-repo') 00105 else: 00106 rel_path = os.path.join(checkouts_dir, repo_name) 00107 00108 abs_co_path = os.path.abspath(rel_path) 00109 # cache paths into repo_pkgs 00110 repos_pkgs = {} 00111 00112 for pkg in rospkg.list_by_path('manifest.xml', rel_path, cache=repos_pkgs): 00113 if pkg not in all_pkgs: 00114 # de-resolve externals #2456. This logic assumes that the 00115 # vcs is SVN and that they URLs are consistently 00116 # specified. It will probably take a lot more logic to get 00117 # this perfectly right 00118 override_path = None 00119 true_uri = uri 00120 try: 00121 pkg_path = repos_pkgs[pkg] 00122 if vcs == 'svn': 00123 vcs0, true_uri = guess_vcs_uri(pkg_path) 00124 # rel_path is incorrect if true_uri doesn't 00125 # match. recompute rel_path by getting URL of package 00126 # and slicing. 00127 if true_uri is None: 00128 print >> sys.stderr, "unable to guess VCS URI of [%s]"%(pkg_path) 00129 elif true_uri != uri: 00130 url_path = get_svn_url(pkg_path) 00131 override_path = url_path[len(true_uri):] 00132 else: 00133 # list_pkgs_by_path converts paths to abspath to avoid some path bugs. 00134 # this requires us to always override. 00135 # In the future, the format should just assume absolute URLs instead of composing URLs 00136 pkg_path = os.path.abspath(pkg_path) 00137 override_path = pkg_path[len(abs_co_path):] 00138 else: 00139 #DVCS systems don't allow URL sub-indexing 00140 override_path = '' 00141 if vcs == 'git': 00142 # give the package the uri of its submodule, if appropriate 00143 vcs1, true_uri = guess_vcs_uri(pkg_path) 00144 if 'github.com/' in uri and uri.endswith('.git'): 00145 true_uri = uri[:-4] 00146 except: 00147 traceback.print_exc() 00148 pass 00149 all_pkgs[pkg] = [pkg, name, true_uri, pkg_path, override_path] 00150 00151 pkgs_dom = getDOMImplementation().createDocument(None, 'pkgs', None) 00152 pkgs_node = pkgs_dom.documentElement 00153 00154 mega_yaml = [] 00155 00156 for k, v in all_pkgs.iteritems(): 00157 pkg, repo, uri, rel_path, override_path = v 00158 assert (rel_path and rel_path != os.sep), "Relative path calculation is messed up, package is [%s]"%(pkg) 00159 00160 manifest_p = rel_path+os.sep+'manifest.xml' 00161 try: 00162 manifest = parse(manifest_p) 00163 try: 00164 m_obj = ctx.manifests[pkg] 00165 mega_yaml.append({'name': pkg, 'brief': m_obj.brief, 'description': m_obj.description or '', 'repo': repo}) 00166 except KeyError: 00167 print >> sys.stderr, "no manifest for [%s]"%(pkg) 00168 00169 manifest_node = manifest.documentElement 00170 manifest_node.setAttribute("name", k) 00171 manifest_node.setAttribute("repo", repo) 00172 manifest_node.setAttribute("repo_host", uri) 00173 #TODO: change all this just to use absolute URLs. rel-path generation is too unstable 00174 base_rel_path = os.path.join(checkouts_dir, name) 00175 rel_path = rel_path[len(base_rel_path):] 00176 if override_path is not None: 00177 manifest_node.setAttribute("path", override_path) 00178 else: 00179 manifest_node.setAttribute("path", rel_path) 00180 00181 if manifest_node is None: 00182 print >> sys.stderr, "manifest_node empty", pkg, repo, uri, rel_path, override_path 00183 else: 00184 pkgs_node.appendChild(manifest_node) 00185 except Exception as e: 00186 print "error parsing %s [%s]: %s"%(pkg, manifest_p, str(e)) 00187 00188 print "writing megamanifest..." 00189 try: 00190 os.makedirs(ctx.docdir) 00191 except: 00192 pass 00193 fname = os.path.join(ctx.docdir, 'megamanifest.xml') 00194 with open(fname, 'w') as f: 00195 print "pkgs_node is ", pkgs_node 00196 #pkgs_node.writexml = ___writexml 00197 if pkgs_node.nodeType == Node.ELEMENT_NODE: 00198 pkgs_node.writexml = types.MethodType(_Element__writexml, pkgs_node) 00199 else: 00200 print "OTHER NODE TYPE", pkgs_node.nodeType 00201 print "successfully changed method" 00202 text = pkgs_node.toxml(encoding='utf-8') 00203 print "text is", text 00204 f.write(text) 00205 00206 fname2 = os.path.join(ctx.docdir, 'megamanifest.yaml') 00207 with open(fname2, 'w') as f: 00208 f.write(yaml.safe_dump(mega_yaml, default_style="'")) 00209 00210 return [fname, fname2]