-
Notifications
You must be signed in to change notification settings - Fork 1
/
get-min
76 lines (76 loc) · 3.97 KB
/
get-min
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import os
import subprocess
import argparse
import json
import urllib2
import base64
import sys
DEFAULT_PROFILE='~/.get/default.json'
def log(message):
if len(message)>0:sys.stderr.write('%s\n'%message)
class Path:
def __init__(self):self.items=os.environ['PATH'].split(':')
def prepend(self,item):
if not item in self:self.items.insert(0,item)
def append(self,item):
if not item in self:self.items.append(item)
def __str__(self):return ':'.join(self.items)
def __contains__(self,item):return item in self.items
class Chdir:
def __init__(self,directory):self.directory=directory
def __enter__(self):self.previous=os.getcwd();os.chdir(self.directory);log("Changing directory to '%s'..."%self.directory);return self
def __exit__(self,exc_type,exc_val,exc_tb):log("Restoring directory to '%s'..."%self.previous);os.chdir(self.previous)
def git(parameters):
try:
command=['git']+parameters;log('Running: %s'%' '.join(command));output=subprocess.check_output(command);lines=output.split('\n')
for line in lines:log(line)
except:log('Unable to clone repository.');exit(1)
def add_repository(url,directory):
target=os.path.expanduser(directory);target=os.path.abspath(target);url=os.path.expanduser(url);parent,file=os.path.split(target)
if not os.path.exists(parent):os.makedirs(parent)
if not os.path.exists(target):
with Chdir(parent):log('Checking out repository...');git(['clone',url,target])
else:
with Chdir(target):log('Updating the repository...');git(['pull'])
return target
def read_profile(filename):
with open(filename) as f:profile=f.read();profile=json.loads(profile)
return profile
def main():
parser=argparse.ArgumentParser(description='Clone or update git repositories and ensure they are available on the path.');parser.add_argument('profile',nargs='?',default=DEFAULT_PROFILE,help='JSON encoded profile as a string, file or URL. If no profile is specified then the default local path of ~/.get/default.json will be used');parser.add_argument('-u','--username',help='Username for basic HTTP authentication');parser.add_argument('-p','--password',help='Username for basic HTTP authentication');parser.add_argument('-P','--persist',action='store_true',default=False,help='Persist the path modifications by appending to ~/.bash_profile');parser.add_argument('-s','--save',action='store_true',default=False,help='Merge the profile into the default profile for future updates');options=parser.parse_args();profile=None
try:profile=json.loads(options.profile)
except:
file=os.path.expanduser(options.profile)
try:profile=read_profile(file)
except:
request=urllib2.Request(options.profile);username=options.username
try:
if not username:username=os.environ['GET_USERNAME']
except:pass
password=options.password
try:
if not password:password=os.environ['GET_PASSWORD']
except:pass
if username and password:base64string=base64.encodestring('%s:%s'%(username,password)).replace('\n','');request.add_header('Authorization','Basic %s'%base64string)
try:response=urllib2.urlopen(request);profile=response.read();profile=json.loads(profile)
except:pass
if not profile:log("Unable to load profile '%s'."%options.profile);sys.exit(0)
repositories=[]
for key,value in profile.iteritems():repositories.append(add_repository(value,'~/.get/%s'%key))
path=Path();exports=[]
if options.persist:
for repository in repositories:
if not repository in path:exports.append('export PATH=%s:$PATH\n'%repository)
if len(exports)>0:
with open(os.path.expanduser('~/.bash_profile'),'a') as file:
file.write('\n')
for export in exports:file.write(export)
for repository in repositories:path.prepend(repository)
print('export PATH=%s'%path)
if options.save and options.profile!=DEFAULT_PROFILE:
log('Saving profile...');default={};default_filename=os.path.expanduser(DEFAULT_PROFILE)
try:default=read_profile(default_filename)
except:pass
default=dict(default.items()+profile.items())
with open(default_filename,'w') as file:json.dump(default,file)
if __name__=='__main__':main()