Morpheus / Mbed OS mbed-Client-Morpheus-hg

Dependencies:   mbed-os

Committer:
Christopher Haster
Date:
Thu Mar 31 03:20:59 2016 -0500
Revision:
79:7be8ab60beec
Parent:
77:46124d75dae7
Optimized hash lookup for hg

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