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
- Committer:
- Christopher Haster
- Date:
- 2016-03-30
- Revision:
- 17:1e487c450f06
- Parent:
- 16:b54f256e339e
- Child:
- 18:1b4252106474
File content as of revision 17:1e487c450f06:
#!/usr/bin/env python import argparse import sys import re import subprocess import os import contextlib import collections import shutil from itertools import * # Subparser handling parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() def subcommand(name, *args, **kwargs): def subcommand(command): subparser = subparsers.add_parser(name, **kwargs) for arg in args: if arg.endswith('?'): subparser.add_argument(arg.strip('?'), nargs='?') elif arg.endswith('*'): pass else: subparser.add_argument(arg) def thunk(parsed_args): ordered_args = [vars(parsed_args)[arg.strip('?*')] if not arg.endswith('*') else remainder for arg in args] return command(*ordered_args) subparser.set_defaults(command=thunk) return command return subcommand # Process execution class ProcessException(Exception): pass def popen(command, stdin=None, **kwargs): # print for debugging print ' '.join(command) proc = subprocess.Popen(command, **kwargs) if proc.wait() != 0: raise ProcessException(proc.returncode) def pquery(command, stdin=None, **kwargs): proc = subprocess.Popen(command, stdout=subprocess.PIPE, **kwargs) stdout, _ = proc.communicate(stdin) if proc.returncode != 0: raise ProcessException(proc.returncode) return stdout # Directory navigation @contextlib.contextmanager def cd(newdir): prevdir = os.getcwd() os.chdir(newdir) try: yield finally: os.chdir(prevdir) def iterlibs(dir=None): for root, dirs, files in os.walk(dir or os.getcwd()): if os.path.basename(root).startswith('.'): del dirs[:] continue for file in files: if file.startswith('.'): continue elif file.endswith('.lib'): with open(os.path.join(root, file)) as f: yield f.read().strip(), os.path.join(root, file[:-4]) if file[:-4] in dirs: dirs.remove(file[:-4]) def savelib(repo): print repo.name, '->', repo.url with open(repo.lib, 'w') as f: f.write(repo.url + '\n') # Handling for multiple version controls class Repo(object): def __init__(self, path=None): self.path = path or os.getcwd() self.name = os.path.basename(self.path) self.update() @classmethod def fromurl(cls, url, name=None): repo = cls.__new__(cls) m = re.match('^(.*/([+a-zA-Z0-9_-]+)/?)(?:#(.*))?$', url) repo.repo = m.group(1) repo.name = name or m.group(2) repo.hash = m.group(3) repo.path = os.path.join(os.getcwd(), repo.name) return repo @property def lib(self): return self.path + '.lib' @property def url(self): if self.repo: if self.hash: return self.repo + '#' + self.hash else: return self.repo def update(self): if os.path.isdir(self.path): self.type = self.gettype() self.hash = self.gethash() if os.path.isfile(self.lib): with open(self.lib) as f: temp = Repo.fromurl(f.read()) self.repo = temp.repo def gettype(self): for type, dir in [('hg', '.hg'), ('git', '.git')]: if os.path.isdir(os.path.join(self.path, dir)): return type def gethash(self): with cd(self.path): if self.type == 'git': return pquery(['git', 'rev-parse', '--short', 'HEAD']).strip() elif self.type == 'hg': return pquery(['hg', 'id', '-i']).strip() # Clone command @subcommand('import', 'url', 'name?', help='recursively import a repository') def import_(url, name=None): repo = Repo.fromurl(url, name) for type in ['hg', 'git']: try: popen([type, 'clone', repo.repo, repo.path]) break except: pass repo.type = repo.gettype() if repo.hash: with cd(repo.path): popen([repo.type, 'checkout', repo.hash]) repo.update() with cd(repo.path): for url, lib in iterlibs(): import_(url, lib) # Deploy command @subcommand('deploy', help='recursively import libraries in current directory') def deploy(): for url, lib in iterlibs(): import_(url, lib) # Install/uninstall command @subcommand('add', 'url', 'name?', help='add a library to the current repository') def add(url, name): cwd = Repo() repo = Repo.fromurl(url, name) import_(url) repo.update() savelib(repo) popen([cwd.type, 'add', repo.lib]) @subcommand('remove', 'library', help='remove a library from the current repository folder') def remove(library): cwd = Repo() repo = Repo(library) popen([cwd.type, 'rm', '-f', repo.lib]) try: if cwd.type == 'hg': os.remove(repo.lib) shutil.rmtree(repo.path) except OSError: pass # Publish command @subcommand('publish', help='recursively publish changes to remote repositories') def publish(): cwd = Repo() for url, lib in iterlibs(): if os.path.isdir(lib): with cd(lib): publish() synch() if cwd.type == 'hg': modified = pquery(['hg', 'status']) elif cwd.type == 'git': modified = pquery(['git', 'diff', '--name-only', 'HEAD']) if modified: print cwd.path print 'Uncommitted changes in %s' % cwd.name raw_input('Press enter to commit/push') popen([cwd.type, 'commit'] + (['-a'] if cwd.type == 'git' else [])) popen([cwd.type, 'push'] + (['-a'] if cwd.type == 'git' else [])) # Synch command @subcommand('synch', help='synchronize lib files') def synch(): cwd = Repo() for url, lib in iterlibs(): repo = Repo.fromurl(url, lib) repo.update() if lib == repo.url: continue savelib(repo) if cwd.type == 'git': popen([cwd.type, 'add', repo.lib]) # Compile command @subcommand('compile', 'args*', help='compile project using workspace_tools') def compile(args): cwd = Repo() if not os.path.isdir('mbed-os'): sys.stderr.write('Warning! mbed-os not found?') sys.exit(-1) if not os.path.isfile('mbed_settings.py'): shutil.copy('mbed-os/tools/settings.py', 'mbed_settings.py') if os.path.isfile('MACROS.txt'): with open('MACROS.txt') as f: macros = f.read().splitlines() env = os.environ.copy() env['PYTHONPATH'] = '.' popen(['python', 'mbed-os/tools/make.py'] + list(chain.from_iterable(izip(repeat('-D'), macros))) + ['--source=%s' % cwd.path, '--build=%s' % os.path.join(cwd.path, '.build')] + args, env=env) # Export command @subcommand('export', 'args*', help='generate project files') def export(args): cwd = Repo() if not os.path.isdir('mbed-os'): sys.stderr.write('Warning! mbed-os not found?') sys.exit(-1) if not os.path.isfile('mbed_settings.py'): shutil.copy('mbed-os/tools/settings.py', 'mbed_settings.py') popen(['python', 'mbed-os/tools/project.py', '--source=%s' % cwd.path] + args) # Parse/run command args, remainder = parser.parse_known_args() status = args.command(args) sys.exit(status or 0)