2 # pylint: disable-msg=C0301,W0613,W0612,C0103,E0611,W0511
9 Various functions dealing with portage
19 from portage import config as portage_config
20 from portage import settings as portage_settings
24 from portage import dep as portage_dep
27 from portage import portage_dep
29 sys.path.insert(0, "/usr/lib/gentoolkit/pym")
31 import gentoolkit.query
34 __docformat__ = 'restructuredtext'
36 ENV = portage_config(clone=portage_settings)
37 LOGGER = logging.getLogger(__name__)
38 LOGGER.setLevel(logging.DEBUG)
39 LOGGER.addHandler(logging.StreamHandler())
44 Return a dict of overlay names with their paths
46 {'reponame': '/path/to/repo', ...}
48 @returns: dict with repoman/paths
51 porttrees = [ENV['PORTDIR']] + \
52 [os.path.realpath(t) for t in ENV["PORTDIR_OVERLAY"].split()]
54 for path in porttrees:
55 repo_name_path = os.path.join(path, 'profiles/repo_name')
57 repo_name = open(repo_name_path, 'r').readline().strip()
58 treemap[repo_name] = path
59 except (OSError,IOError):
60 LOGGER.warn("No repo_name in %s" % path)
63 def get_installed_ver(cpn):
65 Return PV for installed version of package
67 @param cpn: cat/pkg-ver
70 @returns: string version or None if not pkg installed
74 #Return first version installed
75 #XXX Log warning if more than one installed (SLOT)?
76 pkg = gentoolkit.find_installed_packages(cpn, masked=True)[0]
77 return pkg.get_version()
83 Return True if cpn is valid portage category/pn-pv
85 @param cpn: cat/pkg-ver
88 @returns: True if installed, False if not installed
90 if portage_dep.isvalidatom(cpn):
96 def ebuild_exists(cat_pkg):
99 Checks if an ebuild exists in portage tree or overlay
101 @param cat_pkg: portage category/packagename
102 @type cat_pkg: string
104 @returns: True if ebuild exists, False if no ebuild exists
107 pkgs = gentoolkit.query.Query(cat_pkg).find()
113 #def run_tests(ebuild_path):
115 # Use portage to run tests
117 # Some day I'll figure out how to get portage to do this directly. Some day.
119 # @param ebuild_path: full path to ebuild
120 # @type ebuild_path: string
121 # @returns: None if succeed, raises OSError if fails to unpack
124 # cmd = "/usr/bin/python /usr/bin/ebuild %s test" % ebuild_path
126 # (status, output) = commands.getstatusoutput(cmd)
130 def unpack_ebuild(ebuild_path):
132 Use portage to unpack an ebuild
134 Some day I'll figure out how to get portage to do this directly. Some day.
136 @param ebuild_path: full path to ebuild
137 @type ebuild_path: string
138 @returns: None if succeed, raises OSError if fails to unpack
141 (status, output) = commands.getstatusoutput("ebuild %s digest setup clean unpack" % ebuild_path)
143 #Portage's error message, sometimes.
144 #Couldn't determine PN or PV so we misnamed ebuild
145 if 'does not follow correct package syntax' in output:
147 LOGGER.error("Misnamed ebuild: %s" % ebuild_path)
148 LOGGER.error("Try using -n or -v to force PN or PV")
149 os.unlink(ebuild_path)
154 def find_s_dir(p, cat):
156 Try to get ${S} by determining what directories were unpacked
158 @param p: portage ${P}
161 @param cat: valid portage category
164 @returns: string with directory name if detected, empty string
165 if S=WORKDIR, None if couldn't find S
170 workdir = get_workdir(p, cat)
171 files = os.listdir(workdir)
173 for unpacked in files:
174 if os.path.isdir(os.path.join(workdir, unpacked)):
175 dirs.append(unpacked)
177 #Only one directory, must be it.
183 #XXX Need to search whole tree for setup.py
184 LOGGER.error("Can't determine ${S}")
185 LOGGER.error("Unpacked multiple directories: %s" % dirs)
187 def get_workdir(p, cat):
191 @param p: portage ${P}
194 @param cat: valid portage category
197 @return: string of portage_tmpdir/cp
200 return '%s/portage/%s/%s/work' % (get_portage_tmpdir(), cat, p)
202 def get_portdir_overlay():
203 """Return PORTDIR_OVERLAY from /etc/make.conf"""
204 return ENV['PORTDIR_OVERLAY'].split(" ")[0]
206 def get_portage_tmpdir():
207 """Return PORTAGE_TMPDIR from /etc/make.conf"""
208 return ENV["PORTAGE_TMPDIR"]
211 """Return PORTDIR from /etc/make.conf"""
212 return ENV["PORTDIR"]
215 """Return first ACCEPT_KEYWORDS from /etc/make.conf"""
216 #Choose the first arch they have, in case of multiples.
219 arch = ENV["ACCEPT_KEYWORDS"].split(' ')[0]
221 LOGGER.error("No ACCEPT_KEYWORDS found, using ~x86")
224 #New ebuilds must be ~arch
226 if not arch.startswith('~'):
230 def make_overlay_dir(category, pn, overlay):
232 Create directory(s) in overlay for ebuild
234 @param category: valid portage category
235 @type category: string
237 @param pn: portage ${PN}
240 @param overlay: portage overlay directory
241 @type overlay: string
243 @return: string of full directory name
247 ebuild_dir = os.path.join(overlay, category, pn)
248 if not os.path.isdir(ebuild_dir):
250 os.makedirs(ebuild_dir)
258 def find_egg_info_dir(root):
260 Locate all files matching supplied filename pattern in and below
261 supplied root directory.
263 for path, dirs, files in os.walk(os.path.abspath(root)):
264 for this_dir in dirs:
265 if this_dir.endswith(".egg-info"):
266 return os.path.normpath(os.path.join(path, this_dir, ".."))
268 #Unused as of now. Could be used to find setup.py
269 #def find_files(pattern, root):
271 # Locate all files matching supplied filename pattern in and below
272 # supplied root directory.
274 # for path, dirs, files in os.walk(os.path.abspath(root)):
275 # for filename in fnmatch.filter(dirs, pattern):
276 # yield os.path.join(path, filename)
277 if __name__ == '__main__':
278 print get_repo_names()