Mercurial > traipse_dev
comparison upmana/mercurial/archival.py @ 121:496dbf12a6cb alpha
Traipse Alpha 'OpenRPG' {091030-00}
Traipse is a distribution of OpenRPG that is designed to be easy to setup and go.
Traipse also makes it easy for developers to work on code without fear of
sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the
code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the
productivity of the user.
Update Summary (Cleaning up for Beta):
Adds Bookmarks (Alpha) with cool Smiley Star and Plus Symbol images!
Changes made to the map for increased portability. SnowDog has changes planned in
Core, though.
Added an initial push to the BCG. Not much to see, just shows off how it is
re-writing Main code.
Fix to remote admin commands
Minor fix to texted based server, works in /System/ folder
Some Core changes to gametree to correctly disply Pretty Print, thanks David!
Fix to Splitter Nodes not being created.
Added images to Plugin Control panel for Autostart feature
Fix to massive amounts of images loading; from Core
fix to gsclient so with_statement imports
Added 'boot' command to remote admin
Prep work in Pass tool for remote admin rankings and different passwords, ei,
Server, Admin, Moderator, etc.
Remote Admin Commands more organized, more prep work.
Added Confirmation window for sent nodes.
Minor changes to allow for portability to an OpenSUSE linux OS (hopefully without
breaking)
{091028}
Made changes to gametree to start working with Element Tree, mostly from Core
Minor changes to Map to start working with Element Tree, from Core
Preliminary changes to map efficiency, from FlexiRPG
Miniatures Layer pop up box allows users to turn off Mini labels, from FlexiRPG
Changes to main.py to start working with Element Tree
{091029}
Changes made to server to start working with Element Tree.
Changes made to Meta Server Lib. Prepping test work for a multi meta network
page.
Minor bug fixed with mini to gametree
Zoom Mouse plugin added.
{091030}
Getting ready for Beta. Server needs debugging so Alpha remains bugged.
Plugin UI code cleaned. Auto start works with a graphic, pop-up asks to enable or
disable plugin.
Update Manager now has a partially working Status Bar. Status Bar captures
terminal text, so Merc out put is visible. Manifest.xml file, will be renamed, is
now much cleaner.
Debug Console has a clear button and a Report Bug button. Prep work for a Term2Win
class in Debug Console.
Known: Current Alpha fails in Windows.
author | sirebral |
---|---|
date | Fri, 30 Oct 2009 22:21:40 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
120:d86e762a994f | 121:496dbf12a6cb |
---|---|
1 # archival.py - revision archival for mercurial | |
2 # | |
3 # Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | |
4 # | |
5 # This software may be used and distributed according to the terms of the | |
6 # GNU General Public License version 2, incorporated herein by reference. | |
7 | |
8 from i18n import _ | |
9 from node import hex | |
10 import util | |
11 import cStringIO, os, stat, tarfile, time, zipfile | |
12 import zlib, gzip | |
13 | |
14 def tidyprefix(dest, prefix, suffixes): | |
15 '''choose prefix to use for names in archive. make sure prefix is | |
16 safe for consumers.''' | |
17 | |
18 if prefix: | |
19 prefix = util.normpath(prefix) | |
20 else: | |
21 if not isinstance(dest, str): | |
22 raise ValueError('dest must be string if no prefix') | |
23 prefix = os.path.basename(dest) | |
24 lower = prefix.lower() | |
25 for sfx in suffixes: | |
26 if lower.endswith(sfx): | |
27 prefix = prefix[:-len(sfx)] | |
28 break | |
29 lpfx = os.path.normpath(util.localpath(prefix)) | |
30 prefix = util.pconvert(lpfx) | |
31 if not prefix.endswith('/'): | |
32 prefix += '/' | |
33 if prefix.startswith('../') or os.path.isabs(lpfx) or '/../' in prefix: | |
34 raise util.Abort(_('archive prefix contains illegal components')) | |
35 return prefix | |
36 | |
37 class tarit(object): | |
38 '''write archive to tar file or stream. can write uncompressed, | |
39 or compress with gzip or bzip2.''' | |
40 | |
41 class GzipFileWithTime(gzip.GzipFile): | |
42 | |
43 def __init__(self, *args, **kw): | |
44 timestamp = None | |
45 if 'timestamp' in kw: | |
46 timestamp = kw.pop('timestamp') | |
47 if timestamp is None: | |
48 self.timestamp = time.time() | |
49 else: | |
50 self.timestamp = timestamp | |
51 gzip.GzipFile.__init__(self, *args, **kw) | |
52 | |
53 def _write_gzip_header(self): | |
54 self.fileobj.write('\037\213') # magic header | |
55 self.fileobj.write('\010') # compression method | |
56 # Python 2.6 deprecates self.filename | |
57 fname = getattr(self, 'name', None) or self.filename | |
58 flags = 0 | |
59 if fname: | |
60 flags = gzip.FNAME | |
61 self.fileobj.write(chr(flags)) | |
62 gzip.write32u(self.fileobj, long(self.timestamp)) | |
63 self.fileobj.write('\002') | |
64 self.fileobj.write('\377') | |
65 if fname: | |
66 self.fileobj.write(fname + '\000') | |
67 | |
68 def __init__(self, dest, prefix, mtime, kind=''): | |
69 self.prefix = tidyprefix(dest, prefix, ['.tar', '.tar.bz2', '.tar.gz', | |
70 '.tgz', '.tbz2']) | |
71 self.mtime = mtime | |
72 | |
73 def taropen(name, mode, fileobj=None): | |
74 if kind == 'gz': | |
75 mode = mode[0] | |
76 if not fileobj: | |
77 fileobj = open(name, mode + 'b') | |
78 gzfileobj = self.GzipFileWithTime(name, mode + 'b', | |
79 zlib.Z_BEST_COMPRESSION, | |
80 fileobj, timestamp=mtime) | |
81 return tarfile.TarFile.taropen(name, mode, gzfileobj) | |
82 else: | |
83 return tarfile.open(name, mode + kind, fileobj) | |
84 | |
85 if isinstance(dest, str): | |
86 self.z = taropen(dest, mode='w:') | |
87 else: | |
88 # Python 2.5-2.5.1 have a regression that requires a name arg | |
89 self.z = taropen(name='', mode='w|', fileobj=dest) | |
90 | |
91 def addfile(self, name, mode, islink, data): | |
92 i = tarfile.TarInfo(self.prefix + name) | |
93 i.mtime = self.mtime | |
94 i.size = len(data) | |
95 if islink: | |
96 i.type = tarfile.SYMTYPE | |
97 i.mode = 0777 | |
98 i.linkname = data | |
99 data = None | |
100 i.size = 0 | |
101 else: | |
102 i.mode = mode | |
103 data = cStringIO.StringIO(data) | |
104 self.z.addfile(i, data) | |
105 | |
106 def done(self): | |
107 self.z.close() | |
108 | |
109 class tellable(object): | |
110 '''provide tell method for zipfile.ZipFile when writing to http | |
111 response file object.''' | |
112 | |
113 def __init__(self, fp): | |
114 self.fp = fp | |
115 self.offset = 0 | |
116 | |
117 def __getattr__(self, key): | |
118 return getattr(self.fp, key) | |
119 | |
120 def write(self, s): | |
121 self.fp.write(s) | |
122 self.offset += len(s) | |
123 | |
124 def tell(self): | |
125 return self.offset | |
126 | |
127 class zipit(object): | |
128 '''write archive to zip file or stream. can write uncompressed, | |
129 or compressed with deflate.''' | |
130 | |
131 def __init__(self, dest, prefix, mtime, compress=True): | |
132 self.prefix = tidyprefix(dest, prefix, ('.zip',)) | |
133 if not isinstance(dest, str): | |
134 try: | |
135 dest.tell() | |
136 except (AttributeError, IOError): | |
137 dest = tellable(dest) | |
138 self.z = zipfile.ZipFile(dest, 'w', | |
139 compress and zipfile.ZIP_DEFLATED or | |
140 zipfile.ZIP_STORED) | |
141 self.date_time = time.gmtime(mtime)[:6] | |
142 | |
143 def addfile(self, name, mode, islink, data): | |
144 i = zipfile.ZipInfo(self.prefix + name, self.date_time) | |
145 i.compress_type = self.z.compression | |
146 # unzip will not honor unix file modes unless file creator is | |
147 # set to unix (id 3). | |
148 i.create_system = 3 | |
149 ftype = stat.S_IFREG | |
150 if islink: | |
151 mode = 0777 | |
152 ftype = stat.S_IFLNK | |
153 i.external_attr = (mode | ftype) << 16L | |
154 self.z.writestr(i, data) | |
155 | |
156 def done(self): | |
157 self.z.close() | |
158 | |
159 class fileit(object): | |
160 '''write archive as files in directory.''' | |
161 | |
162 def __init__(self, name, prefix, mtime): | |
163 if prefix: | |
164 raise util.Abort(_('cannot give prefix when archiving to files')) | |
165 self.basedir = name | |
166 self.opener = util.opener(self.basedir) | |
167 | |
168 def addfile(self, name, mode, islink, data): | |
169 if islink: | |
170 self.opener.symlink(data, name) | |
171 return | |
172 f = self.opener(name, "w", atomictemp=True) | |
173 f.write(data) | |
174 f.rename() | |
175 destfile = os.path.join(self.basedir, name) | |
176 os.chmod(destfile, mode) | |
177 | |
178 def done(self): | |
179 pass | |
180 | |
181 archivers = { | |
182 'files': fileit, | |
183 'tar': tarit, | |
184 'tbz2': lambda name, prefix, mtime: tarit(name, prefix, mtime, 'bz2'), | |
185 'tgz': lambda name, prefix, mtime: tarit(name, prefix, mtime, 'gz'), | |
186 'uzip': lambda name, prefix, mtime: zipit(name, prefix, mtime, False), | |
187 'zip': zipit, | |
188 } | |
189 | |
190 def archive(repo, dest, node, kind, decode=True, matchfn=None, | |
191 prefix=None, mtime=None): | |
192 '''create archive of repo as it was at node. | |
193 | |
194 dest can be name of directory, name of archive file, or file | |
195 object to write archive to. | |
196 | |
197 kind is type of archive to create. | |
198 | |
199 decode tells whether to put files through decode filters from | |
200 hgrc. | |
201 | |
202 matchfn is function to filter names of files to write to archive. | |
203 | |
204 prefix is name of path to put before every archive member.''' | |
205 | |
206 def write(name, mode, islink, getdata): | |
207 if matchfn and not matchfn(name): return | |
208 data = getdata() | |
209 if decode: | |
210 data = repo.wwritedata(name, data) | |
211 archiver.addfile(name, mode, islink, data) | |
212 | |
213 if kind not in archivers: | |
214 raise util.Abort(_("unknown archive type '%s'") % kind) | |
215 | |
216 ctx = repo[node] | |
217 archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0]) | |
218 | |
219 if repo.ui.configbool("ui", "archivemeta", True): | |
220 write('.hg_archival.txt', 0644, False, | |
221 lambda: 'repo: %s\nnode: %s\n' % ( | |
222 hex(repo.changelog.node(0)), hex(node))) | |
223 for f in ctx: | |
224 ff = ctx.flags(f) | |
225 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, ctx[f].data) | |
226 archiver.done() |