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
Diff: neo.py
- Revision:
- 3:47aa05d37724
- Child:
- 4:6e987db7a950
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/neo.py Wed Mar 30 20:17:20 2016 +0000 @@ -0,0 +1,201 @@ +#!/usr/bin/env python + +import argparse +import sys +import re +import subprocess +import os +import contextlib +import collections + +# 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: + subparser.add_argument(arg) + + def thunk(parsed_args): + ordered_args = [vars(parsed_args)[arg] 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): + # print for debugging + print ' '.join(command) + proc = subprocess.Popen(command) + + if proc.wait() != 0: + raise ProcessException(proc.returncode) + +def pquery(command, stdin=None): + proc = subprocess.Popen(command, stdout=subprocess.PIPE) + 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 file in os.listdir(dir or os.getcwd()): + if file.startswith('.'): + continue + elif os.path.isfile(file) and file.endswith('.lib'): + with open(file) as f: + yield f.read().strip() + +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): + repo = cls.__new__(cls) + + m = re.match('^(.*/([+a-zA-Z0-9_-]+)/?)(?:#(.*))?$', url) + repo.repo = m.group(1) + repo.name = 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 [('git', '.git'), ('hg', '.hg')]: + 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', + help='recursively import a repository') +def import_(url): + repo = Repo.fromurl(url) + + for type in ['git', 'hg']: + try: + popen([type, 'clone', repo.repo]) + 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 lib in iterlibs(): + import_(lib) + +# Install/uninstall command +@subcommand('install', 'url', + help='add a submodule to the current repository') +def install(url): + cwd = Repo() + repo = Repo.fromurl(url) + + import_(url) + + repo.update() + savelib(repo) + + popen([cwd.type, 'add', repo.lib]) + +@subcommand('uninstall', 'module', + help='remove a submodule') +def uninstall(module): + cwd = Repo() + repo = Repo(module) + + popen([cwd.type, 'rm', '-f', repo.lib]) + if cwd.type == 'hg': + popen(['rm', '-f', repo.lib]) + + popen(['rm', '-rf', repo.path]) + +# Synch command +@subcommand('synch', + help='synchronize lib files') +def synch(): + cwd = Repo() + + for lib in iterlibs(): + repo = Repo.fromurl(lib) + repo.update() + if lib == repo.url: + continue + + savelib(repo) + + if cwd.type == 'git': + popen([cwd.type, 'add', repo.lib]) + +# Parse/run command +args = parser.parse_args() +status = args.command(args) +sys.exit(status or 0) +