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@4:6e987db7a950, 2016-03-30 (annotated)
- Committer:
- screamer
- Date:
- Wed Mar 30 20:34:40 2016 +0000
- Revision:
- 4:6e987db7a950
- Parent:
- 3:47aa05d37724
- Child:
- 5:37ac884d9477
Changes to neo.py methods etc
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| screamer | 4:6e987db7a950 | 1 | #!/usr/bin/env python |
| screamer | 4:6e987db7a950 | 2 | |
| screamer | 4:6e987db7a950 | 3 | import argparse |
| screamer | 4:6e987db7a950 | 4 | import sys |
| screamer | 4:6e987db7a950 | 5 | import re |
| screamer | 4:6e987db7a950 | 6 | import subprocess |
| screamer | 4:6e987db7a950 | 7 | import os |
| screamer | 4:6e987db7a950 | 8 | import contextlib |
| screamer | 4:6e987db7a950 | 9 | import collections |
| screamer | 4:6e987db7a950 | 10 | |
| screamer | 4:6e987db7a950 | 11 | # Subparser handling |
| screamer | 4:6e987db7a950 | 12 | parser = argparse.ArgumentParser() |
| screamer | 4:6e987db7a950 | 13 | subparsers = parser.add_subparsers() |
| screamer | 4:6e987db7a950 | 14 | |
| screamer | 4:6e987db7a950 | 15 | def subcommand(name, *args, **kwargs): |
| screamer | 4:6e987db7a950 | 16 | def subcommand(command): |
| screamer | 4:6e987db7a950 | 17 | subparser = subparsers.add_parser(name, **kwargs) |
| screamer | 4:6e987db7a950 | 18 | |
| screamer | 4:6e987db7a950 | 19 | for arg in args: |
| screamer | 4:6e987db7a950 | 20 | subparser.add_argument(arg) |
| screamer | 4:6e987db7a950 | 21 | |
| screamer | 4:6e987db7a950 | 22 | def thunk(parsed_args): |
| screamer | 4:6e987db7a950 | 23 | ordered_args = [vars(parsed_args)[arg] for arg in args] |
| screamer | 4:6e987db7a950 | 24 | return command(*ordered_args) |
| screamer | 4:6e987db7a950 | 25 | |
| screamer | 4:6e987db7a950 | 26 | subparser.set_defaults(command=thunk) |
| screamer | 4:6e987db7a950 | 27 | return command |
| screamer | 4:6e987db7a950 | 28 | return subcommand |
| screamer | 4:6e987db7a950 | 29 | |
| screamer | 4:6e987db7a950 | 30 | # Process execution |
| screamer | 4:6e987db7a950 | 31 | class ProcessException(Exception): |
| screamer | 4:6e987db7a950 | 32 | pass |
| screamer | 4:6e987db7a950 | 33 | |
| screamer | 4:6e987db7a950 | 34 | def popen(command, stdin=None): |
| screamer | 4:6e987db7a950 | 35 | # print for debugging |
| screamer | 4:6e987db7a950 | 36 | print ' '.join(command) |
| screamer | 4:6e987db7a950 | 37 | proc = subprocess.Popen(command) |
| screamer | 4:6e987db7a950 | 38 | |
| screamer | 4:6e987db7a950 | 39 | if proc.wait() != 0: |
| screamer | 4:6e987db7a950 | 40 | raise ProcessException(proc.returncode) |
| screamer | 4:6e987db7a950 | 41 | |
| screamer | 4:6e987db7a950 | 42 | def pquery(command, stdin=None): |
| screamer | 4:6e987db7a950 | 43 | proc = subprocess.Popen(command, stdout=subprocess.PIPE) |
| screamer | 4:6e987db7a950 | 44 | stdout, _ = proc.communicate(stdin) |
| screamer | 4:6e987db7a950 | 45 | |
| screamer | 4:6e987db7a950 | 46 | if proc.returncode != 0: |
| screamer | 4:6e987db7a950 | 47 | raise ProcessException(proc.returncode) |
| screamer | 4:6e987db7a950 | 48 | |
| screamer | 4:6e987db7a950 | 49 | return stdout |
| screamer | 4:6e987db7a950 | 50 | |
| screamer | 4:6e987db7a950 | 51 | # Directory navigation |
| screamer | 4:6e987db7a950 | 52 | @contextlib.contextmanager |
| screamer | 4:6e987db7a950 | 53 | def cd(newdir): |
| screamer | 4:6e987db7a950 | 54 | prevdir = os.getcwd() |
| screamer | 4:6e987db7a950 | 55 | os.chdir(newdir) |
| screamer | 4:6e987db7a950 | 56 | try: |
| screamer | 4:6e987db7a950 | 57 | yield |
| screamer | 4:6e987db7a950 | 58 | finally: |
| screamer | 4:6e987db7a950 | 59 | os.chdir(prevdir) |
| screamer | 4:6e987db7a950 | 60 | |
| screamer | 4:6e987db7a950 | 61 | def iterlibs(dir=None): |
| screamer | 4:6e987db7a950 | 62 | for file in os.listdir(dir or os.getcwd()): |
| screamer | 4:6e987db7a950 | 63 | if file.startswith('.'): |
| screamer | 4:6e987db7a950 | 64 | continue |
| screamer | 4:6e987db7a950 | 65 | elif os.path.isfile(file) and file.endswith('.lib'): |
| screamer | 4:6e987db7a950 | 66 | with open(file) as f: |
| screamer | 4:6e987db7a950 | 67 | yield f.read().strip() |
| screamer | 4:6e987db7a950 | 68 | |
| screamer | 4:6e987db7a950 | 69 | def savelib(repo): |
| screamer | 4:6e987db7a950 | 70 | print repo.name, '->', repo.url |
| screamer | 4:6e987db7a950 | 71 | |
| screamer | 4:6e987db7a950 | 72 | with open(repo.lib, 'w') as f: |
| screamer | 4:6e987db7a950 | 73 | f.write(repo.url + '\n') |
| screamer | 4:6e987db7a950 | 74 | |
| screamer | 4:6e987db7a950 | 75 | |
| screamer | 4:6e987db7a950 | 76 | # Handling for multiple version controls |
| screamer | 4:6e987db7a950 | 77 | class Repo(object): |
| screamer | 4:6e987db7a950 | 78 | def __init__(self, path=None): |
| screamer | 4:6e987db7a950 | 79 | self.path = path or os.getcwd() |
| screamer | 4:6e987db7a950 | 80 | self.name = os.path.basename(self.path) |
| screamer | 4:6e987db7a950 | 81 | self.update() |
| screamer | 4:6e987db7a950 | 82 | |
| screamer | 4:6e987db7a950 | 83 | @classmethod |
| screamer | 4:6e987db7a950 | 84 | def fromurl(cls, url): |
| screamer | 4:6e987db7a950 | 85 | repo = cls.__new__(cls) |
| screamer | 4:6e987db7a950 | 86 | |
| screamer | 4:6e987db7a950 | 87 | m = re.match('^(.*/([+a-zA-Z0-9_-]+)/?)(?:#(.*))?$', url) |
| screamer | 4:6e987db7a950 | 88 | repo.repo = m.group(1) |
| screamer | 4:6e987db7a950 | 89 | repo.name = m.group(2) |
| screamer | 4:6e987db7a950 | 90 | repo.hash = m.group(3) |
| screamer | 4:6e987db7a950 | 91 | |
| screamer | 4:6e987db7a950 | 92 | repo.path = os.path.join(os.getcwd(), repo.name) |
| screamer | 4:6e987db7a950 | 93 | return repo |
| screamer | 4:6e987db7a950 | 94 | |
| screamer | 4:6e987db7a950 | 95 | @property |
| screamer | 4:6e987db7a950 | 96 | def lib(self): |
| screamer | 4:6e987db7a950 | 97 | return self.path + '.lib' |
| screamer | 3:47aa05d37724 | 98 | |
| screamer | 4:6e987db7a950 | 99 | @property |
| screamer | 4:6e987db7a950 | 100 | def url(self): |
| screamer | 4:6e987db7a950 | 101 | if self.repo: |
| screamer | 4:6e987db7a950 | 102 | if self.hash: |
| screamer | 4:6e987db7a950 | 103 | return self.repo + '#' + self.hash |
| screamer | 4:6e987db7a950 | 104 | else: |
| screamer | 4:6e987db7a950 | 105 | return self.repo |
| screamer | 4:6e987db7a950 | 106 | |
| screamer | 4:6e987db7a950 | 107 | def update(self): |
| screamer | 4:6e987db7a950 | 108 | if os.path.isdir(self.path): |
| screamer | 4:6e987db7a950 | 109 | self.type = self.gettype() |
| screamer | 4:6e987db7a950 | 110 | self.hash = self.gethash() |
| screamer | 4:6e987db7a950 | 111 | |
| screamer | 4:6e987db7a950 | 112 | if os.path.isfile(self.lib): |
| screamer | 4:6e987db7a950 | 113 | with open(self.lib) as f: |
| screamer | 4:6e987db7a950 | 114 | temp = Repo.fromurl(f.read()) |
| screamer | 4:6e987db7a950 | 115 | self.repo = temp.repo |
| screamer | 4:6e987db7a950 | 116 | |
| screamer | 4:6e987db7a950 | 117 | def gettype(self): |
| screamer | 4:6e987db7a950 | 118 | for type, dir in [('git', '.git'), ('hg', '.hg')]: |
| screamer | 4:6e987db7a950 | 119 | if os.path.isdir(os.path.join(self.path, dir)): |
| screamer | 4:6e987db7a950 | 120 | return type |
| screamer | 4:6e987db7a950 | 121 | |
| screamer | 4:6e987db7a950 | 122 | def gethash(self): |
| screamer | 4:6e987db7a950 | 123 | with cd(self.path): |
| screamer | 4:6e987db7a950 | 124 | if self.type == 'git': |
| screamer | 4:6e987db7a950 | 125 | return pquery(['git', 'rev-parse', '--short', 'HEAD']).strip() |
| screamer | 4:6e987db7a950 | 126 | elif self.type == 'hg': |
| screamer | 4:6e987db7a950 | 127 | return pquery(['hg', 'id', '-i']).strip() |
| screamer | 4:6e987db7a950 | 128 | |
| screamer | 4:6e987db7a950 | 129 | # Clone command |
| screamer | 4:6e987db7a950 | 130 | @subcommand('import', 'url', |
| screamer | 4:6e987db7a950 | 131 | help='recursively import a repository') |
| screamer | 4:6e987db7a950 | 132 | def import_(url): |
| screamer | 4:6e987db7a950 | 133 | repo = Repo.fromurl(url) |
| screamer | 4:6e987db7a950 | 134 | |
| screamer | 4:6e987db7a950 | 135 | for type in ['git', 'hg']: |
| screamer | 4:6e987db7a950 | 136 | try: |
| screamer | 4:6e987db7a950 | 137 | popen([type, 'clone', repo.repo]) |
| screamer | 4:6e987db7a950 | 138 | break |
| screamer | 4:6e987db7a950 | 139 | except: |
| screamer | 4:6e987db7a950 | 140 | pass |
| screamer | 4:6e987db7a950 | 141 | |
| screamer | 4:6e987db7a950 | 142 | repo.type = repo.gettype() |
| screamer | 4:6e987db7a950 | 143 | |
| screamer | 4:6e987db7a950 | 144 | if repo.hash: |
| screamer | 4:6e987db7a950 | 145 | with cd(repo.path): |
| screamer | 4:6e987db7a950 | 146 | popen([repo.type, 'checkout', repo.hash]) |
| screamer | 4:6e987db7a950 | 147 | |
| screamer | 4:6e987db7a950 | 148 | repo.update() |
| screamer | 4:6e987db7a950 | 149 | |
| screamer | 4:6e987db7a950 | 150 | with cd(repo.path): |
| screamer | 4:6e987db7a950 | 151 | for lib in iterlibs(): |
| screamer | 4:6e987db7a950 | 152 | import_(lib) |
| screamer | 4:6e987db7a950 | 153 | |
| screamer | 4:6e987db7a950 | 154 | # Install/uninstall command |
| screamer | 4:6e987db7a950 | 155 | @subcommand('add', 'url', |
| screamer | 4:6e987db7a950 | 156 | help='add a library to the current repository') |
| screamer | 4:6e987db7a950 | 157 | def add(url): |
| screamer | 4:6e987db7a950 | 158 | cwd = Repo() |
| screamer | 4:6e987db7a950 | 159 | repo = Repo.fromurl(url) |
| screamer | 4:6e987db7a950 | 160 | |
| screamer | 4:6e987db7a950 | 161 | import_(url) |
| screamer | 4:6e987db7a950 | 162 | |
| screamer | 4:6e987db7a950 | 163 | repo.update() |
| screamer | 4:6e987db7a950 | 164 | savelib(repo) |
| screamer | 4:6e987db7a950 | 165 | |
| screamer | 4:6e987db7a950 | 166 | popen([cwd.type, 'add', repo.lib]) |
| screamer | 4:6e987db7a950 | 167 | |
| screamer | 4:6e987db7a950 | 168 | @subcommand('remove', 'library', |
| screamer | 4:6e987db7a950 | 169 | help='remove a library from the current repository folder') |
| screamer | 4:6e987db7a950 | 170 | def remove(library): |
| screamer | 4:6e987db7a950 | 171 | cwd = Repo() |
| screamer | 4:6e987db7a950 | 172 | repo = Repo(library) |
| screamer | 4:6e987db7a950 | 173 | |
| screamer | 4:6e987db7a950 | 174 | popen([cwd.type, 'rm', '-f', repo.lib]) |
| screamer | 4:6e987db7a950 | 175 | if cwd.type == 'hg': |
| screamer | 4:6e987db7a950 | 176 | popen(['rm', '-f', repo.lib]) |
| screamer | 4:6e987db7a950 | 177 | |
| screamer | 4:6e987db7a950 | 178 | popen(['rm', '-rf', repo.path]) |
| screamer | 4:6e987db7a950 | 179 | |
| screamer | 4:6e987db7a950 | 180 | # Synch command |
| screamer | 4:6e987db7a950 | 181 | @subcommand('synch', |
| screamer | 4:6e987db7a950 | 182 | help='synchronize lib files') |
| screamer | 4:6e987db7a950 | 183 | def synch(): |
| screamer | 4:6e987db7a950 | 184 | cwd = Repo() |
| screamer | 4:6e987db7a950 | 185 | |
| screamer | 4:6e987db7a950 | 186 | for lib in iterlibs(): |
| screamer | 4:6e987db7a950 | 187 | repo = Repo.fromurl(lib) |
| screamer | 4:6e987db7a950 | 188 | repo.update() |
| screamer | 4:6e987db7a950 | 189 | if lib == repo.url: |
| screamer | 4:6e987db7a950 | 190 | continue |
| screamer | 4:6e987db7a950 | 191 | |
| screamer | 4:6e987db7a950 | 192 | savelib(repo) |
| screamer | 4:6e987db7a950 | 193 | |
| screamer | 4:6e987db7a950 | 194 | if cwd.type == 'git': |
| screamer | 4:6e987db7a950 | 195 | popen([cwd.type, 'add', repo.lib]) |
| screamer | 4:6e987db7a950 | 196 | |
| screamer | 4:6e987db7a950 | 197 | # Parse/run command |
| screamer | 4:6e987db7a950 | 198 | args = parser.parse_args() |
| screamer | 4:6e987db7a950 | 199 | status = args.command(args) |
| screamer | 4:6e987db7a950 | 200 | sys.exit(status or 0) |
| screamer | 4:6e987db7a950 | 201 |