mercurial/archival.py
changeset 4868 192cd95c2ba8
parent 4862 6f08bc1bd00b
child 4933 667290b6c95e
equal deleted inserted replaced
4857:8be7ba425621 4868:192cd95c2ba8
    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()