84 self.z = taropen(dest, mode='w:') |
84 self.z = taropen(dest, mode='w:') |
85 else: |
85 else: |
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() |
98 |
105 |
99 class tellable: |
106 class tellable: |
128 self.z = zipfile.ZipFile(dest, 'w', |
135 self.z = zipfile.ZipFile(dest, 'w', |
129 compress and zipfile.ZIP_DEFLATED or |
136 compress and zipfile.ZIP_DEFLATED or |
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): |
143 self.z.close() |
154 self.z.close() |
144 |
155 |
147 |
158 |
148 def __init__(self, name, prefix, mtime): |
159 def __init__(self, name, prefix, mtime): |
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 | |
164 |
154 getattr(os, 'O_BINARY', 0) | |
165 def addfile(self, name, mode, islink, data): |
155 getattr(os, 'O_NOFOLLOW', 0)) |
166 if islink: |
156 |
167 self.opener.symlink(data, name) |
157 def addfile(self, name, mode, data): |
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 |
168 |
177 |
169 archivers = { |
178 archivers = { |
189 |
198 |
190 matchfn is function to filter names of files to write to archive. |
199 matchfn is function to filter names of files to write to archive. |
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() |