1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
# debpartial_mirror - partial debian mirror package tool
# (c) 2004 Otavio Salvador <otavio@debian.org>, Marco Presi <zufus@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import os
import sys
import apt_pkg
from cdd import FileSystem
from debpartial_mirror import Download
class Pool:
"""
This class provides methods to manage pool dirs into the
partial-mirror.
"""
def __init__(self, backend):
self._backend = backend
self._got_files = []
self._containsForeignPackages = False
self._filesystem = FileSystem.FileSystem(
backend["mirror_dir"],
backend["name"]
)
def _process_package(self, pkg):
"""
This method is called for each package and should be override
in each child class.
"""
raise NotImplemented
def _calc_need_files(self):
"""
This method is called to build the list of need files to
permit to us to clean up the mirror. If you need to handle in
a special way to calc it, you're free to override this method.
"""
if not len(self._got_files):
self._backend.process()
need_files = []
for architecture in self._backend["architectures"]:
need_files.extend([pkg['Filename'] for pkg in self._backend.get_binary_list(architecture).values()])
else:
need_files = self._got_files
return need_files
def _link_internal(self, pkg, mirror):
filename = pkg['Filename']
self._filesystem.mkdir(os.path.dirname(filename))
src = self._backend["mirror_dir"] + "/" + mirror["name"] + "/" + filename
dst = os.path.join(self._filesystem.base(), filename)
if not os.path.exists(dst):
try:
print "Linking [%s] %s" % (mirror["name"], filename)
os.link (src, dst)
except OSError, msg:
print "Error while linking a file:"
print " [%s] %s" % (mirror["name"], filename)
print " System message: %s" % msg
sys.exit(1) #TODO: fixme
self._got_files.append(filename)
def upgrade(self):
"""
Manage the pool upgrade process
TODO: Handle source packages.
"""
def processPackage(pkg, architecture):
foundList = self._backend.get_binary_list(architecture).whereis(pkg["Package"])
if foundList in (self._backend.get_binary_list(architecture), self._backend.get_full_binary_list(architecture)):
self._process_package(pkg)
else: # required dependency from another mirror
for backend in self._backend.backends:
if backend.get_full_binary_list(architecture) == foundList:
break
else:
raise RuntimeError("No backend found for %s", pkg["Package"])
self._link_internal(pkg, backend)
self._containsForeignPackages = True
for architecture in self._backend["architectures"]:
for pkg in self._backend.get_binary_list(architecture).values():
filename = pkg['Filename']
if not self._filesystem.exists(filename):
processPackage(pkg, architecture)
elif self._filesystem.md5sum(filename) == pkg['MD5sum']:
self._got_files.append(filename)
else:
print 'Removing corrupted package', pkg['Package']
self._filesystem.remove(filename)
processPackage(pkg, architecture)
def clean (self):
"""
Clean old files
"""
need_files = self._calc_need_files()
# Walk in all debian related files of mirror
for current in self._filesystem.match("^.+\.(dsc|(diff|tar)\.gz|deb|udeb)$"):
if current not in need_files:
print "Removing unneeded file: %s" % current
self._filesystem.remove(current)
try:
self._filesystem.rmdir(os.path.dirname(current), True)
except OSError:
pass
def containsForeignPackages(self):
return self._containsForeignPackages
class RemotePool (Pool):
"""
This class provides methods to fill pool dir downloading remote files
"""
def __init__ (self, backend):
Pool.__init__(self, backend) # Call parent constructor
self.download = Download.Download(name = "Pool_" + backend["name"]) # Our Download manager
def _process_package (self, pkg):
self._filesystem.mkdir(os.path.dirname(pkg['Filename']))
self.download.get(
os.path.join(self._backend["server"], pkg['Filename']),
os.path.join(self._filesystem.base(), pkg['Filename'])
)
self._got_files.append(pkg['Filename'])
def upgrade (self):
Pool.upgrade(self) # Call parent method
self.download.wait_mine() # Wait until our downloads finish
class LocalPool (Pool):
"""
This class provides methods to fill pool dir linking from local files
"""
def _process_package (self):
self._filesystem.mkdir(os.path.dirname(pkg['Filename']))
os.link(
self._backend["server"].split('file://')[1] + pkg,
self._local + pkg
)
self._got_files.append(pkg['Filename'])
class MergePool (Pool):
"""
This class provides methods to fill pool dir mergin other pools
"""
def _calc_need_files(self):
need_files = []
for architecture in self._backend["architectures"]:
for mirror in self._backend.get_mirrors():
for pkg in self._backend.get_packages_for_mirror(mirror, architecture).values():
need_files.append(pkg['Filename'])
return need_files
def merge (self):
for architecture in self._backend["architectures"]:
for mirror in self._backend.get_mirrors():
for pkg in self._backend.get_packages_for_mirror(mirror, architecture).values():
self._link_internal(pkg, mirror)
|