Morpheus / Mbed OS mbed-Client-Morpheus-hg

Dependencies:   mbed-os

Committer:
Christopher Haster
Date:
Wed Mar 30 20:23:51 2016 -0500
Revision:
69:eb600c35d6ac
Parent:
68:14cc5a81333d
Parent:
67:c3b033f16424
Child:
70:e6f7587c6562
Child:
72:08d69d476038
Merged changes

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