Mercurial > public > mercurial-scm > hg
annotate mercurial/util.py @ 1241:3b4f05ff3130
Add support for cloning with hardlinks on windows.
In order to use hardlinks, the win32file module is needed, and this is
present in ActivePython. If it isn't present, or hardlinks are not supported
on the underlying filesystem, a regular copy is used.
When using hardlinks the biggest benefit is probably the saving in space,
but cloning can be much quicker. For example cloning the Xen tree
(non trivial) without an update goes from about 95s to 15s.
Unix-like platforms should be unaffected, although should be more tolerant on
filesystems that don't support hard links.
(tweaked by mpm to deal with new copyfiles function)
--- hg.orig/mercurial/commands.py 2005-09-13 19:32:53.000000000 -0500
+++ hg/mercurial/commands.py 2005-09-14 12:11:34.000000000 -0500
@@ -620,10 +620,6 @@ def clone(ui, source, dest=None, **opts)
if other.dev() != -1:
abspath = os.path.abspath(source)
- copyfile = (os.stat(dest).st_dev == other.dev()
- and getattr(os, 'link', None) or shutil.copy2)
- if copyfile is not shutil.copy2:
- ui.note("cloning by hardlink\n")
# we use a lock here because if we race with commit, we can
# end up with extra data in the cloned revlogs that's not
@@ -638,7 +634,7 @@ def clone(ui, source, dest=None, **opts)
for f in files.split():
src = os.path.join(source, ".hg", f)
dst = os.path.join(dest, ".hg", f)
- util.copyfiles(src, dst, copyfile)
+ util.copyfiles(src, dst)
repo = hg.repository(ui, dest)
Index: hg/mercurial/util.py
===================================================================
--- hg.orig/mercurial/util.py 2005-09-08 00:15:25.000000000 -0500
+++ hg/mercurial/util.py 2005-09-14 12:16:49.000000000 -0500
@@ -12,7 +12,7 @@ platform-specific details from the core.
import os, errno
from demandload import *
-demandload(globals(), "re cStringIO")
+demandload(globals(), "re cStringIO shutil")
def binary(s):
"""return true if a string is binary data using diff's heuristic"""
@@ -217,17 +217,28 @@ def rename(src, dst):
os.unlink(dst)
os.rename(src, dst)
-def copyfiles(src, dst, copyfile):
- """Copy a directory tree, files are copied using 'copyfile'."""
+def copyfiles(src, dst, hardlink=None):
+ """Copy a directory tree using hardlinks if possible"""
+
+ if hardlink is None:
+ hardlink = (os.stat(src).st_dev ==
+ os.stat(os.path.dirname(dst)).st_dev)
if os.path.isdir(src):
os.mkdir(dst)
for name in os.listdir(src):
srcname = os.path.join(src, name)
dstname = os.path.join(dst, name)
- copyfiles(srcname, dstname, copyfile)
+ copyfiles(srcname, dstname, hardlink)
else:
- copyfile(src, dst)
+ if hardlink:
+ try:
+ os_link(src, dst)
+ except:
+ hardlink = False
+ shutil.copy2(src, dst)
+ else:
+ shutil.copy2(src, dst)
def opener(base):
"""
@@ -244,13 +255,13 @@ def opener(base):
if mode[0] != "r":
try:
- s = os.stat(f)
+ nlink = nlinks(f)
except OSError:
d = os.path.dirname(f)
if not os.path.isdir(d):
os.makedirs(d)
else:
- if s.st_nlink > 1:
+ if nlink > 1:
file(f + ".tmp", "wb").write(file(f, "rb").read())
rename(f+".tmp", f)
@@ -266,10 +277,41 @@ def _makelock_file(info, pathname):
def _readlock_file(pathname):
return file(pathname).read()
+def nlinks(pathname):
+ """Return number of hardlinks for the given file."""
+ return os.stat(pathname).st_nlink
+
+if hasattr(os, 'link'):
+ os_link = os.link
+else:
+ def os_link(src, dst):
+ raise OSError(0, "Hardlinks not supported")
+
# Platform specific variants
if os.name == 'nt':
nulldev = 'NUL:'
+ try: # ActivePython can create hard links using win32file module
+ import win32file
+
+ def os_link(src, dst): # NB will only succeed on NTFS
+ win32file.CreateHardLink(dst, src)
+
+ def nlinks(pathname):
+ """Return number of hardlinks for the given file."""
+ try:
+ fh = win32file.CreateFile(pathname,
+ win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
+ None, win32file.OPEN_EXISTING, 0, None)
+ res = win32file.GetFileInformationByHandle(fh)
+ fh.Close()
+ return res[7]
+ except:
+ return os.stat(pathname).st_nlink
+
+ except ImportError:
+ pass
+
def is_exec(f, last):
return last
author | Stephen Darnell |
---|---|
date | Wed, 14 Sep 2005 12:22:20 -0500 |
parents | a7b8812973d9 |
children | 1945754e466b |
rev | line source |
---|---|
1082 | 1 """ |
2 util.py - Mercurial utility functions and platform specfic implementations | |
3 | |
4 Copyright 2005 K. Thananchayan <thananck@yahoo.com> | |
5 | |
6 This software may be used and distributed according to the terms | |
7 of the GNU General Public License, incorporated herein by reference. | |
8 | |
9 This contains helper routines that are independent of the SCM core and hide | |
10 platform-specific details from the core. | |
11 """ | |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
12 |
704
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
13 import os, errno |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
14 from demandload import * |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
15 demandload(globals(), "re cStringIO shutil") |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
16 |
1015
22571b8d35d3
Add automatic binary file detection to diff and export
mpm@selenic.com
parents:
917
diff
changeset
|
17 def binary(s): |
1082 | 18 """return true if a string is binary data using diff's heuristic""" |
1015
22571b8d35d3
Add automatic binary file detection to diff and export
mpm@selenic.com
parents:
917
diff
changeset
|
19 if s and '\0' in s[:4096]: |
22571b8d35d3
Add automatic binary file detection to diff and export
mpm@selenic.com
parents:
917
diff
changeset
|
20 return True |
22571b8d35d3
Add automatic binary file detection to diff and export
mpm@selenic.com
parents:
917
diff
changeset
|
21 return False |
22571b8d35d3
Add automatic binary file detection to diff and export
mpm@selenic.com
parents:
917
diff
changeset
|
22 |
556 | 23 def unique(g): |
1082 | 24 """return the uniq elements of iterable g""" |
556 | 25 seen = {} |
26 for f in g: | |
27 if f not in seen: | |
28 seen[f] = 1 | |
29 yield f | |
30 | |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
31 class Abort(Exception): |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
32 """Raised if a command needs to print an error and exit.""" |
508 | 33 |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
34 def always(fn): return True |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
35 def never(fn): return False |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
36 |
1062 | 37 def globre(pat, head='^', tail='$'): |
724
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
38 "convert a glob pattern into a regexp" |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
39 i, n = 0, len(pat) |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
40 res = '' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
41 group = False |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
42 def peek(): return i < n and pat[i] |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
43 while i < n: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
44 c = pat[i] |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
45 i = i+1 |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
46 if c == '*': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
47 if peek() == '*': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
48 i += 1 |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
49 res += '.*' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
50 else: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
51 res += '[^/]*' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
52 elif c == '?': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
53 res += '.' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
54 elif c == '[': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
55 j = i |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
56 if j < n and pat[j] in '!]': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
57 j += 1 |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
58 while j < n and pat[j] != ']': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
59 j += 1 |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
60 if j >= n: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
61 res += '\\[' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
62 else: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
63 stuff = pat[i:j].replace('\\','\\\\') |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
64 i = j + 1 |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
65 if stuff[0] == '!': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
66 stuff = '^' + stuff[1:] |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
67 elif stuff[0] == '^': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
68 stuff = '\\' + stuff |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
69 res = '%s[%s]' % (res, stuff) |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
70 elif c == '{': |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
71 group = True |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
72 res += '(?:' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
73 elif c == '}' and group: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
74 res += ')' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
75 group = False |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
76 elif c == ',' and group: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
77 res += '|' |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
78 else: |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
79 res += re.escape(c) |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
80 return head + res + tail |
1c0c413cccdd
Get add and locate to use new repo and dirstate walk code.
Bryan O'Sullivan <bos@serpentine.com>
parents:
705
diff
changeset
|
81 |
812
b65af904d6d7
Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents:
782
diff
changeset
|
82 _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} |
b65af904d6d7
Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents:
782
diff
changeset
|
83 |
884
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
84 def pathto(n1, n2): |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
85 '''return the relative path from one place to another. |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
86 this returns a path in the form used by the local filesystem, not hg.''' |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
87 if not n1: return localpath(n2) |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
88 a, b = n1.split('/'), n2.split('/') |
884
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
89 a.reverse(), b.reverse() |
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
90 while a and b and a[-1] == b[-1]: |
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
91 a.pop(), b.pop() |
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
92 b.reverse() |
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
93 return os.sep.join((['..'] * len(a)) + b) |
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
878
diff
changeset
|
94 |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
95 def canonpath(root, cwd, myname): |
1082 | 96 """return the canonical path of myname, given cwd and root""" |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
97 rootsep = root + os.sep |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
98 name = myname |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
99 if not name.startswith(os.sep): |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
100 name = os.path.join(root, cwd, name) |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
101 name = os.path.normpath(name) |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
102 if name.startswith(rootsep): |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
103 return pconvert(name[len(rootsep):]) |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
104 elif name == root: |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
105 return '' |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
106 else: |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
107 raise Abort('%s not under root' % myname) |
897 | 108 |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
109 def matcher(canonroot, cwd, names, inc, exc, head=''): |
1082 | 110 """build a function to match a set of file patterns |
111 | |
112 arguments: | |
113 canonroot - the canonical root of the tree you're matching against | |
114 cwd - the current working directory, if relevant | |
115 names - patterns to find | |
116 inc - patterns to include | |
117 exc - patterns to exclude | |
118 head - a regex to prepend to patterns to control whether a match is rooted | |
119 | |
120 a pattern is one of: | |
121 're:<regex>' | |
122 'glob:<shellglob>' | |
123 'path:<explicit path>' | |
124 'relpath:<relative path>' | |
125 '<relative path>' | |
126 | |
127 returns: | |
128 a 3-tuple containing | |
129 - list of explicit non-pattern names passed in | |
130 - a bool match(filename) function | |
131 - a bool indicating if any patterns were passed in | |
132 | |
133 todo: | |
134 make head regex a rooted bool | |
135 """ | |
136 | |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
137 def patkind(name): |
888
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
138 for prefix in 're:', 'glob:', 'path:', 'relpath:': |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
139 if name.startswith(prefix): return name.split(':', 1) |
812
b65af904d6d7
Reduce the amount of stat traffic generated by a walk.
Bryan O'Sullivan <bos@serpentine.com>
parents:
782
diff
changeset
|
140 for c in name: |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
141 if c in _globchars: return 'glob', name |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
142 return 'relpath', name |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
143 |
888
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
144 def regex(kind, name, tail): |
742 | 145 '''convert a pattern into a regular expression''' |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
146 if kind == 're': |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
147 return name |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
148 elif kind == 'path': |
888
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
149 return '^' + re.escape(name) + '(?:/|$)' |
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
150 elif kind == 'relpath': |
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
151 return head + re.escape(name) + tail |
742 | 152 return head + globre(name, '', tail) |
153 | |
154 def matchfn(pats, tail): | |
155 """build a matching function from a set of patterns""" | |
156 if pats: | |
888
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
157 pat = '(?:%s)' % '|'.join([regex(k, p, tail) for (k, p) in pats]) |
742 | 158 return re.compile(pat).match |
159 | |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
160 def globprefix(pat): |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
161 '''return the non-glob prefix of a path, e.g. foo/* -> foo''' |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
162 root = [] |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
163 for p in pat.split(os.sep): |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
164 if patkind(p)[0] == 'glob': break |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
165 root.append(p) |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
166 return '/'.join(root) |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
167 |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
168 pats = [] |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
169 files = [] |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
170 roots = [] |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
171 for kind, name in map(patkind, names): |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
172 if kind in ('glob', 'relpath'): |
1081
8b7d63489db3
Change canonpath to not know about repo objects
mpm@selenic.com
parents:
1075
diff
changeset
|
173 name = canonpath(canonroot, cwd, name) |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
174 if name == '': |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
175 kind, name = 'glob', '**' |
888
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
176 if kind in ('glob', 'path', 're'): |
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
177 pats.append((kind, name)) |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
178 if kind == 'glob': |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
179 root = globprefix(name) |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
180 if root: roots.append(root) |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
181 elif kind == 'relpath': |
888
e7a943e8c52b
Fix up handling of regexp paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
886
diff
changeset
|
182 files.append((kind, name)) |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
183 roots.append(name) |
897 | 184 |
820
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
185 patmatch = matchfn(pats, '$') or always |
89985a1b3427
Clean up walk and changes code to use normalised names properly.
Bryan O'Sullivan <bos@serpentine.com>
parents:
814
diff
changeset
|
186 filematch = matchfn(files, '(?:/|$)') or always |
897 | 187 incmatch = always |
188 if inc: | |
189 incmatch = matchfn(map(patkind, inc), '(?:/|$)') | |
190 excmatch = lambda fn: False | |
191 if exc: | |
192 excmatch = matchfn(map(patkind, exc), '(?:/|$)') | |
742 | 193 |
1031
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
194 return (roots, |
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
195 lambda fn: (incmatch(fn) and not excmatch(fn) and |
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
196 (fn.endswith('/') or |
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
197 (not pats and not files) or |
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
198 (pats and patmatch(fn)) or |
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
199 (files and filematch(fn)))), |
503aaf19a040
Rewrite log command. New version is faster and more featureful.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1015
diff
changeset
|
200 (inc or exc or (pats and pats != [('glob', '**')])) and True) |
742 | 201 |
521 | 202 def system(cmd, errprefix=None): |
508 | 203 """execute a shell command that must succeed""" |
204 rc = os.system(cmd) | |
205 if rc: | |
521 | 206 errmsg = "%s %s" % (os.path.basename(cmd.split(None, 1)[0]), |
207 explain_exit(rc)[0]) | |
208 if errprefix: | |
209 errmsg = "%s: %s" % (errprefix, errmsg) | |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
869
diff
changeset
|
210 raise Abort(errmsg) |
508 | 211 |
421 | 212 def rename(src, dst): |
1082 | 213 """forcibly rename a file""" |
421 | 214 try: |
215 os.rename(src, dst) | |
216 except: | |
217 os.unlink(dst) | |
218 os.rename(src, dst) | |
219 | |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
220 def copyfiles(src, dst, hardlink=None): |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
221 """Copy a directory tree using hardlinks if possible""" |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
222 |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
223 if hardlink is None: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
224 hardlink = (os.stat(src).st_dev == |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
225 os.stat(os.path.dirname(dst)).st_dev) |
698
df78d8ccac4c
Use python function instead of external 'cp' command when cloning repos.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
667
diff
changeset
|
226 |
1207 | 227 if os.path.isdir(src): |
228 os.mkdir(dst) | |
229 for name in os.listdir(src): | |
230 srcname = os.path.join(src, name) | |
231 dstname = os.path.join(dst, name) | |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
232 copyfiles(srcname, dstname, hardlink) |
1207 | 233 else: |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
234 if hardlink: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
235 try: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
236 os_link(src, dst) |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
237 except: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
238 hardlink = False |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
239 shutil.copy2(src, dst) |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
240 else: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
241 shutil.copy2(src, dst) |
698
df78d8ccac4c
Use python function instead of external 'cp' command when cloning repos.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
667
diff
changeset
|
242 |
1090 | 243 def opener(base): |
244 """ | |
245 return a function that opens files relative to base | |
246 | |
247 this function is used to hide the details of COW semantics and | |
248 remote file access from higher level code. | |
249 """ | |
250 p = base | |
251 def o(path, mode="r"): | |
252 f = os.path.join(p, path) | |
253 | |
254 mode += "b" # for that other OS | |
255 | |
256 if mode[0] != "r": | |
257 try: | |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
258 nlink = nlinks(f) |
1090 | 259 except OSError: |
260 d = os.path.dirname(f) | |
261 if not os.path.isdir(d): | |
262 os.makedirs(d) | |
263 else: | |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
264 if nlink > 1: |
1090 | 265 file(f + ".tmp", "wb").write(file(f, "rb").read()) |
266 rename(f+".tmp", f) | |
267 | |
268 return file(f, mode) | |
269 | |
270 return o | |
271 | |
704
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
272 def _makelock_file(info, pathname): |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
273 ld = os.open(pathname, os.O_CREAT | os.O_WRONLY | os.O_EXCL) |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
274 os.write(ld, info) |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
275 os.close(ld) |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
276 |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
277 def _readlock_file(pathname): |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
278 return file(pathname).read() |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
279 |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
280 def nlinks(pathname): |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
281 """Return number of hardlinks for the given file.""" |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
282 return os.stat(pathname).st_nlink |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
283 |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
284 if hasattr(os, 'link'): |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
285 os_link = os.link |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
286 else: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
287 def os_link(src, dst): |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
288 raise OSError(0, "Hardlinks not supported") |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
289 |
1082 | 290 # Platform specific variants |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
291 if os.name == 'nt': |
461 | 292 nulldev = 'NUL:' |
293 | |
1241
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
294 try: # ActivePython can create hard links using win32file module |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
295 import win32file |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
296 |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
297 def os_link(src, dst): # NB will only succeed on NTFS |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
298 win32file.CreateHardLink(dst, src) |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
299 |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
300 def nlinks(pathname): |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
301 """Return number of hardlinks for the given file.""" |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
302 try: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
303 fh = win32file.CreateFile(pathname, |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
304 win32file.GENERIC_READ, win32file.FILE_SHARE_READ, |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
305 None, win32file.OPEN_EXISTING, 0, None) |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
306 res = win32file.GetFileInformationByHandle(fh) |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
307 fh.Close() |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
308 return res[7] |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
309 except: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
310 return os.stat(pathname).st_nlink |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
311 |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
312 except ImportError: |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
313 pass |
3b4f05ff3130
Add support for cloning with hardlinks on windows.
Stephen Darnell
parents:
1207
diff
changeset
|
314 |
441 | 315 def is_exec(f, last): |
316 return last | |
317 | |
318 def set_exec(f, mode): | |
319 pass | |
515 | 320 |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
321 def pconvert(path): |
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
322 return path.replace("\\", "/") |
422
10c43444a38e
[PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents:
421
diff
changeset
|
323 |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
324 def localpath(path): |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
325 return path.replace('/', '\\') |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
326 |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
327 def normpath(path): |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
328 return pconvert(os.path.normpath(path)) |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
329 |
704
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
330 makelock = _makelock_file |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
331 readlock = _readlock_file |
461 | 332 |
782
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
333 def explain_exit(code): |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
334 return "exited with status %d" % code, code |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
335 |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
336 else: |
461 | 337 nulldev = '/dev/null' |
338 | |
441 | 339 def is_exec(f, last): |
1082 | 340 """check whether a file is executable""" |
441 | 341 return (os.stat(f).st_mode & 0100 != 0) |
342 | |
343 def set_exec(f, mode): | |
344 s = os.stat(f).st_mode | |
345 if (s & 0100 != 0) == mode: | |
346 return | |
347 if mode: | |
348 # Turn on +x for every +r bit when making a file executable | |
349 # and obey umask. | |
350 umask = os.umask(0) | |
351 os.umask(umask) | |
352 os.chmod(f, s | (s & 0444) >> 2 & ~umask) | |
353 else: | |
354 os.chmod(f, s & 0666) | |
355 | |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
356 def pconvert(path): |
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
357 return path |
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
diff
changeset
|
358 |
886
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
359 def localpath(path): |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
360 return path |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
361 |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
362 normpath = os.path.normpath |
509de8ab6f31
Fix walk path handling on Windows
Bryan O'Sullivan <bos@serpentine.com>
parents:
884
diff
changeset
|
363 |
422
10c43444a38e
[PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents:
421
diff
changeset
|
364 def makelock(info, pathname): |
704
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
365 try: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
366 os.symlink(info, pathname) |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
367 except OSError, why: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
368 if why.errno == errno.EEXIST: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
369 raise |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
370 else: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
371 _makelock_file(info, pathname) |
422
10c43444a38e
[PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents:
421
diff
changeset
|
372 |
10c43444a38e
[PATCH] Enables lock work under the other 'OS'
mpm@selenic.com
parents:
421
diff
changeset
|
373 def readlock(pathname): |
704
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
374 try: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
375 return os.readlink(pathname) |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
376 except OSError, why: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
377 if why.errno == errno.EINVAL: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
378 return _readlock_file(pathname) |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
379 else: |
5ca319a641e1
Make makelock and readlock work on filesystems without symlink support.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
698
diff
changeset
|
380 raise |
782
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
381 |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
382 def explain_exit(code): |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
383 """return a 2-tuple (desc, code) describing a process's status""" |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
384 if os.WIFEXITED(code): |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
385 val = os.WEXITSTATUS(code) |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
386 return "exited with status %d" % val, val |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
387 elif os.WIFSIGNALED(code): |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
388 val = os.WTERMSIG(code) |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
389 return "killed by signal %d" % val, val |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
390 elif os.WIFSTOPPED(code): |
912
302f83b85054
Minor tweak: os.STOPSIG -> os.WSTOPSIG. Pychecker spotted this one.
mark.williamson@cl.cam.ac.uk
parents:
897
diff
changeset
|
391 val = os.WSTOPSIG(code) |
782
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
392 return "stopped by signal %d" % val, val |
cdb9e95b2fab
Provided platform dependent implementations for explain_exit
thananck@yahoo.com
parents:
742
diff
changeset
|
393 raise ValueError("invalid exit code") |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
394 |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
395 class chunkbuffer(object): |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
396 """Allow arbitrary sized chunks of data to be efficiently read from an |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
397 iterator over chunks of arbitrary size.""" |
1200 | 398 |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
399 def __init__(self, in_iter, targetsize = 2**16): |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
400 """in_iter is the iterator that's iterating over the input chunks. |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
401 targetsize is how big a buffer to try to maintain.""" |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
402 self.in_iter = iter(in_iter) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
403 self.buf = '' |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
404 self.targetsize = int(targetsize) |
1200 | 405 if self.targetsize <= 0: |
406 raise ValueError("targetsize must be greater than 0, was %d" % | |
407 targetsize) | |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
408 self.iterempty = False |
1200 | 409 |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
410 def fillbuf(self): |
1200 | 411 """Ignore target size; read every chunk from iterator until empty.""" |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
412 if not self.iterempty: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
413 collector = cStringIO.StringIO() |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
414 collector.write(self.buf) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
415 for ch in self.in_iter: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
416 collector.write(ch) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
417 self.buf = collector.getvalue() |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
418 self.iterempty = True |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
419 |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
420 def read(self, l): |
1200 | 421 """Read L bytes of data from the iterator of chunks of data. |
422 Returns less than L bytes if the iterator runs dry.""" | |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
423 if l > len(self.buf) and not self.iterempty: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
424 # Clamp to a multiple of self.targetsize |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
425 targetsize = self.targetsize * ((l // self.targetsize) + 1) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
426 collector = cStringIO.StringIO() |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
427 collector.write(self.buf) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
428 collected = len(self.buf) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
429 for chunk in self.in_iter: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
430 collector.write(chunk) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
431 collected += len(chunk) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
432 if collected >= targetsize: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
433 break |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
434 if collected < targetsize: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
435 self.iterempty = True |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
436 self.buf = collector.getvalue() |
1200 | 437 s, self.buf = self.buf[:l], buffer(self.buf, l) |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
438 return s |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
439 |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
440 def filechunkiter(f, size = 65536): |
1200 | 441 """Create a generator that produces all the data in the file size |
442 (default 65536) bytes at a time. Chunks may be less than size | |
443 bytes if the chunk is the last chunk in the file, or the file is a | |
444 socket or some other type of file that sometimes reads less data | |
445 than is requested.""" | |
1199
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
446 s = f.read(size) |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
447 while len(s) >= 0: |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
448 yield s |
78ceaf83f28f
Created a class in util called chunkbuffer that buffers reads from an
Eric Hopper <hopper@omnifarious.org>
parents:
1169
diff
changeset
|
449 s = f.read(size) |