]> git.ipfire.org Git - people/stevee/pakfire.git/blob - pakfire/repository/local.py
Add copyright information to all files.
[people/stevee/pakfire.git] / pakfire / repository / local.py
1 #!/usr/bin/python
2 ###############################################################################
3 # #
4 # Pakfire - The IPFire package management system #
5 # Copyright (C) 2011 Pakfire development team #
6 # #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
11 # #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
16 # #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 # #
20 ###############################################################################
21
22 import logging
23 import os
24 import shutil
25
26 import base
27 import index
28 import metadata
29
30 import pakfire.compress as compress
31 import pakfire.packages as packages
32 import pakfire.util as util
33
34 from pakfire.constants import *
35
36 class RepositoryDir(base.RepositoryFactory):
37 def __init__(self, pakfire, name, description, path, type="binary"):
38 base.RepositoryFactory.__init__(self, pakfire, name, description)
39
40 # Path to files.
41 self.path = path
42
43 # Save type.
44 assert type in ("binary", "source",)
45 self.type = type
46
47 # Create index
48 self.index = index.IndexDir(self.pakfire, self)
49
50 def remove(self):
51 self.index.clear()
52 util.rm(self.path)
53
54 @property
55 def priority(self):
56 """
57 The local repository has always a high priority.
58 """
59 return 10
60
61 @property
62 def local(self):
63 # Yes, this is local.
64 return True
65
66 def collect_packages(self, *args, **kwargs):
67 """
68 Proxy function to add packages to the index.
69 """
70
71 for pkg in self.index.collect_packages(*args, **kwargs):
72 # The path of the package in the repository
73 repo_filename = os.path.join(self.path, os.path.basename(pkg.filename))
74
75 # Do we need to copy the package files?
76 copy = True
77
78 # Check, if the package does already exists and check if the
79 # files are really equal.
80 if os.path.exists(repo_filename):
81 pkg_exists = packages.open(self.pakfire, self, repo_filename)
82 copy = False
83
84 # Check UUID at first (faster) and check the file hash to be
85 # absolutely sure.
86 # Otherwise, unlink the existing file and replace it with the
87 # new one.
88 if pkg.uuid != pkg_exists.uuid and pkg.hash1 != pkg_exists.hash1:
89 # Do not copy the file if it is already okay.
90 copy = True
91 os.unlink(repo_filename)
92
93 del pkg_exists
94
95 if copy:
96 logging.debug("Copying package '%s' to repository." % pkg)
97 repo_dirname = os.path.dirname(repo_filename)
98 if not os.path.exists(repo_dirname):
99 os.makedirs(repo_dirname)
100
101 # Try to use a hard link if possible, if we cannot do that we simply
102 # copy the file.
103 try:
104 os.link(pkg.filename, repo_filename)
105 except OSError:
106 shutil.copy2(pkg.filename, repo_filename)
107
108 def save(self, path=None, algo="xz"):
109 """
110 This function saves the database and metadata to path so it can
111 be exported to a remote repository.
112 """
113 if not path:
114 path = self.path
115
116 # Create filenames
117 metapath = os.path.join(path, METADATA_DOWNLOAD_PATH)
118 db_path = os.path.join(metapath, METADATA_DATABASE_FILE)
119 md_path = os.path.join(metapath, METADATA_DOWNLOAD_FILE)
120
121 if not os.path.exists(metapath):
122 os.makedirs(metapath)
123
124 else:
125 # If a database is present, we remove it because we want to start
126 # with a clean environment.
127 if os.path.exists(db_path):
128 os.unlink(db_path)
129
130 # Save the database to path and get the filename.
131 self.index.write(db_path)
132
133 # Make a reference to the database file that it will get a unique name
134 # so we won't get into any trouble with caching proxies.
135 db_hash = util.calc_hash1(db_path)
136
137 db_path2 = os.path.join(os.path.dirname(db_path),
138 "%s-%s" % (db_hash, os.path.basename(db_path)))
139
140 # Compress the database.
141 if algo:
142 compress.compress(db_path, algo=algo, progress=True)
143
144 if not os.path.exists(db_path2):
145 shutil.move(db_path, db_path2)
146 else:
147 os.unlink(db_path)
148
149 # Create a new metadata object and add out information to it.
150 md = metadata.Metadata(self.pakfire, self)
151
152 # Save name of the hashed database to the metadata.
153 md.database = os.path.basename(db_path2)
154 md.database_hash1 = db_hash
155 md.database_compression = algo
156
157 # Save metdata to repository.
158 md.save(md_path)
159
160
161 class RepositoryBuild(RepositoryDir):
162 def __init__(self, pakfire):
163 # XXX need to add distro information to this path
164 path = pakfire.config.get("local_build_repo_path")
165
166 # Create path if it does not exist.
167 if not os.path.exists(path):
168 os.makedirs(path)
169
170 RepositoryDir.__init__(self, pakfire, "build", "Locally built packages", path)
171
172 @property
173 def local(self):
174 """
175 Yes, this is local.
176 """
177 return True
178
179 @property
180 def priority(self):
181 return 20000
182
183
184 class RepositoryLocal(base.RepositoryFactory):
185 def __init__(self, pakfire):
186 base.RepositoryFactory.__init__(self, pakfire, "@system", "Local repository")
187
188 self.index = index.IndexLocal(self.pakfire, self)
189
190 # Tell the solver, that these are the installed packages.
191 self.pool.set_installed(self.solver_repo)
192
193 @property
194 def priority(self):
195 """
196 The local repository has always a high priority.
197 """
198 return 10
199
200 def add_package(self, pkg):
201 # Add package to the database.
202 self.index.db.add_package(pkg)
203
204 self.index.add_package(pkg)
205
206 def rem_package(self, pkg):
207 # Remove package from the database.
208 self.index.rem_package(pkg)