comparison mercurial/util.py @ 7732:3793802ea41b

Make util.find_exe alway returns existing file, fixing issue1459 It seems like the old behaviour with different handling for commands with and without path was intended, but I think this behaviour of util.find_exe is better: * Always returns existing file * or None if command not found - no default * Windows: Returned file thus always ends with extension from PATHEXT This fixes http://www.selenic.com/mercurial/bts/issue1459. The change might fix other unintended behaviour too.
author Mads Kiilerich <mads@kiilerich.com>
date Sun, 25 Jan 2009 21:20:13 +0100
parents 0895f95451e7
children b2410ed2cbe9
comparison
equal deleted inserted replaced
7731:737f274d1915 7732:3793802ea41b
651 if hg: 651 if hg:
652 set_hgexecutable(hg) 652 set_hgexecutable(hg)
653 elif main_is_frozen(): 653 elif main_is_frozen():
654 set_hgexecutable(sys.executable) 654 set_hgexecutable(sys.executable)
655 else: 655 else:
656 set_hgexecutable(find_exe('hg', 'hg')) 656 set_hgexecutable(find_exe('hg') or 'hg')
657 return _hgexecutable 657 return _hgexecutable
658 658
659 def set_hgexecutable(path): 659 def set_hgexecutable(path):
660 """set location of the 'hg' executable""" 660 """set location of the 'hg' executable"""
661 global _hgexecutable 661 global _hgexecutable
1268 # if you change this stub into a real check, please try to implement the 1268 # if you change this stub into a real check, please try to implement the
1269 # username and groupname functions above, too. 1269 # username and groupname functions above, too.
1270 def isowner(fp, st=None): 1270 def isowner(fp, st=None):
1271 return True 1271 return True
1272 1272
1273 def find_in_path(name, path, default=None): 1273 def find_exe(command):
1274 '''find name in search path. path can be string (will be split 1274 '''Find executable for command searching like cmd.exe does.
1275 with os.pathsep), or iterable thing that returns strings. if name 1275 If command is a basename then PATH is searched for command.
1276 found, return path to name. else return default. name is looked up 1276 PATH isn't searched if command is an absolute or relative path.
1277 using cmd.exe rules, using PATHEXT.''' 1277 An extension from PATHEXT is found and added if not present.
1278 if isinstance(path, str): 1278 If command isn't found None is returned.'''
1279 path = path.split(os.pathsep)
1280
1281 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD') 1279 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
1282 pathext = pathext.lower().split(os.pathsep) 1280 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
1283 isexec = os.path.splitext(name)[1].lower() in pathext 1281 if os.path.splitext(command)[1].lower() in pathexts:
1284 1282 pathexts = ['']
1285 for p in path: 1283
1286 p_name = os.path.join(p, name) 1284 def findexisting(pathcommand):
1287 1285 'Will append extension (if needed) and return existing file'
1288 if isexec and os.path.exists(p_name): 1286 for ext in pathexts:
1289 return p_name 1287 executable = pathcommand + ext
1290 1288 if os.path.exists(executable):
1291 for ext in pathext: 1289 return executable
1292 p_name_ext = p_name + ext 1290 return None
1293 if os.path.exists(p_name_ext): 1291
1294 return p_name_ext 1292 if os.sep in command:
1295 return default 1293 return findexisting(command)
1294
1295 for path in os.environ.get('PATH', '').split(os.pathsep):
1296 executable = findexisting(os.path.join(path, command))
1297 if executable is not None:
1298 return executable
1299 return None
1296 1300
1297 def set_signal_handler(): 1301 def set_signal_handler():
1298 try: 1302 try:
1299 set_signal_handler_win32() 1303 set_signal_handler_win32()
1300 except NameError: 1304 except NameError:
1456 """ 1460 """
1457 if st is None: 1461 if st is None:
1458 st = fstat(fp) 1462 st = fstat(fp)
1459 return st.st_uid == os.getuid() 1463 return st.st_uid == os.getuid()
1460 1464
1461 def find_in_path(name, path, default=None): 1465 def find_exe(command):
1462 '''find name in search path. path can be string (will be split 1466 '''Find executable for command searching like which does.
1463 with os.pathsep), or iterable thing that returns strings. if name 1467 If command is a basename then PATH is searched for command.
1464 found, return path to name. else return default.''' 1468 PATH isn't searched if command is an absolute or relative path.
1465 if isinstance(path, str): 1469 If command isn't found None is returned.'''
1466 path = path.split(os.pathsep) 1470 if sys.platform == 'OpenVMS':
1467 for p in path: 1471 return command
1468 p_name = os.path.join(p, name) 1472
1469 if os.path.exists(p_name): 1473 def findexisting(executable):
1470 return p_name 1474 'Will return executable if existing file'
1471 return default 1475 if os.path.exists(executable):
1476 return executable
1477 return None
1478
1479 if os.sep in command:
1480 return findexisting(command)
1481
1482 for path in os.environ.get('PATH', '').split(os.pathsep):
1483 executable = findexisting(os.path.join(path, command))
1484 if executable is not None:
1485 return executable
1486 return None
1472 1487
1473 def set_signal_handler(): 1488 def set_signal_handler():
1474 pass 1489 pass
1475
1476 def find_exe(name, default=None):
1477 '''find path of an executable.
1478 if name contains a path component, return it as is. otherwise,
1479 use normal executable search path.'''
1480
1481 if os.sep in name or sys.platform == 'OpenVMS':
1482 # don't check the executable bit. if the file isn't
1483 # executable, whoever tries to actually run it will give a
1484 # much more useful error message.
1485 return name
1486 return find_in_path(name, os.environ.get('PATH', ''), default=default)
1487 1490
1488 def mktempcopy(name, emptyok=False, createmode=None): 1491 def mktempcopy(name, emptyok=False, createmode=None):
1489 """Create a temporary file with the same contents from name 1492 """Create a temporary file with the same contents from name
1490 1493
1491 The permission bits are copied from the original file. 1494 The permission bits are copied from the original file.