279
282
# copy posixpath.abspath, but use os.getcwdu instead
280
283
if not posixpath.isabs(path):
281
284
path = posixpath.join(getcwd(), path)
282
return _posix_normpath(path)
285
return posixpath.normpath(path)
285
288
def _posix_realpath(path):
286
289
return posixpath.realpath(path.encode(_fs_enc)).decode(_fs_enc)
289
def _posix_normpath(path):
290
path = posixpath.normpath(path)
291
# Bug 861008: posixpath.normpath() returns a path normalized according to
292
# the POSIX standard, which stipulates (for compatibility reasons) that two
293
# leading slashes must not be simplified to one, and only if there are 3 or
294
# more should they be simplified as one. So we treat the leading 2 slashes
295
# as a special case here by simply removing the first slash, as we consider
296
# that breaking POSIX compatibility for this obscure feature is acceptable.
297
# This is not a paranoid precaution, as we notably get paths like this when
298
# the repo is hosted at the root of the filesystem, i.e. in "/".
299
if path.startswith('//'):
304
292
def _win32_fixdrive(path):
305
293
"""Force drive letters to be consistent.
2194
2153
return file_kind_from_stat_mode(mode)
2195
2154
file_kind_from_stat_mode = file_kind_from_stat_mode_thunk
2197
def file_stat(f, _lstat=os.lstat):
2157
def file_kind(f, _lstat=os.lstat):
2159
return file_kind_from_stat_mode(_lstat(f).st_mode)
2201
2160
except OSError, e:
2202
2161
if getattr(e, 'errno', None) in (errno.ENOENT, errno.ENOTDIR):
2203
2162
raise errors.NoSuchFile(f)
2206
def file_kind(f, _lstat=os.lstat):
2207
stat_value = file_stat(f, _lstat)
2208
return file_kind_from_stat_mode(stat_value.st_mode)
2210
2166
def until_no_eintr(f, *a, **kw):
2211
2167
"""Run f(*a, **kw), retrying if an EINTR error occurs.
2271
2227
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
2274
if sys.platform.startswith('linux'):
2231
if sys.platform == 'linux2':
2275
2232
def _local_concurrency():
2277
return os.sysconf('SC_NPROCESSORS_ONLN')
2278
except (ValueError, OSError, AttributeError):
2234
prefix = 'processor'
2235
for line in file('/proc/cpuinfo', 'rb'):
2236
if line.startswith(prefix):
2237
concurrency = int(line[line.find(':')+1:]) + 1
2280
2239
elif sys.platform == 'darwin':
2281
2240
def _local_concurrency():
2282
2241
return subprocess.Popen(['sysctl', '-n', 'hw.availcpu'],
2283
2242
stdout=subprocess.PIPE).communicate()[0]
2284
elif "bsd" in sys.platform:
2243
elif sys.platform[0:7] == 'freebsd':
2285
2244
def _local_concurrency():
2286
2245
return subprocess.Popen(['sysctl', '-n', 'hw.ncpu'],
2287
2246
stdout=subprocess.PIPE).communicate()[0]
2315
2274
concurrency = os.environ.get('BZR_CONCURRENCY', None)
2316
2275
if concurrency is None:
2318
import multiprocessing
2320
# multiprocessing is only available on Python >= 2.6
2322
concurrency = _local_concurrency()
2323
except (OSError, IOError):
2326
concurrency = multiprocessing.cpu_count()
2277
concurrency = _local_concurrency()
2278
except (OSError, IOError):
2328
2281
concurrency = int(concurrency)
2329
2282
except (TypeError, ValueError):
2400
2353
except UnicodeDecodeError:
2401
2354
raise errors.BzrError("Can't decode username as %s." % \
2403
except ImportError, e:
2404
if sys.platform != 'win32':
2406
if str(e) != 'No module named pwd':
2408
# https://bugs.launchpad.net/bzr/+bug/660174
2409
# getpass.getuser() is unable to return username on Windows
2410
# if there is no USERNAME environment variable set.
2411
# That could be true if bzr is running as a service,
2412
# e.g. running `bzr serve` as a service on Windows.
2413
# We should not fail with traceback in this case.
2414
username = u'UNKNOWN'
2415
2356
return username
2418
def available_backup_name(base, exists):
2419
"""Find a non-existing backup file name.
2421
This will *not* create anything, this only return a 'free' entry. This
2422
should be used for checking names in a directory below a locked
2423
tree/branch/repo to avoid race conditions. This is LBYL (Look Before You
2424
Leap) and generally discouraged.
2426
:param base: The base name.
2428
:param exists: A callable returning True if the path parameter exists.
2431
name = "%s.~%d~" % (base, counter)
2434
name = "%s.~%d~" % (base, counter)
2438
def set_fd_cloexec(fd):
2439
"""Set a Unix file descriptor's FD_CLOEXEC flag. Do nothing if platform
2440
support for this is not available.
2444
old = fcntl.fcntl(fd, fcntl.F_GETFD)
2445
fcntl.fcntl(fd, fcntl.F_SETFD, old | fcntl.FD_CLOEXEC)
2446
except (ImportError, AttributeError):
2447
# Either the fcntl module or specific constants are not present
2451
def find_executable_on_path(name):
2452
"""Finds an executable on the PATH.
2454
On Windows, this will try to append each extension in the PATHEXT
2455
environment variable to the name, if it cannot be found with the name
2458
:param name: The base name of the executable.
2459
:return: The path to the executable found or None.
2461
path = os.environ.get('PATH')
2464
path = path.split(os.pathsep)
2465
if sys.platform == 'win32':
2466
exts = os.environ.get('PATHEXT', '').split(os.pathsep)
2467
exts = [ext.lower() for ext in exts]
2468
base, ext = os.path.splitext(name)
2470
if ext.lower() not in exts:
2478
f = os.path.join(d, name) + ext
2479
if os.access(f, os.X_OK):
2484
def _posix_is_local_pid_dead(pid):
2485
"""True if pid doesn't correspond to live process on this machine"""
2487
# Special meaning of unix kill: just check if it's there.
2490
if e.errno == errno.ESRCH:
2491
# On this machine, and really not found: as sure as we can be
2494
elif e.errno == errno.EPERM:
2495
# exists, though not ours
2498
mutter("os.kill(%d, 0) failed: %s" % (pid, e))
2499
# Don't really know.
2502
# Exists and our process: not dead.
2505
if sys.platform == "win32":
2506
is_local_pid_dead = win32utils.is_local_pid_dead
2508
is_local_pid_dead = _posix_is_local_pid_dead
2511
def fdatasync(fileno):
2512
"""Flush file contents to disk if possible.
2514
:param fileno: Integer OS file handle.
2515
:raises TransportNotPossible: If flushing to disk is not possible.
2517
fn = getattr(os, 'fdatasync', getattr(os, 'fsync', None))