6 # the GNU General Public License, incorporated herein by reference. |
6 # the GNU General Public License, incorporated herein by reference. |
7 |
7 |
8 from i18n import _ |
8 from i18n import _ |
9 from node import * |
9 from node import * |
10 import cStringIO, os, stat, tarfile, time, util, zipfile |
10 import cStringIO, os, stat, tarfile, time, util, zipfile |
|
11 import zlib, gzip |
11 |
12 |
12 def tidyprefix(dest, prefix, suffixes): |
13 def tidyprefix(dest, prefix, suffixes): |
13 '''choose prefix to use for names in archive. make sure prefix is |
14 '''choose prefix to use for names in archive. make sure prefix is |
14 safe for consumers.''' |
15 safe for consumers.''' |
15 |
16 |
34 |
35 |
35 class tarit: |
36 class tarit: |
36 '''write archive to tar file or stream. can write uncompressed, |
37 '''write archive to tar file or stream. can write uncompressed, |
37 or compress with gzip or bzip2.''' |
38 or compress with gzip or bzip2.''' |
38 |
39 |
|
40 class GzipFileWithTime(gzip.GzipFile): |
|
41 |
|
42 def __init__(self, *args, **kw): |
|
43 timestamp = None |
|
44 if 'timestamp' in kw: |
|
45 timestamp = kw.pop('timestamp') |
|
46 if timestamp == None: |
|
47 self.timestamp = time.time() |
|
48 else: |
|
49 self.timestamp = timestamp |
|
50 gzip.GzipFile.__init__(self, *args, **kw) |
|
51 |
|
52 def _write_gzip_header(self): |
|
53 self.fileobj.write('\037\213') # magic header |
|
54 self.fileobj.write('\010') # compression method |
|
55 fname = self.filename[:-3] |
|
56 flags = 0 |
|
57 if fname: |
|
58 flags = gzip.FNAME |
|
59 self.fileobj.write(chr(flags)) |
|
60 gzip.write32u(self.fileobj, long(self.timestamp)) |
|
61 self.fileobj.write('\002') |
|
62 self.fileobj.write('\377') |
|
63 if fname: |
|
64 self.fileobj.write(fname + '\000') |
|
65 |
39 def __init__(self, dest, prefix, mtime, kind=''): |
66 def __init__(self, dest, prefix, mtime, kind=''): |
40 self.prefix = tidyprefix(dest, prefix, ['.tar', '.tar.bz2', '.tar.gz', |
67 self.prefix = tidyprefix(dest, prefix, ['.tar', '.tar.bz2', '.tar.gz', |
41 '.tgz', '.tbz2']) |
68 '.tgz', '.tbz2']) |
42 self.mtime = mtime |
69 self.mtime = mtime |
|
70 |
|
71 def taropen(name, mode, fileobj=None): |
|
72 if kind == 'gz': |
|
73 mode = mode[0] |
|
74 if not fileobj: |
|
75 fileobj = open(name, mode) |
|
76 gzfileobj = self.GzipFileWithTime(name, mode + 'b', |
|
77 zlib.Z_BEST_COMPRESSION, |
|
78 fileobj, timestamp=mtime) |
|
79 return tarfile.TarFile.taropen(name, mode, gzfileobj) |
|
80 else: |
|
81 return tarfile.open(name, mode + kind, fileobj) |
|
82 |
43 if isinstance(dest, str): |
83 if isinstance(dest, str): |
44 self.z = tarfile.open(dest, mode='w:'+kind) |
84 self.z = taropen(dest, mode='w:') |
45 else: |
85 else: |
46 # 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 |
47 self.z = tarfile.open(name='', mode='w|'+kind, fileobj=dest) |
87 self.z = taropen(name='', mode='w|', fileobj=dest) |
48 |
88 |
49 def addfile(self, name, mode, data): |
89 def addfile(self, name, mode, data): |
50 i = tarfile.TarInfo(self.prefix + name) |
90 i = tarfile.TarInfo(self.prefix + name) |
51 i.mtime = self.mtime |
91 i.mtime = self.mtime |
52 i.size = len(data) |
92 i.size = len(data) |