Mercurial > public > mercurial-scm > hg
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. |