annotate mercurial/windows.py @ 8364:fa901423ac23

windows: avoid deleting non-empty reparse points If a hg repository including working directory is a reparse point (directory symlinked or a junction point), then using os.removedirs will remove the reparse point erroneously. This is fixed by only removing directories if they are empty.
author Henrik Stuart <henrik.stuart@edlund.dk>
date Tue, 12 May 2009 15:50:44 +0200
parents 7de68012f86e
children b6d0fa8c7685
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8226
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
1 # windows.py - Windows utility function implementations for Mercurial
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
2 #
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
3 # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
4 #
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
5 # This software may be used and distributed according to the terms of the
8b2cd04a6e97 put license and copyright info into comment blocks
Martin Geisler <mg@lazybytes.net>
parents: 8225
diff changeset
6 # GNU General Public License version 2, incorporated herein by reference.
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
7
7914
48661519913f windows: add various missing import
Steve Borho <steve@borho.org>
parents: 7913
diff changeset
8 from i18n import _
8312
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8226
diff changeset
9 import osutil, error
b87a50b7125c separate import lines from mercurial and general python modules
Simon Heimberg <simohe@besonet.ch>
parents: 8226
diff changeset
10 import errno, msvcrt, os, re, sys
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
11 nulldev = 'NUL:'
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
12
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
13 umask = 002
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
14
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
15 class winstdout:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
16 '''stdout on windows misbehaves if sent through a pipe'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
17
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
18 def __init__(self, fp):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
19 self.fp = fp
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
20
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
21 def __getattr__(self, key):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
22 return getattr(self.fp, key)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
23
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
24 def close(self):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
25 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
26 self.fp.close()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
27 except: pass
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
28
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
29 def write(self, s):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
30 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
31 # This is workaround for "Not enough space" error on
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
32 # writing large size of data to console.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
33 limit = 16000
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
34 l = len(s)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
35 start = 0
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
36 while start < l:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
37 end = start + limit
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
38 self.fp.write(s[start:end])
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
39 start = end
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
40 except IOError, inst:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
41 if inst.errno != 0: raise
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
42 self.close()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
43 raise IOError(errno.EPIPE, 'Broken pipe')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
44
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
45 def flush(self):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
46 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
47 return self.fp.flush()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
48 except IOError, inst:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
49 if inst.errno != errno.EINVAL: raise
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
50 self.close()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
51 raise IOError(errno.EPIPE, 'Broken pipe')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
52
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
53 sys.stdout = winstdout(sys.stdout)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
54
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
55 def _is_win_9x():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
56 '''return true if run on windows 95, 98 or me.'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
57 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
58 return sys.getwindowsversion()[3] == 1
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
59 except AttributeError:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
60 return 'command' in os.environ.get('comspec', '')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
61
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
62 def openhardlinks():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
63 return not _is_win_9x and "win32api" in locals()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
64
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
65 def system_rcpath():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
66 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
67 return system_rcpath_win32()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
68 except:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
69 return [r'c:\mercurial\mercurial.ini']
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
70
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
71 def user_rcpath():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
72 '''return os-specific hgrc search path to the user dir'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
73 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
74 path = user_rcpath_win32()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
75 except:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
76 home = os.path.expanduser('~')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
77 path = [os.path.join(home, 'mercurial.ini'),
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
78 os.path.join(home, '.hgrc')]
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
79 userprofile = os.environ.get('USERPROFILE')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
80 if userprofile:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
81 path.append(os.path.join(userprofile, 'mercurial.ini'))
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
82 path.append(os.path.join(userprofile, '.hgrc'))
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
83 return path
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
84
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
85 def parse_patch_output(output_line):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
86 """parses the output produced by patch and returns the file name"""
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
87 pf = output_line[14:]
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
88 if pf[0] == '`':
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
89 pf = pf[1:-1] # Remove the quotes
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
90 return pf
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
91
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
92 def sshargs(sshcmd, host, user, port):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
93 '''Build argument list for ssh or Plink'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
94 pflag = 'plink' in sshcmd.lower() and '-P' or '-p'
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
95 args = user and ("%s@%s" % (user, host)) or host
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
96 return port and ("%s %s %s" % (args, pflag, port)) or args
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
97
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
98 def testpid(pid):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
99 '''return False if pid dead, True if running or not known'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
100 return True
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
101
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
102 def set_flags(f, l, x):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
103 pass
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
104
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
105 def set_binary(fd):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
106 # When run without console, pipes may expose invalid
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
107 # fileno(), usually set to -1.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
108 if hasattr(fd, 'fileno') and fd.fileno() >= 0:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
109 msvcrt.setmode(fd.fileno(), os.O_BINARY)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
110
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
111 def pconvert(path):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
112 return '/'.join(path.split(os.sep))
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
113
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
114 def localpath(path):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
115 return path.replace('/', '\\')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
116
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
117 def normpath(path):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
118 return pconvert(os.path.normpath(path))
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
119
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
120 def samestat(s1, s2):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
121 return False
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
122
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
123 # A sequence of backslashes is special iff it precedes a double quote:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
124 # - if there's an even number of backslashes, the double quote is not
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
125 # quoted (i.e. it ends the quoted region)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
126 # - if there's an odd number of backslashes, the double quote is quoted
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
127 # - in both cases, every pair of backslashes is unquoted into a single
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
128 # backslash
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
129 # (See http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx )
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
130 # So, to quote a string, we must surround it in double quotes, double
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
131 # the number of backslashes that preceed double quotes and add another
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
132 # backslash before every double quote (being careful with the double
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
133 # quote we've appended to the end)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
134 _quotere = None
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
135 def shellquote(s):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
136 global _quotere
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
137 if _quotere is None:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
138 _quotere = re.compile(r'(\\*)("|\\$)')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
139 return '"%s"' % _quotere.sub(r'\1\1\\\2', s)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
140
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
141 def quotecommand(cmd):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
142 """Build a command string suitable for os.popen* calls."""
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
143 # The extra quotes are needed because popen* runs the command
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
144 # through the current COMSPEC. cmd.exe suppress enclosing quotes.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
145 return '"' + cmd + '"'
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
146
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
147 def popen(command, mode='r'):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
148 # Work around "popen spawned process may not write to stdout
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
149 # under windows"
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
150 # http://bugs.python.org/issue1366
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
151 command += " 2> %s" % nulldev
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
152 return os.popen(quotecommand(command), mode)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
153
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
154 def explain_exit(code):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
155 return _("exited with status %d") % code, code
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
156
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
157 # if you change this stub into a real check, please try to implement the
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
158 # username and groupname functions above, too.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
159 def isowner(fp, st=None):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
160 return True
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
161
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
162 def find_exe(command):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
163 '''Find executable for command searching like cmd.exe does.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
164 If command is a basename then PATH is searched for command.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
165 PATH isn't searched if command is an absolute or relative path.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
166 An extension from PATHEXT is found and added if not present.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
167 If command isn't found None is returned.'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
168 pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
169 pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
170 if os.path.splitext(command)[1].lower() in pathexts:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
171 pathexts = ['']
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
172
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
173 def findexisting(pathcommand):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
174 'Will append extension (if needed) and return existing file'
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
175 for ext in pathexts:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
176 executable = pathcommand + ext
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
177 if os.path.exists(executable):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
178 return executable
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
179 return None
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
180
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
181 if os.sep in command:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
182 return findexisting(command)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
183
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
184 for path in os.environ.get('PATH', '').split(os.pathsep):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
185 executable = findexisting(os.path.join(path, command))
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
186 if executable is not None:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
187 return executable
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
188 return None
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
189
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
190 def set_signal_handler():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
191 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
192 set_signal_handler_win32()
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
193 except NameError:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
194 pass
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
195
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
196 def statfiles(files):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
197 '''Stat each file in files and yield stat or None if file does not exist.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
198 Cluster and cache stat per directory to minimize number of OS stat calls.'''
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
199 ncase = os.path.normcase
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
200 sep = os.sep
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
201 dircache = {} # dirname -> filename -> status | None if file does not exist
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
202 for nf in files:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
203 nf = ncase(nf)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
204 pos = nf.rfind(sep)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
205 if pos == -1:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
206 dir, base = '.', nf
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
207 else:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
208 dir, base = nf[:pos+1], nf[pos+1:]
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
209 cache = dircache.get(dir, None)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
210 if cache is None:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
211 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
212 dmap = dict([(ncase(n), s)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
213 for n, k, s in osutil.listdir(dir, True)])
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
214 except OSError, err:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
215 # handle directory not found in Python version prior to 2.5
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
216 # Python <= 2.4 returns native Windows code 3 in errno
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
217 # Python >= 2.5 returns ENOENT and adds winerror field
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
218 # EINVAL is raised if dir is not a directory.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
219 if err.errno not in (3, errno.ENOENT, errno.EINVAL,
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
220 errno.ENOTDIR):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
221 raise
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
222 dmap = {}
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
223 cache = dircache.setdefault(dir, dmap)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
224 yield cache.get(base, None)
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
225
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
226 def getuser():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
227 '''return name of current user'''
7949
443c0c8636ac windows: get Abort from error
Matt Mackall <mpm@selenic.com>
parents: 7934
diff changeset
228 raise error.Abort(_('user name not available - set USERNAME '
7934
ec4784bb7d75 windows: break import cycle with util
Martin Geisler <mg@daimi.au.dk>
parents: 7933
diff changeset
229 'environment variable'))
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
230
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
231 def username(uid=None):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
232 """Return the name of the user with the given uid.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
233
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
234 If uid is None, return the name of the current user."""
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
235 return None
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
236
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
237 def groupname(gid=None):
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
238 """Return the name of the group with the given gid.
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
239
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
240 If gid is None, return the name of the current group."""
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
241 return None
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
242
8364
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
243 def _removedirs(name):
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
244 """special version of os.removedirs that does not remove symlinked
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
245 directories or junction points if they actually contain files"""
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
246 if osutil.listdir(name):
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
247 return
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
248 os.rmdir(name)
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
249 head, tail = os.path.split(name)
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
250 if not tail:
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
251 head, tail = os.path.split(head)
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
252 while head and tail:
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
253 try:
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
254 if osutil.listdir(name):
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
255 return
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
256 os.rmdir(head)
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
257 except:
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
258 break
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
259 head, tail = os.path.split(head)
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
260
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
261 def unlink(f):
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
262 """unlink and remove the directory if it is empty"""
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
263 os.unlink(f)
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
264 # try removing directories that might now be empty
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
265 try:
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
266 _removedirs(os.path.dirname(f))
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
267 except OSError:
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
268 pass
fa901423ac23 windows: avoid deleting non-empty reparse points
Henrik Stuart <henrik.stuart@edlund.dk>
parents: 8330
diff changeset
269
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
270 try:
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
271 # override functions with win32 versions if possible
7932
96501a4abbec windows: fix import of win32.py (was util_win32.py)
Sune Foldager <cryo@cyanite.org>
parents: 7914
diff changeset
272 from win32 import *
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
273 if not _is_win_9x():
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
274 posixfile = posixfile_nt
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
275 try:
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
276 # fast, buffered POSIX-like file support
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
277 from osutil import posixfile as _posixfile
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
278 def posixfile(name, mode='r', buffering=-1):
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
279 # wrap osutil.posixfile to provide friendlier exceptions
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
280 try:
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
281 return _posixfile(name, mode, buffering)
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
282 except WindowsError, err:
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
283 raise WinIOError(err)
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
284 posixfile.__doc__ = _posixfile.__doc__
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
285 except ImportError:
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
286 # slow, unbuffered POSIX-like file support
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
287 posixfile = posixfile_nt
7890
e710f0f592b2 util: split out posix, windows, and win32 modules
Matt Mackall <mpm@selenic.com>
parents:
diff changeset
288 except ImportError:
8330
7de68012f86e Windows: improve performance via buffered I/O
Bryan O'Sullivan <bos@serpentine.com>
parents: 8312
diff changeset
289 posixfile = file