diff --git a/libtaskotron/ext/fedora/koji_utils.py b/libtaskotron/ext/fedora/koji_utils.py
--- a/libtaskotron/ext/fedora/koji_utils.py
+++ b/libtaskotron/ext/fedora/koji_utils.py
@@ -145,6 +145,37 @@
 
         return result
 
+    @staticmethod
+    def _compute_arches(arches, arch_exclude, src):
+        '''
+        From requested arches compute a final list of arches to be used by Koji calls.
+        The input parameters have the same meaning as documented in :meth:`nvr_to_urls`.
+
+        :return: a set of arches to be used
+        :rtype: set of str
+        '''
+        arches = set(arches)
+        arch_exclude = set(arch_exclude)
+        # populate arches if 'all' requested
+        if 'all' in arches:
+            arches.discard('all')
+            arches.update(config.get_config().supported_arches + ['noarch'])
+
+        # add binary arches if base arches are specified
+        for arch in arches.copy():
+            if arch in arch_utils.Arches.base:
+                arches.update(arch_utils.Arches.binary[arch])
+
+        if src:
+            arches.add('src')
+        else:
+            arch_exclude.add('src')
+
+        # exclude unwanted arches
+        arches.difference_update(arch_exclude)
+
+        return arches
+
     def nvr_to_urls(self, nvr, arches=['all'], arch_exclude=[], debuginfo=False, src=True):
         '''Get list of URLs for RPMs corresponding to a build.
 
@@ -168,24 +199,8 @@
         '''
         log.info('Querying Koji for a list of RPMS for: %s', nvr)
 
-        arches = set(arches)
-        # populate arches if 'all' requested
-        if 'all' in arches:
-            arches.discard('all')
-            arches.update(config.get_config().supported_arches + ['noarch'])
+        arches = list(self._compute_arches(arches, arch_exclude, src))
 
-        # add binary arches if base arches are specified
-        for arch in arches.copy():
-            if arch in arch_utils.Arches.base:
-                arches.update(arch_utils.Arches.binary[arch])
-
-        if src:
-            arches.add('src')
-
-        # exclude unwanted arches
-        arches.difference_update(set(arch_exclude))
-
-        arches = list(arches)
         if not arches:
             log.debug('Nothing to query for, the combination of `arches`, `arch_exclude` and '
                       '`src` ended up an empty list.')
@@ -300,16 +315,13 @@
             retrieved
         '''
         log.info('Getting build logs for: %s', nvr)
-        arch_exclude = list(arch_exclude)
 
-        # add binary arches if base arches are specified
-        archlist = list(arches)
-        for arch in arches:
-            if arch in arch_utils.Arches.base:
-                archlist.extend(arch_utils.Arches.binary[arch])
-        arches = list(set(archlist))
         # there seem to be no logs in Koji for 'src'
-        arch_exclude.append('src')
+        arches = self._compute_arches(arches, arch_exclude, src=False)
+        if not arches:
+            log.debug('Nothing to query for, the combination of `arches` and `arch_exclude` ended '
+                      'up an empty list.')
+            return {'ok': [], 'error': []}
 
         # list the RPMs for the koji build, so that we know which arches to download logs for
         try:
@@ -320,13 +332,10 @@
 
         # download for each arch
         build_arches = set([rpm['arch'] for rpm in build_rpms])
+        build_arches.intersection_update(arches)
         ok = []
         error = []
         for build_arch in build_arches:
-            if build_arch not in arches and 'all' not in arches:
-                continue
-            if build_arch in arch_exclude:
-                continue
             nevra = hawkey.split_nevra(nvr + '.' + build_arch)
             url = self.build_log_url.format(pkg_url=config.get_config().pkg_url, nevra=nevra)
 
diff --git a/testing/test_koji_utils.py b/testing/test_koji_utils.py
--- a/testing/test_koji_utils.py
+++ b/testing/test_koji_utils.py
@@ -16,6 +16,7 @@
 from libtaskotron import exceptions as exc
 from libtaskotron import config
 from libtaskotron import file_utils
+from libtaskotron import arch_utils
 
 from test_file_utils import mock_download
 
@@ -158,6 +159,70 @@
         with pytest.raises(exc.TaskotronRemoteError):
             test_koji.rpms_to_build([self.ref_filename])
 
+    # =====================
+    #    _compute_arches()
+    # =====================
+
+    def test_add_binary_arches(self):
+        '''specifying basearch should add all binary arches'''
+        ref_arch = 'i386'
+        bin_arches = arch_utils.Arches.binary[ref_arch]
+        arches = koji_utils.KojiClient._compute_arches(arches=[ref_arch], arch_exclude=[],
+                                                       src=False)
+        assert arches == set(bin_arches)
+
+    def test_keep_extra_arch_with_all(self):
+        '''Arches should not be thrown away even if 'all' is specified (there might be some extra
+        obscure arches specified in addition)'''
+        ref_arch = ['all', 'obscure_arch']
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=[], src=False)
+        assert 'all' not in arches
+        assert 'obscure_arch' in arches
+
+    def test_src(self):
+        # src enabled
+        ref_arch = ['all']
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=[], src=True)
+        assert 'src' in arches
+
+        # src disabled
+        ref_arch = ['all', 'src']
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=[], src=False)
+        assert 'src' not in arches
+
+    def test_only_src(self):
+        ref_arch = []
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=[], src=True)
+        assert arches == set(['src'])
+
+    def test_arch_exclude(self):
+        ref_arch = ['all']
+
+        # arch_exclude disabled
+        ref_exclude = []
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=ref_exclude,
+                                                       src=False)
+        for arch in ref_exclude:
+            if arch in config.get_config().supported_arches:
+                assert arch in arches
+
+        # arch_exclude enabled
+        ref_exclude = ['x86_64']
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=ref_exclude,
+                                                       src=False)
+        for arch in ref_exclude:
+            assert arch not in arches
+
+    def test_arch_exclude_override_explicit(self):
+        '''arch_exclude should work even when the same arch is explicitly stated in arches'''
+        ref_exclude = ['x86_64']
+        ref_arch = ref_exclude + ['i386']
+
+        arches = koji_utils.KojiClient._compute_arches(arches=ref_arch, arch_exclude=ref_exclude,
+                                                       src=False)
+        for arch in ref_exclude:
+            assert arch not in arches
+
     # ===================
     #    nvr_to_urls()
     # ===================
@@ -173,58 +238,13 @@
             assert url.startswith(koji_baseurl)
             assert url.endswith('.rpm')
 
-    def should_i386_rpmurls_query_i686(self):
-        self.ref_arch = 'i386'
-        stub_koji = Dingus(getBuild__returns=self.ref_build,
-                           listRPMs__returns=self.ref_rpms)
-        test_koji = koji_utils.KojiClient(stub_koji)
-
-        test_koji.nvr_to_urls(self.ref_nvr, arches=[self.ref_arch])
-
-        listrpm_calls = stub_koji.calls('listRPMs')
-        requested_arches = listrpm_calls[0][2]['arches']
-        assert 'i686' in requested_arches
-        assert 'i386' in requested_arches
-
-    def test_keep_extra_arch_with_all(self):
-        '''Arches should not be thrown away even if 'all' is specified (there might be some extra
-        obscure arches specified in addition)'''
-        self.ref_arch = ['all', 'obscure_arch']
-        stub_koji = Dingus(getBuild__returns=self.ref_build)
-        test_koji = koji_utils.KojiClient(stub_koji)
-
-        test_koji.nvr_to_urls(self.ref_nvr, arches=self.ref_arch)
-
-        listrpm_calls = stub_koji.calls('listRPMs')
-        requested_arches = listrpm_calls[0][2]['arches']
-        assert 'all' not in requested_arches
-        assert 'obscure_arch' in requested_arches
-
     def should_not_throw_exception_norpms(self):
         '''It's possible to have no RPMs (for the given arch) in a build'''
         stub_koji = Dingus(getBuild__returns = self.ref_build)
         test_koji = koji_utils.KojiClient(stub_koji)
 
         test_koji.nvr_to_urls(self.ref_nvr, arches = [self.ref_arch])
 
-    def test_nvr_to_urls_src_filtering(self):
-        stub_koji = Dingus(getBuild__returns=self.ref_build)
-        test_koji = koji_utils.KojiClient(stub_koji)
-
-        # src enabled
-        test_koji.nvr_to_urls(self.ref_nvr, src=True, debuginfo=True)
-        listrpm_calls = stub_koji.calls('listRPMs')
-        assert len(listrpm_calls) == 1
-        requested_arches = listrpm_calls[0][2]['arches']
-        assert 'src' in requested_arches
-
-        # src disabled
-        test_koji.nvr_to_urls(self.ref_nvr, src=False, debuginfo=True)
-        listrpm_calls = stub_koji.calls('listRPMs')
-        assert len(listrpm_calls) == 2
-        requested_arches = listrpm_calls[1][2]['arches']
-        assert 'src' not in requested_arches
-
     def test_nvr_to_urls_debuginfo(self):
         stub_koji = Dingus(getBuild__returns=self.ref_build,
                            listRPMs__returns=self.ref_rpms)
@@ -241,63 +261,14 @@
                                  if 'debuginfo' not in rpm['name']])
         assert all(['debuginfo' not in url for url in urls])
 
-    def test_nvr_to_urls_only_src(self):
-        stub_koji = Dingus(getBuild__returns=self.ref_build)
-        test_koji = koji_utils.KojiClient(stub_koji)
-
-        # arch disabled, src enabled
-        test_koji.nvr_to_urls(self.ref_nvr, arches=[], src=True)
-        listrpm_calls = stub_koji.calls('listRPMs')
-        requested_arches = listrpm_calls[0][2]['arches']
-        assert len(requested_arches) == 1
-        assert 'src' in requested_arches
-
     def should_not_query_no_arch_no_src(self):
         '''If there's no arch to query for, should not perform the query'''
         stub_koji = mock.Mock()
         test_koji = koji_utils.KojiClient(stub_koji)
 
         test_koji.nvr_to_urls(self.ref_nvr, arches=[], src=False)
         assert not stub_koji.called
 
-    def test_arch_exclude(self):
-        stub_koji = Dingus(getBuild__returns=self.ref_build)
-        test_koji = koji_utils.KojiClient(stub_koji)
-        ref_exclude = ['x86_64']
-
-        # arch_exclude disabled
-        test_koji.nvr_to_urls(self.ref_nvr, src=True, debuginfo=True)
-        listrpm_calls = stub_koji.calls('listRPMs')
-        assert len(listrpm_calls) == 1
-        requested_arches = listrpm_calls[0][2]['arches']
-        for arch in ref_exclude:
-            if arch in config.get_config().supported_arches:
-                assert arch in requested_arches
-
-        # arch_exclude enabled
-        test_koji.nvr_to_urls(self.ref_nvr, arch_exclude=ref_exclude, src=True, debuginfo=True)
-        listrpm_calls = stub_koji.calls('listRPMs')
-        assert len(listrpm_calls) == 2
-        requested_arches = listrpm_calls[1][2]['arches']
-        for arch in ref_exclude:
-            assert arch not in requested_arches
-
-    def test_arch_exclude_override_explicit(self):
-        '''arch_exclude should work even when the same arch is explicitly stated in arches'''
-        stub_koji = Dingus(getBuild__returns=self.ref_build)
-        test_koji = koji_utils.KojiClient(stub_koji)
-        ref_exclude = ['x86_64']
-        ref_arch = ref_exclude + ['i386']
-
-        # arch_exclude enabled
-        test_koji.nvr_to_urls(self.ref_nvr, arches=ref_arch, arch_exclude=ref_exclude,
-                              src=True, debuginfo=True)
-        listrpm_calls = stub_koji.calls('listRPMs')
-        assert len(listrpm_calls) == 1
-        requested_arches = listrpm_calls[0][2]['arches']
-        for arch in ref_exclude:
-            assert arch not in requested_arches
-
     # ====================
     #    get_nvr_rpms()
     # ====================
@@ -434,21 +405,6 @@
         with pytest.raises(exc.TaskotronRemoteError):
             test_koji.get_build_log(self.ref_nvr, dest=None)
 
-    def test_build_log_add_binary_archs(self, monkeypatch):
-        '''specifying basearch should query for concrete binary arches'''
-        self.ref_arch = 'i686'
-        ref_base_arch = 'i386'
-        stub_koji = mock.Mock()
-        stub_koji.listBuildRPMs.return_value = self.ref_rpms
-        test_koji = koji_utils.KojiClient(stub_koji)
-        stub_download = mock.Mock()
-        monkeypatch.setattr(file_utils, 'download', stub_download)
-
-        test_koji.get_build_log(self.ref_nvr, dest=None, arches=[ref_base_arch])
-
-        assert stub_download.call_count == 1
-        assert '/%s/' % self.ref_arch in stub_download.call_args[1]['url']
-
     def test_build_log_do_nothing_different_arch(self, monkeypatch):
         '''if only unavailable arches are requested, do nothing and don't crash'''
         ref_arch = 'armv7hl'  # not available in self.rpms

