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