# This script requires [pyyaml](http://pyyaml.org/wiki/PyYAMLDocumentation). It # also requires all supported VCS to be in PATH so they can be invoked from a # shell # Supported VCS are Subversion, Mercurial # # Installation procedure on Windows: # - Install Python with the Windows installer # - Install Microsoft Visual C++ 2010 Express Edition # - clone PyYAML from Bitbucket repository https://bitbucket.org/xi/pyyaml/src # - open a shell in the PyYAML directory # - run {VC2010++Path}/Common7/Tools/vsvars32.bat in shell # - run `python setup.py install` in *the same* shell import re, yaml, os, sys, xml.dom, tempfile, shutil from xml.dom.minidom import parseString, parse from subprocess import Popen, PIPE def stop(n): if n > 0 and not 'PROMPT' in os.environ: print("Hit ENTER to continue") input() sys.exit(n) def cmd(command): p = Popen(command, 0, None, None, PIPE, PIPE) p.wait() return p # ========= Fetchers ========= def fetch_svn(key, type, url, tag): rev = "HEAD" if not tag == False: # get repo url p = cmd(['svn','info','--xml', url]) dom = parse(p.stdout) try: repourl = dom.getElementsByTagName("root")[0].firstChild.nodeValue except Exception as e: raise Exception("Could not retrieve repository information", url) if tag == "latest": # get latest tag revision p = cmd(['svn','log',"--limit=1","--xml","-q",repourl+"/tags"]) try: dom = parse(p.stdout) rev = dom.getElementsByTagName("logentry")[0].attributes["revision"].nodeValue except Exception as e: wait = 1 print("Warning: This repository seems to have no tags! Using HEAD revision instead.") print("- Given URL", url) print("- /tags URL", repourl+"/tags/latest") else: # get revision of supplied tag p = cmd(['svn','info',"--xml",repourl+"/tags/"+tag]) try: if p.returncode != 0: raise Exception("Svn info error", p.returncode) dom = parse(p.stdout) rev = dom.getElementsByTagName("commit")[0].attributes["revision"].nodeValue except Exception as e: wait = 1 print("Warning: Tag not found! Using HEAD revision instead.") print("- Given URL", url) print("- /tags URL", repourl+"/tags/"+tag) p = cmd(['svn','co',url,key,"-r",rev]) return p.returncode == 0 def fetch_hg(key, type, url, tag): if tag == False: tag = "tip" elif tag == "latest": # find latest tag p = cmd(['hg','parents','-y','--template',"{latesttag}","-R",url]) tag = p.stdout.readall().decode(sys.stdout.encoding) print(tag) if not tag or tag == "null": print("Warning: No Tags were found! Using 'tip' instead.") wait = 1 tag = "tip" p = cmd(['hg','clone','-Uqy',url,key]) if p.returncode != 0: raise Exception("Error cloning repository", key, url) p = cmd(['hg','update','-y','-r',tag,'-R',key]) if p.returncode != 0: print("Warning: Could not update to selected tag '"+tag+"'! Using 'tip' instead.") wait = 1 p = cmd(['hg','update','-y','-r','tip','-R',key]) if p.returncode != 0: raise Exception("Error updating repository", key, url) return p.returncode == 0 Fetchers = { 'subversion' : fetch_svn, 'svn' : fetch_svn, 'mercurial' : fetch_hg, 'hg' : fetch_hg, } # ========= Testers ========= def test_svn(url): p = cmd(['svn','info','--non-interactive',url]) return p.returncode == 0 def test_hg(url): # create temporary directory tmpdir = tempfile.mkdtemp('', 'fetchlibs-') p = cmd(['hg','clone','-Uy','-r0',url,tmpdir]) shutil.rmtree(tmpdir) return p.returncode == 0 Testers = { 'mercurial' : test_hg, 'subversion': test_svn, } wait = 0 try: stream = open(".pkgmeta", 'r') doc = yaml.load(stream) except Exception as e: print(e) stop(1) if 'externals' in doc: externals = doc['externals']; for key in externals: external = externals[key] key = os.path.relpath(key) url = external['url'] tag = False type = False if 'tag' in external: tag = external['tag'] if os.path.exists(key): print("Directory already exists, remove it to fetch the library again") print("-", key) wait = 1 continue if 'type' in external: type = external['type'] # try to detect repository type by URL protocol if type == False: if re.match("^svn:", url): type = 'subversion' elif re.match("^git:", url): type = 'git' # detect repository type by probing if type == False: print("Probing url to detect repository type of", url) for test in Testers: print("- probing for", test) if Testers[test](url): print("- Detected", test) type = test break if type in Fetchers: try: Fetchers[type](key, type, url, tag) except Exception as e: wait = 1 print("Error fetching",key,":\n-",e) raise e else: print("Unknown or unsupported VCS:", type, url) print("The script also does not yet support challenge-response authentication, sorry!") wait = 1 continue stop(wait)