| OLD | NEW | 
|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python | 
| 2 # coding: utf-8 | 2 # coding: utf-8 | 
| 3 | 3 | 
| 4 # This file is part of the Adblock Plus build tools, | 4 # This file is part of the Adblock Plus build tools, | 
| 5 # Copyright (C) 2006-2014 Eyeo GmbH | 5 # Copyright (C) 2006-2014 Eyeo GmbH | 
| 6 # | 6 # | 
| 7 # Adblock Plus is free software: you can redistribute it and/or modify | 7 # Adblock Plus is free software: you can redistribute it and/or modify | 
| 8 # it under the terms of the GNU General Public License version 3 as | 8 # it under the terms of the GNU General Public License version 3 as | 
| 9 # published by the Free Software Foundation. | 9 # published by the Free Software Foundation. | 
| 10 # | 10 # | 
| 11 # Adblock Plus is distributed in the hope that it will be useful, | 11 # Adblock Plus is distributed in the hope that it will be useful, | 
| 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 14 # GNU General Public License for more details. | 14 # GNU General Public License for more details. | 
| 15 # | 15 # | 
| 16 # You should have received a copy of the GNU General Public License | 16 # You should have received a copy of the GNU General Public License | 
| 17 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 17 # along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 18 | 18 | 
| 19 import sys | 19 import sys | 
| 20 import os | 20 import os | 
| 21 import posixpath | 21 import posixpath | 
| 22 import re | 22 import re | 
| 23 import io | 23 import io | 
| 24 import errno | 24 import errno | 
| 25 import logging | 25 import logging | 
| 26 import subprocess | 26 import subprocess | 
| 27 import urlparse | 27 import urlparse | 
|  | 28 | 
| 28 from collections import OrderedDict | 29 from collections import OrderedDict | 
|  | 30 from ConfigParser import RawConfigParser | 
| 29 | 31 | 
| 30 USAGE = """ | 32 USAGE = """ | 
| 31 A dependencies file should look like this: | 33 A dependencies file should look like this: | 
| 32 | 34 | 
| 33   # VCS-specific root URLs for the repositories | 35   # VCS-specific root URLs for the repositories | 
| 34   _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/ | 36   _root = hg:https://hg.adblockplus.org/ git:https://github.com/adblockplus/ | 
| 35   # File to update this script from (optional) | 37   # File to update this script from (optional) | 
| 36   _self = buildtools/ensure_dependencies.py | 38   _self = buildtools/ensure_dependencies.py | 
| 37   # Check out elemhidehelper repository into extensions/elemhidehelper directory | 39   # Check out elemhidehelper repository into extensions/elemhidehelper directory | 
| 38   # at tag "1.2". | 40   # at tag "1.2". | 
| 39   extensions/elemhidehelper = elemhidehelper 1.2 | 41   extensions/elemhidehelper = elemhidehelper 1.2 | 
| 40   # Check out buildtools repository into buildtools directory at VCS-specific | 42   # Check out buildtools repository into buildtools directory at VCS-specific | 
| 41   # revision IDs. | 43   # revision IDs. | 
| 42   buildtools = buildtools hg:016d16f7137b git:f3f8692f82e5 | 44   buildtools = buildtools hg:016d16f7137b git:f3f8692f82e5 | 
| 43 """ | 45 """ | 
| 44 | 46 | 
| 45 class Mercurial(): | 47 class SCM(object): | 
|  | 48   def _ignore(self, target, file_name): | 
|  | 49     with open(file_name, 'a+') as f: | 
|  | 50       file_content = [l.strip() for l in f.readlines()] | 
|  | 51       if not target in file_content: | 
|  | 52         if len(file_content): | 
|  | 53           f.seek(-1, os.SEEK_CUR) | 
|  | 54           last_character = f.read(1) | 
|  | 55           if not last_character in "\r\n": | 
|  | 56             f.write(os.linesep) | 
|  | 57         f.write(target) | 
|  | 58         f.write(os.linesep) | 
|  | 59 | 
|  | 60 class Mercurial(SCM): | 
| 46   def istype(self, repodir): | 61   def istype(self, repodir): | 
| 47     return os.path.exists(os.path.join(repodir, ".hg")) | 62     return os.path.exists(os.path.join(repodir, ".hg")) | 
| 48 | 63 | 
| 49   def clone(self, source, target): | 64   def clone(self, source, target): | 
| 50     if not source.endswith("/"): | 65     if not source.endswith("/"): | 
| 51       source += "/" | 66       source += "/" | 
| 52     subprocess.check_call(["hg", "clone", "--quiet", "--noupdate", source, targe
     t]) | 67     subprocess.check_call(["hg", "clone", "--quiet", "--noupdate", source, targe
     t]) | 
| 53 | 68 | 
| 54   def get_revision_id(self, repo, rev=None): | 69   def get_revision_id(self, repo, rev=None): | 
| 55     command = ["hg", "id", "--repository", repo, "--id"] | 70     command = ["hg", "id", "--repository", repo, "--id"] | 
| 56     if rev: | 71     if rev: | 
| 57       command.extend(["--rev", rev]) | 72       command.extend(["--rev", rev]) | 
| 58 | 73 | 
| 59     # Ignore stderr output and return code here: if revision lookup failed we | 74     # Ignore stderr output and return code here: if revision lookup failed we | 
| 60     # should simply return an empty string. | 75     # should simply return an empty string. | 
| 61     result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess
     .PIPE).communicate()[0] | 76     result = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess
     .PIPE).communicate()[0] | 
| 62     return result.strip() | 77     return result.strip() | 
| 63 | 78 | 
| 64   def pull(self, repo): | 79   def pull(self, repo): | 
| 65     subprocess.check_call(["hg", "pull", "--repository", repo, "--quiet"]) | 80     subprocess.check_call(["hg", "pull", "--repository", repo, "--quiet"]) | 
| 66 | 81 | 
| 67   def update(self, repo, rev): | 82   def update(self, repo, rev): | 
| 68     subprocess.check_call(["hg", "update", "--repository", repo, "--quiet", "--c
     heck", "--rev", rev]) | 83     subprocess.check_call(["hg", "update", "--repository", repo, "--quiet", "--c
     heck", "--rev", rev]) | 
| 69 | 84 | 
| 70 class Git(): | 85   def ignore(self, target, repo): | 
|  | 86 | 
|  | 87     if not self.istype(target): | 
|  | 88 | 
|  | 89       config_path = os.path.join(repo, ".hg", "hgrc") | 
|  | 90       ignore_path = os.path.join(".", ".hg", "dependencies") | 
|  | 91 | 
|  | 92       config = RawConfigParser() | 
|  | 93       config.read(config_path) | 
|  | 94 | 
|  | 95       if not config.has_section("ui"): | 
|  | 96         config.add_section("ui") | 
|  | 97 | 
|  | 98       if not config.has_option("ui", "ignore.dependencies"): | 
|  | 99         config.set("ui", "ignore.dependencies", ignore_path) | 
|  | 100         with open(config_path, "w") as stream: | 
|  | 101           config.write(stream) | 
|  | 102       else: | 
|  | 103         ignore_path = config.get("ui", "ignore.dependencies") | 
|  | 104 | 
|  | 105       module = os.path.relpath(target, repo) | 
|  | 106       self._ignore(module, ignore_path) | 
|  | 107 | 
|  | 108 class Git(SCM): | 
| 71   def istype(self, repodir): | 109   def istype(self, repodir): | 
| 72     return os.path.exists(os.path.join(repodir, ".git")) | 110     return os.path.exists(os.path.join(repodir, ".git")) | 
| 73 | 111 | 
| 74   def clone(self, source, target): | 112   def clone(self, source, target): | 
| 75     source = source.rstrip("/") | 113     source = source.rstrip("/") | 
| 76     if not source.endswith(".git"): | 114     if not source.endswith(".git"): | 
| 77       source += ".git" | 115       source += ".git" | 
| 78     subprocess.check_call(["git", "clone", "--quiet", source, target]) | 116     subprocess.check_call(["git", "clone", "--quiet", source, target]) | 
| 79 | 117 | 
| 80   def get_revision_id(self, repo, rev="HEAD"): | 118   def get_revision_id(self, repo, rev="HEAD"): | 
| 81     command = ["git", "rev-parse", "--revs-only", rev] | 119     command = ["git", "rev-parse", "--revs-only", rev] | 
| 82     return subprocess.check_output(command, cwd=repo).strip() | 120     return subprocess.check_output(command, cwd=repo).strip() | 
| 83 | 121 | 
| 84   def pull(self, repo): | 122   def pull(self, repo): | 
| 85     subprocess.check_call(["git", "fetch", "--quiet", "--all", "--tags"], cwd=re
     po) | 123     subprocess.check_call(["git", "fetch", "--quiet", "--all", "--tags"], cwd=re
     po) | 
| 86 | 124 | 
| 87   def update(self, repo, rev): | 125   def update(self, repo, rev): | 
| 88     subprocess.check_call(["git", "checkout", "--quiet", rev], cwd=repo) | 126     subprocess.check_call(["git", "checkout", "--quiet", rev], cwd=repo) | 
| 89 | 127 | 
|  | 128   def ignore(self, target, repo): | 
|  | 129     module = os.path.relpath(target, repo) | 
|  | 130     exclude_file = os.path.join(repo, ".git", "info", "exclude") | 
|  | 131     self._ignore(module, exclude_file) | 
|  | 132 | 
| 90 repo_types = { | 133 repo_types = { | 
| 91   "hg": Mercurial(), | 134   "hg": Mercurial(), | 
| 92   "git": Git(), | 135   "git": Git(), | 
| 93 } | 136 } | 
| 94 | 137 | 
| 95 def parse_spec(path, line): | 138 def parse_spec(path, line): | 
| 96   if "=" not in line: | 139   if "=" not in line: | 
| 97     logging.warning("Invalid line in file %s: %s" % (path, line)) | 140     logging.warning("Invalid line in file %s: %s" % (path, line)) | 
| 98     return None, None | 141     return None, None | 
| 99 | 142 | 
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 154 | 197 | 
| 155 def get_repo_type(repo): | 198 def get_repo_type(repo): | 
| 156   for name, repotype in repo_types.iteritems(): | 199   for name, repotype in repo_types.iteritems(): | 
| 157     if repotype.istype(repo): | 200     if repotype.istype(repo): | 
| 158       return name | 201       return name | 
| 159   return None | 202   return None | 
| 160 | 203 | 
| 161 def ensure_repo(parentrepo, target, roots, sourcename): | 204 def ensure_repo(parentrepo, target, roots, sourcename): | 
| 162   if os.path.exists(target): | 205   if os.path.exists(target): | 
| 163     return | 206     return | 
| 164 |  | 
| 165   parenttype = get_repo_type(parentrepo) | 207   parenttype = get_repo_type(parentrepo) | 
| 166   type = None | 208   type = None | 
| 167   for key in roots: | 209   for key in roots: | 
| 168     if key == parenttype or (key in repo_types and type is None): | 210     if key == parenttype or (key in repo_types and type is None): | 
| 169       type = key | 211       type = key | 
| 170   if type is None: | 212   if type is None: | 
| 171     raise Exception("No valid source found to create %s" % target) | 213     raise Exception("No valid source found to create %s" % target) | 
| 172 | 214 | 
| 173   url = urlparse.urljoin(roots[type], sourcename) | 215   url = urlparse.urljoin(roots[type], sourcename) | 
| 174   logging.info("Cloning repository %s into %s" % (url, target)) | 216   logging.info("Cloning repository %s into %s" % (url, target)) | 
| 175   repo_types[type].clone(url, target) | 217   repo_types[type].clone(url, target) | 
| 176 | 218 | 
|  | 219   for repo in repo_types.itervalues(): | 
|  | 220     if repo.istype(parentrepo): | 
|  | 221       repo.ignore(target, parentrepo) | 
|  | 222 | 
| 177 def update_repo(target, revisions): | 223 def update_repo(target, revisions): | 
| 178   type = get_repo_type(target) | 224   type = get_repo_type(target) | 
| 179   if type is None: | 225   if type is None: | 
| 180     logging.warning("Type of repository %s unknown, skipping update" % target) | 226     logging.warning("Type of repository %s unknown, skipping update" % target) | 
| 181     return | 227     return | 
| 182 | 228 | 
| 183   if type in revisions: | 229   if type in revisions: | 
| 184     revision = revisions[type] | 230     revision = revisions[type] | 
| 185   elif "*" in revisions: | 231   elif "*" in revisions: | 
| 186     revision = revisions["*"] | 232     revision = revisions["*"] | 
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 246       else: | 292       else: | 
| 247         logging.warning("Cannot restart %s automatically, please rerun" % target
     ) | 293         logging.warning("Cannot restart %s automatically, please rerun" % target
     ) | 
| 248 | 294 | 
| 249 if __name__ == "__main__": | 295 if __name__ == "__main__": | 
| 250   logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) | 296   logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) | 
| 251   repos = sys.argv[1:] | 297   repos = sys.argv[1:] | 
| 252   if not len(repos): | 298   if not len(repos): | 
| 253     repos = [os.getcwd()] | 299     repos = [os.getcwd()] | 
| 254   for repo in repos: | 300   for repo in repos: | 
| 255     resolve_deps(repo) | 301     resolve_deps(repo) | 
| OLD | NEW | 
|---|