22import re
33import sys
44import os
5+ import errno
56
67
7- recursive = True
8- base_url = 'https://api.github.com'
9- # /repos/:owner/:repo/git/trees/:sha?recursive=:bool
10- tree_endpoint = base_url + '/repos/{}/{}/git/trees/{}?recursive={}'
11- contents_endpoint = base_url + '/repos/{}/{}/contents'
12- commits_endpoint = base_url + '/repos/{}/{}/commits'
13- base_normalize_regex = re .compile (r'.*github\.com\/' )
8+ GH_API_BASE_URL = 'https://api.github.com'
9+ GH_REPO_CONTENTS_ENDPOINT = GH_API_BASE_URL + '/repos/{}/{}/contents'
10+ BASE_NORMALIZE_REGEX = re .compile (r'.*github\.com\/' )
1411
1512
1613def exit_with_m (m = 'An error occured' ):
17- print m
18- sys .exit ()
19-
20-
21- def joinp (* args ):
22- '/' .join (args )
23-
14+ print (m )
15+ sys .exit (1 )
2416
2517def mkdir_p (path ):
2618 try :
2719 os .makedirs (path )
28- except OSError as exc : # Python >2.5
29- if exc .errno == errno .EEXIST and os .path .isdir (path ):
20+ except OSError as err : # Python >2.5
21+ if err .errno == errno .EEXIST and os .path .isdir (path ):
3022 pass
3123 else :
3224 raise
3325
34-
35- def fetch_file (req_url , file_path ):
36- r = requests .get (req_url , stream = True )
26+ def clone_file (download_url , file_path ):
27+ """
28+ Clones the file at the download_url to the file_path
29+ """
30+ print ('Cloning file' , file_path )
31+ r = requests .get (download_url , stream = True )
3732 try :
3833 r .raise_for_status ()
3934 except Exception as e :
40- exit_with_m ('Failed fetching ' + req_url , e )
35+ exit_with_m ('Failed cloneing ' + download_url , e )
4136
4237 with open (file_path , 'wb' ) as fd :
43- for chunk in req .iter_content (chunk_size = 128 ):
38+ for chunk in r .iter_content (chunk_size = 128 ):
4439 fd .write (chunk )
4540
46-
47- def fetch (base_url , path = None ):
41+ def clone (base_url , path = None ):
4842 """
49- Recursively fetch the repo metadata
43+ Recursively clones the path
5044 """
51- req_url = base_url if not path else joinp (base_url , path )
52- # Request
45+ print ('Cloning directory' , path )
46+ req_url = base_url if not path else os .path .join (base_url , path )
47+ # Get path metadata
5348 r = requests .get (req_url )
54-
5549 try :
5650 r .raise_for_status ()
5751 except Exception as e :
58- exit_with_m ('Failed fetching repo metdata: ' , e )
59-
52+ exit_with_m ('Failed fetching metadata of dir: ' , e )
6053 repo_data = r .json ()
6154
55+ # Create path locally
56+ mkdir_p (path )
57+
6258 if isinstance (repo_data , list ):
63- # Recursively fetch content
59+ # Recursively clone content
6460 for item in repo_data :
6561 if item ['type' ] == 'dir' :
66- # create dir and then fetch recursively
67- print 'Walking dir: %s' % item ['path' ]
68- path = joinp (path , item ['path' ])
69- fetch (joinp (base_url , path ))
62+ # Fetch dir recursively
63+ clone (base_url , item ['path' ])
7064 else :
71- # download it
72- # Ensure dir directory exists locally
73- mkdir_p (path )
74- print 'Fetching file: %s' % item ['path' ]
65+ # Fetch the file
66+ clone_file (item ['download_url' ], item ['path' ])
7567
7668
77- if len (sys .argv ) > 1 :
69+ ###
70+ # Main
71+ ###
72+ arg_len = len (sys .argv )
73+ if arg_len >= 2 :
74+ # Github URL
7875 gh_url = sys .argv [1 ]
76+ # Normalize & parse input
77+ normal_gh_url = re .sub (BASE_NORMALIZE_REGEX , '' , gh_url ).replace ('/tree' , '' )
78+ gh_url_comps = normal_gh_url .split ('/' )
79+ user , repo = gh_url_comps [:2 ]
80+ branch = gh_url_comps [2 ]
81+ path = os .path .join (* gh_url_comps [3 :])
7982else :
8083 exit_with_m ('Nothing to clone :(' )
8184
82- # Normalize & parse input
83- norm_gh_url = re .sub (base_normalize_regex , '' , gh_url )
84- gh_url_comps = norm_gh_url .split ('/' )
85- user , repo = gh_url_comps [:2 ]
86- branch = gh_url_comps [3 ]
87- path = joinp (gh_url_comps [4 :])
88-
89-
90- api_req_url = contents_endpoint .format (user , repo )
91-
92- print "Fetching sub repo %s..." % (api_req_url )
93-
94- fetch (api_req_url , path )
85+ api_req_url = GH_REPO_CONTENTS_ENDPOINT .format (user , repo )
86+ print ("Cloning into '%s'..." % path )
87+ clone (api_req_url , path )
88+ print ("done." )
0 commit comments