comparison mercurial/util.py @ 6062:3c3b126e5619

Make files in .hg inherit the permissions from .hg/store
author Alexis S. L. Carvalho <alexis@cecm.usp.br>
date Sat, 09 Feb 2008 18:38:54 -0200
parents 090b1a665901
children 59a9dc9562e2 e85deb6dcf9d
comparison
equal deleted inserted replaced
6061:de08788511d7 6062:3c3b126e5619
1296 def encodedopener(openerfn, fn): 1296 def encodedopener(openerfn, fn):
1297 def o(path, *args, **kw): 1297 def o(path, *args, **kw):
1298 return openerfn(fn(path), *args, **kw) 1298 return openerfn(fn(path), *args, **kw)
1299 return o 1299 return o
1300 1300
1301 def mktempcopy(name, emptyok=False): 1301 def mktempcopy(name, emptyok=False, createmode=None):
1302 """Create a temporary file with the same contents from name 1302 """Create a temporary file with the same contents from name
1303 1303
1304 The permission bits are copied from the original file. 1304 The permission bits are copied from the original file.
1305 1305
1306 If the temporary file is going to be truncated immediately, you 1306 If the temporary file is going to be truncated immediately, you
1317 try: 1317 try:
1318 st_mode = os.lstat(name).st_mode & 0777 1318 st_mode = os.lstat(name).st_mode & 0777
1319 except OSError, inst: 1319 except OSError, inst:
1320 if inst.errno != errno.ENOENT: 1320 if inst.errno != errno.ENOENT:
1321 raise 1321 raise
1322 st_mode = 0666 & ~_umask 1322 st_mode = createmode
1323 if st_mode is None:
1324 st_mode = ~_umask
1325 st_mode &= 0666
1323 os.chmod(temp, st_mode) 1326 os.chmod(temp, st_mode)
1324 if emptyok: 1327 if emptyok:
1325 return temp 1328 return temp
1326 try: 1329 try:
1327 try: 1330 try:
1348 1351
1349 All writes will be redirected to a temporary copy of the original 1352 All writes will be redirected to a temporary copy of the original
1350 file. When rename is called, the copy is renamed to the original 1353 file. When rename is called, the copy is renamed to the original
1351 name, making the changes visible. 1354 name, making the changes visible.
1352 """ 1355 """
1353 def __init__(self, name, mode): 1356 def __init__(self, name, mode, createmode):
1354 self.__name = name 1357 self.__name = name
1355 self.temp = mktempcopy(name, emptyok=('w' in mode)) 1358 self.temp = mktempcopy(name, emptyok=('w' in mode),
1359 createmode=createmode)
1356 posixfile.__init__(self, self.temp, mode) 1360 posixfile.__init__(self, self.temp, mode)
1357 1361
1358 def rename(self): 1362 def rename(self):
1359 if not self.closed: 1363 if not self.closed:
1360 posixfile.close(self) 1364 posixfile.close(self)
1364 if not self.closed: 1368 if not self.closed:
1365 try: 1369 try:
1366 os.unlink(self.temp) 1370 os.unlink(self.temp)
1367 except: pass 1371 except: pass
1368 posixfile.close(self) 1372 posixfile.close(self)
1373
1374 def makedirs(name, mode=None):
1375 """recursive directory creation with parent mode inheritance"""
1376 try:
1377 os.mkdir(name)
1378 if mode is not None:
1379 os.chmod(name, mode)
1380 return
1381 except OSError, err:
1382 if err.errno == errno.EEXIST:
1383 return
1384 if err.errno != errno.ENOENT:
1385 raise
1386 parent = os.path.abspath(os.path.dirname(name))
1387 makedirs(parent, mode)
1388 makedirs(name, mode)
1369 1389
1370 class opener(object): 1390 class opener(object):
1371 """Open files relative to a base directory 1391 """Open files relative to a base directory
1372 1392
1373 This class is used to hide the details of COW semantics and 1393 This class is used to hide the details of COW semantics and
1377 self.base = base 1397 self.base = base
1378 if audit: 1398 if audit:
1379 self.audit_path = path_auditor(base) 1399 self.audit_path = path_auditor(base)
1380 else: 1400 else:
1381 self.audit_path = always 1401 self.audit_path = always
1402 self.createmode = None
1382 1403
1383 def __getattr__(self, name): 1404 def __getattr__(self, name):
1384 if name == '_can_symlink': 1405 if name == '_can_symlink':
1385 self._can_symlink = checklink(self.base) 1406 self._can_symlink = checklink(self.base)
1386 return self._can_symlink 1407 return self._can_symlink
1387 raise AttributeError(name) 1408 raise AttributeError(name)
1388 1409
1410 def _fixfilemode(self, name):
1411 if self.createmode is None:
1412 return
1413 os.chmod(name, self.createmode & 0666)
1414
1389 def __call__(self, path, mode="r", text=False, atomictemp=False): 1415 def __call__(self, path, mode="r", text=False, atomictemp=False):
1390 self.audit_path(path) 1416 self.audit_path(path)
1391 f = os.path.join(self.base, path) 1417 f = os.path.join(self.base, path)
1392 1418
1393 if not text and "b" not in mode: 1419 if not text and "b" not in mode:
1394 mode += "b" # for that other OS 1420 mode += "b" # for that other OS
1395 1421
1422 nlink = -1
1396 if mode[0] != "r": 1423 if mode[0] != "r":
1397 try: 1424 try:
1398 nlink = nlinks(f) 1425 nlink = nlinks(f)
1399 except OSError: 1426 except OSError:
1400 nlink = 0 1427 nlink = 0
1401 d = os.path.dirname(f) 1428 d = os.path.dirname(f)
1402 if not os.path.isdir(d): 1429 if not os.path.isdir(d):
1403 os.makedirs(d) 1430 makedirs(d, self.createmode)
1404 if atomictemp: 1431 if atomictemp:
1405 return atomictempfile(f, mode) 1432 return atomictempfile(f, mode, self.createmode)
1406 if nlink > 1: 1433 if nlink > 1:
1407 rename(mktempcopy(f), f) 1434 rename(mktempcopy(f), f)
1408 return posixfile(f, mode) 1435 fp = posixfile(f, mode)
1436 if nlink == 0:
1437 self._fixfilemode(f)
1438 return fp
1409 1439
1410 def symlink(self, src, dst): 1440 def symlink(self, src, dst):
1411 self.audit_path(dst) 1441 self.audit_path(dst)
1412 linkname = os.path.join(self.base, dst) 1442 linkname = os.path.join(self.base, dst)
1413 try: 1443 try:
1415 except OSError: 1445 except OSError:
1416 pass 1446 pass
1417 1447
1418 dirname = os.path.dirname(linkname) 1448 dirname = os.path.dirname(linkname)
1419 if not os.path.exists(dirname): 1449 if not os.path.exists(dirname):
1420 os.makedirs(dirname) 1450 makedirs(dirname, self.createmode)
1421 1451
1422 if self._can_symlink: 1452 if self._can_symlink:
1423 try: 1453 try:
1424 os.symlink(src, linkname) 1454 os.symlink(src, linkname)
1425 except OSError, err: 1455 except OSError, err:
1427 (src, err.strerror), linkname) 1457 (src, err.strerror), linkname)
1428 else: 1458 else:
1429 f = self(dst, "w") 1459 f = self(dst, "w")
1430 f.write(src) 1460 f.write(src)
1431 f.close() 1461 f.close()
1462 self._fixfilemode(dst)
1432 1463
1433 class chunkbuffer(object): 1464 class chunkbuffer(object):
1434 """Allow arbitrary sized chunks of data to be efficiently read from an 1465 """Allow arbitrary sized chunks of data to be efficiently read from an
1435 iterator over chunks of arbitrary size.""" 1466 iterator over chunks of arbitrary size."""
1436 1467