##// END OF EJS Templates
merge with crew-stable
Alexis S. L. Carvalho -
r4868:192cd95c merge default
parent child Browse files
Show More
@@ -0,0 +1,6 b''
1 % files
2 dangling -> nothing
3 % tar
4 dangling -> nothing
5 % zip
6 dangling -> nothing
@@ -86,12 +86,19 b' class tarit:'
86 # Python 2.5-2.5.1 have a regression that requires a name arg
86 # Python 2.5-2.5.1 have a regression that requires a name arg
87 self.z = taropen(name='', mode='w|', fileobj=dest)
87 self.z = taropen(name='', mode='w|', fileobj=dest)
88
88
89 def addfile(self, name, mode, data):
89 def addfile(self, name, mode, islink, data):
90 i = tarfile.TarInfo(self.prefix + name)
90 i = tarfile.TarInfo(self.prefix + name)
91 i.mtime = self.mtime
91 i.mtime = self.mtime
92 i.size = len(data)
92 i.size = len(data)
93 i.mode = mode
93 if islink:
94 self.z.addfile(i, cStringIO.StringIO(data))
94 i.type = tarfile.SYMTYPE
95 i.mode = 0777
96 i.linkname = data
97 data = None
98 else:
99 i.mode = mode
100 data = cStringIO.StringIO(data)
101 self.z.addfile(i, data)
95
102
96 def done(self):
103 def done(self):
97 self.z.close()
104 self.z.close()
@@ -130,13 +137,17 b' class zipit:'
130 zipfile.ZIP_STORED)
137 zipfile.ZIP_STORED)
131 self.date_time = time.gmtime(mtime)[:6]
138 self.date_time = time.gmtime(mtime)[:6]
132
139
133 def addfile(self, name, mode, data):
140 def addfile(self, name, mode, islink, data):
134 i = zipfile.ZipInfo(self.prefix + name, self.date_time)
141 i = zipfile.ZipInfo(self.prefix + name, self.date_time)
135 i.compress_type = self.z.compression
142 i.compress_type = self.z.compression
136 # unzip will not honor unix file modes unless file creator is
143 # unzip will not honor unix file modes unless file creator is
137 # set to unix (id 3).
144 # set to unix (id 3).
138 i.create_system = 3
145 i.create_system = 3
139 i.external_attr = (mode | stat.S_IFREG) << 16L
146 ftype = stat.S_IFREG
147 if islink:
148 mode = 0777
149 ftype = stat.S_IFLNK
150 i.external_attr = (mode | ftype) << 16L
140 self.z.writestr(i, data)
151 self.z.writestr(i, data)
141
152
142 def done(self):
153 def done(self):
@@ -149,19 +160,17 b' class fileit:'
149 if prefix:
160 if prefix:
150 raise util.Abort(_('cannot give prefix when archiving to files'))
161 raise util.Abort(_('cannot give prefix when archiving to files'))
151 self.basedir = name
162 self.basedir = name
152 self.dirs = {}
163 self.opener = util.opener(self.basedir)
153 self.oflags = (os.O_CREAT | os.O_EXCL | os.O_WRONLY |
154 getattr(os, 'O_BINARY', 0) |
155 getattr(os, 'O_NOFOLLOW', 0))
156
164
157 def addfile(self, name, mode, data):
165 def addfile(self, name, mode, islink, data):
166 if islink:
167 self.opener.symlink(data, name)
168 return
169 f = self.opener(name, "w", atomictemp=True)
170 f.write(data)
171 f.rename()
158 destfile = os.path.join(self.basedir, name)
172 destfile = os.path.join(self.basedir, name)
159 destdir = os.path.dirname(destfile)
173 os.chmod(destfile, mode)
160 if destdir not in self.dirs:
161 if not os.path.isdir(destdir):
162 os.makedirs(destdir)
163 self.dirs[destdir] = 1
164 os.fdopen(os.open(destfile, self.oflags, mode), 'wb').write(data)
165
174
166 def done(self):
175 def done(self):
167 pass
176 pass
@@ -191,20 +200,20 b' def archive(repo, dest, node, kind, deco'
191
200
192 prefix is name of path to put before every archive member.'''
201 prefix is name of path to put before every archive member.'''
193
202
194 def write(name, mode, data):
203 def write(name, mode, islink, data):
195 if matchfn and not matchfn(name): return
204 if matchfn and not matchfn(name): return
196 if decode:
205 if decode:
197 data = repo.wwritedata(name, data)
206 data = repo.wwritedata(name, data)
198 archiver.addfile(name, mode, data)
207 archiver.addfile(name, mode, islink, data)
199
208
200 ctx = repo.changectx(node)
209 ctx = repo.changectx(node)
201 archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0])
210 archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0])
202 m = ctx.manifest()
211 m = ctx.manifest()
203 items = m.items()
212 items = m.items()
204 items.sort()
213 items.sort()
205 write('.hg_archival.txt', 0644,
214 write('.hg_archival.txt', 0644, False,
206 'repo: %s\nnode: %s\n' % (hex(repo.changelog.node(0)), hex(node)))
215 'repo: %s\nnode: %s\n' % (hex(repo.changelog.node(0)), hex(node)))
207 for filename, filenode in items:
216 for filename, filenode in items:
208 write(filename, m.execf(filename) and 0755 or 0644,
217 write(filename, m.execf(filename) and 0755 or 0644, m.linkf(filename),
209 repo.file(filename).read(filenode))
218 repo.file(filename).read(filenode))
210 archiver.done()
219 archiver.done()
@@ -542,9 +542,9 b' def make_filename(repo, pat, node,'
542 try:
542 try:
543 if node:
543 if node:
544 expander.update(node_expander)
544 expander.update(node_expander)
545 if node and revwidth is not None:
545 if node:
546 expander['r'] = (lambda:
546 expander['r'] = (lambda:
547 str(repo.changelog.rev(node)).zfill(revwidth))
547 str(repo.changelog.rev(node)).zfill(revwidth or 0))
548 if total is not None:
548 if total is not None:
549 expander['N'] = lambda: str(total)
549 expander['N'] = lambda: str(total)
550 if seqno is not None:
550 if seqno is not None:
@@ -548,9 +548,10 b' def docopy(ui, repo, pats, opts, wlock):'
548 targets[abstarget] = abssrc
548 targets[abstarget] = abssrc
549 if abstarget != origsrc:
549 if abstarget != origsrc:
550 if repo.dirstate.state(origsrc) == 'a':
550 if repo.dirstate.state(origsrc) == 'a':
551 ui.warn(_("%s was marked for addition. "
551 if not ui.quiet:
552 "%s will not be committed as a copy.\n")
552 ui.warn(_("%s has not been committed yet, so no copy "
553 % (repo.pathto(origsrc, cwd), reltarget))
553 "data will be stored for %s.\n")
554 % (repo.pathto(origsrc, cwd), reltarget))
554 if abstarget not in repo.dirstate and not opts.get('dry_run'):
555 if abstarget not in repo.dirstate and not opts.get('dry_run'):
555 repo.add([abstarget], wlock)
556 repo.add([abstarget], wlock)
556 elif not opts.get('dry_run'):
557 elif not opts.get('dry_run'):
@@ -2471,6 +2472,8 b' def serve(ui, repo, **opts):'
2471 for o in optlist.split():
2472 for o in optlist.split():
2472 if opts[o]:
2473 if opts[o]:
2473 parentui.setconfig("web", o, str(opts[o]))
2474 parentui.setconfig("web", o, str(opts[o]))
2475 if repo.ui != parentui:
2476 repo.ui.setconfig("web", o, str(opts[o]))
2474
2477
2475 if repo is None and not ui.config("web", "webdir_conf"):
2478 if repo is None and not ui.config("web", "webdir_conf"):
2476 raise hg.RepoError(_("There is no Mercurial repository here"
2479 raise hg.RepoError(_("There is no Mercurial repository here"
@@ -1184,4 +1184,4 b' class hgweb(object):'
1184
1184
1185 def do_stream_out(self, req):
1185 def do_stream_out(self, req):
1186 req.httphdr("application/mercurial-0.1")
1186 req.httphdr("application/mercurial-0.1")
1187 streamclone.stream_out(self.repo, req)
1187 streamclone.stream_out(self.repo, req, untrusted=True)
@@ -197,13 +197,13 b' def create_server(ui, repo):'
197 return open(opt, 'w')
197 return open(opt, 'w')
198 return default
198 return default
199
199
200 address = ui.config("web", "address", "")
200 address = repo.ui.config("web", "address", "")
201 port = int(ui.config("web", "port", 8000))
201 port = int(repo.ui.config("web", "port", 8000))
202 use_ipv6 = ui.configbool("web", "ipv6")
202 use_ipv6 = repo.ui.configbool("web", "ipv6")
203 webdir_conf = ui.config("web", "webdir_conf")
203 webdir_conf = repo.ui.config("web", "webdir_conf")
204 ssl_cert = ui.config("web", "certificate")
204 ssl_cert = repo.ui.config("web", "certificate")
205 accesslog = openlog(ui.config("web", "accesslog", "-"), sys.stdout)
205 accesslog = openlog(repo.ui.config("web", "accesslog", "-"), sys.stdout)
206 errorlog = openlog(ui.config("web", "errorlog", "-"), sys.stderr)
206 errorlog = openlog(repo.ui.config("web", "errorlog", "-"), sys.stderr)
207
207
208 if use_threads:
208 if use_threads:
209 try:
209 try:
@@ -460,15 +460,7 b' class localrepository(repo.repository):'
460 def wwrite(self, filename, data, flags):
460 def wwrite(self, filename, data, flags):
461 data = self._filter("decode", filename, data)
461 data = self._filter("decode", filename, data)
462 if "l" in flags:
462 if "l" in flags:
463 f = self.wjoin(filename)
463 self.wopener.symlink(data, filename)
464 try:
465 os.unlink(f)
466 except OSError:
467 pass
468 d = os.path.dirname(f)
469 if not os.path.exists(d):
470 os.makedirs(d)
471 os.symlink(data, f)
472 else:
464 else:
473 try:
465 try:
474 if self._link(filename):
466 if self._link(filename):
@@ -56,11 +56,11 b' def walkrepo(root):'
56 #
56 #
57 # server writes out raw file data.
57 # server writes out raw file data.
58
58
59 def stream_out(repo, fileobj):
59 def stream_out(repo, fileobj, untrusted=False):
60 '''stream out all metadata files in repository.
60 '''stream out all metadata files in repository.
61 writes to file-like object, must support write() and optional flush().'''
61 writes to file-like object, must support write() and optional flush().'''
62
62
63 if not repo.ui.configbool('server', 'uncompressed'):
63 if not repo.ui.configbool('server', 'uncompressed', untrusted=untrusted):
64 fileobj.write('1\n')
64 fileobj.write('1\n')
65 return
65 return
66
66
@@ -540,7 +540,7 b' def _matcher(canonroot, cwd, names, inc,'
540
540
541 return (roots, match, (inc or exc or anypats) and True)
541 return (roots, match, (inc or exc or anypats) and True)
542
542
543 _hgexecutable = None
543 _hgexecutable = 'hg'
544
544
545 def set_hgexecutable(path):
545 def set_hgexecutable(path):
546 """remember location of the 'hg' executable if easily possible
546 """remember location of the 'hg' executable if easily possible
@@ -549,7 +549,8 b' def set_hgexecutable(path):'
549 fall back to 'hg' in this case.
549 fall back to 'hg' in this case.
550 """
550 """
551 global _hgexecutable
551 global _hgexecutable
552 _hgexecutable = path and os.path.abspath(path) or 'hg'
552 if path:
553 _hgexecutable = os.path.abspath(path)
553
554
554 def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None):
555 def system(cmd, environ={}, cwd=None, onerr=None, errprefix=None):
555 '''enhanced shell command execution.
556 '''enhanced shell command execution.
@@ -1181,70 +1182,95 b' def encodedopener(openerfn, fn):'
1181 return openerfn(fn(path), *args, **kw)
1182 return openerfn(fn(path), *args, **kw)
1182 return o
1183 return o
1183
1184
1184 def opener(base, audit=True):
1185 def mktempcopy(name, emptyok=False):
1186 """Create a temporary file with the same contents from name
1187
1188 The permission bits are copied from the original file.
1189
1190 If the temporary file is going to be truncated immediately, you
1191 can use emptyok=True as an optimization.
1192
1193 Returns the name of the temporary file.
1185 """
1194 """
1186 return a function that opens files relative to base
1195 d, fn = os.path.split(name)
1196 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
1197 os.close(fd)
1198 # Temporary files are created with mode 0600, which is usually not
1199 # what we want. If the original file already exists, just copy
1200 # its mode. Otherwise, manually obey umask.
1201 try:
1202 st_mode = os.lstat(name).st_mode
1203 except OSError, inst:
1204 if inst.errno != errno.ENOENT:
1205 raise
1206 st_mode = 0666 & ~_umask
1207 os.chmod(temp, st_mode)
1208 if emptyok:
1209 return temp
1210 try:
1211 try:
1212 ifp = posixfile(name, "rb")
1213 except IOError, inst:
1214 if inst.errno == errno.ENOENT:
1215 return temp
1216 if not getattr(inst, 'filename', None):
1217 inst.filename = name
1218 raise
1219 ofp = posixfile(temp, "wb")
1220 for chunk in filechunkiter(ifp):
1221 ofp.write(chunk)
1222 ifp.close()
1223 ofp.close()
1224 except:
1225 try: os.unlink(temp)
1226 except: pass
1227 raise
1228 return temp
1187
1229
1188 this function is used to hide the details of COW semantics and
1230 class atomictempfile(posixfile):
1231 """file-like object that atomically updates a file
1232
1233 All writes will be redirected to a temporary copy of the original
1234 file. When rename is called, the copy is renamed to the original
1235 name, making the changes visible.
1236 """
1237 def __init__(self, name, mode):
1238 self.__name = name
1239 self.temp = mktempcopy(name, emptyok=('w' in mode))
1240 posixfile.__init__(self, self.temp, mode)
1241
1242 def rename(self):
1243 if not self.closed:
1244 posixfile.close(self)
1245 rename(self.temp, localpath(self.__name))
1246
1247 def __del__(self):
1248 if not self.closed:
1249 try:
1250 os.unlink(self.temp)
1251 except: pass
1252 posixfile.close(self)
1253
1254 class opener(object):
1255 """Open files relative to a base directory
1256
1257 This class is used to hide the details of COW semantics and
1189 remote file access from higher level code.
1258 remote file access from higher level code.
1190 """
1259 """
1191 def mktempcopy(name, emptyok=False):
1260 def __init__(self, base, audit=True):
1192 d, fn = os.path.split(name)
1261 self.base = base
1193 fd, temp = tempfile.mkstemp(prefix='.%s-' % fn, dir=d)
1262 self.audit = audit
1194 os.close(fd)
1195 # Temporary files are created with mode 0600, which is usually not
1196 # what we want. If the original file already exists, just copy
1197 # its mode. Otherwise, manually obey umask.
1198 try:
1199 st_mode = os.lstat(name).st_mode
1200 except OSError, inst:
1201 if inst.errno != errno.ENOENT:
1202 raise
1203 st_mode = 0666 & ~_umask
1204 os.chmod(temp, st_mode)
1205 if emptyok:
1206 return temp
1207 try:
1208 try:
1209 ifp = posixfile(name, "rb")
1210 except IOError, inst:
1211 if inst.errno == errno.ENOENT:
1212 return temp
1213 if not getattr(inst, 'filename', None):
1214 inst.filename = name
1215 raise
1216 ofp = posixfile(temp, "wb")
1217 for chunk in filechunkiter(ifp):
1218 ofp.write(chunk)
1219 ifp.close()
1220 ofp.close()
1221 except:
1222 try: os.unlink(temp)
1223 except: pass
1224 raise
1225 return temp
1226
1263
1227 class atomictempfile(posixfile):
1264 def __getattr__(self, name):
1228 """the file will only be copied when rename is called"""
1265 if name == '_can_symlink':
1229 def __init__(self, name, mode):
1266 self._can_symlink = checklink(self.base)
1230 self.__name = name
1267 return self._can_symlink
1231 self.temp = mktempcopy(name, emptyok=('w' in mode))
1268 raise AttributeError(name)
1232 posixfile.__init__(self, self.temp, mode)
1233 def rename(self):
1234 if not self.closed:
1235 posixfile.close(self)
1236 rename(self.temp, localpath(self.__name))
1237 def __del__(self):
1238 if not self.closed:
1239 try:
1240 os.unlink(self.temp)
1241 except: pass
1242 posixfile.close(self)
1243
1269
1244 def o(path, mode="r", text=False, atomictemp=False):
1270 def __call__(self, path, mode="r", text=False, atomictemp=False):
1245 if audit:
1271 if self.audit:
1246 audit_path(path)
1272 audit_path(path)
1247 f = os.path.join(base, path)
1273 f = os.path.join(self.base, path)
1248
1274
1249 if not text and "b" not in mode:
1275 if not text and "b" not in mode:
1250 mode += "b" # for that other OS
1276 mode += "b" # for that other OS
@@ -1263,7 +1289,25 b' def opener(base, audit=True):'
1263 rename(mktempcopy(f), f)
1289 rename(mktempcopy(f), f)
1264 return posixfile(f, mode)
1290 return posixfile(f, mode)
1265
1291
1266 return o
1292 def symlink(self, src, dst):
1293 if self.audit:
1294 audit_path(dst)
1295 linkname = os.path.join(self.base, dst)
1296 try:
1297 os.unlink(linkname)
1298 except OSError:
1299 pass
1300
1301 dirname = os.path.dirname(linkname)
1302 if not os.path.exists(dirname):
1303 os.makedirs(dirname)
1304
1305 if self._can_symlink:
1306 os.symlink(src, linkname)
1307 else:
1308 f = self(self, dst, "w")
1309 f.write(src)
1310 f.close()
1267
1311
1268 class chunkbuffer(object):
1312 class chunkbuffer(object):
1269 """Allow arbitrary sized chunks of data to be efficiently read from an
1313 """Allow arbitrary sized chunks of data to be efficiently read from an
@@ -64,8 +64,13 b' unzip -t test.zip'
64
64
65 hg archive -t tar - | tar tf - | sed "s/$QTIP/TIP/"
65 hg archive -t tar - | tar tf - | sed "s/$QTIP/TIP/"
66
66
67 hg archive -r 0 -t tar rev-%r.tar
68 if [ -f rev-0.tar ]; then
69 echo 'rev-0.tar created'
70 fi
71
67 echo '% empty repo'
72 echo '% empty repo'
68 hg init ../empty
73 hg init ../empty
69 cd ../empty
74 cd ../empty
70 hg archive ../test-empty
75 hg archive ../test-empty
71 exit 0 No newline at end of file
76 exit 0
@@ -38,5 +38,6 b' test-TIP/.hg_archival.txt'
38 test-TIP/bar
38 test-TIP/bar
39 test-TIP/baz/bletch
39 test-TIP/baz/bletch
40 test-TIP/foo
40 test-TIP/foo
41 rev-0.tar created
41 % empty repo
42 % empty repo
42 abort: repository has no revisions
43 abort: repository has no revisions
@@ -3,13 +3,13 b' foo: not copying - file is not managed'
3 abort: no files to copy
3 abort: no files to copy
4 ? foo
4 ? foo
5 # dry-run; print a warning that this is not a real copy; foo is added
5 # dry-run; print a warning that this is not a real copy; foo is added
6 foo was marked for addition. bar will not be committed as a copy.
6 foo has not been committed yet, so no copy data will be stored for bar.
7 A foo
7 A foo
8 # should print a warning that this is not a real copy; bar is added
8 # should print a warning that this is not a real copy; bar is added
9 foo was marked for addition. bar will not be committed as a copy.
9 foo has not been committed yet, so no copy data will be stored for bar.
10 A bar
10 A bar
11 # should print a warning that this is not a real copy; foo is added
11 # should print a warning that this is not a real copy; foo is added
12 bar was marked for addition. foo will not be committed as a copy.
12 bar has not been committed yet, so no copy data will be stored for foo.
13 A foo
13 A foo
14 # dry-run; should show that foo is clean
14 # dry-run; should show that foo is clean
15 C foo
15 C foo
@@ -3,9 +3,15 b''
3 hg init test
3 hg init test
4 cd test
4 cd test
5
5
6 echo '[web]' > .hg/hgrc
7 echo 'accesslog = access.log' >> .hg/hgrc
8
6 echo % Without -v
9 echo % Without -v
7 hg serve -a localhost -p 20063 -d --pid-file=hg.pid
10 hg serve -a localhost -p 20063 -d --pid-file=hg.pid
8 cat hg.pid >> "$DAEMON_PIDS"
11 cat hg.pid >> "$DAEMON_PIDS"
12 if [ -f access.log ]; then
13 echo 'access log created - .hg/hgrc respected'
14 fi
9
15
10 echo % With -v
16 echo % With -v
11 hg serve -a localhost -p 20064 -d --pid-file=hg.pid -v
17 hg serve -a localhost -p 20064 -d --pid-file=hg.pid -v
@@ -1,3 +1,4 b''
1 % Without -v
1 % Without -v
2 access log created - .hg/hgrc respected
2 % With -v
3 % With -v
3 listening at http://localhost:20064/
4 listening at http://localhost:20064/
General Comments 0
You need to be logged in to leave comments. Login now