3333import urllib2
3434import zipfile
3535import argparse
36+ import tempfile
3637
3738
3839# Application version
39- ver = '0.9.10 '
40+ ver = '1.0.0 '
4041
4142# Default paths to Mercurial and Git
4243hg_cmd = 'hg'
121122verbose = False
122123very_verbose = False
123124install_requirements = True
125+ cache_repositories = True
124126
125127# stores current working directory for recursive operations
126128cwd_root = ""
@@ -264,10 +266,19 @@ def init(path):
264266 if not os .path .exists (path ):
265267 os .mkdir (path )
266268
269+ def cleanup ():
270+ info ("Cleaning up library build folder" )
271+ for fl in os .listdir ('.' ):
272+ if not fl .startswith ('.' ):
273+ if os .path .isfile (fl ):
274+ os .remove (fl )
275+ else :
276+ shutil .rmtree (fl )
277+
267278 def clone (url , path = None , depth = None , protocol = None ):
268279 m = Bld .isurl (url )
269280 if not m :
270- raise ProcessException (1 , "Not an mbed library build URL" )
281+ raise ProcessException (1 , "Not a library build URL" )
271282
272283 try :
273284 Bld .init (path )
@@ -277,60 +288,51 @@ def clone(url, path=None, depth=None, protocol=None):
277288 error (e [1 ], e [0 ])
278289
279290 def fetch_rev (url , rev ):
280- tmp_file = os .path .join ('.' + Bld .name , '.rev-' + rev + '.zip' )
281- arch_dir = 'mbed-' + rev
291+ rev_file = os .path .join ('.' + Bld .name , '.rev-' + rev + '.zip' )
282292 try :
283- if not os .path .exists (tmp_file ):
284- action ("Downloading mbed library build \" %s\" (might take a minute)" % rev )
285- outfd = open (tmp_file , 'wb' )
293+ if not os .path .exists (rev_file ):
294+ action ("Downloading library build \" %s\" (might take a minute)" % rev )
295+ outfd = open (rev_file , 'wb' )
286296 inurl = urllib2 .urlopen (url )
287297 outfd .write (inurl .read ())
288298 outfd .close ()
289299 except :
290- if os .path .isfile (tmp_file ):
291- os .remove (tmp_file )
300+ if os .path .isfile (rev_file ):
301+ os .remove (rev_file )
292302 raise Exception (128 , "Download failed!\n Please try again later." )
293303
304+ def unpack_rev (rev ):
305+ rev_file = os .path .join ('.' + Bld .name , '.rev-' + rev + '.zip' )
294306 try :
295- with zipfile .ZipFile (tmp_file ) as zf :
296- action ("Unpacking mbed library build \" %s\" in \" %s\" " % (rev , os .getcwd ()))
297- zf .extractall ()
307+ with zipfile .ZipFile (rev_file ) as zf :
308+ action ("Unpacking library build \" %s\" in \" %s\" " % (rev , os .getcwd ()))
309+ zf .extractall ('.' )
298310 except :
299- if os .path .isfile (tmp_file ):
300- os .remove (tmp_file )
301- if os .path .isfile (arch_dir ):
302- rmtree_readonly (arch_dir )
303- raise Exception (128 , "An error occurred while unpacking mbed library archive \" %s\" in \" %s\" " % (tmp_file , os .getcwd ()))
311+ if os .path .isfile (rev_file ):
312+ os .remove (rev_file )
313+ raise Exception (128 , "An error occurred while unpacking library archive \" %s\" in \" %s\" " % (rev_file , os .getcwd ()))
304314
305315 def checkout (rev , clean = False ):
306316 url = Bld .geturl ()
307317 m = Bld .isurl (url )
308318 if not m :
309- raise ProcessException (1 , "Not an mbed library build URL" )
319+ raise ProcessException (1 , "Not a library build URL" )
310320 rev = Hg .remoteid (m .group (1 ), rev )
311321 if not rev :
312- error ("Unable to fetch late mbed library revision" )
313-
314- if rev != Bld .getrev ():
315- info ("Cleaning up library build folder" )
316- for fl in os .listdir ('.' ):
317- if not fl .startswith ('.' ):
318- if os .path .isfile (fl ):
319- os .remove (fl )
320- else :
321- shutil .rmtree (fl )
322+ error ("Unable to fetch library build information" )
323+
324+ arch_url = m .group (1 ) + '/archive/' + rev + '.zip'
325+ Bld .fetch_rev (arch_url , rev )
326+
327+ if rev != Bld .getrev () or clean :
328+ Bld .cleanup ()
322329
323330 info ("Checkout \" %s\" in %s" % (rev , os .path .basename (os .getcwd ())))
324- arch_url = m .group (1 ) + '/archive/' + rev + '.zip'
325- arch_dir = m .group (7 ) + '-' + rev
326331 try :
327- if not os . path . exists ( arch_dir ):
328- Bld .fetch_rev ( arch_url , rev )
332+ Bld . unpack_rev ( rev )
333+ Bld .seturl ( url + '/' + rev )
329334 except Exception as e :
330- if os .path .exists (arch_dir ):
331- rmtree_readonly (arch_dir )
332335 error (e [1 ], e [0 ])
333- Bld .seturl (url + '/' + rev )
334336
335337 def update (rev = None , clean = False , clean_files = False , is_local = False ):
336338 return Bld .checkout (rev , clean )
@@ -339,6 +341,7 @@ def untracked():
339341 return ""
340342
341343 def seturl (url ):
344+ info ("Setting url to \" %s\" in %s" % (url , os .getcwd ()))
342345 if not os .path .exists ('.' + Bld .name ):
343346 os .mkdir ('.' + Bld .name )
344347
@@ -382,6 +385,9 @@ def isurl(url):
382385 def init (path = None ):
383386 popen ([hg_cmd , 'init' ] + ([path ] if path else []) + (['-v' ] if very_verbose else ([] if verbose else ['-q' ])))
384387
388+ def cleanup ():
389+ return True
390+
385391 def clone (url , name = None , depth = None , protocol = None ):
386392 popen ([hg_cmd , 'clone' , formaturl (url , protocol ), name ] + (['-v' ] if very_verbose else ([] if verbose else ['-q' ])))
387393
@@ -445,11 +451,36 @@ def outgoing():
445451 raise e
446452 return 0
447453
454+ def seturl (url ):
455+ info ("Setting url to \" %s\" in %s" % (url , os .getcwd ()))
456+ hgrc = os .path .join ('.hg' , 'hgrc' )
457+ tagpaths = '[paths]'
458+ remote = 'default'
459+ lines = []
460+
461+ try :
462+ with open (hgrc ) as f :
463+ lines = f .read ().splitlines ()
464+ except IOError :
465+ pass
466+
467+ if tagpaths in lines :
468+ idx = lines .index (tagpaths )
469+ m = re .match (r'^([\w_]+)\s*=\s*(.*)$' , lines [idx + 1 ])
470+ if m :
471+ remote = m .group (1 )
472+ del lines [idx + 1 ]
473+ lines .insert (idx , remote + ' = ' + url )
474+ else :
475+ lines .append (tagpaths )
476+ lines .append (remote + ' = ' + url )
477+
448478 def geturl ():
449479 tagpaths = '[paths]'
450480 default_url = ''
451481 url = ''
452- if os .path .isfile (os .path .join ('.hg' , 'hgrc' )):
482+
483+ try :
453484 with open (os .path .join ('.hg' , 'hgrc' )) as f :
454485 lines = f .read ().splitlines ()
455486 if tagpaths in lines :
@@ -460,8 +491,11 @@ def geturl():
460491 default_url = m .group (2 )
461492 else :
462493 url = m .group (2 )
463- if default_url :
464- url = default_url
494+ except IOError :
495+ pass
496+
497+ if default_url :
498+ url = default_url
465499
466500 return formaturl (url or pquery ([hg_cmd , 'paths' , 'default' ]).strip ())
467501
@@ -551,6 +585,11 @@ def isurl(url):
551585 def init (path = None ):
552586 popen ([git_cmd , 'init' ] + ([path ] if path else []) + ([] if very_verbose else ['-q' ]))
553587
588+ def cleanup ():
589+ info ("Cleaning up Git index" )
590+ if os .path .exists (os .path .join ('.git' , 'logs' )):
591+ rmtree_readonly (os .path .join ('.git' , 'logs' ))
592+
554593 def clone (url , name = None , depth = None , protocol = None ):
555594 popen ([git_cmd , 'clone' , formaturl (url , protocol ), name ] + (['--depth' , depth ] if depth else []) + (['-v' ] if very_verbose else ([] if verbose else ['-q' ])))
556595
@@ -623,10 +662,10 @@ def checkout(rev, clean=False):
623662 popen ([git_cmd , 'checkout' , rev ] + (['-f' ] if clean else []) + ([] if very_verbose else ['-q' ]))
624663
625664 def update (rev = None , clean = False , clean_files = False , is_local = False ):
626- if clean :
627- Git .discard (clean_files )
628665 if not is_local :
629666 Git .fetch ()
667+ if clean :
668+ Git .discard (clean_files )
630669 if rev :
631670 Git .checkout (rev , clean )
632671 else :
@@ -638,11 +677,11 @@ def update(rev=None, clean=False, clean_files=False, is_local=False):
638677 except ProcessException :
639678 pass
640679 else :
641- err = "Unable to update \" %s\" in \" %s\" .\n " % (os .path .basename (os .getcwd ()), os .getcwd ())
680+ err = "Unable to update \" %s\" in \" %s\" ." % (os .path .basename (os .getcwd ()), os .getcwd ())
642681 if not remote :
643- info (err + "The local repository is not associated with a remote one." )
682+ info (err + " The local repository is not associated with a remote one." )
644683 if not branch :
645- info (err + "Working set is not on a branch." )
684+ info (err + " Working set is not on a branch." )
646685
647686 def status ():
648687 return pquery ([git_cmd , 'status' , '-s' ] + (['-v' ] if very_verbose else []))
@@ -698,6 +737,10 @@ def getremotes(rtype='fetch'):
698737 result .append ([remote [0 ], remote [1 ], t ])
699738 return result
700739
740+ def seturl (url ):
741+ info ("Setting url to \" %s\" in %s" % (url , os .getcwd ()))
742+ return pquery ([git_cmd , 'remote' , 'set-url' , 'origin' , url ]).strip ()
743+
701744 def geturl ():
702745 url = ""
703746 remotes = Git .getremotes ()
@@ -810,12 +853,15 @@ def fromurl(cls, url, path=None):
810853 repo .path = os .path .abspath (path or os .path .join (os .getcwd (), repo .name ))
811854 repo .url = formaturl (m_repo_url .group (1 ))
812855 repo .rev = m_repo_url .group (3 )
813- if repo .rev and not re .match (r'^([a-fA-F0-9]{6,40})$' , repo .rev ):
856+ if repo .rev and repo . rev != 'latest' and not re .match (r'^([a-fA-F0-9]{6,40})$' , repo .rev ):
814857 error ('Invalid revision (%s)' % repo .rev , - 1 )
815858 else :
816859 error ('Invalid repository (%s)' % url .strip (), - 1 )
817860
818- repo .cache = Program (repo .path ).get_cfg ('CACHE' )
861+ cache_cfg = Global ().get_cfg ('CACHE' , '' )
862+ if cache_repositories and cache_cfg and cache_cfg != 'none' and cache_cfg != 'off' and cache_cfg != 'disabled' :
863+ loc = cache_cfg if (cache_cfg and cache_cfg != 'on' and cache_cfg != 'enabled' ) else None
864+ repo .cache = loc or os .path .join (tempfile .gettempdir (), 'mbed-repo-cache' )
819865
820866 return repo
821867
@@ -846,7 +892,11 @@ def fromrepo(cls, path=None):
846892
847893 repo .path = os .path .abspath (path )
848894 repo .name = os .path .basename (repo .path )
849- repo .cache = Program (repo .path ).get_cfg ('CACHE' )
895+
896+ cache_cfg = Global ().get_cfg ('CACHE' , '' )
897+ if cache_repositories and cache_cfg and cache_cfg != 'none' and cache_cfg != 'off' and cache_cfg != 'disabled' :
898+ loc = cache_cfg if (cache_cfg and cache_cfg != 'on' and cache_cfg != 'enabled' ) else None
899+ repo .cache = loc or os .path .join (tempfile .gettempdir (), 'mbed-repo-cache' )
850900
851901 repo .sync ()
852902
@@ -1004,10 +1054,13 @@ def clone(self, url, path, rev=None, depth=None, protocol=None, **kwargs):
10041054 shutil .copytree (cache , path )
10051055
10061056 with cd (path ):
1057+ scm .seturl (formaturl (url , protocol ))
1058+ scm .cleanup ()
10071059 info ("Update cached copy from remote repository" )
10081060 scm .update (rev , True )
10091061 main = False
10101062 except (ProcessException , IOError ):
1063+ info ("Discarding cached repository" )
10111064 if os .path .isdir (path ):
10121065 rmtree_readonly (path )
10131066
@@ -1160,7 +1213,7 @@ def __init__(self, path=None, print_warning=False):
11601213 if self .is_cwd and print_warning :
11611214 warning (
11621215 "Could not find mbed program in current path \" %s\" .\n "
1163- "You can fix this by calling \" mbed new .\" or \" mbed config root . \" in the root of your program." % self .path )
1216+ "You can fix this by calling \" mbed new .\" in the root of your program." % self .path )
11641217
11651218 def get_cfg (self , * args , ** kwargs ):
11661219 return Cfg (self .path ).get (* args , ** kwargs ) or Global ().get_cfg (* args , ** kwargs )
@@ -1304,18 +1357,15 @@ def add_tools(self, path):
13041357 error ("An error occurred while cloning the mbed SDK tools from \" %s\" " % mbed_sdk_tools_url )
13051358
13061359 def update_tools (self , path ):
1307- if not os .path .exists (path ):
1308- os .mkdir (path )
1309- with cd (path ):
1310- tools_dir = 'tools'
1311- if os .path .exists (tools_dir ):
1312- with cd (tools_dir ):
1313- try :
1314- action ("Updating the mbed 2.0 SDK tools..." )
1315- repo = Repo .fromrepo ()
1316- repo .update ()
1317- except Exception :
1318- error ("An error occurred while update the mbed SDK tools from \" %s\" " % mbed_sdk_tools_url )
1360+ tools_dir = 'tools'
1361+ if os .path .exists (os .path .join (path , tools_dir )):
1362+ with cd (os .path .join (path , tools_dir )):
1363+ try :
1364+ action ("Updating the mbed 2.0 SDK tools..." )
1365+ repo = Repo .fromrepo ()
1366+ repo .update ()
1367+ except Exception :
1368+ error ("An error occurred while update the mbed SDK tools from \" %s\" " % mbed_sdk_tools_url )
13191369
13201370 def get_tools (self ):
13211371 mbed_tools_path = self .get_tools_dir ()
@@ -1373,6 +1423,7 @@ def get_macros(self):
13731423 macros = f .read ().splitlines ()
13741424 return macros
13751425
1426+
13761427 def ignore_build_dir (self ):
13771428 build_path = os .path .join (self .path , self .build_dir )
13781429 if not os .path .exists (build_path ):
@@ -1436,6 +1487,9 @@ def __init__(self, path):
14361487
14371488 # Sets config value
14381489 def set (self , var , val ):
1490+ if not re .match (r'^([\w+-]+)$' , var ):
1491+ error ("%s is invalid config variable name" % var )
1492+
14391493 fl = os .path .join (self .path , self .file )
14401494 try :
14411495 with open (fl ) as f :
@@ -1630,15 +1684,11 @@ def new(name, scm='git', program=False, library=False, mbedlib=False, create_onl
16301684 p .path = cwd_root
16311685 p .set_root ()
16321686 if not create_only and not p .get_os_dir () and not p .get_mbedlib_dir ():
1633- url = mbed_lib_url if mbedlib else mbed_os_url
1687+ url = mbed_lib_url if mbedlib else mbed_os_url + '#latest'
16341688 d = 'mbed' if mbedlib else 'mbed-os'
16351689 try :
16361690 with cd (d_path ):
16371691 add (url , depth = depth , protocol = protocol , top = False )
1638- if not mbedlib :
1639- with cd (d ):
1640- repo = Repo .fromrepo ()
1641- repo .checkout ('latest' )
16421692 except Exception as e :
16431693 if os .path .isdir (os .path .join (d_path , d )):
16441694 rmtree_readonly (os .path .join (d_path , d ))
@@ -1690,7 +1740,8 @@ def import_(url, path=None, ignore=False, depth=None, protocol=None, top=True):
16901740 with cd (repo .path ):
16911741 Program (repo .path ).set_root ()
16921742 try :
1693- repo .checkout (repo .rev , True )
1743+ if repo .rev and repo .getrev () != repo .rev :
1744+ repo .checkout (repo .rev , True )
16941745 except ProcessException as e :
16951746 err = "Unable to update \" %s\" to %s" % (repo .name , repo .revtype (repo .rev , True ))
16961747 if depth :
@@ -2383,6 +2434,10 @@ def config_(var=None, value=None, global_cfg=False, unset=False, list_config=Fal
23832434 else :
23842435 # Find the root of the program
23852436 program = Program (os .getcwd ())
2437+ if program .is_cwd :
2438+ error (
2439+ "Could not find mbed program in current path \" %s\" .\n "
2440+ "Change the current directory to a valid mbed program or use the '--global' option to set global configuration." % program .path )
23862441 with cd (program .path ):
23872442 if unset :
23882443 program .set_cfg (var , None )
0 commit comments