Morpheus / Mbed OS mbed-Client-Morpheus-hg

Dependencies:   mbed-os

Committer:
Christopher Haster
Date:
Tue Mar 29 23:03:50 2016 -0500
Revision:
5:37ac884d9477
Parent:
4:6e987db7a950
Child:
6:622a477ef55c
Added deploy command

Who changed what in which revision?

UserRevisionLine numberNew 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
Christopher Haster 5:37ac884d9477 154 # Deploy command
Christopher Haster 5:37ac884d9477 155 @subcommand('deploy',
Christopher Haster 5:37ac884d9477 156 help='recursively import libraries in current directory')
Christopher Haster 5:37ac884d9477 157 def deploy():
Christopher Haster 5:37ac884d9477 158 for lib in iterlibs():
Christopher Haster 5:37ac884d9477 159 import_(lib)
Christopher Haster 5:37ac884d9477 160
screamer 4:6e987db7a950 161 # Install/uninstall command
screamer 4:6e987db7a950 162 @subcommand('add', 'url',
screamer 4:6e987db7a950 163 help='add a library to the current repository')
screamer 4:6e987db7a950 164 def add(url):
screamer 4:6e987db7a950 165 cwd = Repo()
screamer 4:6e987db7a950 166 repo = Repo.fromurl(url)
screamer 4:6e987db7a950 167
screamer 4:6e987db7a950 168 import_(url)
screamer 4:6e987db7a950 169
screamer 4:6e987db7a950 170 repo.update()
screamer 4:6e987db7a950 171 savelib(repo)
screamer 4:6e987db7a950 172
screamer 4:6e987db7a950 173 popen([cwd.type, 'add', repo.lib])
screamer 4:6e987db7a950 174
screamer 4:6e987db7a950 175 @subcommand('remove', 'library',
screamer 4:6e987db7a950 176 help='remove a library from the current repository folder')
screamer 4:6e987db7a950 177 def remove(library):
screamer 4:6e987db7a950 178 cwd = Repo()
screamer 4:6e987db7a950 179 repo = Repo(library)
screamer 4:6e987db7a950 180
screamer 4:6e987db7a950 181 popen([cwd.type, 'rm', '-f', repo.lib])
screamer 4:6e987db7a950 182 if cwd.type == 'hg':
screamer 4:6e987db7a950 183 popen(['rm', '-f', repo.lib])
screamer 4:6e987db7a950 184
screamer 4:6e987db7a950 185 popen(['rm', '-rf', repo.path])
screamer 4:6e987db7a950 186
screamer 4:6e987db7a950 187 # Synch command
screamer 4:6e987db7a950 188 @subcommand('synch',
screamer 4:6e987db7a950 189 help='synchronize lib files')
screamer 4:6e987db7a950 190 def synch():
screamer 4:6e987db7a950 191 cwd = Repo()
screamer 4:6e987db7a950 192
screamer 4:6e987db7a950 193 for lib in iterlibs():
screamer 4:6e987db7a950 194 repo = Repo.fromurl(lib)
screamer 4:6e987db7a950 195 repo.update()
screamer 4:6e987db7a950 196 if lib == repo.url:
screamer 4:6e987db7a950 197 continue
screamer 4:6e987db7a950 198
screamer 4:6e987db7a950 199 savelib(repo)
screamer 4:6e987db7a950 200
screamer 4:6e987db7a950 201 if cwd.type == 'git':
screamer 4:6e987db7a950 202 popen([cwd.type, 'add', repo.lib])
screamer 4:6e987db7a950 203
screamer 4:6e987db7a950 204 # Parse/run command
screamer 4:6e987db7a950 205 args = parser.parse_args()
screamer 4:6e987db7a950 206 status = args.command(args)
screamer 4:6e987db7a950 207 sys.exit(status or 0)
screamer 4:6e987db7a950 208