Morpheus / Mbed OS mbed-Client-Morpheus-hg

Dependencies:   mbed-os

Committer:
screamer
Date:
Fri Apr 01 14:46:49 2016 +0100
Revision:
70:e6f7587c6562
Parent:
69:eb600c35d6ac
Child:
71:ddc08f2d5697
Logging

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