comparison mercurial/archival.py @ 11558:d8f6458434ec

archival: remove prefix argument from archivers When the archivers work on the full we can reuse the same archiver with different prefixes (for different subrepositories).
author Martin Geisler <mg@lazybytes.net>
date Wed, 14 Jul 2010 20:25:31 +0200
parents 57bdc2239535
children 1ef70bdd1e62
comparison
equal deleted inserted replaced
11557:57bdc2239535 11558:d8f6458434ec
10 import cmdutil 10 import cmdutil
11 import util 11 import util
12 import cStringIO, os, stat, tarfile, time, zipfile 12 import cStringIO, os, stat, tarfile, time, zipfile
13 import zlib, gzip 13 import zlib, gzip
14 14
15 def tidyprefix(dest, prefix, suffixes): 15 def tidyprefix(dest, kind, prefix):
16 '''choose prefix to use for names in archive. make sure prefix is 16 '''choose prefix to use for names in archive. make sure prefix is
17 safe for consumers.''' 17 safe for consumers.'''
18 18
19 if prefix: 19 if prefix:
20 prefix = util.normpath(prefix) 20 prefix = util.normpath(prefix)
21 else: 21 else:
22 if not isinstance(dest, str): 22 if not isinstance(dest, str):
23 raise ValueError('dest must be string if no prefix') 23 raise ValueError('dest must be string if no prefix')
24 prefix = os.path.basename(dest) 24 prefix = os.path.basename(dest)
25 lower = prefix.lower() 25 lower = prefix.lower()
26 for sfx in suffixes: 26 for sfx in exts.get(kind, []):
27 if lower.endswith(sfx): 27 if lower.endswith(sfx):
28 prefix = prefix[:-len(sfx)] 28 prefix = prefix[:-len(sfx)]
29 break 29 break
30 lpfx = os.path.normpath(util.localpath(prefix)) 30 lpfx = os.path.normpath(util.localpath(prefix))
31 prefix = util.pconvert(lpfx) 31 prefix = util.pconvert(lpfx)
78 self.fileobj.write('\002') 78 self.fileobj.write('\002')
79 self.fileobj.write('\377') 79 self.fileobj.write('\377')
80 if fname: 80 if fname:
81 self.fileobj.write(fname + '\000') 81 self.fileobj.write(fname + '\000')
82 82
83 def __init__(self, dest, prefix, mtime, kind=''): 83 def __init__(self, dest, mtime, kind=''):
84 self.prefix = tidyprefix(dest, prefix, ['.tar', '.tar.bz2', '.tar.gz',
85 '.tgz', '.tbz2'])
86 self.mtime = mtime 84 self.mtime = mtime
87 85
88 def taropen(name, mode, fileobj=None): 86 def taropen(name, mode, fileobj=None):
89 if kind == 'gz': 87 if kind == 'gz':
90 mode = mode[0] 88 mode = mode[0]
102 else: 100 else:
103 # Python 2.5-2.5.1 have a regression that requires a name arg 101 # Python 2.5-2.5.1 have a regression that requires a name arg
104 self.z = taropen(name='', mode='w|', fileobj=dest) 102 self.z = taropen(name='', mode='w|', fileobj=dest)
105 103
106 def addfile(self, name, mode, islink, data): 104 def addfile(self, name, mode, islink, data):
107 i = tarfile.TarInfo(self.prefix + name) 105 i = tarfile.TarInfo(name)
108 i.mtime = self.mtime 106 i.mtime = self.mtime
109 i.size = len(data) 107 i.size = len(data)
110 if islink: 108 if islink:
111 i.type = tarfile.SYMTYPE 109 i.type = tarfile.SYMTYPE
112 i.mode = 0777 110 i.mode = 0777
141 139
142 class zipit(object): 140 class zipit(object):
143 '''write archive to zip file or stream. can write uncompressed, 141 '''write archive to zip file or stream. can write uncompressed,
144 or compressed with deflate.''' 142 or compressed with deflate.'''
145 143
146 def __init__(self, dest, prefix, mtime, compress=True): 144 def __init__(self, dest, mtime, compress=True):
147 self.prefix = tidyprefix(dest, prefix, ('.zip',))
148 if not isinstance(dest, str): 145 if not isinstance(dest, str):
149 try: 146 try:
150 dest.tell() 147 dest.tell()
151 except (AttributeError, IOError): 148 except (AttributeError, IOError):
152 dest = tellable(dest) 149 dest = tellable(dest)
154 compress and zipfile.ZIP_DEFLATED or 151 compress and zipfile.ZIP_DEFLATED or
155 zipfile.ZIP_STORED) 152 zipfile.ZIP_STORED)
156 self.date_time = time.gmtime(mtime)[:6] 153 self.date_time = time.gmtime(mtime)[:6]
157 154
158 def addfile(self, name, mode, islink, data): 155 def addfile(self, name, mode, islink, data):
159 i = zipfile.ZipInfo(self.prefix + name, self.date_time) 156 i = zipfile.ZipInfo(name, self.date_time)
160 i.compress_type = self.z.compression 157 i.compress_type = self.z.compression
161 # unzip will not honor unix file modes unless file creator is 158 # unzip will not honor unix file modes unless file creator is
162 # set to unix (id 3). 159 # set to unix (id 3).
163 i.create_system = 3 160 i.create_system = 3
164 ftype = stat.S_IFREG 161 ftype = stat.S_IFREG
172 self.z.close() 169 self.z.close()
173 170
174 class fileit(object): 171 class fileit(object):
175 '''write archive as files in directory.''' 172 '''write archive as files in directory.'''
176 173
177 def __init__(self, name, prefix, mtime): 174 def __init__(self, name, mtime):
178 if prefix:
179 raise util.Abort(_('cannot give prefix when archiving to files'))
180 self.basedir = name 175 self.basedir = name
181 self.opener = util.opener(self.basedir) 176 self.opener = util.opener(self.basedir)
182 177
183 def addfile(self, name, mode, islink, data): 178 def addfile(self, name, mode, islink, data):
184 if islink: 179 if islink:
194 pass 189 pass
195 190
196 archivers = { 191 archivers = {
197 'files': fileit, 192 'files': fileit,
198 'tar': tarit, 193 'tar': tarit,
199 'tbz2': lambda name, prefix, mtime: tarit(name, prefix, mtime, 'bz2'), 194 'tbz2': lambda name, mtime: tarit(name, mtime, 'bz2'),
200 'tgz': lambda name, prefix, mtime: tarit(name, prefix, mtime, 'gz'), 195 'tgz': lambda name, mtime: tarit(name, mtime, 'gz'),
201 'uzip': lambda name, prefix, mtime: zipit(name, prefix, mtime, False), 196 'uzip': lambda name, mtime: zipit(name, mtime, False),
202 'zip': zipit, 197 'zip': zipit,
203 } 198 }
204 199
205 def archive(repo, dest, node, kind, decode=True, matchfn=None, 200 def archive(repo, dest, node, kind, decode=True, matchfn=None,
206 prefix=None, mtime=None): 201 prefix=None, mtime=None):
215 hgrc. 210 hgrc.
216 211
217 matchfn is function to filter names of files to write to archive. 212 matchfn is function to filter names of files to write to archive.
218 213
219 prefix is name of path to put before every archive member.''' 214 prefix is name of path to put before every archive member.'''
215
216 if kind == 'files':
217 if prefix:
218 raise util.Abort(_('cannot give prefix when archiving to files'))
219 else:
220 prefix = tidyprefix(dest, kind, prefix)
220 221
221 def write(name, mode, islink, getdata): 222 def write(name, mode, islink, getdata):
222 if matchfn and not matchfn(name): 223 if matchfn and not matchfn(name):
223 return 224 return
224 data = getdata() 225 data = getdata()
225 if decode: 226 if decode:
226 data = repo.wwritedata(name, data) 227 data = repo.wwritedata(name, data)
227 archiver.addfile(name, mode, islink, data) 228 archiver.addfile(prefix + name, mode, islink, data)
228 229
229 if kind not in archivers: 230 if kind not in archivers:
230 raise util.Abort(_("unknown archive type '%s'") % kind) 231 raise util.Abort(_("unknown archive type '%s'") % kind)
231 232
232 ctx = repo[node] 233 ctx = repo[node]
233 archiver = archivers[kind](dest, prefix, mtime or ctx.date()[0]) 234 archiver = archivers[kind](dest, mtime or ctx.date()[0])
234 235
235 if repo.ui.configbool("ui", "archivemeta", True): 236 if repo.ui.configbool("ui", "archivemeta", True):
236 def metadata(): 237 def metadata():
237 base = 'repo: %s\nnode: %s\nbranch: %s\n' % ( 238 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
238 hex(repo.changelog.node(0)), hex(node), ctx.branch()) 239 hex(repo.changelog.node(0)), hex(node), ctx.branch())