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