Morpheus / Mbed OS mbed-Client-Morpheus-hg

Dependencies:   mbed-os

Committer:
screamer
Date:
Fri Apr 01 15:03:53 2016 +0100
Revision:
75:081959a31b02
Parent:
74:09b1f16aea24
Child:
77:46124d75dae7
Ignores for Mercurial (.hg/hgignore)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Christopher Haster 15:a6b1f4e65bf4 1 #!/usr/bin/env python
Christopher Haster 15:a6b1f4e65bf4 2
Christopher Haster 15:a6b1f4e65bf4 3 import argparse
Christopher Haster 15:a6b1f4e65bf4 4 import sys
Christopher Haster 15:a6b1f4e65bf4 5 import re
Christopher Haster 15:a6b1f4e65bf4 6 import subprocess
Christopher Haster 15:a6b1f4e65bf4 7 import os
Christopher Haster 15:a6b1f4e65bf4 8 import contextlib
Christopher Haster 15:a6b1f4e65bf4 9 import shutil
Christopher Haster 35:ffcfa5ace437 10 from collections import *
Christopher Haster 15:a6b1f4e65bf4 11 from itertools import *
Christopher Haster 15:a6b1f4e65bf4 12
screamer 47:386f8c519142 13 # Default paths to Mercurial and Git
Christopher Haster 50:3770a8991c11 14 hg_cmd = 'hg'
Christopher Haster 50:3770a8991c11 15 git_cmd = 'git'
screamer 47:386f8c519142 16
Christopher Haster 15:a6b1f4e65bf4 17 # Subparser handling
Christopher Haster 15:a6b1f4e65bf4 18 parser = argparse.ArgumentParser()
Christopher Haster 15:a6b1f4e65bf4 19 subparsers = parser.add_subparsers()
Christopher Haster 15:a6b1f4e65bf4 20
screamer 75:081959a31b02 21 hg_ignore = """
screamer 75:081959a31b02 22 syntax: regexp
screamer 75:081959a31b02 23 \.build$
screamer 75:081959a31b02 24 \.export$
screamer 75:081959a31b02 25 \.git$
screamer 75:081959a31b02 26 \.svn$
screamer 75:081959a31b02 27 \.orig$
screamer 75:081959a31b02 28 \.msub$
screamer 75:081959a31b02 29 \.meta$
screamer 75:081959a31b02 30 \.ctags
screamer 75:081959a31b02 31 \.uvproj$
screamer 75:081959a31b02 32 \.uvopt$
screamer 75:081959a31b02 33 \.project$
screamer 75:081959a31b02 34 \.cproject$
screamer 75:081959a31b02 35 \.launch$
screamer 75:081959a31b02 36 \.project$
screamer 75:081959a31b02 37 \.cproject$
screamer 75:081959a31b02 38 \.launch$
screamer 75:081959a31b02 39 Makefile$
screamer 75:081959a31b02 40 \.ewp$
screamer 75:081959a31b02 41 \.eww$
screamer 75:081959a31b02 42 \.htm$
screamer 75:081959a31b02 43 Debug$
screamer 75:081959a31b02 44 .settings$
screamer 75:081959a31b02 45 """
screamer 75:081959a31b02 46
screamer 70:e6f7587c6562 47 def message(msg):
screamer 70:e6f7587c6562 48 return "["+os.path.basename(sys.argv[0])+"] "+msg+"\n"
screamer 70:e6f7587c6562 49
screamer 63:3b00ba456e00 50 def log(msg):
screamer 70:e6f7587c6562 51 sys.stderr.write(message(msg))
screamer 70:e6f7587c6562 52
screamer 70:e6f7587c6562 53 def action(msg):
screamer 70:e6f7587c6562 54 sys.stderr.write("---\n"+message(msg))
screamer 63:3b00ba456e00 55
screamer 63:3b00ba456e00 56 def error(msg, code):
screamer 70:e6f7587c6562 57 sys.stderr.write("---\n["+os.path.basename(sys.argv[0])+" ERROR] "+msg+"\n---\n")
screamer 63:3b00ba456e00 58 sys.exit(code)
screamer 70:e6f7587c6562 59
screamer 70:e6f7587c6562 60 def repo_or_die():
screamer 70:e6f7587c6562 61 repo = Repo.fromrepo()
screamer 70:e6f7587c6562 62 if repo.scm is None:
screamer 70:e6f7587c6562 63 error("Current folder is not a repository", -1)
screamer 70:e6f7587c6562 64
Christopher Haster 15:a6b1f4e65bf4 65 def subcommand(name, *args, **kwargs):
Christopher Haster 15:a6b1f4e65bf4 66 def subcommand(command):
Christopher Haster 15:a6b1f4e65bf4 67 subparser = subparsers.add_parser(name, **kwargs)
Christopher Haster 15:a6b1f4e65bf4 68
Christopher Haster 15:a6b1f4e65bf4 69 for arg in args:
Christopher Haster 15:a6b1f4e65bf4 70 if arg.endswith('?'):
Christopher Haster 15:a6b1f4e65bf4 71 subparser.add_argument(arg.strip('?'), nargs='?')
Christopher Haster 15:a6b1f4e65bf4 72 elif arg.endswith('*'):
Christopher Haster 15:a6b1f4e65bf4 73 pass
Christopher Haster 15:a6b1f4e65bf4 74 else:
Christopher Haster 15:a6b1f4e65bf4 75 subparser.add_argument(arg)
Christopher Haster 15:a6b1f4e65bf4 76
Christopher Haster 15:a6b1f4e65bf4 77 def thunk(parsed_args):
Christopher Haster 15:a6b1f4e65bf4 78 ordered_args = [vars(parsed_args)[arg.strip('?*')]
Christopher Haster 15:a6b1f4e65bf4 79 if not arg.endswith('*') else remainder
Christopher Haster 15:a6b1f4e65bf4 80 for arg in args]
Christopher Haster 15:a6b1f4e65bf4 81 return command(*ordered_args)
Christopher Haster 15:a6b1f4e65bf4 82
Christopher Haster 15:a6b1f4e65bf4 83 subparser.set_defaults(command=thunk)
Christopher Haster 15:a6b1f4e65bf4 84 return command
Christopher Haster 15:a6b1f4e65bf4 85 return subcommand
Christopher Haster 15:a6b1f4e65bf4 86
Christopher Haster 72:08d69d476038 87
Christopher Haster 15:a6b1f4e65bf4 88 # Process execution
Christopher Haster 15:a6b1f4e65bf4 89 class ProcessException(Exception):
Christopher Haster 15:a6b1f4e65bf4 90 pass
Christopher Haster 15:a6b1f4e65bf4 91
Christopher Haster 15:a6b1f4e65bf4 92 def popen(command, stdin=None, **kwargs):
Christopher Haster 15:a6b1f4e65bf4 93 # print for debugging
screamer 71:ddc08f2d5697 94 log("Exec "+' '.join(command))
Christopher Haster 15:a6b1f4e65bf4 95 proc = subprocess.Popen(command, **kwargs)
Christopher Haster 15:a6b1f4e65bf4 96
Christopher Haster 15:a6b1f4e65bf4 97 if proc.wait() != 0:
Christopher Haster 15:a6b1f4e65bf4 98 raise ProcessException(proc.returncode)
Christopher Haster 15:a6b1f4e65bf4 99
Christopher Haster 15:a6b1f4e65bf4 100 def pquery(command, stdin=None, **kwargs):
Christopher Haster 15:a6b1f4e65bf4 101 proc = subprocess.Popen(command, stdout=subprocess.PIPE, **kwargs)
Christopher Haster 15:a6b1f4e65bf4 102 stdout, _ = proc.communicate(stdin)
Christopher Haster 15:a6b1f4e65bf4 103
Christopher Haster 15:a6b1f4e65bf4 104 if proc.returncode != 0:
Christopher Haster 15:a6b1f4e65bf4 105 raise ProcessException(proc.returncode)
Christopher Haster 15:a6b1f4e65bf4 106
Christopher Haster 15:a6b1f4e65bf4 107 return stdout
Christopher Haster 15:a6b1f4e65bf4 108
Christopher Haster 15:a6b1f4e65bf4 109 # Directory navigation
Christopher Haster 15:a6b1f4e65bf4 110 @contextlib.contextmanager
Christopher Haster 15:a6b1f4e65bf4 111 def cd(newdir):
Christopher Haster 15:a6b1f4e65bf4 112 prevdir = os.getcwd()
Christopher Haster 15:a6b1f4e65bf4 113 os.chdir(newdir)
Christopher Haster 15:a6b1f4e65bf4 114 try:
Christopher Haster 15:a6b1f4e65bf4 115 yield
Christopher Haster 15:a6b1f4e65bf4 116 finally:
Christopher Haster 15:a6b1f4e65bf4 117 os.chdir(prevdir)
Christopher Haster 15:a6b1f4e65bf4 118
Christopher Haster 72:08d69d476038 119 def relpath(root, path):
Christopher Haster 72:08d69d476038 120 return path[len(root)+1:]
Christopher Haster 72:08d69d476038 121
Christopher Haster 15:a6b1f4e65bf4 122 # Handling for multiple version controls
Christopher Haster 35:ffcfa5ace437 123 scms = OrderedDict()
Christopher Haster 35:ffcfa5ace437 124 def scm(name):
Christopher Haster 35:ffcfa5ace437 125 def scm(cls):
Christopher Haster 35:ffcfa5ace437 126 scms[name] = cls()
Christopher Haster 35:ffcfa5ace437 127 return cls
Christopher Haster 35:ffcfa5ace437 128 return scm
Christopher Haster 35:ffcfa5ace437 129
Christopher Haster 35:ffcfa5ace437 130 def staticclass(cls):
Christopher Haster 35:ffcfa5ace437 131 for k, v in cls.__dict__.items():
Christopher Haster 36:5f4546dde73b 132 if hasattr(v, '__call__') and not k.startswith('__'):
Christopher Haster 35:ffcfa5ace437 133 setattr(cls, k, staticmethod(v))
Christopher Haster 35:ffcfa5ace437 134
Christopher Haster 35:ffcfa5ace437 135 return cls
Christopher Haster 35:ffcfa5ace437 136
Christopher Haster 35:ffcfa5ace437 137 @scm('hg')
Christopher Haster 35:ffcfa5ace437 138 @staticclass
Christopher Haster 35:ffcfa5ace437 139 class Hg(object):
Christopher Haster 64:012dffea11fd 140 name = 'hg'
Christopher Haster 64:012dffea11fd 141
Christopher Haster 35:ffcfa5ace437 142 def clone(url, name=None, hash=None):
screamer 70:e6f7587c6562 143 action("Cloning "+name+" from "+url)
screamer 47:386f8c519142 144 popen([hg_cmd, 'clone', url, name] + (['-u', hash] if hash else []))
Christopher Haster 35:ffcfa5ace437 145
screamer 63:3b00ba456e00 146 def add(file):
screamer 70:e6f7587c6562 147 action("Adding "+file)
screamer 63:3b00ba456e00 148 popen([hg_cmd, 'add', file])
screamer 63:3b00ba456e00 149
Christopher Haster 35:ffcfa5ace437 150 def remove(file):
screamer 70:e6f7587c6562 151 action("Removing "+file)
screamer 47:386f8c519142 152 popen([hg_cmd, 'rm', '-f', file])
Christopher Haster 35:ffcfa5ace437 153 try:
Christopher Haster 35:ffcfa5ace437 154 os.remove(file)
Christopher Haster 35:ffcfa5ace437 155 except OSError:
Christopher Haster 35:ffcfa5ace437 156 pass
Christopher Haster 35:ffcfa5ace437 157
screamer 63:3b00ba456e00 158 def commit():
screamer 63:3b00ba456e00 159 popen([hg_cmd, 'commit'])
screamer 63:3b00ba456e00 160
screamer 63:3b00ba456e00 161 def push():
screamer 70:e6f7587c6562 162 action("Pushing to remote repository")
screamer 63:3b00ba456e00 163 popen([hg_cmd, 'push'])
screamer 63:3b00ba456e00 164
Christopher Haster 35:ffcfa5ace437 165 def pull(hash=None):
screamer 70:e6f7587c6562 166 action("Pulling from remote repository")
screamer 47:386f8c519142 167 popen([hg_cmd, 'pull'])
screamer 47:386f8c519142 168 popen([hg_cmd, 'update'] + (['-r', hash] if hash else []))
Christopher Haster 35:ffcfa5ace437 169
Christopher Haster 68:14cc5a81333d 170 def status():
Christopher Haster 68:14cc5a81333d 171 popen([hg_cmd, 'status'])
Christopher Haster 68:14cc5a81333d 172
screamer 63:3b00ba456e00 173 def hash():
screamer 63:3b00ba456e00 174 return pquery([hg_cmd, 'id', '-i']).strip().strip('+')
screamer 75:081959a31b02 175
screamer 63:3b00ba456e00 176 def dirty():
screamer 63:3b00ba456e00 177 return pquery([hg_cmd, 'status', '-q'])
Christopher Haster 35:ffcfa5ace437 178
Christopher Haster 44:5ff277e7f754 179 def ignore(file):
Christopher Haster 52:25da1dfebd7a 180 hooked = False
Christopher Haster 52:25da1dfebd7a 181 hook = 'ignore.local = .hg/hgignore'
Christopher Haster 52:25da1dfebd7a 182 with open('.hg/hgrc') as f:
Christopher Haster 52:25da1dfebd7a 183 if hook not in f.read().splitlines():
Christopher Haster 52:25da1dfebd7a 184 with open('.hg/hgrc', 'a') as f:
Christopher Haster 52:25da1dfebd7a 185 f.write('[ui]\n')
Christopher Haster 52:25da1dfebd7a 186 f.write(hook + '\n')
Christopher Haster 52:25da1dfebd7a 187
Christopher Haster 44:5ff277e7f754 188 file = '^%s/' % file
screamer 46:915be4b5a8f0 189 exclude = '.hg/hgignore'
Christopher Haster 74:09b1f16aea24 190 with open(exclude) as f:
Christopher Haster 74:09b1f16aea24 191 if file not in f.read().splitlines():
Christopher Haster 74:09b1f16aea24 192 with open(exclude, 'a') as f:
Christopher Haster 74:09b1f16aea24 193 f.write(file + '\n')
Christopher Haster 42:58b35941ebd0 194
Christopher Haster 44:5ff277e7f754 195 def unignore(file):
Christopher Haster 44:5ff277e7f754 196 file = '^%s/' % file
screamer 46:915be4b5a8f0 197 exclude = '.hg/hgignore'
Christopher Haster 42:58b35941ebd0 198 if not os.path.isfile(exclude):
Christopher Haster 42:58b35941ebd0 199 return
Christopher Haster 42:58b35941ebd0 200
Christopher Haster 42:58b35941ebd0 201 with open(exclude) as f:
Christopher Haster 42:58b35941ebd0 202 lines = f.read().splitlines()
Christopher Haster 42:58b35941ebd0 203
Christopher Haster 44:5ff277e7f754 204 if file not in lines:
Christopher Haster 42:58b35941ebd0 205 return
Christopher Haster 42:58b35941ebd0 206
Christopher Haster 44:5ff277e7f754 207 lines.remove(file)
Christopher Haster 42:58b35941ebd0 208
Christopher Haster 42:58b35941ebd0 209 with open(exclude, 'w') as f:
Christopher Haster 42:58b35941ebd0 210 f.write('\n'.join(lines) + '\n')
Christopher Haster 42:58b35941ebd0 211
Christopher Haster 35:ffcfa5ace437 212 @scm('git')
Christopher Haster 35:ffcfa5ace437 213 @staticclass
Christopher Haster 35:ffcfa5ace437 214 class Git(object):
Christopher Haster 64:012dffea11fd 215 name = 'git'
Christopher Haster 64:012dffea11fd 216
Christopher Haster 35:ffcfa5ace437 217 def clone(url, name=None, hash=None):
screamer 70:e6f7587c6562 218 action("Cloning "+name+" from "+url)
screamer 47:386f8c519142 219 popen([git_cmd, 'clone', url, name])
Christopher Haster 35:ffcfa5ace437 220 if hash:
Christopher Haster 39:8d6f31570710 221 with cd(name):
screamer 47:386f8c519142 222 popen([git_cmd, 'checkout', '-q', hash])
Christopher Haster 35:ffcfa5ace437 223
screamer 63:3b00ba456e00 224 def add(file):
screamer 70:e6f7587c6562 225 action("Adding "+file)
screamer 63:3b00ba456e00 226 popen([git_cmd, 'add', file])
screamer 63:3b00ba456e00 227
screamer 63:3b00ba456e00 228 def remove(file):
screamer 70:e6f7587c6562 229 action("Removing "+file)
screamer 63:3b00ba456e00 230 popen([git_cmd, 'rm', '-f', file])
Christopher Haster 39:8d6f31570710 231
screamer 63:3b00ba456e00 232 def commit():
screamer 63:3b00ba456e00 233 popen([git_cmd, 'commit', '-a'])
screamer 63:3b00ba456e00 234
screamer 63:3b00ba456e00 235 def push():
screamer 70:e6f7587c6562 236 action("Pushing to remote repository")
screamer 63:3b00ba456e00 237 popen([git_cmd, 'push', '--all'])
screamer 63:3b00ba456e00 238
Christopher Haster 39:8d6f31570710 239 def pull(hash=None):
screamer 70:e6f7587c6562 240 action("Pulling from remote repository")
screamer 47:386f8c519142 241 popen([git_cmd, 'fetch', 'origin'])
screamer 47:386f8c519142 242 popen([git_cmd, 'merge'] + ([hash] if hash else []))
Christopher Haster 35:ffcfa5ace437 243
Christopher Haster 68:14cc5a81333d 244 def status():
Christopher Haster 68:14cc5a81333d 245 popen([git_cmd, 'status', '-s'])
Christopher Haster 68:14cc5a81333d 246
screamer 63:3b00ba456e00 247 def hash():
screamer 63:3b00ba456e00 248 return pquery([git_cmd, 'rev-parse', '--short', 'HEAD']).strip()
screamer 63:3b00ba456e00 249
screamer 63:3b00ba456e00 250 def dirty():
screamer 63:3b00ba456e00 251 return pquery([git_cmd, 'diff', '--name-only', 'HEAD'])
Christopher Haster 40:2446665dfdf8 252
Christopher Haster 44:5ff277e7f754 253 def ignore(file):
Christopher Haster 42:58b35941ebd0 254 exclude = '.git/info/exclude'
Christopher Haster 74:09b1f16aea24 255 with open(exclude) as f:
Christopher Haster 74:09b1f16aea24 256 if file not in f.read().splitlines():
Christopher Haster 74:09b1f16aea24 257 with open(exclude, 'a') as f:
Christopher Haster 74:09b1f16aea24 258 f.write(file + '\n')
Christopher Haster 42:58b35941ebd0 259
Christopher Haster 44:5ff277e7f754 260 def unignore(file):
Christopher Haster 42:58b35941ebd0 261 exclude = '.git/info/exclude'
Christopher Haster 42:58b35941ebd0 262 if not os.path.isfile(exclude):
Christopher Haster 42:58b35941ebd0 263 return
Christopher Haster 42:58b35941ebd0 264
Christopher Haster 42:58b35941ebd0 265 with open(exclude) as f:
Christopher Haster 42:58b35941ebd0 266 lines = f.read().splitlines()
Christopher Haster 42:58b35941ebd0 267
Christopher Haster 44:5ff277e7f754 268 if file not in lines:
Christopher Haster 42:58b35941ebd0 269 return
Christopher Haster 42:58b35941ebd0 270
Christopher Haster 44:5ff277e7f754 271 lines.remove(file)
Christopher Haster 42:58b35941ebd0 272
Christopher Haster 42:58b35941ebd0 273 with open(exclude, 'w') as f:
Christopher Haster 42:58b35941ebd0 274 f.write('\n'.join(lines) + '\n')
Christopher Haster 40:2446665dfdf8 275
Christopher Haster 35:ffcfa5ace437 276
Christopher Haster 35:ffcfa5ace437 277 # Repository object
Christopher Haster 15:a6b1f4e65bf4 278 class Repo(object):
Christopher Haster 36:5f4546dde73b 279 @classmethod
Christopher Haster 36:5f4546dde73b 280 def fromurl(cls, url, path=None):
Christopher Haster 36:5f4546dde73b 281 repo = cls()
Christopher Haster 36:5f4546dde73b 282
Christopher Haster 54:3cb9f99bbaaa 283 m = re.match('^(.*/([\w+-]+)(?:\.\w+)?)/?(?:#(.*))?$', url.strip())
Christopher Haster 36:5f4546dde73b 284 repo.name = os.path.basename(path or m.group(2))
Christopher Haster 36:5f4546dde73b 285 repo.path = os.path.abspath(
Christopher Haster 36:5f4546dde73b 286 path or os.path.join(os.getcwd(), repo.name))
Christopher Haster 36:5f4546dde73b 287
Christopher Haster 36:5f4546dde73b 288 repo.repo = m.group(1)
Christopher Haster 36:5f4546dde73b 289 repo.hash = m.group(3)
Christopher Haster 36:5f4546dde73b 290 return repo
Christopher Haster 15:a6b1f4e65bf4 291
Christopher Haster 15:a6b1f4e65bf4 292 @classmethod
Christopher Haster 36:5f4546dde73b 293 def fromlib(cls, lib=None):
Christopher Haster 36:5f4546dde73b 294 assert lib.endswith('.lib')
Christopher Haster 36:5f4546dde73b 295 with open(lib) as f:
Christopher Haster 36:5f4546dde73b 296 return cls.fromurl(f.read(), lib[:-4])
Christopher Haster 15:a6b1f4e65bf4 297
Christopher Haster 36:5f4546dde73b 298 @classmethod
Christopher Haster 36:5f4546dde73b 299 def fromrepo(cls, path=None):
Christopher Haster 36:5f4546dde73b 300 repo = cls()
Christopher Haster 36:5f4546dde73b 301 repo.path = os.path.abspath(path or os.getcwd())
Christopher Haster 36:5f4546dde73b 302 repo.name = os.path.basename(repo.path)
Christopher Haster 15:a6b1f4e65bf4 303
Christopher Haster 36:5f4546dde73b 304 repo.synch()
Christopher Haster 15:a6b1f4e65bf4 305 return repo
Christopher Haster 15:a6b1f4e65bf4 306
Christopher Haster 15:a6b1f4e65bf4 307 @property
Christopher Haster 15:a6b1f4e65bf4 308 def lib(self):
Christopher Haster 15:a6b1f4e65bf4 309 return self.path + '.lib'
Christopher Haster 15:a6b1f4e65bf4 310
Christopher Haster 15:a6b1f4e65bf4 311 @property
Christopher Haster 15:a6b1f4e65bf4 312 def url(self):
Christopher Haster 15:a6b1f4e65bf4 313 if self.repo:
screamer 60:52dc8fcb07d8 314 return self.repo + '/' + ('#'+self.hash if self.hash else '')
Christopher Haster 15:a6b1f4e65bf4 315
Christopher Haster 36:5f4546dde73b 316 def synch(self):
Christopher Haster 15:a6b1f4e65bf4 317 if os.path.isdir(self.path):
Christopher Haster 39:8d6f31570710 318 try:
Christopher Haster 39:8d6f31570710 319 self.scm = self.getscm()
Christopher Haster 39:8d6f31570710 320 self.hash = self.gethash()
Christopher Haster 39:8d6f31570710 321 self.libs = list(self.getlibs())
Christopher Haster 39:8d6f31570710 322 except ProcessException:
Christopher Haster 39:8d6f31570710 323 pass
Christopher Haster 15:a6b1f4e65bf4 324
Christopher Haster 37:bf73ffd98cca 325 if os.path.isfile(self.lib):
Christopher Haster 39:8d6f31570710 326 try:
Christopher Haster 39:8d6f31570710 327 self.repo = self.getrepo()
Christopher Haster 39:8d6f31570710 328 except ProcessException:
Christopher Haster 39:8d6f31570710 329 pass
Christopher Haster 37:bf73ffd98cca 330
Christopher Haster 35:ffcfa5ace437 331 def getscm(self):
Christopher Haster 36:5f4546dde73b 332 for name, scm in scms.items():
Christopher Haster 36:5f4546dde73b 333 if os.path.isdir(os.path.join(self.path, '.'+name)):
Christopher Haster 36:5f4546dde73b 334 return scm
Christopher Haster 35:ffcfa5ace437 335
Christopher Haster 15:a6b1f4e65bf4 336 def gethash(self):
Christopher Haster 66:bfe0df4ef9f5 337 if self.scm:
Christopher Haster 66:bfe0df4ef9f5 338 with cd(self.path):
Christopher Haster 66:bfe0df4ef9f5 339 return self.scm.hash()
Christopher Haster 15:a6b1f4e65bf4 340
Christopher Haster 36:5f4546dde73b 341 def getlibs(self):
Christopher Haster 36:5f4546dde73b 342 for root, dirs, files in os.walk(self.path):
Christopher Haster 36:5f4546dde73b 343 dirs[:] = [d for d in dirs if not d.startswith('.')]
Christopher Haster 36:5f4546dde73b 344 files[:] = [f for f in files if not f.startswith('.')]
Christopher Haster 36:5f4546dde73b 345
Christopher Haster 36:5f4546dde73b 346 for file in files:
Christopher Haster 36:5f4546dde73b 347 if file.endswith('.lib'):
Christopher Haster 36:5f4546dde73b 348 yield Repo.fromlib(os.path.join(root, file))
Christopher Haster 49:977ea8d3e661 349 if file[:-4] in dirs:
Christopher Haster 49:977ea8d3e661 350 dirs.remove(file[:-4])
Christopher Haster 36:5f4546dde73b 351
Christopher Haster 37:bf73ffd98cca 352 def getrepo(self):
Christopher Haster 37:bf73ffd98cca 353 with open(self.lib) as f:
Christopher Haster 37:bf73ffd98cca 354 return Repo.fromurl(f.read()).repo
Christopher Haster 37:bf73ffd98cca 355
Christopher Haster 36:5f4546dde73b 356 def write(self):
Christopher Haster 38:0ca5eea23af9 357 if os.path.isfile(self.lib):
Christopher Haster 38:0ca5eea23af9 358 with open(self.lib) as f:
Christopher Haster 38:0ca5eea23af9 359 if f.read().strip() == self.url.strip():
Christopher Haster 44:5ff277e7f754 360 print self.name, 'unmodified'
Christopher Haster 38:0ca5eea23af9 361 return
Christopher Haster 36:5f4546dde73b 362
Christopher Haster 38:0ca5eea23af9 363 with open(self.lib, 'w') as f:
Christopher Haster 38:0ca5eea23af9 364 f.write(self.url + '\n')
Christopher Haster 36:5f4546dde73b 365
Christopher Haster 44:5ff277e7f754 366 print self.name, '->', self.url
Christopher Haster 44:5ff277e7f754 367
Christopher Haster 15:a6b1f4e65bf4 368 # Clone command
Christopher Haster 15:a6b1f4e65bf4 369 @subcommand('import', 'url', 'name?',
screamer 63:3b00ba456e00 370 help='Import a program tree')
Christopher Haster 36:5f4546dde73b 371 def import_(url, path=None):
Christopher Haster 36:5f4546dde73b 372 repo = Repo.fromurl(url, path)
Christopher Haster 15:a6b1f4e65bf4 373
Christopher Haster 35:ffcfa5ace437 374 for scm in scms.values():
Christopher Haster 15:a6b1f4e65bf4 375 try:
Christopher Haster 35:ffcfa5ace437 376 scm.clone(repo.repo, repo.path, repo.hash)
Christopher Haster 15:a6b1f4e65bf4 377 break
Christopher Haster 35:ffcfa5ace437 378 except ProcessException:
Christopher Haster 15:a6b1f4e65bf4 379 pass
Christopher Haster 15:a6b1f4e65bf4 380
Christopher Haster 36:5f4546dde73b 381 repo.synch()
Christopher Haster 15:a6b1f4e65bf4 382
Christopher Haster 15:a6b1f4e65bf4 383 with cd(repo.path):
Christopher Haster 36:5f4546dde73b 384 for lib in repo.libs:
Christopher Haster 36:5f4546dde73b 385 import_(lib.url, lib.path)
Christopher Haster 72:08d69d476038 386 repo.scm.ignore(relpath(repo.path, lib.path))
Christopher Haster 15:a6b1f4e65bf4 387
Christopher Haster 19:6ace1080b8bb 388 if (not os.path.isfile('mbed_settings.py') and
Christopher Haster 19:6ace1080b8bb 389 os.path.isfile('mbed-os/tools/settings.py')):
screamer 30:dcc9ff39aee3 390 shutil.copy('mbed-os/tools/default_settings.py', 'mbed_settings.py')
Christopher Haster 19:6ace1080b8bb 391
Christopher Haster 15:a6b1f4e65bf4 392 # Deploy command
Christopher Haster 15:a6b1f4e65bf4 393 @subcommand('deploy',
screamer 63:3b00ba456e00 394 help='Import library in the current program or library')
Christopher Haster 15:a6b1f4e65bf4 395 def deploy():
Christopher Haster 36:5f4546dde73b 396 repo = Repo.fromrepo()
Christopher Haster 36:5f4546dde73b 397 for lib in repo.libs:
Christopher Haster 36:5f4546dde73b 398 import_(lib.url, lib.path)
Christopher Haster 72:08d69d476038 399 repo.scm.ignore(relpath(repo.path, lib.path))
Christopher Haster 15:a6b1f4e65bf4 400
Christopher Haster 15:a6b1f4e65bf4 401 # Install/uninstall command
Christopher Haster 15:a6b1f4e65bf4 402 @subcommand('add', 'url', 'name?',
screamer 63:3b00ba456e00 403 help='Add a library to the current program or library')
Christopher Haster 36:5f4546dde73b 404 def add(url, path=None):
Christopher Haster 36:5f4546dde73b 405 repo = Repo.fromrepo()
Christopher Haster 15:a6b1f4e65bf4 406
Christopher Haster 36:5f4546dde73b 407 lib = Repo.fromurl(url, path)
Christopher Haster 36:5f4546dde73b 408 import_(lib.url, lib.path)
Christopher Haster 72:08d69d476038 409 repo.scm.ignore(relpath(repo.path, lib.path))
Christopher Haster 36:5f4546dde73b 410 lib.synch()
Christopher Haster 15:a6b1f4e65bf4 411
Christopher Haster 36:5f4546dde73b 412 lib.write()
Christopher Haster 36:5f4546dde73b 413 repo.scm.add(lib.lib)
Christopher Haster 15:a6b1f4e65bf4 414
Christopher Haster 36:5f4546dde73b 415 @subcommand('remove', 'path',
screamer 63:3b00ba456e00 416 help='Remove a library from the current program or library')
Christopher Haster 36:5f4546dde73b 417 def remove(path):
Christopher Haster 36:5f4546dde73b 418 repo = Repo.fromrepo()
Christopher Haster 36:5f4546dde73b 419 lib = Repo.fromrepo(path)
Christopher Haster 15:a6b1f4e65bf4 420
Christopher Haster 36:5f4546dde73b 421 repo.scm.remove(lib.lib)
Christopher Haster 36:5f4546dde73b 422 shutil.rmtree(lib.path)
Christopher Haster 72:08d69d476038 423 repo.scm.unignore(relpath(repo.path, lib.path))
Christopher Haster 15:a6b1f4e65bf4 424
Christopher Haster 15:a6b1f4e65bf4 425 # Publish command
Christopher Haster 15:a6b1f4e65bf4 426 @subcommand('publish',
screamer 63:3b00ba456e00 427 help='Publish working tree to remote repositories')
Christopher Haster 18:1b4252106474 428 def publish(always=True):
screamer 67:c3b033f16424 429 repo_or_die()
Christopher Haster 36:5f4546dde73b 430 repo = Repo.fromrepo()
Christopher Haster 36:5f4546dde73b 431 for lib in repo.libs:
Christopher Haster 36:5f4546dde73b 432 with cd(lib.path):
Christopher Haster 36:5f4546dde73b 433 publish(False)
Christopher Haster 36:5f4546dde73b 434 synch()
Christopher Haster 15:a6b1f4e65bf4 435
Christopher Haster 36:5f4546dde73b 436 dirty = repo.scm.dirty()
Christopher Haster 17:1e487c450f06 437
Christopher Haster 36:5f4546dde73b 438 if dirty:
screamer 70:e6f7587c6562 439 action('Uncommitted changes in %s (%s)' % (repo.name, repo.path))
screamer 63:3b00ba456e00 440 raw_input('Press enter to commit and push: ')
Christopher Haster 36:5f4546dde73b 441 repo.scm.commit()
Christopher Haster 17:1e487c450f06 442
Christopher Haster 36:5f4546dde73b 443 if dirty or always:
Christopher Haster 18:1b4252106474 444 try:
Christopher Haster 36:5f4546dde73b 445 repo.scm.push()
Christopher Haster 18:1b4252106474 446 except ProcessException as e:
Christopher Haster 18:1b4252106474 447 sys.exit(e[0])
Christopher Haster 15:a6b1f4e65bf4 448
Christopher Haster 20:84d6e18cbc20 449 # Update command
Christopher Haster 20:84d6e18cbc20 450 @subcommand('update', 'ref?',
screamer 63:3b00ba456e00 451 help='Update current program or library and recursively update all libraries')
Christopher Haster 20:84d6e18cbc20 452 def update(ref=None):
screamer 67:c3b033f16424 453 repo_or_die()
Christopher Haster 36:5f4546dde73b 454 repo = Repo.fromrepo()
Christopher Haster 36:5f4546dde73b 455 repo.scm.pull(ref)
Christopher Haster 36:5f4546dde73b 456
Christopher Haster 36:5f4546dde73b 457 for lib in repo.libs:
Christopher Haster 37:bf73ffd98cca 458 if (not os.path.isfile(lib.lib) or
Christopher Haster 37:bf73ffd98cca 459 lib.repo != Repo.fromrepo(lib.path).repo):
Christopher Haster 36:5f4546dde73b 460 with cd(lib.path):
Christopher Haster 36:5f4546dde73b 461 if lib.cwd.dirty():
screamer 63:3b00ba456e00 462 error('Uncommitted changes in %s (%s)\n'
screamer 63:3b00ba456e00 463 % (lib.name, lib.path), 1)
Christopher Haster 20:84d6e18cbc20 464
Christopher Haster 36:5f4546dde73b 465 shutil.rmtree(lib.path)
Christopher Haster 72:08d69d476038 466 repo.scm.unignore(relpath(repo.path, lib.path))
Christopher Haster 36:5f4546dde73b 467
Christopher Haster 36:5f4546dde73b 468 repo.synch()
Christopher Haster 36:5f4546dde73b 469
Christopher Haster 36:5f4546dde73b 470 for lib in repo.libs:
Christopher Haster 45:5a91306f7924 471 if os.path.isdir(lib.path):
Christopher Haster 45:5a91306f7924 472 with cd(lib.path):
Christopher Haster 45:5a91306f7924 473 update(lib.hash)
Christopher Haster 45:5a91306f7924 474 else:
Christopher Haster 42:58b35941ebd0 475 import_(lib.url, lib.path)
Christopher Haster 72:08d69d476038 476 repo.scm.ignore(relpath(repo.path, lib.path))
Christopher Haster 20:84d6e18cbc20 477
Christopher Haster 15:a6b1f4e65bf4 478 # Synch command
Christopher Haster 15:a6b1f4e65bf4 479 @subcommand('synch',
screamer 63:3b00ba456e00 480 help='Synchronize library references (.lib files)')
Christopher Haster 15:a6b1f4e65bf4 481 def synch():
Christopher Haster 36:5f4546dde73b 482 repo = Repo.fromrepo()
Christopher Haster 36:5f4546dde73b 483 for lib in repo.libs:
Christopher Haster 36:5f4546dde73b 484 lib.synch()
Christopher Haster 43:8a4a902a0654 485 lib.write()
Christopher Haster 15:a6b1f4e65bf4 486
Christopher Haster 15:a6b1f4e65bf4 487 # Compile command
Christopher Haster 15:a6b1f4e65bf4 488 @subcommand('compile', 'args*',
screamer 63:3b00ba456e00 489 help='Compile project using mbed OS build system')
Christopher Haster 15:a6b1f4e65bf4 490 def compile(args):
Christopher Haster 15:a6b1f4e65bf4 491 if not os.path.isdir('mbed-os'):
screamer 63:3b00ba456e00 492 error('mbed-os not found?\n', -1)
Christopher Haster 15:a6b1f4e65bf4 493
Christopher Haster 40:2446665dfdf8 494 repo = Repo.fromrepo()
Christopher Haster 40:2446665dfdf8 495
Christopher Haster 21:1a3f920b6f07 496 macros = []
Christopher Haster 15:a6b1f4e65bf4 497 if os.path.isfile('MACROS.txt'):
Christopher Haster 15:a6b1f4e65bf4 498 with open('MACROS.txt') as f:
Christopher Haster 15:a6b1f4e65bf4 499 macros = f.read().splitlines()
Christopher Haster 15:a6b1f4e65bf4 500
Christopher Haster 15:a6b1f4e65bf4 501 env = os.environ.copy()
Christopher Haster 15:a6b1f4e65bf4 502 env['PYTHONPATH'] = '.'
Christopher Haster 15:a6b1f4e65bf4 503 popen(['python', 'mbed-os/tools/make.py']
Christopher Haster 15:a6b1f4e65bf4 504 + list(chain.from_iterable(izip(repeat('-D'), macros)))
Christopher Haster 36:5f4546dde73b 505 + ['--source=%s' % repo.path,
Christopher Haster 36:5f4546dde73b 506 '--build=%s' % os.path.join(repo.path, '.build')]
Christopher Haster 15:a6b1f4e65bf4 507 + args,
Christopher Haster 15:a6b1f4e65bf4 508 env=env)
Christopher Haster 15:a6b1f4e65bf4 509
Christopher Haster 15:a6b1f4e65bf4 510 # Export command
Christopher Haster 15:a6b1f4e65bf4 511 @subcommand('export', 'args*',
screamer 63:3b00ba456e00 512 help='Generate project files for IDE')
Christopher Haster 15:a6b1f4e65bf4 513 def export(args):
Christopher Haster 15:a6b1f4e65bf4 514 if not os.path.isdir('mbed-os'):
screamer 63:3b00ba456e00 515 error('mbed-os not found?\n', -1)
Christopher Haster 15:a6b1f4e65bf4 516
Christopher Haster 40:2446665dfdf8 517 repo = Repo.fromrepo()
Christopher Haster 40:2446665dfdf8 518
Christopher Haster 41:59e9d808ee05 519 macros = []
Christopher Haster 41:59e9d808ee05 520 if os.path.isfile('MACROS.txt'):
Christopher Haster 41:59e9d808ee05 521 with open('MACROS.txt') as f:
Christopher Haster 41:59e9d808ee05 522 macros = f.read().splitlines()
Christopher Haster 41:59e9d808ee05 523
Christopher Haster 18:1b4252106474 524 env = os.environ.copy()
Christopher Haster 18:1b4252106474 525 env['PYTHONPATH'] = '.'
Christopher Haster 15:a6b1f4e65bf4 526 popen(['python', 'mbed-os/tools/project.py',
Christopher Haster 36:5f4546dde73b 527 '--source=%s' % repo.path]
Christopher Haster 41:59e9d808ee05 528 + list(chain.from_iterable(izip(repeat('-D'), macros)))
Christopher Haster 18:1b4252106474 529 + args,
Christopher Haster 18:1b4252106474 530 env=env)
Christopher Haster 15:a6b1f4e65bf4 531
Christopher Haster 68:14cc5a81333d 532 # Helpful status commands
Christopher Haster 65:905ba27af203 533 @subcommand('ls',
Christopher Haster 61:5c3f41de9d97 534 help='list repositories recursively')
Christopher Haster 61:5c3f41de9d97 535 def list_(prefix=''):
Christopher Haster 61:5c3f41de9d97 536 repo = Repo.fromrepo()
Christopher Haster 61:5c3f41de9d97 537 print prefix + repo.name, '(%s)' % repo.hash
Christopher Haster 61:5c3f41de9d97 538
Christopher Haster 61:5c3f41de9d97 539 for i, lib in enumerate(repo.libs):
Christopher Haster 61:5c3f41de9d97 540 if prefix:
Christopher Haster 61:5c3f41de9d97 541 nprefix = prefix[:-3] + ('| ' if prefix[-3] == '|' else ' ')
Christopher Haster 61:5c3f41de9d97 542 else:
Christopher Haster 61:5c3f41de9d97 543 nprefix = ''
Christopher Haster 61:5c3f41de9d97 544
Christopher Haster 61:5c3f41de9d97 545 nprefix += '|- ' if i < len(repo.libs)-1 else '`- '
Christopher Haster 61:5c3f41de9d97 546
Christopher Haster 61:5c3f41de9d97 547 with cd(lib.path):
Christopher Haster 61:5c3f41de9d97 548 list_(nprefix)
Christopher Haster 61:5c3f41de9d97 549
Christopher Haster 68:14cc5a81333d 550 @subcommand('status',
Christopher Haster 68:14cc5a81333d 551 help='show status of nested repositories')
Christopher Haster 68:14cc5a81333d 552 def status():
Christopher Haster 68:14cc5a81333d 553 repo = Repo.fromrepo()
Christopher Haster 68:14cc5a81333d 554 if repo.scm.dirty():
Christopher Haster 68:14cc5a81333d 555 print '---', repo.name, '---'
Christopher Haster 68:14cc5a81333d 556 repo.scm.status()
Christopher Haster 68:14cc5a81333d 557
Christopher Haster 68:14cc5a81333d 558 for lib in repo.libs:
Christopher Haster 68:14cc5a81333d 559 with cd(lib.path):
Christopher Haster 68:14cc5a81333d 560 status()
Christopher Haster 68:14cc5a81333d 561
Christopher Haster 15:a6b1f4e65bf4 562 # Parse/run command
Christopher Haster 15:a6b1f4e65bf4 563 args, remainder = parser.parse_known_args()
Christopher Haster 15:a6b1f4e65bf4 564 status = args.command(args)
Christopher Haster 15:a6b1f4e65bf4 565 sys.exit(status or 0)
Christopher Haster 15:a6b1f4e65bf4 566