Subject: yum patch for RHEL6
From: Gordan Bobic <gordan@bobich.net>
Date: Fri, 10 Sep 2010 23:59:05 +0100
Fri, 10 Sep 2010 23:59:05 +0100
If anybody is interested, attached are:
1) yum 3.2.27 patch for RHEL6 (applies after other RHEL6 yum patches, so
it may not apply cleanly against vanilla yum 3.2.27)
2) Modified spec file for RHEL6.
I haven't tested this extensively yet, but it works for me so far.
To build the RHEL6 package with the patch:
wget http://path/to/mirror/yum-3.2.27-12.el6.src.rpm
rpm -ivh yum-3.2.27-12.el6.src.rpm
Put the patch in ~/rpmbuild/SOURCES
Put the spec in ~/rpmbuild/SPECS
rpmbuild -ba yum.spec
I hope somebody finds this useful.
Gordan
%{!?python_sitelib: %define python_sitelib %(python -c "from distutils.sysconfig import
get_python_lib; print get_python_lib()")}
Summary: RPM installer/updater
Name: yum
Version: 3.2.27
Release: 12vs%{?dist}
License: GPLv2+
Group: System Environment/Base
Source0: http://yum.baseurl.org/download/3.2/%{name}-%{version}.tar.gz
Source1: yum.conf.fedora
Source2: yum-updatesd.conf.fedora
Patch0: installonlyn-enable.patch
Patch1: yum-mirror-priority.patch
Patch2: yum-manpage-files.patch
Patch3: yum-multilib-policy-best.patch
Patch4: no-more-exactarchlist.patch
Patch5: geode-arch.patch
Patch32: yum-distro-sync.patch
Patch33: yum-install-cmd-exit+provides-msgs+docs.patch
Patch34: yum-history-user.patch
Patch35: yum-PK-search-API.patch
Patch36: yum-history-list-errors+summary-user-column.patch
Patch37: yum-groupremove-leaf-only.patch
Patch38: yum-md-reget+yumvars+searchPrco.patch
Patch39: BZ-588911-yum.log-perms.patch
Patch40: BZ-577627-installroot-double-prefix.patch
Patch41: BZ-588910-nocontext-tsflag.patch
Patch42: BZ-588908-many-install-update-speedup.patch
Patch43: BZ-590340-move-rpmdb-from-cache.patch
Patch44: BZ-590339-edge-case-depsolving.patch
Patch45: BZ-593522-install-obs-arch.patch
Patch46: BZ-595553-akmods-cache-defense.patch
Patch47: BZ-602354-plugin-hooks-verify-transaction.patch
Patch48: BZ-584262-downgrade-dep-chain-remove.patch
Patch49: BZ-598639-rpm-bindings-api-change-fix.patch
Patch50: BZ-603002-group_remove_leaf-empty-transaction.patch
Patch51: BZ-604080-localinstall-obsoleted.patch
Patch64: yum-ppc64-preferred.patch
Patch65: yum-3.2.27-i18n-off.patch
Patch99: yum-3.2.27-chroot.patch
URL: http://yum.baseurl.org/
BuildArch: noarch
BuildRequires: python
BuildRequires: gettext
BuildRequires: intltool
Conflicts: pirut < 1.1.4
Requires: python >= 2.4, rpm-python, rpm >= 0:4.4.2
Requires: python-iniparse
Requires: python-sqlite
Requires: python-urlgrabber >= 3.9.0-8
Requires: yum-metadata-parser >= 1.1.0
Requires: pygpgme
Obsoletes: yum-skip-broken, yum-basearchonly
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
%description
Yum is a utility that can check for and automatically download and
install updated RPM packages. Dependencies are obtained and downloaded
automatically prompting the user as necessary.
%package updatesd
Summary: Update notification daemon
Group: Applications/System
Requires: yum = %{version}-%{release}
Requires: dbus-python
Requires: pygobject2
Requires(preun): /sbin/chkconfig
Requires(post): /sbin/chkconfig
Requires(preun): /sbin/service
Requires(post): /sbin/service
%description updatesd
yum-updatesd provides a daemon which checks for available updates and
can notify you when they are available via email, syslog or dbus.
%prep
%setup -q
%patch1 -p0
%patch2 -p1
%patch3 -p0
%patch4 -p0
%patch5 -p1
%patch32 -p1
%patch33 -p1
%patch34 -p1
%patch35 -p1
%patch36 -p1
%patch37 -p1
%patch38 -p1
%patch39 -p1
%patch40 -p1
%patch41 -p1
%patch42 -p1
%patch43 -p1
%patch44 -p1
%patch45 -p1
%patch46 -p1
%patch47 -p1
%patch48 -p1
%patch49 -p1
%patch50 -p1
%patch51 -p1
%patch64 -p0
%patch65 -p1
%patch99 -p1
%build
make
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT install
install -m 644 %{SOURCE1} $RPM_BUILD_ROOT/%{_sysconfdir}/yum.conf
mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/yum/pluginconf.d $RPM_BUILD_ROOT/usr/lib/yum-plugins
# for now, move repodir/yum.conf back
mv $RPM_BUILD_ROOT/%{_sysconfdir}/yum/repos.d $RPM_BUILD_ROOT/%{_sysconfdir}/yum.repos.d
rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/yum/yum.conf
# yum-updatesd has moved to the separate source version
rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/yum/yum-updatesd.conf
rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/rc.d/init.d/yum-updatesd
rm -f $RPM_BUILD_ROOT/%{_sysconfdir}/dbus-1/system.d/yum-updatesd.conf
rm -f $RPM_BUILD_ROOT/%{_sbindir}/yum-updatesd
rm -f $RPM_BUILD_ROOT/%{_mandir}/man*/yum-updatesd*
rm -f $RPM_BUILD_ROOT/%{_datadir}/yum-cli/yumupd.py*
# Ghost files:
mkdir -p $RPM_BUILD_ROOT/var/lib/yum/history
mkdir -p $RPM_BUILD_ROOT/var/lib/yum/plugins
mkdir -p $RPM_BUILD_ROOT/var/lib/yum/yumdb
touch $RPM_BUILD_ROOT/var/lib/yum/uuid
%find_lang %name
%clean
rm -rf $RPM_BUILD_ROOT
%files -f %{name}.lang
%defattr(-, root, root, -)
%doc README AUTHORS COPYING TODO INSTALL ChangeLog
%config(noreplace) %{_sysconfdir}/yum.conf
%dir %{_sysconfdir}/yum
%config(noreplace) %{_sysconfdir}/yum/version-groups.conf
%dir %{_sysconfdir}/yum.repos.d
%config(noreplace) %{_sysconfdir}/logrotate.d/yum
%{_sysconfdir}/bash_completion.d
%dir %{_datadir}/yum-cli
%{_datadir}/yum-cli/*
%{_bindir}/yum
%{python_sitelib}/yum
%{python_sitelib}/rpmUtils
%dir /var/cache/yum
%dir /var/lib/yum
%ghost /var/lib/yum/uuid
%ghost /var/lib/yum/history
%ghost /var/lib/yum/plugins
%ghost /var/lib/yum/yumdb
%{_mandir}/man*/yum.*
%{_mandir}/man*/yum-shell*
# plugin stuff
%dir %{_sysconfdir}/yum/pluginconf.d
%dir /usr/lib/yum-plugins
%changelog
* Wed Jun 16 2010 James Antill <james.antill@redhat.com> - 3.2.27-12
- Stop allowing installation of obsoleted, only by installed.
- Resolves: rhbz#604080
* Fri Jun 11 2010 James Antill <james.antill@redhat.com> - 3.2.27-10
- Stop downgrade dep. chain removals
- Resolves: rhbz#584262
- Fix for rpm bindings api change
- Resolves: rhbz#598639
- Add plugin hooks for verify transaction pre/post.
- Resolves: rhbz#602354
- Fix groupremove_leaf_only when it empties the transaction.
- Resolves: rhbz#603002
* Tue May 25 2010 James Antill <james.antill@redhat.com> - 3.2.27-9
- Fix installs of obsoleted multiarch packages.
- Resolves: rhbz#593522
- Create a defense against akmod style postinst install hacks.
- Resolves: rhbz#595553
* Tue May 11 2010 James Antill <james.antill@redhat.com> - 3.2.27-8
- Move rpmdb cache/indexes to /var/lib
- Resolves: rhbz#590340
- Fix old missing recheck in depsolve
- Resolves: rhbz#590339
* Tue May 4 2010 James Antill <james.antill@redhat.com> - 3.2.27-7
- A few minor bugfixes from upstream
- yum.log perms
- Resolves: rhbz#588911
- installroot double prefixing, on anaconda/kickstart install
- Resolves: rhbz#577627
- Add nocontexts flag to tsflags, if available.
- Resolves: rhbz#588910
- Speedup many install/update of same pkg.
- Resolves: rhbz#588908
- Correct os.path.link => os.path.islink typo, for dynamic yum vars.
- Resolves: rhbz#588907
* Fri Apr 16 2010 James Antill <james.antill@redhat.com> - 3.2.27-4
- A few minor bugfixes from upstream
- Add dynamic FS based yumvars
- Resolves: rhbz#576703
* Fri Mar 26 2010 James Antill <james.antill@redhat.com> - 3.2.27-3
- 3.2.27 from Fedora, and a couple of minor patches
- Resolves: rhbz#576703
* Thu Mar 18 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.27-1
- 3.2.27 from upstream (more or less the same as 3.2.26-6 but with a new number
* Thu Mar 11 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.26-6
- should be the final HEAD update before 3.2.27
* Thu Feb 24 2010 James Antill <james@fedoraproject.org> - 3.2.26-5
- new HEAD, minor features and speed.
* Wed Feb 17 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.26-4
- new HEAD to fix the fix to the fix
* Tue Feb 16 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.26-3
- latest head - including fixes to searchPrcos
* Wed Feb 10 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.26-2
- grumble.
* Tue Feb 9 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.26-1
- final 3.2.26
* Mon Feb 8 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.25-14
- $uuid, pkgtags searching, latest HEAD patch - pre 3.2.26
* Fri Jan 28 2010 James Antill <james at fedoraproject.org> - 3.2.25-13
- A couple of bugfixes, most notably:
- you can now install gpg keys again!
- bad installed file requires don't get cached.
* Fri Jan 22 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.25-12
- someone forgot to push their changes
* Fri Jan 22 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.25-11
- more fixes, more fun
* Fri Jan 15 2010 James Antill <james at fedoraproject.org> - 3.2.25-10
- latest head
- Fixes for pungi, rpmdb caching and kernel-PAE-devel duplicates finding
- among others.
* Mon Jan 4 2010 Seth Vidal <skvidal at fedoraproject.org> - 3.2.25-8
- latest head
* Thu Dec 10 2009 James Antill <james at fedoraproject.org> - 3.2.25-7
- Fixes the mash bug, lookup in the tsInfo too. :(
- And fix the txmbr/po confusion ... third build the charm.
* Fri Dec 4 2009 James Antill <james at fedoraproject.org> - 3.2.25-4
- Fixes for yum clean all, BZ 544173
- Also allow "yum clean rpmdb" to work, bad tester, bad.
* Thu Dec 3 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.25-2
- rebuild yum with latest HEAD patch
- add rpmdb caching patch james wrote to see if it breaks everyone :)
* Wed Oct 14 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.25-1
- 3.2.25
* Wed Sep 30 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-9
- revert yum. import patch b/c it breaks a bunch of things
* Wed Sep 30 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-8
- fix up broken build b/c of version-groups.conf file
* Tue Sep 29 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-7
- fixes for odd outputs from ts.run and logs for what we store in history
* Wed Sep 23 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-6
- new head patch - fixes some issues with history and chroots
* Mon Sep 21 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-5
- latest head patch - includes yum history feature.
* Tue Sep 15 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-4
- new head patch - translation updates and a few bug fixes
* Wed Sep 9 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-3
- add geode arch patch for https://bugzilla.redhat.com/show_bug.cgi?id=518415
* Thu Sep 3 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-2
- modify cachedir to include variables
* Thu Sep 3 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.24-1
- 3.2.24
* Wed Sep 2 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-16
- fix globbing issue 520810
* Mon Aug 31 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-15
- one more head update - fixes some fairly ugly but kind of minor bugs
* Tue Aug 18 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-14
- update to latest head pre 3.2.24
- add requirement on python-urlgrabber 3.9.0 and up
* Wed Aug 5 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-13
- latest head - right after freeze
* Tue Aug 4 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-12
- latest head - right before freeze :)
* Mon Jul 27 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.23-11
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild
* Wed Jul 22 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-10
- remove exactarchlist by request for rawhide
* Thu Jul 2 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-9
- update to latest head - make livecd creation work again in rawhide
- disable one of the man page patches until after 3.2.24 is released b/c
of the changes to the man page in the head patch
* Mon Jun 22 2009 James Antill <james at fedoraproject.org> - 3.2.23-8
- Update to latest head:
- Fix old recursion bug, found by new code.
- Resolves: bug#507220
* Sun Jun 21 2009 James Antill <james at fedoraproject.org> - 3.2.23-6
- Update to latest head:
- Unbreak delPackage() excludes.
- Other fixes/etc.
* Fri Jun 19 2009 James Antill <james at fedoraproject.org> - 3.2.23-5
- Actually apply the HEAD patch included yesterday :).
* Thu Jun 18 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-4
- update to latest head
* Mon Jun 8 2009 Seth Vidal <skvidal at fedoraproject.org>
- truncate changelog
* Wed May 20 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-2
- add patch to close rpmdb completely
* Tue May 19 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.23-1
- 3.2.23
* Mon May 11 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.22-5
- jump up to almost 3.2.23.
- had to move patch0 around a bit until we rebase to 3.2.23
* Thu Apr 9 2009 James Antill <james at fedoraproject.org> - 3.2.22-4
- fix typo for yum-complete-transaction message.
* Wed Apr 8 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.22-3
- fix for file:// urls which makes things in pungi/mash work
* Tue Apr 7 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.22-2
- yum-HEAD minus the yumdb patches
* Tue Mar 24 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.22-1
- 3.2.22 - 3 patches beyond 3.2.21-16
* Mon Mar 16 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-16
- fix for 490490
* Fri Mar 13 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-15
- update to upstream git to fix conditionals problem on anaconda installs
* Thu Mar 12 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-14
- latest HEAD
* Tue Mar 10 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-13
- f11beta build
* Wed Mar 4 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-12
- second verse, same as the first
* Fri Feb 27 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-10
- merge up a lot of fixes from latest HEAD
* Wed Feb 25 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.2.21-10
- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild
* Tue Feb 10 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-9
- merge up to latest yum head - sort of a pre 3.2.22
* Wed Feb 4 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-8
- fix for YumHeaderPackages so it plays nicely w/createrepo and mergerepo, etc
* Thu Jan 29 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-7
- update HEAD patch to fix repodiff (and EVR comparisons in certain cases)
* Tue Jan 27 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-6
- patch to keep anaconda (and other callers) happy
- remove old 6hr patch which is now upstream
* Mon Jan 26 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-4
- patch to latest HEAD to test a number of fixes for alpha
* Tue Jan 20 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-3
- add a small patch to make things play a bit nicer with the logging module
in 2.6
* Wed Jan 7 2009 Seth Vidal <skvidal at fedoraproject.org> - 3.2.21-1
- bump to 3.2.21
* Thu Dec 18 2008 James Antill <james@fedoraproject.org> - 3.2.20-8
- merge latest from upstream
- move to 6hr metadata
* Mon Dec 8 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.20-7
- merge patch from upstream and remove now old obsoletes patch
* Thu Dec 04 2008 Jesse Keating <jkeating@redhat.com> - 3.2.20-6
- Add patch from upstream to fix cases where obsoletes are disabled. (jantill)
* Sat Nov 29 2008 Ignacio Vazquez-Abrams <ivazqueznet+rpm@gmail.com> - 3.2.20-5
- Rebuild for Python 2.6
* Wed Nov 26 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.20-4
- update head patch
* Wed Oct 29 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.20-3
- full patch against HEAD for skipbroken fixes (among others)
* Mon Oct 27 2008 James Antill <james@fedoraproject.org> - 3.2.20-2
- Fix listTransaction for skipped packages.
* Mon Oct 27 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.20-1
- 3.2.20
* Thu Oct 23 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.19-6
- update HEAD patch
* Wed Oct 15 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.19-5
- rebase against 3.2.X HEAD
* Tue Oct 14 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.19-4
- pull patch from git to bring us up to current(ish)
* Wed Sep 3 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.19-3
- add patch to fix yum install name.arch matching
* Thu Aug 28 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.19-2
- add patch to fix mash's parser use.
* Wed Aug 27 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.19-1
- 3.2.19
* Thu Aug 7 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.18-1
- 3.2.18
* Wed Jul 10 2008 Seth Vidal <skvidal@fedoraproject.org> - 3.2.17-2
- add patch from upstream for bug in compare_providers
* Wed Jul 9 2008 Seth Vidal <skvidal@fedoraproject.org> - 3.2.17-1
- 3.2.17
* Tue Jun 24 2008 Jesse Keating <jkeating@redhat.com> - 3.2.16-4
- Add a couple more upstream patches for even more multilib fixes
* Tue Jun 24 2008 Jesse Keating <jkeating@redhat.com> - 3.2.16-3
- Add another patch from upstream for multilib policy and noarch
* Sun May 18 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.16-2
- stupid, stupid, stupid
* Fri May 16 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.16-1
- 3.2.16
* Tue Apr 15 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.14-9
- nine is the luckiest number that there will ever be
* Tue Apr 15 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.14-8
- after many tries - this one fixes translations AND pungi
* Thu Apr 10 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.14-5
- once more, with feeling
* Thu Apr 10 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.14-4
- another big-head-patch
* Wed Apr 9 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.14-3
- apply patch to bring this up to where HEAD is now.
* Tue Apr 8 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.14-1
- remove committed patch
- obsoletes yum-basearchonly
* Tue Apr 1 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.13-2
- fix minor typo in comps.py for jkeating
* Thu Mar 20 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.13-1
- 3.2.13
* Mon Mar 17 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.12-5
- update manpage patch to close bug 437703. Thakns to Kulbir Saini for the patch
* Fri Mar 14 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.12-4
- multilib_policy=best is now the default
* Thu Mar 13 2008 Seth Vidal <skvidal at fedoraproject.org>
- add jeff sheltren's patch to close rh bug 428825
* Tue Mar 4 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.12-3
- set failovermethod to 'priority' to make jkeating happy
* Tue Mar 4 2008 Seth Vidal <skvidal at fedoraproject.org> 3.2.12-2
- fix mutually obsoleting providers (like glibc!)
* Mon Mar 3 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.12-1
- 3.2.12
* Fri Feb 8 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.11-1
- 3.2.11
* Sun Jan 27 2008 James Bowes <jbowes@redhat.com> 3.2.10-3
- Remove yumupd.py
* Fri Jan 25 2008 Seth Vidal <skvidal at fedoraproject.org> - 3.2.10-1
- 3.2.10
- add pygpgme dep
diff -Nurp yum-3.2.27/cli.py yum-3.2.27.new/cli.py
--- yum-3.2.27/cli.py 2010-09-10 23:34:55.068467419 +0100
+++ yum-3.2.27.new/cli.py 2010-09-10 23:28:07.262718791 +0100
@@ -1347,13 +1347,14 @@ class YumOptionParser(OptionParser):
def getRoot(self,opts):
# If the conf file is inside the installroot - use that.
# otherwise look for it in the normal root
+ if opts.conffile is None:
+ opts.conffile = '/etc/yum/yum.conf'
+ if opts.installroot:
+ if os.access(opts.installroot+opts.conffile, os.R_OK):
+ opts.conffile = opts.installroot+opts.conffile
+ elif os.access(opts.installroot+'/etc/yum.conf', os.R_OK):
+ opts.conffile = opts.installroot+'/etc/yum.conf'
if opts.installroot:
- if os.access(opts.installroot+'/'+opts.conffile, os.R_OK):
- opts.conffile = opts.installroot+'/'+opts.conffile
- elif opts.conffile == '/etc/yum/yum.conf':
- # check if /installroot/etc/yum.conf exists.
- if os.access(opts.installroot+'/etc/yum.conf', os.R_OK):
- opts.conffile = opts.installroot+'/etc/yum.conf'
root=opts.installroot
else:
root = '/'
@@ -1394,7 +1395,7 @@ class YumOptionParser(OptionParser):
action="store_true",
help=_("run entirely from system cache, don't update cache"))
group.add_option("-c", "--config", dest="conffile",
- default='/etc/yum/yum.conf',
+ default=None,
help=_("config file location"), metavar='[config file]')
group.add_option("-R", "--randomwait", dest="sleeptime", type='int',
default=None,
diff -Nurp yum-3.2.27/cli.py.orig yum-3.2.27.new/cli.py.orig
--- yum-3.2.27/cli.py.orig 1970-01-01 01:00:00.000000000 +0100
+++ yum-3.2.27.new/cli.py.orig 2010-09-10 23:25:16.136344564 +0100
@@ -0,0 +1,1502 @@
+#!/usr/bin/python -t
+# 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 Library 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.
+# Copyright 2005 Duke University
+# Written by Seth Vidal
+
+"""
+Command line interface yum class and related.
+"""
+
+import os
+import re
+import sys
+import time
+import random
+import logging
+from optparse import OptionParser,OptionGroup
+import rpm
+
+from weakref import proxy as weakref
+
+import output
+import shell
+import yum
+import yum.Errors
+import yum.logginglevels
+import yum.misc
+import yum.plugins
+from rpmUtils.arch import isMultiLibArch
+from yum import _
+from yum.rpmtrans import RPMTransaction
+import signal
+import yumcommands
+
+from yum.i18n import to_unicode, to_utf8
+
+def sigquit(signum, frame):
+ """ SIGQUIT handler for the yum cli. """
+ print >> sys.stderr, "Quit signal sent - exiting immediately"
+ sys.exit(1)
+
+class CliError(yum.Errors.YumBaseError):
+
+ """
+ Command line interface related Exception.
+ """
+
+ def __init__(self, args=''):
+ yum.Errors.YumBaseError.__init__(self)
+ self.args = args
+
+class YumBaseCli(yum.YumBase, output.YumOutput):
+ """This is the base class for yum cli.
+ Inherits from yum.YumBase and output.YumOutput """
+
+ def __init__(self):
+ # handle sigquit early on
+ signal.signal(signal.SIGQUIT, sigquit)
+ yum.YumBase.__init__(self)
+ output.YumOutput.__init__(self)
+ logging.basicConfig()
+ self.logger = logging.getLogger("yum.cli")
+ self.verbose_logger = logging.getLogger("yum.verbose.cli")
+ self.yum_cli_commands = {}
+ self.registerCommand(yumcommands.InstallCommand())
+ self.registerCommand(yumcommands.UpdateCommand())
+ self.registerCommand(yumcommands.InfoCommand())
+ self.registerCommand(yumcommands.ListCommand())
+ self.registerCommand(yumcommands.EraseCommand())
+ self.registerCommand(yumcommands.GroupCommand())
+ self.registerCommand(yumcommands.GroupListCommand())
+ self.registerCommand(yumcommands.GroupInstallCommand())
+ self.registerCommand(yumcommands.GroupRemoveCommand())
+ self.registerCommand(yumcommands.GroupInfoCommand())
+ self.registerCommand(yumcommands.MakeCacheCommand())
+ self.registerCommand(yumcommands.CleanCommand())
+ self.registerCommand(yumcommands.ProvidesCommand())
+ self.registerCommand(yumcommands.CheckUpdateCommand())
+ self.registerCommand(yumcommands.SearchCommand())
+ self.registerCommand(yumcommands.UpgradeCommand())
+ self.registerCommand(yumcommands.LocalInstallCommand())
+ self.registerCommand(yumcommands.ResolveDepCommand())
+ self.registerCommand(yumcommands.ShellCommand())
+ self.registerCommand(yumcommands.DepListCommand())
+ self.registerCommand(yumcommands.RepoListCommand())
+ self.registerCommand(yumcommands.HelpCommand())
+ self.registerCommand(yumcommands.ReInstallCommand())
+ self.registerCommand(yumcommands.DowngradeCommand())
+ self.registerCommand(yumcommands.VersionCommand())
+ self.registerCommand(yumcommands.HistoryCommand())
+ self.registerCommand(yumcommands.CheckRpmdbCommand())
+ self.registerCommand(yumcommands.DistroSyncCommand())
+
+ def registerCommand(self, command):
+ for name in command.getNames():
+ if name in self.yum_cli_commands:
+ raise yum.Errors.ConfigError(_('Command "%s" already defined') % name)
+ self.yum_cli_commands[name] = command
+
+ def doRepoSetup(self, thisrepo=None, dosack=1):
+ """grabs the repomd.xml for each enabled repository
+ and sets up the basics of the repository"""
+
+ if self._repos and thisrepo is None:
+ return self._repos
+
+ if not thisrepo:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Setting up repositories'))
+
+ # Call parent class to do the bulk of work
+ # (this also ensures that reposetup plugin hook is called)
+ if thisrepo:
+ yum.YumBase._getRepos(self, thisrepo=thisrepo, doSetup=True)
+ else:
+ yum.YumBase._getRepos(self, thisrepo=thisrepo)
+
+ if dosack: # so we can make the dirs and grab the repomd.xml but not import
the md
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Reading repository metadata in from local files'))
+ self._getSacks(thisrepo=thisrepo)
+
+ return self._repos
+
+ def _makeUsage(self):
+ """
+ Format an attractive usage string for yum, listing subcommand
+ names and summary usages.
+ """
+ usage = 'yum [options] COMMAND\n\nList of Commands:\n\n'
+ commands = yum.misc.unique(self.yum_cli_commands.values())
+ commands.sort(key=lambda x: x.getNames()[0])
+ for command in commands:
+ # XXX Remove this when getSummary is common in plugins
+ try:
+ summary = command.getSummary()
+ usage += "%-14s %s\n" % (command.getNames()[0], summary)
+ except (AttributeError, NotImplementedError):
+ usage += "%s\n" % command.getNames()[0]
+
+ return usage
+
+ def getOptionsConfig(self, args):
+ """parses command line arguments, takes cli args:
+ sets up self.conf and self.cmds as well as logger objects
+ in base instance"""
+
+ self.optparser = YumOptionParser(base=self, usage=self._makeUsage())
+
+ # Parse only command line options that affect basic yum setup
+ opts = self.optparser.firstParse(args)
+
+ # Just print out the version if that's what the user wanted
+ if opts.version:
+ print yum.__version__
+ opts.quiet = True
+ opts.verbose = False
+
+ # get the install root to use
+ root = self.optparser.getRoot(opts)
+
+ if opts.quiet:
+ opts.debuglevel = 0
+ if opts.verbose:
+ opts.debuglevel = opts.errorlevel = 6
+
+ # Read up configuration options and initialise plugins
+ try:
+ pc = self.preconf
+ pc.fn = opts.conffile
+ pc.root = root
+ pc.init_plugins = not opts.noplugins
+ pc.plugin_types = (yum.plugins.TYPE_CORE,
+ yum.plugins.TYPE_INTERACTIVE)
+ pc.optparser = self.optparser
+ pc.debuglevel = opts.debuglevel
+ pc.errorlevel = opts.errorlevel
+ pc.disabled_plugins = self.optparser._splitArg(opts.disableplugins)
+ pc.enabled_plugins = self.optparser._splitArg(opts.enableplugins)
+ pc.releasever = opts.releasever
+ self.conf
+
+ except yum.Errors.ConfigError, e:
+ self.logger.critical(_('Config Error: %s'), e)
+ sys.exit(1)
+ except ValueError, e:
+ self.logger.critical(_('Options Error: %s'), e)
+ sys.exit(1)
+
+ # update usage in case plugins have added commands
+ self.optparser.set_usage(self._makeUsage())
+
+ self.plugins.run('args', args=args)
+ # Now parse the command line for real and
+ # apply some of the options to self.conf
+ (opts, self.cmds) = self.optparser.setupYumConfig(args=args)
+
+ if opts.version:
+ self.conf.cache = 1
+ yum_progs = self.run_with_package_names
+ done = False
+ def sm_ui_time(x):
+ return time.strftime("%Y-%m-%d %H:%M", time.gmtime(x))
+ def sm_ui_date(x): # For changelogs, there is no time
+ return time.strftime("%Y-%m-%d", time.gmtime(x))
+ for pkg in sorted(self.rpmdb.returnPackages(patterns=yum_progs)):
+ # We should only have 1 version of each...
+ if done: print ""
+ done = True
+ if pkg.epoch == '0':
+ ver = '%s-%s.%s' % (pkg.version, pkg.release, pkg.arch)
+ else:
+ ver = '%s:%s-%s.%s' % (pkg.epoch,
+ pkg.version, pkg.release, pkg.arch)
+ name = "%s%s%s" % (self.term.MODE['bold'], pkg.name,
+ self.term.MODE['normal'])
+ print _(" Installed: %s-%s at %s") %(name, ver,
+ sm_ui_time(pkg.installtime))
+ print _(" Built : %s at %s") % (pkg.packager,
+ sm_ui_time(pkg.buildtime))
+ print _(" Committed: %s at %s") % (pkg.committer,
+ sm_ui_date(pkg.committime))
+ sys.exit(0)
+
+ if opts.sleeptime is not None:
+ sleeptime = random.randrange(opts.sleeptime*60)
+ else:
+ sleeptime = 0
+
+ # save our original args out
+ self.args = args
+ # save out as a nice command string
+ self.cmdstring = 'yum '
+ for arg in self.args:
+ self.cmdstring += '%s ' % arg
+
+ try:
+ self.parseCommands() # before we return check over the base command + args
+ # make sure they match/make sense
+ except CliError:
+ sys.exit(1)
+
+ # run the sleep - if it's unchanged then it won't matter
+ time.sleep(sleeptime)
+
+ def parseCommands(self):
+ """reads self.cmds and parses them out to make sure that the requested
+ base command + argument makes any sense at all"""
+
+ self.verbose_logger.debug('Yum Version: %s', yum.__version__)
+ self.verbose_logger.log(yum.logginglevels.DEBUG_4,
+ 'COMMAND: %s', self.cmdstring)
+ self.verbose_logger.log(yum.logginglevels.DEBUG_4,
+ 'Installroot: %s', self.conf.installroot)
+ if len(self.conf.commands) == 0 and len(self.cmds) < 1:
+ self.cmds = self.conf.commands
+ else:
+ self.conf.commands = self.cmds
+ if len(self.cmds) < 1:
+ self.logger.critical(_('You need to give some command'))
+ self.usage()
+ raise CliError
+
+ self.basecmd = self.cmds[0] # our base command
+ self.extcmds = self.cmds[1:] # out extended arguments/commands
+
+ if len(self.extcmds) > 0:
+ self.verbose_logger.log(yum.logginglevels.DEBUG_4,
+ 'Ext Commands:\n')
+ for arg in self.extcmds:
+ self.verbose_logger.log(yum.logginglevels.DEBUG_4, ' %s', arg)
+
+ if self.basecmd not in self.yum_cli_commands:
+ self.logger.critical(_('No such command: %s. Please use %s --help'),
+ self.basecmd, sys.argv[0])
+ raise CliError
+
+ self.yum_cli_commands[self.basecmd].doCheck(self, self.basecmd, self.extcmds)
+
+ def doShell(self):
+ """do a shell-like interface for yum commands"""
+
+ yumshell = shell.YumShell(base=self)
+ if len(self.extcmds) == 0:
+ yumshell.cmdloop()
+ else:
+ yumshell.script()
+ return yumshell.result, yumshell.resultmsgs
+
+ def errorSummary(self, errstring):
+ """ parse the error string for 'interesting' errors which can
+ be grouped, such as disk space issues """
+ summary = ''
+ # do disk space report first
+ p = re.compile('needs (\d+)MB on the (\S+) filesystem')
+ disk = {}
+ for m in p.finditer(errstring):
+ if not disk.has_key(m.group(2)):
+ disk[m.group(2)] = int(m.group(1))
+ if disk[m.group(2)] < int(m.group(1)):
+ disk[m.group(2)] = int(m.group(1))
+
+ if disk:
+ summary += _('Disk Requirements:\n')
+ for k in disk:
+ summary += _(' At least %dMB more space needed on the %s filesystem.\n')
% (disk[k], k)
+
+ # TODO: simplify the dependency errors?
+
+ # Fixup the summary
+ summary = _('Error Summary\n-------------\n') + summary
+
+ return summary
+
+
+ def doCommands(self):
+ """
+ Calls the base command passes the extended commands/args out to be
+ parsed (most notably package globs).
+
+ Returns a numeric result code and an optional string
+ - 0 = we're done, exit
+ - 1 = we've errored, exit with error string
+ - 2 = we've got work yet to do, onto the next stage
+ """
+
+ # at this point we know the args are valid - we don't know their meaning
+ # but we know we're not being sent garbage
+
+ # setup our transaction set if the command we're using needs it
+ # compat with odd modules not subclassing YumCommand
+ needTs = True
+ needTsRemove = False
+ cmd = self.yum_cli_commands[self.basecmd]
+ if hasattr(cmd, 'needTs'):
+ needTs = cmd.needTs(self, self.basecmd, self.extcmds)
+ if not needTs and hasattr(cmd, 'needTsRemove'):
+ needTsRemove = cmd.needTsRemove(self, self.basecmd, self.extcmds)
+
+ if needTs or needTsRemove:
+ try:
+ self._getTs(needTsRemove)
+ except yum.Errors.YumBaseError, e:
+ return 1, [str(e)]
+
+ return self.yum_cli_commands[self.basecmd].doCommand(self, self.basecmd, self.extcmds)
+
+ def doTransaction(self):
+ """takes care of package downloading, checking, user confirmation and actually
+ RUNNING the transaction"""
+
+ # just make sure there's not, well, nothing to do
+ if len(self.tsInfo) == 0:
+ self.verbose_logger.info(_('Trying to run the transaction but nothing to
do. Exiting.'))
+ return 1
+
+ # NOTE: In theory we can skip this in -q -y mode, for a slight perf.
+ # gain. But it's probably doom to have a different code path.
+ lsts = self.listTransaction()
+ if self.verbose_logger.isEnabledFor(yum.logginglevels.INFO_1):
+ self.verbose_logger.log(yum.logginglevels.INFO_1, lsts)
+ elif not self.conf.assumeyes:
+ # If we are in quiet, and assumeyes isn't on we want to output
+ # at least the transaction list anyway.
+ self.logger.warn(lsts)
+
+ # Check which packages have to be downloaded
+ downloadpkgs = []
+ stuff_to_download = False
+ install_only = True
+ for txmbr in self.tsInfo.getMembers():
+ if txmbr.ts_state not in ('i', 'u'):
+ install_only = False
+ else:
+ stuff_to_download = True
+ po = txmbr.po
+ if po:
+ downloadpkgs.append(po)
+
+ # Close the connection to the rpmdb so that rpm doesn't hold the SIGINT
+ # handler during the downloads. self.ts is reinitialised later in this
+ # function anyway (initActionTs).
+ self.ts.close()
+
+ # Report the total download size to the user, so he/she can base
+ # the answer on this info
+ if stuff_to_download:
+ self.reportDownloadSize(downloadpkgs, install_only)
+
+ # confirm with user
+ if self._promptWanted():
+ if not self.userconfirm():
+ self.verbose_logger.info(_('Exiting on user Command'))
+ return 1
+
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Downloading Packages:'))
+ problems = self.downloadPkgs(downloadpkgs, callback_total=self.download_callback_total_cb)
+
+ if len(problems) > 0:
+ errstring = ''
+ errstring += _('Error Downloading Packages:\n')
+ for key in problems:
+ errors = yum.misc.unique(problems[key])
+ for error in errors:
+ errstring += ' %s: %s\n' % (key, error)
+ raise yum.Errors.YumBaseError, errstring
+
+ # Check GPG signatures
+ if self.gpgsigcheck(downloadpkgs) != 0:
+ return 1
+
+ if self.conf.rpm_check_debug:
+ rcd_st = time.time()
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Running rpm_check_debug'))
+ msgs = self._run_rpm_check_debug()
+ if msgs:
+ rpmlib_only = True
+ for msg in msgs:
+ if msg.startswith('rpmlib('):
+ continue
+ rpmlib_only = False
+ if rpmlib_only:
+ print _("ERROR You need to update rpm to handle:")
+ else:
+ print _('ERROR with rpm_check_debug vs depsolve:')
+
+ for msg in msgs:
+ print to_utf8(msg)
+
+ if rpmlib_only:
+ return 1, [_('RPM needs to be updated')]
+ return 1, [_('Please report this error in %s') % self.conf.bugtracker_url]
+
+ self.verbose_logger.debug('rpm_check_debug time: %0.3f' % (time.time()
- rcd_st))
+
+ tt_st = time.time()
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Running Transaction Test'))
+ if not self.conf.diskspacecheck:
+ self.tsInfo.probFilterFlags.append(rpm.RPMPROB_FILTER_DISKSPACE)
+
+
+ testcb = RPMTransaction(self, test=True)
+
+ self.initActionTs()
+ # save our dsCallback out
+ dscb = self.dsCallback
+ self.dsCallback = None # dumb, dumb dumb dumb!
+ self.populateTs(keepold=0) # sigh
+ tserrors = self.ts.test(testcb)
+ del testcb
+
+ if len(tserrors) > 0:
+ errstring = _('Transaction Check Error:\n')
+ for descr in tserrors:
+ errstring += ' %s\n' % to_unicode(descr)
+
+ raise yum.Errors.YumBaseError, errstring + '\n' + \
+ self.errorSummary(errstring)
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Transaction Test Succeeded'))
+ del self.ts
+
+ self.verbose_logger.debug('Transaction Test time: %0.3f' % (time.time() - tt_st))
+
+ # unset the sigquit handler
+ signal.signal(signal.SIGQUIT, signal.SIG_DFL)
+
+ ts_st = time.time()
+ self.initActionTs() # make a new, blank ts to populate
+ self.populateTs(keepold=0) # populate the ts
+ self.ts.check() #required for ordering
+ self.ts.order() # order
+
+ # put back our depcheck callback
+ self.dsCallback = dscb
+ # setup our rpm ts callback
+ cb = RPMTransaction(self,
+ display=output.YumCliRPMCallBack(weakref(self)))
+ if self.conf.debuglevel < 2:
+ cb.display.output = False
+
+ self.verbose_logger.log(yum.logginglevels.INFO_2, _('Running Transaction'))
+ resultobject = self.runTransaction(cb=cb)
+
+ self.verbose_logger.debug('Transaction time: %0.3f' % (time.time() - ts_st))
+ # close things
+ self.verbose_logger.log(yum.logginglevels.INFO_1,
+ self.postTransactionOutput())
+
+ # put back the sigquit handler
+ signal.signal(signal.SIGQUIT, sigquit)
+
+ return resultobject.return_code
+
+ def gpgsigcheck(self, pkgs):
+ '''Perform GPG signature verification on the given packages, installing
+ keys if possible
+
+ Returns non-zero if execution should stop (user abort).
+ Will raise YumBaseError if there's a problem
+ '''
+ for po in pkgs:
+ result, errmsg = self.sigCheckPkg(po)
+
+ if result == 0:
+ # Verified ok, or verify not req'd
+ continue
+
+ elif result == 1:
+ if not sys.stdin.isatty() and not self.conf.assumeyes:
+ raise yum.Errors.YumBaseError, \
+ _('Refusing to automatically import keys when running '
\
+ 'unattended.\nUse "-y" to override.')
+
+ # the callback here expects to be able to take options which
+ # userconfirm really doesn't... so fake it
+ self.getKeyForPackage(po, lambda x, y, z: self.userconfirm())
+
+ else:
+ # Fatal error
+ raise yum.Errors.YumBaseError, errmsg
+
+ return 0
+
+ def _maybeYouMeant(self, arg):
+ """ If install argument doesn't match with case, tell the user. """
+ matches = self.doPackageLists(patterns=[arg], ignore_case=True)
+ matches = matches.installed + matches.available
+ matches = set(map(lambda x: x.name, matches))
+ if matches:
+ msg = self.fmtKeyValFill(_(' * Maybe you meant: '),
+ ", ".join(matches))
+ self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
+
+ def _checkMaybeYouMeant(self, arg, always_output=True):
+ """ If the update/remove argument doesn't match with case, or due
+ to not being installed, tell the user. """
+ # always_output is a wart due to update/remove not producing the
+ # same output.
+ matches = self.doPackageLists(patterns=[arg], ignore_case=False)
+ if (matches.installed or (not matches.available and
+ self.returnInstalledPackagesByDep(arg))):
+ return # Found a match so ignore
+ hibeg = self.term.MODE['bold']
+ hiend = self.term.MODE['normal']
+ if matches.available:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Package(s) %s%s%s available, but not installed.'),
+ hibeg, arg, hiend)
+ return
+
+ # No package name, so do the maybeYouMeant thing here too
+ matches = self.doPackageLists(patterns=[arg], ignore_case=True)
+ if not matches.installed and matches.available:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Package(s) %s%s%s available, but not installed.'),
+ hibeg, arg, hiend)
+ return
+ matches = set(map(lambda x: x.name, matches.installed))
+ if always_output or matches:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('No package %s%s%s available.'),
+ hibeg, arg, hiend)
+ if matches:
+ msg = self.fmtKeyValFill(_(' * Maybe you meant: '),
+ ", ".join(matches))
+ self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
+
+ def installPkgs(self, userlist):
+ """Attempts to take the user specified list of packages/wildcards
+ and install them, or if they are installed, update them to a newer
+ version. If a complete version number if specified, attempt to
+ upgrade (or downgrade if they have been removed) them to the
+ specified version"""
+ # get the list of available packages
+ # iterate over the user's list
+ # add packages to Transaction holding class if they match.
+ # if we've added any packages to the transaction then return 2 and a string
+ # if we've hit a snag, return 1 and the failure explanation
+ # if we've got nothing to do, return 0 and a 'nothing available to install'
string
+
+ oldcount = len(self.tsInfo)
+
+ done = False
+ for arg in userlist:
+ if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
+ os.path.exists(arg))):
+ self.localInstall(filelist=[arg])
+ continue # it was something on disk and it ended in rpm
+ # no matter what we don't go looking at repos
+ try:
+ self.install(pattern=arg)
+ except yum.Errors.InstallError:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('No package %s%s%s available.'),
+ self.term.MODE['bold'], arg,
+ self.term.MODE['normal'])
+ self._maybeYouMeant(arg)
+ else:
+ done = True
+ if len(self.tsInfo) > oldcount:
+ return 2, [_('Package(s) to install')]
+
+ if not done:
+ return 1, [_('Nothing to do')]
+ return 0, [_('Nothing to do')]
+
+ def updatePkgs(self, userlist, quiet=0):
+ """take user commands and populate transaction wrapper with
+ packages to be updated"""
+
+ # if there is no userlist, then do global update below
+ # this is probably 90% of the calls
+ # if there is a userlist then it's for updating pkgs, not obsoleting
+
+ oldcount = len(self.tsInfo)
+ if len(userlist) == 0: # simple case - do them all
+ self.update()
+
+ else:
+ # go through the userlist - look for items that are local rpms. If we find
them
+ # pass them off to localInstall() and then move on
+ localupdates = []
+ for item in userlist:
+ if (item.endswith('.rpm') and (yum.misc.re_remote_url(item) or
+ os.path.exists(item))):
+ localupdates.append(item)
+
+ if len(localupdates) > 0:
+ self.localInstall(filelist=localupdates, updateonly=1)
+ for item in localupdates:
+ userlist.remove(item)
+
+ for arg in userlist:
+ if not self.update(pattern=arg):
+ self._checkMaybeYouMeant(arg)
+
+ if len(self.tsInfo) > oldcount:
+ change = len(self.tsInfo) - oldcount
+ msg = _('%d packages marked for Update') % change
+ return 2, [msg]
+ else:
+ return 0, [_('No Packages marked for Update')]
+
+ # Note that we aren't in __init__ yet for a couple of reasons, but we
+ # probably will get there for 3.2.28.
+ def distroSyncPkgs(self, userlist):
+ """ This does either upgrade/downgrade, depending on if the latest
+ installed version is older or newer. We allow "selection" but not
+ local packages (use tmprepo, or something). """
+
+ dupdates = []
+ ipkgs = {}
+ for pkg in sorted(self.rpmdb.returnPackages(patterns=userlist)):
+ ipkgs[pkg.name] = pkg
+
+ obsoletes = []
+ if self.conf.obsoletes:
+ obsoletes = self.up.getObsoletesTuples(newest=1)
+
+ for (obsoleting, installed) in obsoletes:
+ if installed[0] not in ipkgs:
+ continue
+ dupdates.extend(self.update(pkgtup=installed))
+ for (obsoleting, installed) in obsoletes:
+ if installed[0] not in ipkgs:
+ continue
+ del ipkgs[installed[0]]
+
+ apkgs = {}
+ for pkg in self.pkgSack.returnNewestByName():
+ if pkg.name not in ipkgs:
+ continue
+ apkgs[pkg.name] = pkg
+
+ for ipkgname in ipkgs:
+ if ipkgname not in apkgs:
+ continue
+
+ ipkg = ipkgs[ipkgname]
+ apkg = apkgs[ipkgname]
+ if ipkg.verEQ(apkg):
+ continue
+ if self.allowedMultipleInstalls(apkg):
+ found = False
+ for napkg in self.rpmdb.searchNames([apkg.name]):
+ if napkg.verEQ(apkg):
+ found = True
+ elif napkg.verGT(apkg):
+ dupdates.extend(self.remove(po=napkg))
+ if found:
+ continue
+ dupdates.extend(self.install(pattern=apkg.name))
+ elif ipkg.verLT(apkg):
+ n,a,e,v,r = apkg.pkgtup
+ dupdates.extend(self.update(name=n, epoch=e, ver=v, rel=r))
+ else:
+ n,a,e,v,r = apkg.pkgtup
+ dupdates.extend(self.downgrade(name=n, epoch=e, ver=v, rel=r))
+
+ if dupdates:
+ msg = _('%d packages marked for Distribution Synchronization') % len(dupdates)
+ return 2, [msg]
+ else:
+ return 0, [_('No Packages marked for Distribution Synchronization')]
+
+ def erasePkgs(self, userlist):
+ """take user commands and populate a transaction wrapper with packages
+ to be erased/removed"""
+
+ oldcount = len(self.tsInfo)
+
+ for arg in userlist:
+ if not self.remove(pattern=arg):
+ self._checkMaybeYouMeant(arg, always_output=False)
+
+ if len(self.tsInfo) > oldcount:
+ change = len(self.tsInfo) - oldcount
+ msg = _('%d packages marked for removal') % change
+ return 2, [msg]
+ else:
+ return 0, [_('No Packages marked for removal')]
+
+ def downgradePkgs(self, userlist):
+ """Attempts to take the user specified list of packages/wildcards
+ and downgrade them. If a complete version number if specified,
+ attempt to downgrade them to the specified version"""
+
+ oldcount = len(self.tsInfo)
+
+ for arg in userlist:
+ if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
+ os.path.exists(arg))):
+ self.downgradeLocal(arg)
+ continue # it was something on disk and it ended in rpm
+ # no matter what we don't go looking at repos
+
+ try:
+ self.downgrade(pattern=arg)
+ except yum.Errors.DowngradeError:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('No package %s%s%s available.'),
+ self.term.MODE['bold'], arg,
+ self.term.MODE['normal'])
+ self._maybeYouMeant(arg)
+ if len(self.tsInfo) > oldcount:
+ return 2, [_('Package(s) to downgrade')]
+ return 0, [_('Nothing to do')]
+
+ def reinstallPkgs(self, userlist):
+ """Attempts to take the user specified list of packages/wildcards
+ and reinstall them. """
+
+ oldcount = len(self.tsInfo)
+
+ for arg in userlist:
+ if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
+ os.path.exists(arg))):
+ self.reinstallLocal(arg)
+ continue # it was something on disk and it ended in rpm
+ # no matter what we don't go looking at repos
+
+ try:
+ self.reinstall(pattern=arg)
+ except yum.Errors.ReinstallRemoveError:
+ self._checkMaybeYouMeant(arg, always_output=False)
+ except yum.Errors.ReinstallInstallError, e:
+ ipkg = self.rpmdb.returnPackages(patterns=[arg])[0]
+ xmsg = ''
+ if 'from_repo' in ipkg.yumdb_info:
+ xmsg = ipkg.yumdb_info.from_repo
+ xmsg = _(' (from %s)') % xmsg
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Installed package %s%s%s%s not available.'),
+ self.term.MODE['bold'], ipkg,
+ self.term.MODE['normal'], xmsg)
+ except yum.Errors.ReinstallError, e:
+ assert False, "Shouldn't happen, but just in case"
+ self.verbose_logger.log(yum.logginglevels.INFO_2, e)
+ if len(self.tsInfo) > oldcount:
+ return 2, [_('Package(s) to reinstall')]
+ return 0, [_('Nothing to do')]
+
+ def localInstall(self, filelist, updateonly=0):
+ """handles installs/updates of rpms provided on the filesystem in a
+ local dir (ie: not from a repo)"""
+
+ # read in each package into a YumLocalPackage Object
+ # append it to self.localPackages
+ # check if it can be installed or updated based on nevra versus rpmdb
+ # don't import the repos until we absolutely need them for depsolving
+
+ if len(filelist) == 0:
+ return 0, [_('No Packages Provided')]
+
+ installing = False
+ for pkg in filelist:
+ txmbrs = self.installLocal(pkg, updateonly=updateonly)
+ if txmbrs:
+ installing = True
+
+ if installing:
+ return 2, [_('Package(s) to install')]
+ return 0, [_('Nothing to do')]
+
+ def returnPkgLists(self, extcmds, installed_available=False):
+ """Returns packages lists based on arguments on the cli.returns a
+ GenericHolder instance with the following lists defined:
+ available = list of packageObjects
+ installed = list of packageObjects
+ updates = tuples of packageObjects (updating, installed)
+ extras = list of packageObjects
+ obsoletes = tuples of packageObjects (obsoleting, installed)
+ recent = list of packageObjects
+
+ installed_available = that the available package list is present
+ as .hidden_available when doing any of:
+ all/available/installed
+ """
+
+ special = ['available', 'installed', 'all', 'extras', 'updates', 'recent',
+ 'obsoletes']
+
+ pkgnarrow = 'all'
+ done_hidden_available = False
+ done_hidden_installed = False
+ if len(extcmds) > 0:
+ if installed_available and extcmds[0] == 'installed':
+ done_hidden_available = True
+ extcmds.pop(0)
+ elif installed_available and extcmds[0] == 'available':
+ done_hidden_installed = True
+ extcmds.pop(0)
+ elif extcmds[0] in special:
+ pkgnarrow = extcmds.pop(0)
+
+ ypl = self.doPackageLists(pkgnarrow=pkgnarrow, patterns=extcmds,
+ ignore_case=True)
+ if self.conf.showdupesfromrepos:
+ ypl.available += ypl.reinstall_available
+
+ if installed_available:
+ ypl.hidden_available = ypl.available
+ ypl.hidden_installed = ypl.installed
+ if done_hidden_available:
+ ypl.available = []
+ if done_hidden_installed:
+ ypl.installed = []
+ return ypl
+
+ def search(self, args):
+ """cli wrapper method for module search function, searches simple
+ text tags in a package object"""
+
+ # call the yum module search function with lists of tags to search
+ # and what to search for
+ # display the list of matches
+
+ searchlist = ['name', 'summary', 'description', 'url']
+ dups = self.conf.showdupesfromrepos
+ args = map(to_unicode, args)
+ matching = self.searchGenerator(searchlist, args,
+ showdups=dups, keys=True)
+
+ okeys = set()
+ akeys = set()
+ for (po, keys, matched_value) in matching:
+ if keys != okeys:
+ if akeys:
+ print ""
+ # Print them in the order they were passed
+ used_keys = [arg for arg in args if arg in keys]
+ print self.fmtSection(_('Matched: %s') % ", ".join(used_keys))
+ okeys = keys
+ akeys.update(keys)
+ self.matchcallback(po, matched_value, args)
+
+ for arg in args:
+ if arg not in akeys:
+ self.logger.warning(_('Warning: No matches found for: %s'), arg)
+
+ if not akeys:
+ return 0, [_('No Matches found')]
+ return 0, matching
+
+ def deplist(self, args):
+ """cli wrapper method for findDeps method takes a list of packages and
+ returns a formatted deplist for that package"""
+
+ pkgs = []
+ for arg in args:
+ if (arg.endswith('.rpm') and (yum.misc.re_remote_url(arg) or
+ os.path.exists(arg))):
+ thispkg = yum.packages.YumUrlPackage(self, self.ts, arg)
+ pkgs.append(thispkg)
+ else:
+ ematch, match, unmatch = self.pkgSack.matchPackageNames([arg])
+ for po in ematch + match:
+ pkgs.append(po)
+
+ results = self.findDeps(pkgs)
+ self.depListOutput(results)
+
+ return 0, []
+
+ def provides(self, args):
+ """use the provides methods in the rpmdb and pkgsack to produce a list
+ of items matching the provides strings. This is a cli wrapper to the
+ module"""
+
+ old_sdup = self.conf.showdupesfromrepos
+ # For output, as searchPackageProvides() is always in showdups mode
+ self.conf.showdupesfromrepos = True
+ cb = self.matchcallback_verbose
+ matching = self.searchPackageProvides(args, callback=cb,
+ callback_has_matchfor=True)
+ self.conf.showdupesfromrepos = old_sdup
+
+ if len(matching) == 0:
+ for arg in args:
+ if '*' in arg or (arg and arg[0] == '/'):
+ continue
+ self.logger.warning(_('Warning: 3.0.x versions of yum would erroneously
match against filenames.\n You can use "%s*/%s%s" and/or "%s*bin/%s%s" to get that behaviour'),
+ self.term.MODE['bold'], arg,
+ self.term.MODE['normal'],
+ self.term.MODE['bold'], arg,
+ self.term.MODE['normal'])
+ return 0, ['No Matches found']
+
+ return 0, []
+
+ def resolveDepCli(self, args):
+ """returns a package (one per user arg) that provide the supplied arg"""
+
+ for arg in args:
+ try:
+ pkg = self.returnPackageByDep(arg)
+ except yum.Errors.YumBaseError:
+ self.logger.critical(_('No Package Found for %s'), arg)
+ else:
+ msg = '%s:%s-%s-%s.%s' % (pkg.epoch, pkg.name, pkg.version, pkg.release,
pkg.arch)
+ self.verbose_logger.info(msg)
+
+ return 0, []
+
+ def cleanCli(self, userlist):
+ hdrcode = pkgcode = xmlcode = dbcode = expccode = 0
+ pkgresults = hdrresults = xmlresults = dbresults = expcresults = []
+ if 'all' in userlist:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Cleaning up Everything'))
+ pkgcode, pkgresults = self.cleanPackages()
+ hdrcode, hdrresults = self.cleanHeaders()
+ xmlcode, xmlresults = self.cleanMetadata()
+ dbcode, dbresults = self.cleanSqlite()
+ rpmcode, rpmresults = self.cleanRpmDB()
+ self.plugins.run('clean')
+
+ code = hdrcode + pkgcode + xmlcode + dbcode + rpmcode
+ results = (hdrresults + pkgresults + xmlresults + dbresults +
+ rpmresults)
+ for msg in results:
+ self.logger.debug(msg)
+ return code, []
+
+ if 'headers' in userlist:
+ self.logger.debug(_('Cleaning up Headers'))
+ hdrcode, hdrresults = self.cleanHeaders()
+ if 'packages' in userlist:
+ self.logger.debug(_('Cleaning up Packages'))
+ pkgcode, pkgresults = self.cleanPackages()
+ if 'metadata' in userlist:
+ self.logger.debug(_('Cleaning up xml metadata'))
+ xmlcode, xmlresults = self.cleanMetadata()
+ if 'dbcache' in userlist or 'metadata' in userlist:
+ self.logger.debug(_('Cleaning up database cache'))
+ dbcode, dbresults = self.cleanSqlite()
+ if 'expire-cache' in userlist or 'metadata' in userlist:
+ self.logger.debug(_('Cleaning up expire-cache metadata'))
+ expccode, expcresults = self.cleanExpireCache()
+ if 'rpmdb' in userlist:
+ self.logger.debug(_('Cleaning up cached rpmdb data'))
+ expccode, expcresults = self.cleanRpmDB()
+ if 'plugins' in userlist:
+ self.logger.debug(_('Cleaning up plugins'))
+ self.plugins.run('clean')
+
+ code = hdrcode + pkgcode + xmlcode + dbcode + expccode
+ results = hdrresults + pkgresults + xmlresults + dbresults + expcresults
+ for msg in results:
+ self.verbose_logger.log(yum.logginglevels.INFO_2, msg)
+ return code, []
+
+ def returnGroupLists(self, userlist):
+
+ uservisible=1
+
+ if len(userlist) > 0:
+ if userlist[0] == 'hidden':
+ uservisible=0
+ userlist.pop(0)
+ if not userlist:
+ userlist = None # Match everything...
+
+ installed, available = self.doGroupLists(uservisible=uservisible,
+ patterns=userlist)
+
+ if len(installed) > 0:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Installed Groups:'))
+ for group in installed:
+ if self.verbose_logger.isEnabledFor(yum.logginglevels.DEBUG_3):
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ ' %s (%s)', group.ui_name,
+ group.groupid)
+ else:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ ' %s', group.ui_name)
+
+ if len(available) > 0:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ _('Available Groups:'))
+ for group in available:
+ if self.verbose_logger.isEnabledFor(yum.logginglevels.DEBUG_3):
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ ' %s (%s)', group.ui_name,
+ group.groupid)
+ else:
+ self.verbose_logger.log(yum.logginglevels.INFO_2,
+ ' %s', group.ui_name)
+
+ return 0, [_('Done')]
+
+ def returnGroupInfo(self, userlist):
+ """returns complete information on a list of groups"""
+ for strng in userlist:
+ group_matched = False
+ for group in self.comps.return_groups(strng):
+ self.displayPkgsInGroups(group)
+ group_matched = True
+
+ if not group_matched:
+ self.logger.error(_('Warning: Group %s does not exist.'), strng)
+
+ return 0, []
+
+ def installGroups(self, grouplist):
+ """for each group requested do 'selectGroup' on them."""
+
+ pkgs_used = []
+
+ for group_string in grouplist:
+ group_matched = False
+ for group in self.comps.return_groups(group_string):
+ group_matched = True
+
+
+ try:
+ txmbrs = self.selectGroup(group.groupid)
+ except yum.Errors.GroupsError:
+ self.logger.critical(_('Warning: Group %s does not exist.'), group_string)
+ continue
+ else:
+ pkgs_used.extend(txmbrs)
+
+ if not group_matched:
+ self.logger.error(_('Warning: Group %s does not exist.'), group_string)
+ continue
+
+ if not pkgs_used:
+ return 0, [_('No packages in any requested group available to install or
update')]
+ else:
+ return 2, [_('%d Package(s) to Install') % len(pkgs_used)]
+
+ def removeGroups(self, grouplist):
+ """Remove only packages of the named group(s). Do not recurse."""
+
+ pkgs_used = []
+ for group_string in grouplist:
+ try:
+ txmbrs = self.groupRemove(group_string)
+ except yum.Errors.GroupsError:
+ self.logger.critical(_('No group named %s exists'), group_string)
+ continue
+ else:
+ pkgs_used.extend(txmbrs)
+
+ if not pkgs_used:
+ return 0, [_('No packages to remove from groups')]
+ else:
+ return 2, [_('%d Package(s) to remove') % len(pkgs_used)]
+
+
+
+ def _promptWanted(self):
+ # shortcut for the always-off/always-on options
+ if self.conf.assumeyes:
+ return False
+ if self.conf.alwaysprompt:
+ return True
+
+ # prompt if:
+ # package was added to fill a dependency
+ # package is being removed
+ # package wasn't explictly given on the command line
+ for txmbr in self.tsInfo.getMembers():
+ if txmbr.isDep or \
+ txmbr.ts_state == 'e' or \
+ txmbr.name not in self.extcmds:
+ return True
+
+ # otherwise, don't prompt
+ return False
+
+ def usage(self):
+ ''' Print out command line usage '''
+ sys.stdout.write(self.optparser.format_help())
+
+ def shellUsage(self):
+ ''' Print out the shell usage '''
+ sys.stdout.write(self.optparser.get_usage())
+
+ def _installable(self, pkg, ematch=False):
+
+ """check if the package is reasonably installable, true/false"""
+
+ exactarchlist = self.conf.exactarchlist
+ # we look through each returned possibility and rule out the
+ # ones that we obviously can't use
+
+ if self.rpmdb.contains(po=pkg):
+ self.verbose_logger.log(yum.logginglevels.DEBUG_3,
+ _('Package %s is already installed, skipping'), pkg)
+ return False
+
+ # everything installed that matches the name
+ installedByKey = self.rpmdb.searchNevra(name=pkg.name)
+ comparable = []
+ for instpo in installedByKey:
+ if isMultiLibArch(instpo.arch) == isMultiLibArch(pkg.arch):
+ comparable.append(instpo)
+ else:
+ self.verbose_logger.log(yum.logginglevels.DEBUG_3,
+ _('Discarding non-comparable pkg %s.%s'), instpo.name, instpo.arch)
+ continue
+
+ # go through each package
+ if len(comparable) > 0:
+ for instpo in comparable:
+ if pkg.verGT(instpo): # we're newer - this is an update, pass to them
+ if instpo.name in exactarchlist:
+ if pkg.arch == instpo.arch:
+ return True
+ else:
+ return True
+
+ elif pkg.verEQ(instpo): # same, ignore
+ return False
+
+ elif pkg.verLT(instpo): # lesser, check if the pkgtup is an exactmatch
+ # if so then add it to be installed
+ # if it can be multiply installed
+ # this is where we could handle setting
+ # it to be an 'oldpackage' revert.
+
+ if ematch and self.allowedMultipleInstalls(pkg):
+ return True
+
+ else: # we've not got any installed that match n or n+a
+ self.verbose_logger.log(yum.logginglevels.DEBUG_1, _('No other %s installed,
adding to list for potential install'), pkg.name)
+ return True
+
+ return False
+
+class YumOptionParser(OptionParser):
+ '''Subclass that makes some minor tweaks to make OptionParser do things the
+ "yum way".
+ '''
+
+ def __init__(self,base, **kwargs):
+ # check if this is called with a utils=True/False parameter
+ if 'utils' in kwargs:
+ self._utils = kwargs['utils']
+ del kwargs['utils']
+ else:
+ self._utils = False
+ OptionParser.__init__(self, **kwargs)
+ self.logger = logging.getLogger("yum.cli")
+ self.base = base
+ self.plugin_option_group = OptionGroup(self, _("Plugin Options"))
+ self.add_option_group(self.plugin_option_group)
+
+ self._addYumBasicOptions()
+
+ def error(self, msg):
+ '''This method is overridden so that error output goes to logger. '''
+ self.print_usage()
+ self.logger.critical(_("Command line error: %s"), msg)
+ sys.exit(1)
+
+ def firstParse(self,args):
+ # Parse only command line options that affect basic yum setup
+ try:
+ args = _filtercmdline(
+ ('--noplugins','--version','-q', '-v', "--quiet", "--verbose"),
+ ('-c', '-d', '-e', '--installroot',
+ '--disableplugin', '--enableplugin', '--releasever'),
+ args)
+ except ValueError, arg:
+ self.base.usage()
+ print >> sys.stderr, (_("\n\n%s: %s option requires an argument") %
+ ('Command line error', arg))
+ sys.exit(1)
+ return self.parse_args(args=args)[0]
+
+ @staticmethod
+ def _splitArg(seq):
+ """ Split all strings in seq, at "," and whitespace.
+ Returns a new list. """
+ ret = []
+ for arg in seq:
+ ret.extend(arg.replace(",", " ").split())
+ return ret
+
+ def setupYumConfig(self, args=None):
+ # Now parse the command line for real
+ if not args:
+ (opts, cmds) = self.parse_args()
+ else:
+ (opts, cmds) = self.parse_args(args=args)
+
+ # Let the plugins know what happened on the command line
+ self.base.plugins.setCmdLine(opts, cmds)
+
+ try:
+ # config file is parsed and moving us forward
+ # set some things in it.
+
+ # Handle remaining options
+ if opts.assumeyes:
+ self.base.conf.assumeyes =1
+
+ # Instead of going cache-only for a non-root user, try to use a
+ # user writable cachedir. If that fails fall back to cache-only.
+ if opts.cacheonly:
+ self.base.conf.cache = 1
+ elif not self.base.setCacheDir():
+ self.base.conf.cache = 1
+
+ if opts.obsoletes:
+ self.base.conf.obsoletes = 1
+
+ if opts.installroot:
+ self.base.conf.installroot = opts.installroot
+
+ if opts.skipbroken:
+ self.base.conf.skip_broken = True
+
+ if opts.showdupesfromrepos:
+ self.base.conf.showdupesfromrepos = True
+
+ if opts.color not in (None, 'auto', 'always', 'never',
+ 'tty', 'if-tty', 'yes', 'no', 'on', 'off'):
+ raise ValueError, _("--color takes one of: auto, always, never")
+ elif opts.color is None:
+ if self.base.conf.color != 'auto':
+ self.base.term.reinit(color=self.base.conf.color)
+ else:
+ _remap = {'tty' : 'auto', 'if-tty' : 'auto',
+ '1' : 'always', 'true' : 'always',
+ 'yes' : 'always', 'on' : 'always',
+ '0' : 'always', 'false' : 'always',
+ 'no' : 'never', 'off' : 'never'}
+ opts.color = _remap.get(opts.color, opts.color)
+ if opts.color != 'auto':
+ self.base.term.reinit(color=opts.color)
+
+ if opts.disableexcludes:
+ disable_excludes = self._splitArg(opts.disableexcludes)
+ else:
+ disable_excludes = []
+ self.base.conf.disable_excludes = disable_excludes
+
+ for exclude in self._splitArg(opts.exclude):
+ try:
+ excludelist = self.base.conf.exclude
+ excludelist.append(exclude)
+ self.base.conf.exclude = excludelist
+ except yum.Errors.ConfigError, e:
+ self.logger.critical(e)
+ self.base.usage()
+ sys.exit(1)
+
+ if opts.rpmverbosity is not None:
+ self.base.conf.rpmverbosity = opts.rpmverbosity
+
+ # setup the progress bars/callbacks
+ self.base.setupProgressCallbacks()
+ # setup the callbacks to import gpg pubkeys and confirm them
+ self.base.setupKeyImportCallbacks()
+
+ # Process repo enables and disables in order
+ for opt, repoexp in opts.repos:
+ try:
+ if opt == '--enablerepo':
+ self.base.repos.enableRepo(repoexp)
+ elif opt == '--disablerepo':
+ self.base.repos.disableRepo(repoexp)
+ except yum.Errors.ConfigError, e:
+ self.logger.critical(e)
+ self.base.usage()
+ sys.exit(1)
+
+ # make sure the added repos are setup.
+ if len(opts.repos) > 0:
+ self.base._getRepos(doSetup=True)
+
+ # Disable all gpg key checking, if requested.
+ if opts.nogpgcheck:
+ self.base.conf.gpgcheck = False
+ self.base.conf.repo_gpgcheck = False
+ for repo in self.base.repos.listEnabled():
+ repo.gpgcheck = False
+ repo.repo_gpgcheck = False
+
+ except ValueError, e:
+ self.logger.critical(_('Options Error: %s'), e)
+ self.base.usage()
+ sys.exit(1)
+
+ return opts, cmds
+
+ def getRoot(self,opts):
+ # If the conf file is inside the installroot - use that.
+ # otherwise look for it in the normal root
+ if opts.installroot:
+ if os.access(opts.installroot+'/'+opts.conffile, os.R_OK):
+ opts.conffile = opts.installroot+'/'+opts.conffile
+ elif opts.conffile == '/etc/yum/yum.conf':
+ # check if /installroot/etc/yum.conf exists.
+ if os.access(opts.installroot+'/etc/yum.conf', os.R_OK):
+ opts.conffile = opts.installroot+'/etc/yum.conf'
+ root=opts.installroot
+ else:
+ root = '/'
+ return root
+
+ def _wrapOptParseUsage(self, opt, value, parser, *args, **kwargs):
+ self.base.usage()
+ self.exit()
+
+ def _addYumBasicOptions(self):
+ def repo_optcb(optobj, opt, value, parser):
+ '''Callback for the enablerepo and disablerepo option.
+
+ Combines the values given for these options while preserving order
+ from command line.
+ '''
+ dest = eval('parser.values.%s' % optobj.dest)
+ dest.append((opt, value))
+
+ if self._utils:
+ group = OptionGroup(self, "Yum Base Options")
+ self.add_option_group(group)
+ else:
+ group = self
+
+ # Note that we can't use the default action="help" because of the
+ # fact that print_help() unconditionally does .encode() ... which is
+ # bad on unicode input.
+ group.conflict_handler = "resolve"
+ group.add_option("-h", "--help", action="callback",
+ callback=self._wrapOptParseUsage,
+ help=_("show this help message and exit"))
+ group.conflict_handler = "error"
+
+ group.add_option("-t", "--tolerant", action="store_true",
+ help=_("be tolerant of errors"))
+ group.add_option("-C", "--cacheonly", dest="cacheonly",
+ action="store_true",
+ help=_("run entirely from system cache, don't update cache"))
+ group.add_option("-c", "--config", dest="conffile",
+ default='/etc/yum/yum.conf',
+ help=_("config file location"), metavar='[config file]')
+ group.add_option("-R", "--randomwait", dest="sleeptime", type='int',
+ default=None,
+ help=_("maximum command wait time"), metavar='[minutes]')
+ group.add_option("-d", "--debuglevel", dest="debuglevel", default=None,
+ help=_("debugging output level"), type='int',
+ metavar='[debug level]')
+ group.add_option("--showduplicates", dest="showdupesfromrepos",
+ action="store_true",
+ help=_("show duplicates, in repos, in list/search commands"))
+ group.add_option("-e", "--errorlevel", dest="errorlevel", default=None,
+ help=_("error output level"), type='int',
+ metavar='[error level]')
+ group.add_option("", "--rpmverbosity", default=None,
+ help=_("debugging output level for rpm"),
+ metavar='[debug level name]')
+ group.add_option("-q", "--quiet", dest="quiet", action="store_true",
+ help=_("quiet operation"))
+ group.add_option("-v", "--verbose", dest="verbose", action="store_true",
+ help=_("verbose operation"))
+ group.add_option("-y", "--assumeyes", dest="assumeyes",
+ action="store_true", help=_("answer yes for all questions"))
+ group.add_option("--version", action="store_true",
+ help=_("show Yum version and exit"))
+ group.add_option("--installroot", help=_("set install root"),
+ metavar='[path]')
+ group.add_option("--enablerepo", action='callback',
+ type='string', callback=repo_optcb, dest='repos', default=[],
+ help=_("enable one or more repositories (wildcards allowed)"),
+ metavar='[repo]')
+ group.add_option("--disablerepo", action='callback',
+ type='string', callback=repo_optcb, dest='repos', default=[],
+ help=_("disable one or more repositories (wildcards allowed)"),
+ metavar='[repo]')
+ group.add_option("-x", "--exclude", default=[], action="append",
+ help=_("exclude package(s) by name or glob"), metavar='[package]')
+ group.add_option("", "--disableexcludes", default=[], action="append",
+ help=_("disable exclude from main, for a repo or for everything"),
+ metavar='[repo]')
+ group.add_option("--obsoletes", action="store_true",
+ help=_("enable obsoletes processing during updates"))
+ group.add_option("--noplugins", action="store_true",
+ help=_("disable Yum plugins"))
+ group.add_option("--nogpgcheck", action="store_true",
+ help=_("disable gpg signature checking"))
+ group.add_option("", "--disableplugin", dest="disableplugins", default=[],
+ action="append", help=_("disable plugins by name"),
+ metavar='[plugin]')
+ group.add_option("", "--enableplugin", dest="enableplugins", default=[],
+ action="append", help=_("enable plugins by name"),
+ metavar='[plugin]')
+ group.add_option("--skip-broken", action="store_true", dest="skipbroken",
+ help=_("skip packages with depsolving problems"))
+ group.add_option("", "--color", dest="color", default=None,
+ help=_("control whether color is used"))
+ group.add_option("", "--releasever", dest="releasever", default=None,
+ help=_("set value of $releasever in yum config and repo files"))
+
+
+
+def _filtercmdline(novalopts, valopts, args):
+ '''Keep only specific options from the command line argument list
+
+ This function allows us to peek at specific command line options when using
+ the optparse module. This is useful when some options affect what other
+ options should be available.
+
+ @param novalopts: A sequence of options to keep that don't take an argument.
+ @param valopts: A sequence of options to keep that take a single argument.
+ @param args: The command line arguments to parse (as per sys.argv[:1]
+ @return: A list of strings containing the filtered version of args.
+
+ Will raise ValueError if there was a problem parsing the command line.
+ '''
+ out = []
+ args = list(args) # Make a copy because this func is destructive
+
+ while len(args) > 0:
+ a = args.pop(0)
+ if '=' in a:
+ opt, _ = a.split('=', 1)
+ if opt in valopts:
+ out.append(a)
+
+ elif a in novalopts:
+ out.append(a)
+
+ elif a in valopts:
+ if len(args) < 1:
+ raise ValueError, a
+ next = args.pop(0)
+ if next[0] == '-':
+ raise ValueError, a
+
+ out.extend([a, next])
+
+ else:
+ # Check for single letter options that take a value, where the
+ # value is right up against the option
+ for opt in valopts:
+ if len(opt) == 2 and a.startswith(opt):
+ out.append(a)
+
+ return out
+
diff -Nurp yum-3.2.27/yum/config.py yum-3.2.27.new/yum/config.py
--- yum-3.2.27/yum/config.py 2010-09-10 23:34:55.160468710 +0100
+++ yum-3.2.27.new/yum/config.py 2010-09-10 23:34:22.573596066 +0100
@@ -603,7 +603,27 @@ class StartupConf(BaseConfig):
syslog_ident = Option()
syslog_facility = Option('LOG_DAEMON')
persistdir = Option('/var/lib/yum')
-
+
+ def getRootedPath(self, path, enforce_default=False, defaults_to_host=False):
+ instroot = self.installroot
+ if instroot is None:
+ return path
+
+ if path.startswith('hostfs://'): res = path[9:]
+ elif path.startswith('chrootfs://'): res = instroot + '/' + path[11:]
+ else:
+ tmp = instroot + '/' + path
+
+ if enforce_default:
+ if defaults_to_host: res = path
+ else: res = tmp
+ else:
+ if os.path.exists(tmp): res = tmp
+ elif defaults_to_host: res = path
+ else: res = tmp
+
+ return res
+
class YumConf(StartupConf):
'''
Configuration option definitions for yum.conf\'s [main] section.
@@ -617,6 +637,7 @@ class YumConf(StartupConf):
keepcache = BoolOption(True)
logfile = Option('/var/log/yum.log')
+ lockfile = Option('/var/run/yum.pid')
reposdir = ListOption(['/etc/yum/repos.d', '/etc/yum.repos.d'])
commands = ListOption()
@@ -864,7 +885,7 @@ def readMainConfig(startupconf):
# Apply the installroot to directory options
def _apply_installroot(yumconf, option):
path = getattr(yumconf, option)
- ir_path = yumconf.installroot + path
+ ir_path = yumconf.getRootedPath(path)
ir_path = ir_path.replace('//', '/') # os.path.normpath won't fix this and
# it annoys me
ir_path = varReplace(ir_path, yumvars)
@@ -888,7 +909,7 @@ def readMainConfig(startupconf):
yumvars[fsvar] = val
# These can use the above FS yumvars
- for option in ('cachedir', 'logfile', 'persistdir'):
+ for option in ('cachedir', 'logfile', 'lockfile', 'persistdir'):
_apply_installroot(yumconf, option)
# Add in some extra attributes which aren't actually configuration values
diff -Nurp yum-3.2.27/yum/config.py.orig yum-3.2.27.new/yum/config.py.orig
--- yum-3.2.27/yum/config.py.orig 2010-09-10 23:34:55.127469669 +0100
+++ yum-3.2.27.new/yum/config.py.orig 2010-09-10 23:25:16.227723870 +0100
@@ -854,13 +854,15 @@ def readMainConfig(startupconf):
yumvars['arch'] = startupconf.arch
yumvars['releasever'] = startupconf.releasever
yumvars['uuid'] = startupconf.uuid
+ # Note: We don't setup the FS yumvars here, because we want to be able to
+ # use the core yumvars in persistdir. Which is the base of FS yumvars.
# Read [main] section
yumconf = YumConf()
yumconf.populate(startupconf._parser, 'main')
# Apply the installroot to directory options
- for option in ('cachedir', 'logfile', 'persistdir'):
+ def _apply_installroot(yumconf, option):
path = getattr(yumconf, option)
ir_path = yumconf.installroot + path
ir_path = ir_path.replace('//', '/') # os.path.normpath won't fix this and
@@ -868,6 +870,27 @@ def readMainConfig(startupconf):
ir_path = varReplace(ir_path, yumvars)
setattr(yumconf, option, ir_path)
+ # Read the FS yumvars
+ try:
+ dir_fsvars = yumconf.installroot + "/etc/yum/vars/"
+ fsvars = os.listdir(dir_fsvars)
+ except OSError:
+ fsvars = []
+ for fsvar in fsvars:
+ if os.path.islink(dir_fsvars + fsvar):
+ continue
+ try:
+ val = open(dir_fsvars + fsvar).readline()
+ if val and val[-1] == '\n':
+ val = val[:-1]
+ except (OSError, IOError):
+ continue
+ yumvars[fsvar] = val
+
+ # These can use the above FS yumvars
+ for option in ('cachedir', 'logfile', 'persistdir'):
+ _apply_installroot(yumconf, option)
+
# Add in some extra attributes which aren't actually configuration values
yumconf.yumvar = yumvars
yumconf.uid = 0
diff -Nurp yum-3.2.27/yum/__init__.py yum-3.2.27.new/yum/__init__.py
--- yum-3.2.27/yum/__init__.py 2010-09-10 23:34:55.360468284 +0100
+++ yum-3.2.27.new/yum/__init__.py 2010-09-10 23:26:23.828469671 +0100
@@ -399,8 +399,7 @@ class YumBase(depsolve.Depsolve):
# this check makes sure that our dirs exist properly.
# if they aren't in the installroot then don't prepend the installroot
path
# if we don't do this then anaconda likes to not work.
- if os.path.exists(self.conf.installroot+'/'+reposdir):
- reposdir = self.conf.installroot + '/' + reposdir
+ reposdir = self.conf.getRootedPath(reposdir)
if os.path.isdir(reposdir):
for repofn in sorted(glob.glob('%s/*.repo' % reposdir)):
@@ -1380,8 +1379,7 @@ class YumBase(depsolve.Depsolve):
return
root = self.conf.installroot
- lockfile = root + '/' + lockfile # lock in the chroot
- lockfile = os.path.normpath(lockfile) # get rid of silly preceding extra /
+ lockfile = self.conf.lockfile
mypid=str(os.getpid())
while not self._lock(lockfile, mypid, 0644):
diff -Nurp yum-3.2.27/yum/__init__.py.orig yum-3.2.27.new/yum/__init__.py.orig
--- yum-3.2.27/yum/__init__.py.orig 2010-09-10 23:34:55.310466995 +0100
+++ yum-3.2.27.new/yum/__init__.py.orig 2010-09-10 23:25:16.425340733 +0100
@@ -3496,6 +3496,12 @@ class YumBase(depsolve.Depsolve):
self.logger.critical(_('Cannot add package %s to transaction. Not a compatible
architecture: %s'), pkg, po.arch)
return tx_return
+ if self.conf.obsoletes:
+ obsoleters = po.obsoletedBy(self.rpmdb.searchObsoletes(po.name))
+ if obsoleters:
+ self.logger.critical(_('Cannot install package %s. It is obsoleted
by installed package %s'), po, obsoleters[0])
+ return tx_return
+
# everything installed that matches the name
installedByKey = self.rpmdb.searchNevra(name=po.name)
# go through each package