Merge lp:~mvo/software-center/apt-url-multiarch-support into lp:software-center

Proposed by Michael Vogt
Status: Rejected
Rejected by: dobey
Proposed branch: lp:~mvo/software-center/apt-url-multiarch-support
Merge into: lp:software-center
Diff against target: 210 lines (+133/-21)
4 files modified
softwarecenter/db/application.py (+56/-20)
softwarecenter/ui/gtk3/app.py (+2/-1)
tests/test_database.py (+50/-0)
tests/utils.py (+25/-0)
To merge this branch: bzr merge lp:~mvo/software-center/apt-url-multiarch-support
Reviewer Review Type Date Requested Status
dobey Needs Fixing
Review via email: mp+139501@code.launchpad.net

Description of the change

This branch adds support for apt:pkgname links guessing for non-native pkgnames.

It will e.g. show "software-center apt:absmahjong" correctly on amd64

To post a comment you must log in.
Revision history for this message
dobey (dobey) wrote :

Can you re-merge with trunk and fix the conflicts? I see two of them when I try a merge. Thanks.

review: Needs Fixing
Revision history for this message
dobey (dobey) wrote :

Also, can you use bzr commit --fixes= to link the bug, if it does fix it? Thanks.

Unmerged revisions

3265. By Michael Vogt

trivial pep8 fix

3264. By Michael Vogt

refactor a bit to make it easier to read (hopefully)

3263. By Michael Vogt

move multiarch adjustment code for pkgs into its own function

3262. By Michael Vogt

add support for apt:$pkgname to multiarch transition

3261. By Michael Vogt

add support for finding multiarch pkgs from apt: links

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'softwarecenter/db/application.py'
2--- softwarecenter/db/application.py 2012-11-28 17:36:38 +0000
3+++ softwarecenter/db/application.py 2012-12-12 16:00:39 +0000
4@@ -206,35 +206,71 @@
5 self._app.request = self._app.request.replace(
6 "$distro", self._distro.get_codename())
7
8+ # adjust for multiarch if needed
9+ self._adjust_apturl_for_multiarch_pkgname_if_needed()
10+
11 # load pkg cache
12 self._pkg = None
13 if (self._app.pkgname in self._cache and
14 self._cache[self._app.pkgname].candidate):
15 self._pkg = self._cache[self._app.pkgname]
16
17- # load xapian document
18- self._doc = doc
19+ # load xapian document either from parent or try to get it
20+ # from the database
21+ self._doc = doc or self._get_xapian_document_for_app()
22 if not self._doc:
23+ # if there is no document and no apturl request,
24+ # set error state
25+ debfile_matches = re.findall(r'/', self._app.request)
26+ channel_matches = re.findall(r'channel=[a-z,-]*',
27+ self._app.request)
28+ section_matches = re.findall(r'section=[a-z]*',
29+ self._app.request)
30+ if (not self._pkg and
31+ not debfile_matches and
32+ not channel_matches and
33+ not section_matches):
34+ self._error = _("Not found")
35+ self._error_not_found = utf8(
36+ _(u"There isn\u2019t a "
37+ u"software package called \u201c%s\u201D in your "
38+ u"current software sources.")) % utf8(self.pkgname)
39+
40+ def _adjust_apturl_for_multiarch_pkgname_if_needed(self):
41+ """If this is a apt: url request, adjust to foreign pkgnames if
42+ there is no native package
43+ """
44+ if (self._app.request.startswith("apt:") and
45+ not self._app.pkgname in self._cache):
46+ for arch in self._distro.get_foreign_architectures():
47+ foreign_pkg = "%s:%s" % (self._app.pkgname, arch)
48+ if foreign_pkg in self._cache:
49+ self._app.pkgname += ":" + arch
50+
51+ def _get_xapian_document_for_app(self):
52+ """Try to get the xapian document for the given app, adjust multiarch
53+ as needed
54+ """
55+ try:
56+ doc = self._db.get_xapian_document(
57+ self._app.appname, self._app.pkgname)
58+ except IndexError:
59+ doc = self._try_adjust_apturl_for_multiarch_doc()
60+ return doc
61+
62+ def _try_adjust_apturl_for_multiarch_doc(self):
63+ if not self._app.request.startswith("apt:"):
64+ return None
65+ for arch in self._distro.get_foreign_architectures():
66+ foreign_pkg = "%s:%s" % (self._app.pkgname, arch)
67 try:
68- self._doc = self._db.get_xapian_document(
69- self._app.appname, self._app.pkgname)
70+ doc = self._db.get_xapian_document(
71+ self._app.appname, foreign_pkg)
72+ self._app.pkgname = foreign_pkg
73+ return doc
74 except IndexError:
75- # if there is no document and no apturl request,
76- # set error state
77- debfile_matches = re.findall(r'/', self._app.request)
78- channel_matches = re.findall(r'channel=[a-z,-]*',
79- self._app.request)
80- section_matches = re.findall(r'section=[a-z]*',
81- self._app.request)
82- if (not self._pkg and
83- not debfile_matches and
84- not channel_matches and
85- not section_matches):
86- self._error = _("Not found")
87- self._error_not_found = utf8(
88- _(u"There isn\u2019t a "
89- u"software package called \u201c%s\u201D in your "
90- u"current software sources.")) % utf8(self.pkgname)
91+ continue
92+ return None
93
94 def same_app(self, other):
95 return self.pkgname == other.pkgname
96
97=== modified file 'softwarecenter/ui/gtk3/app.py'
98--- softwarecenter/ui/gtk3/app.py 2012-12-06 16:16:49 +0000
99+++ softwarecenter/ui/gtk3/app.py 2012-12-12 16:00:39 +0000
100@@ -205,7 +205,8 @@
101 # e.g. unity
102 (pkgname, sep, appname) = request.partition("/")
103 if pkgname or appname:
104- app = Application(appname, pkgname)
105+ # add the unaltered request
106+ app = Application(appname, pkgname, request=packages[0])
107 else:
108 LOG.warning('show_available_packages: received %r but '
109 'can not build an Application from it.', request)
110
111=== modified file 'tests/test_database.py'
112--- tests/test_database.py 2012-11-28 15:43:49 +0000
113+++ tests/test_database.py 2012-12-12 16:00:39 +0000
114@@ -20,6 +20,8 @@
115 make_software_center_agent_subscription_dict,
116 make_software_center_agent_app_dict,
117 setup_test_env,
118+ FakeDatabase,
119+ FakeDocument,
120 )
121 setup_test_env()
122
123@@ -907,6 +909,54 @@
124 self.assertEqual(len(self.enquire._matches), 2)
125
126
127+class TestMultiarchAptUrlLp1052920(unittest.TestCase):
128+
129+ def test_multiarch_doc_pkgname_transition(self):
130+ """Test that if a package is only available for a foreign
131+ architecture, the pkgname is automatically adjuested
132+ if there is a apt requests
133+ """
134+ mock_doc = FakeDocument(values={XapianValues.PRICE: '2.99'})
135+ db = FakeDatabase(documents={'pkgname:i386': mock_doc})
136+ app = Application("Multiarch app", "pkgname", request="apt:pkgname")
137+ details = app.get_details(db)
138+ self.assertEqual(details.pkg_state, PkgStates.NEEDS_PURCHASE)
139+ self.assertEqual(details._app.pkgname, "pkgname:i386")
140+
141+ def test_multiarch_no_request_no_transition(self):
142+ """Ensure that the details are not modified if there is no
143+ "apt:" app.request
144+ """
145+ mock_doc = FakeDocument(values={XapianValues.PRICE: '2.99'})
146+ db = FakeDatabase(documents={'pkgname:i386': mock_doc})
147+ app = Application("Multiarch app", "pkgname", request="")
148+ details = app.get_details(db)
149+ self.assertEqual(details.pkg_state, PkgStates.NOT_FOUND)
150+ self.assertEqual(details._app.pkgname, "pkgname")
151+
152+ def test_multiarch_pkg_transition(self):
153+ """Ensure that for apt: urls with a multiarch package is found"""
154+ mock_pkg = Mock()
155+ mock_pkg.is_installed = False
156+ db = FakeDatabase(cache={'pkgname:i386': mock_pkg})
157+ app = Application("Multiarch app", "pkgname", request="apt:pkgname")
158+ details = app.get_details(db)
159+ self.assertEqual(details.pkg_state, PkgStates.UNINSTALLED)
160+ self.assertEqual(details._app.pkgname, "pkgname:i386")
161+
162+ def test_multiarch_pkg_no_request_no_transition(self):
163+ """Ensure that the details are not modified if there is no
164+ "apt:" app.request
165+ """
166+ mock_pkg = Mock()
167+ mock_pkg.is_installed = False
168+ db = FakeDatabase(cache={'pkgname:i386': mock_pkg})
169+ app = Application("Multiarch app", "pkgname", request="")
170+ details = app.get_details(db)
171+ self.assertEqual(details.pkg_state, PkgStates.NOT_FOUND)
172+ self.assertEqual(details._app.pkgname, "pkgname")
173+
174+
175 if __name__ == "__main__":
176 #import logging
177 #logging.basicConfig(level=logging.DEBUG)
178
179=== modified file 'tests/utils.py'
180--- tests/utils.py 2012-11-28 15:43:49 +0000
181+++ tests/utils.py 2012-12-12 16:00:39 +0000
182@@ -478,3 +478,28 @@
183 addons_to_remove, archive_suite):
184 """Emit a fake signal "query-total-size-on-install-done" """
185 self.emit("query-total-size-on-install-done", None, "", 0, 0)
186+
187+
188+class FakeDocument(object):
189+
190+ def __init__(self, values={}):
191+ self._values = values
192+
193+ def get_value(self, value):
194+ return self._values.get(value, "")
195+
196+class FakeDatabase(ObjectWithSignals):
197+
198+ def __init__(self, cache={}, documents={}):
199+ super(FakeDatabase, self).__init__()
200+ self._aptcache = cache
201+ self._mock_documents = documents
202+
203+ def connect(self, *args, **kwargs):
204+ pass
205+
206+ def get_xapian_document(self, appname, pkgname):
207+ if not pkgname in self._mock_documents:
208+ raise IndexError
209+ return self._mock_documents[pkgname]
210+

Subscribers

People subscribed via source and target branches