##// END OF EJS Templates
Merge with main
Brendan Cully -
r9282:f9087eea merge default
parent child Browse files
Show More
@@ -0,0 +1,4 b''
1 #!/bin/sh
2
3 hg clone --quiet $TESTDIR/test-path-normalization.hg t
4 exec hg st -R t
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -249,12 +249,12 b' def reposetup(ui, repo):'
249 key = self._bookmarks[key]
249 key = self._bookmarks[key]
250 return super(bookmark_repo, self).lookup(key)
250 return super(bookmark_repo, self).lookup(key)
251
251
252 def commit(self, *k, **kw):
252 def commitctx(self, ctx, error=False):
253 """Add a revision to the repository and
253 """Add a revision to the repository and
254 move the bookmark"""
254 move the bookmark"""
255 wlock = self.wlock() # do both commit and bookmark with lock held
255 wlock = self.wlock() # do both commit and bookmark with lock held
256 try:
256 try:
257 node = super(bookmark_repo, self).commit(*k, **kw)
257 node = super(bookmark_repo, self).commitctx(ctx, error)
258 if node is None:
258 if node is None:
259 return None
259 return None
260 parents = self.changelog.parents(node)
260 parents = self.changelog.parents(node)
@@ -262,12 +262,13 b' def reposetup(ui, repo):'
262 parents = (parents[0],)
262 parents = (parents[0],)
263 marks = parse(self)
263 marks = parse(self)
264 update = False
264 update = False
265 for mark, n in marks.items():
265 if ui.configbool('bookmarks', 'track.current'):
266 if ui.configbool('bookmarks', 'track.current'):
266 mark = current(self)
267 if mark == current(self) and n in parents:
267 if mark and marks[mark] in parents:
268 marks[mark] = node
268 marks[mark] = node
269 update = True
269 update = True
270 else:
270 else:
271 for mark, n in marks.items():
271 if n in parents:
272 if n in parents:
272 marks[mark] = node
273 marks[mark] = node
273 update = True
274 update = True
@@ -288,10 +289,16 b' def reposetup(ui, repo):'
288 node = self.changelog.tip()
289 node = self.changelog.tip()
289 marks = parse(self)
290 marks = parse(self)
290 update = False
291 update = False
291 for mark, n in marks.items():
292 if ui.configbool('bookmarks', 'track.current'):
292 if n in parents:
293 mark = current(self)
294 if mark and marks[mark] in parents:
293 marks[mark] = node
295 marks[mark] = node
294 update = True
296 update = True
297 else:
298 for mark, n in marks.items():
299 if n in parents:
300 marks[mark] = node
301 update = True
295 if update:
302 if update:
296 write(self, marks)
303 write(self, marks)
297 return result
304 return result
@@ -59,7 +59,7 b' class dirstate(object):'
59 def _foldmap(self):
59 def _foldmap(self):
60 f = {}
60 f = {}
61 for name in self._map:
61 for name in self._map:
62 f[os.path.normcase(name)] = name
62 f[util.realpath(self._join(name))] = name
63 return f
63 return f
64
64
65 @propertycache
65 @propertycache
@@ -340,7 +340,7 b' class dirstate(object):'
340 self._ui.warn(_("not in dirstate: %s\n") % f)
340 self._ui.warn(_("not in dirstate: %s\n") % f)
341
341
342 def _normalize(self, path, knownpath):
342 def _normalize(self, path, knownpath):
343 norm_path = os.path.normcase(path)
343 norm_path = util.realpath(self._join(path))
344 fold_path = self._foldmap.get(norm_path, None)
344 fold_path = self._foldmap.get(norm_path, None)
345 if fold_path is None:
345 if fold_path is None:
346 if knownpath or not os.path.exists(os.path.join(self._root, path)):
346 if knownpath or not os.path.exists(os.path.join(self._root, path)):
@@ -138,7 +138,7 b' def share(ui, source, dest=None, update='
138 try:
138 try:
139 uprev = r.lookup(test)
139 uprev = r.lookup(test)
140 break
140 break
141 except:
141 except LookupError:
142 continue
142 continue
143 _update(r, uprev)
143 _update(r, uprev)
144
144
@@ -36,7 +36,10 b' def _smtp(ui):'
36 if username and password:
36 if username and password:
37 ui.note(_('(authenticating to mail server as %s)\n') %
37 ui.note(_('(authenticating to mail server as %s)\n') %
38 (username))
38 (username))
39 s.login(username, password)
39 try:
40 s.login(username, password)
41 except smtplib.SMTPException, inst:
42 raise util.Abort(inst)
40
43
41 def send(sender, recipients, msg):
44 def send(sender, recipients, msg):
42 try:
45 try:
@@ -182,6 +182,7 b' def readgitpatch(lr):'
182 lineno = 0
182 lineno = 0
183 for line in lr:
183 for line in lr:
184 lineno += 1
184 lineno += 1
185 line = line.rstrip(' \r\n')
185 if line.startswith('diff --git'):
186 if line.startswith('diff --git'):
186 m = gitre.match(line)
187 m = gitre.match(line)
187 if m:
188 if m:
@@ -200,23 +201,23 b' def readgitpatch(lr):'
200 continue
201 continue
201 if line.startswith('rename from '):
202 if line.startswith('rename from '):
202 gp.op = 'RENAME'
203 gp.op = 'RENAME'
203 gp.oldpath = line[12:].rstrip()
204 gp.oldpath = line[12:]
204 elif line.startswith('rename to '):
205 elif line.startswith('rename to '):
205 gp.path = line[10:].rstrip()
206 gp.path = line[10:]
206 elif line.startswith('copy from '):
207 elif line.startswith('copy from '):
207 gp.op = 'COPY'
208 gp.op = 'COPY'
208 gp.oldpath = line[10:].rstrip()
209 gp.oldpath = line[10:]
209 elif line.startswith('copy to '):
210 elif line.startswith('copy to '):
210 gp.path = line[8:].rstrip()
211 gp.path = line[8:]
211 elif line.startswith('deleted file'):
212 elif line.startswith('deleted file'):
212 gp.op = 'DELETE'
213 gp.op = 'DELETE'
213 # is the deleted file a symlink?
214 # is the deleted file a symlink?
214 gp.setmode(int(line.rstrip()[-6:], 8))
215 gp.setmode(int(line[-6:], 8))
215 elif line.startswith('new file mode '):
216 elif line.startswith('new file mode '):
216 gp.op = 'ADD'
217 gp.op = 'ADD'
217 gp.setmode(int(line.rstrip()[-6:], 8))
218 gp.setmode(int(line[-6:], 8))
218 elif line.startswith('new mode '):
219 elif line.startswith('new mode '):
219 gp.setmode(int(line.rstrip()[-6:], 8))
220 gp.setmode(int(line[-6:], 8))
220 elif line.startswith('GIT binary patch'):
221 elif line.startswith('GIT binary patch'):
221 dopatch |= GP_BINARY
222 dopatch |= GP_BINARY
222 gp.binary = True
223 gp.binary = True
@@ -7,7 +7,7 b''
7
7
8 from i18n import _
8 from i18n import _
9 import osutil
9 import osutil
10 import os, sys, errno, stat, getpass, pwd, grp
10 import os, sys, errno, stat, getpass, pwd, grp, fcntl
11
11
12 posixfile = open
12 posixfile = open
13 nulldev = '/dev/null'
13 nulldev = '/dev/null'
@@ -104,6 +104,44 b' def pconvert(path):'
104 def localpath(path):
104 def localpath(path):
105 return path
105 return path
106
106
107 if sys.platform == 'darwin':
108 def realpath(path):
109 '''
110 Returns the true, canonical file system path equivalent to the given
111 path.
112
113 Equivalent means, in this case, resulting in the same, unique
114 file system link to the path. Every file system entry, whether a file,
115 directory, hard link or symbolic link or special, will have a single
116 path preferred by the system, but may allow multiple, differing path
117 lookups to point to it.
118
119 Most regular UNIX file systems only allow a file system entry to be
120 looked up by its distinct path. Obviously, this does not apply to case
121 insensitive file systems, whether case preserving or not. The most
122 complex issue to deal with is file systems transparently reencoding the
123 path, such as the non-standard Unicode normalisation required for HFS+
124 and HFSX.
125 '''
126 # Constants copied from /usr/include/sys/fcntl.h
127 F_GETPATH = 50
128 O_SYMLINK = 0x200000
129
130 try:
131 fd = os.open(path, O_SYMLINK)
132 except OSError, err:
133 if err.errno is errno.ENOENT:
134 return path
135 raise
136
137 try:
138 return fcntl.fcntl(fd, F_GETPATH, '\0' * 1024).rstrip('\0')
139 finally:
140 os.close(fd)
141 else:
142 # Fallback to the likely inadequate Python builtin function.
143 realpath = os.path.realpath
144
107 def shellquote(s):
145 def shellquote(s):
108 if os.sys.platform == 'OpenVMS':
146 if os.sys.platform == 'OpenVMS':
109 return '"%s"' % s
147 return '"%s"' % s
@@ -126,6 +126,15 b' def localpath(path):'
126 def normpath(path):
126 def normpath(path):
127 return pconvert(os.path.normpath(path))
127 return pconvert(os.path.normpath(path))
128
128
129 def realpath(path):
130 '''
131 Returns the true, canonical file system path equivalent to the given
132 path.
133 '''
134 # TODO: There may be a more clever way to do this that also handles other,
135 # less common file systems.
136 return os.path.normpath(os.path.normcase(os.path.realpath(path)))
137
129 def samestat(s1, s2):
138 def samestat(s1, s2):
130 return False
139 return False
131
140
@@ -39,7 +39,7 b' def has_bzr114():'
39 try:
39 try:
40 import bzrlib
40 import bzrlib
41 return (bzrlib.__doc__ != None
41 return (bzrlib.__doc__ != None
42 and bzrlib.version_info[:2] == (1, 14))
42 and bzrlib.version_info[:2] >= (1, 14))
43 except ImportError:
43 except ImportError:
44 return False
44 return False
45
45
General Comments 0
You need to be logged in to leave comments. Login now