[Pkg-bazaar-commits] ./bzr-builddeb/trunk r356: Add UpstreamSource that abstracts methods more.

James Westby james.westby at canonical.com
Sun Jul 26 08:05:34 UTC 2009


------------------------------------------------------------
revno: 356
committer: James Westby <james.westby at canonical.com>
branch nick: trunk
timestamp: Sun 2009-07-26 10:05:34 +0200
message:
  Add UpstreamSource that abstracts methods more.
  
  They currently can only provide the source for a specific version if they can
  find it. The intention is that they will also be able to list availble
  versions and the like at some point.
  
  Thanks Jelmer.
modified:
  cmds.py
  directory.py
  import_dsc.py
  tests/test_upstream.py
  upstream.py
    ------------------------------------------------------------
    revno: 334.4.1
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: trunk
    timestamp: Wed 2009-04-15 15:41:09 +0200
    message:
      Store available sources in a list rather than checking each manually.
    modified:
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.2
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: trunk
    timestamp: Wed 2009-04-15 16:32:25 +0200
    message:
      Move all upstream sources to separate objects.
    modified:
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.3
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Wed 2009-04-15 17:41:56 +0200
    message:
      Move apt-related functions onto AptSource.
    modified:
      tests/test_upstream.py
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.4
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Wed 2009-04-15 21:49:24 +0200
    message:
      Move all source functions onto objects.
    modified:
      tests/test_upstream.py
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.5
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Wed 2009-04-15 22:06:39 +0200
    message:
      Support parsing revision id from version string.
    modified:
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.6
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Wed 2009-04-15 22:13:40 +0200
    message:
      Use UpstreamBranchSource inside of merge-upstream.
    modified:
      cmds.py
    ------------------------------------------------------------
    revno: 334.4.7
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Wed 2009-04-15 22:50:33 +0200
    message:
      Fix merging of upstream branch in merge-upstream.
    modified:
      cmds.py
      import_dsc.py
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.8
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Thu 2009-04-16 00:06:09 +0200
    message:
      Add a stacked upstream source object.
    modified:
      upstream.py
    ------------------------------------------------------------
    revno: 334.4.9
    committer: Jelmer Vernooij <jelmer at samba.org>
    branch nick: obj
    timestamp: Thu 2009-04-16 01:17:50 +0200
    message:
      Fix tests.
    modified:
      tests/test_upstream.py
      upstream.py
        ------------------------------------------------------------
        revno: 334.2.3
        committer: Jelmer Vernooij <jelmer at samba.org>
        branch nick: trunk
        timestamp: Wed 2009-04-15 23:36:10 +0200
        message:
          Use common function for iterating over the available tags.
        modified:
          import_dsc.py
        ------------------------------------------------------------
        revno: 334.2.4
        committer: Jelmer Vernooij <jelmer at samba.org>
        branch nick: trunk
        timestamp: Thu 2009-04-16 00:04:11 +0200
        message:
          Support more tags for upstream versions.
        modified:
          import_dsc.py
-------------- next part --------------
=== modified file 'cmds.py'
--- a/cmds.py	2009-07-15 18:41:07 +0000
+++ b/cmds.py	2009-07-26 08:05:34 +0000
@@ -34,7 +34,6 @@
     urlutils,
     )
 from bzrlib.branch import Branch
-from bzrlib.bzrdir import BzrDir
 from bzrlib.commands import Command
 from bzrlib.errors import (BzrCommandError,
                            NoWorkingTree,
@@ -74,7 +73,7 @@
         MergeModeDistiller,
         NativeSourceDistiller,
         )
-from bzrlib.plugins.builddeb.upstream import UpstreamProvider
+from bzrlib.plugins.builddeb.upstream import UpstreamProvider, UpstreamBranchSource
 from bzrlib.plugins.builddeb.util import (find_changelog,
         get_export_upstream_revision,
         find_last_distribution,
@@ -212,7 +211,12 @@
         is_local = urlparse.urlsplit(location)[0] in ('', 'file')
         if is_local:
             os.chdir(location)
-        tree, branch, relpath = BzrDir.open_containing_tree_or_branch(location)
+        try:
+            tree, _ = WorkingTree.open_containing(location)
+            branch = tree.branch
+        except NoWorkingTree:
+            tree = None
+            branch, _ = Branch.open_containing(location)
         return tree, branch, is_local
 
     def _get_build_tree(self, revision, tree, branch):
@@ -574,11 +578,10 @@
             tarball_filename = os.path.join(orig_dir, dest_name)
 
             if upstream_branch and no_tarball:
-                info("Exporting the upstream branch to create the tarball")
-                rev_tree = upstream_branch.repository.revision_tree(
+                upstream = UpstreamBranchSource(upstream_branch, 
                         upstream_revision)
-                export(rev_tree, tarball_filename, format='tgz',
-                        root="%s-%s" % (package, version.upstream_version))
+                upstream.get_specific_version(package, version.upstream_version,
+                        orig_dir)
             else:
                 try:
                     repack_tarball(location, dest_name, target_dir=orig_dir)

=== modified file 'directory.py'
--- a/directory.py	2009-03-23 23:50:11 +0000
+++ b/directory.py	2009-04-15 23:17:50 +0000
@@ -86,15 +86,5 @@
             else:
                 return urls[version]["Git"]
 
-        if "Hg" in urls[version]:
-            try:
-                import bzrlib.plugins.hg
-            except ImportError:
-                info("This package uses hg. If you would like to "
-                        "access it with bzr then please install bzr-hg"
-                        "and re-run the command.")
-            else:
-                return urls[version]["Hg"]
-
         raise errors.InvalidURL(path=url,
             extra='unsupported VCSes %r found' % urls[version].keys())

=== modified file 'import_dsc.py'
--- a/import_dsc.py	2009-07-21 22:49:34 +0000
+++ b/import_dsc.py	2009-07-26 08:05:34 +0000
@@ -57,6 +57,7 @@
         )
 from bzrlib.export import export
 from bzrlib.osutils import file_iterator, isdir, basename, splitpath
+from bzrlib.revisionspec import RevisionSpec
 from bzrlib.revision import NULL_REVISION
 from bzrlib.trace import warning, info, mutter
 from bzrlib.transform import TreeTransform, cook_conflicts, resolve_conflicts
@@ -73,7 +74,7 @@
                 UpstreamAlreadyImported,
                 UpstreamBranchAlreadyMerged,
                 )
-from bzrlib.plugins.builddeb.util import get_commit_info_from_changelog
+from bzrlib.plugins.builddeb.util import get_commit_info_from_changelog, get_snapshot_revision
 
 
 files_to_ignore = set(['.cvsignore', '.arch-inventory', '.bzrignore',
@@ -1634,16 +1635,23 @@
                 "Should use self.upstream_branch if set"
         tempdir = tempfile.mkdtemp(dir=os.path.join(self.tree.basedir, '..'))
         try:
+            previous_upstream_revision = get_snapshot_revision(previous_version.upstream_version)
             if previous_version is not None:
-                if not self.has_upstream_version_in_packaging_branch(
+                if self.has_upstream_version_in_packaging_branch(
                         previous_version.upstream_version):
+                    upstream_tip = self._revid_of_upstream_version_from_branch(
+                            previous_version.upstream_version)
+                    self._extract_upstream_tree(upstream_tip, tempdir)
+                elif (upstream_branch is not None and 
+                      previous_upstream_revision is not None):
+                    upstream_tip = RevisionSpec.from_string(previous_upstream_revision).as_revision_id(upstream_branch)
+                    assert isinstance(upstream_tip, str)
+                    self._extract_upstream_tree(upstream_tip, tempdir)
+                else:
                     raise BzrCommandError("Unable to find the tag for the "
                             "previous upstream version, %s, in the branch: "
                             "%s" % (previous_version,
                                 self.upstream_tag_name(previous_version)))
-                upstream_tip = self._revid_of_upstream_version_from_branch(
-                        previous_version.upstream_version)
-                self._extract_upstream_tree(upstream_tip, tempdir)
             else:
                 self._create_empty_upstream_tree(tempdir)
             if self.has_upstream_version_in_packaging_branch(version.upstream_version):

=== modified file 'tests/test_upstream.py'
--- a/tests/test_upstream.py	2009-07-15 18:36:36 +0000
+++ b/tests/test_upstream.py	2009-07-26 08:05:34 +0000
@@ -24,14 +24,18 @@
 
 from debian_bundle.changelog import Version
 
-from bzrlib.tests import TestCaseWithTransport
+from bzrlib.tests import (
+        TestCase,
+        TestCaseWithTransport,
+        )
 from bzrlib.plugins.builddeb.errors import (
         MissingUpstreamTarball,
         )
 from bzrlib.plugins.builddeb.upstream import (
         UpstreamProvider,
-        get_apt_command_for_source,
-        provide_with_apt,
+        UpstreamSource,
+        AptSource,
+        PristineTarSource,
         )
 from bzrlib.plugins.builddeb.util import (
         get_parent_dir,
@@ -39,7 +43,7 @@
         )
 
 
-class MockProvider(object):
+class MockProvider(UpstreamSource):
 
     def create_target(self, path):
         parent_dir = get_parent_dir(path)
@@ -51,9 +55,6 @@
         finally:
             f.close()
 
-    def tarball_name(self, package, upstream_version):
-        return tarball_name(package, upstream_version)
-
 
 class MockAptProvider(MockProvider):
 
@@ -64,14 +65,14 @@
         self.upstream_version = None
         self.target_dir = None
 
-    def provide(self, package, upstream_version, target_dir):
+    def get_specific_version(self, package, upstream_version, target_dir):
         self.called_times += 1
         self.package = package
         self.upstream_version = upstream_version
         self.target_dir = target_dir
         if self.find:
             self.create_target(os.path.join(target_dir,
-                    self.tarball_name(package, upstream_version)))
+                    tarball_name(package, upstream_version)))
         return self.find
 
 
@@ -97,7 +98,7 @@
         self.target_dir = target_dir
         if self.find:
             self.create_target(os.path.join(target_dir,
-                    self.tarball_name(package, upstream_version)))
+                    tarball_name(package, upstream_version)))
         return self.find
 
 
@@ -226,23 +227,6 @@
         return self.sources
 
 
-class MockAptCaller(object):
-
-    def __init__(self, work=False):
-        self.work = work
-        self.called = 0
-        self.package = None
-        self.version_str = None
-        self.target_dir = None
-
-    def call(self, package, version_str, target_dir):
-        self.package = package
-        self.version_str = version_str
-        self.target_dir = target_dir
-        self.called += 1
-        return self.work
-
-
 class UpstreamProviderTests(TestCaseWithTransport):
 
     def setUp(self):
@@ -258,20 +242,22 @@
         self.store_dir = "store"
         self.provider = UpstreamProvider(self.tree, self.branch,
                 self.package, self.version, self.store_dir)
+        self.provider._sources = []
         self.providers = {}
-        self.providers["apt"]= MockAptProvider()
-        self.provider._apt_provider = self.providers["apt"].provide
+        self.providers["apt"] = MockAptProvider()
+        self.provider._sources.append(self.providers["apt"])
         self.providers["uscan"] = MockUscanProvider()
-        self.provider._uscan_provider = self.providers["uscan"].provide
+        self.provider._sources.append(self.providers["uscan"])
         self.providers["pristine"] = MockPristineProvider()
-        self.provider._pristine_provider = self.providers["pristine"].provide
+        self.provider._sources.append(self.providers["pristine"])
         self.providers["orig"] = MockOrigSourceProvider()
-        self.provider._orig_source_provider = self.providers["orig"].provide
+        self.provider._sources.append(self.providers["orig"])
         self.providers["upstream"] = MockOtherBranchProvider()
+        self.provider._sources.append(self.providers["upstream"])
         self.provider._upstream_branch_provider = \
                                 self.providers["upstream"].provide
         self.providers["split"] = MockSplitProvider()
-        self.provider._split_provider = self.providers["split"].provide
+        self.provider._sources.append(self.providers["split"])
         self.target_dir = "target"
         self.target_filename = os.path.join(self.target_dir,
                 self.desired_tarball_name)
@@ -436,17 +422,37 @@
         self.provider.allow_split = True
         self.assertSuccesfulCall("uscan", ["pristine", "apt"])
 
+
+class MockAptCaller(object):
+
+    def __init__(self, work=False):
+        self.work = work
+        self.called = 0
+        self.package = None
+        self.version_str = None
+        self.target_dir = None
+
+    def call(self, package, version_str, target_dir):
+        self.package = package
+        self.version_str = version_str
+        self.target_dir = target_dir
+        self.called += 1
+        return self.work
+
+
+class AptSourceTests(TestCase):
+
     def test_get_apt_command_for_source(self):
         self.assertEqual("apt-get source -y --only-source --tar-only "
                 "apackage=someversion",
-                get_apt_command_for_source("apackage", "someversion"))
+                AptSource()._get_command("apackage", "someversion"))
 
     def test_apt_provider_no_package(self):
         caller = MockAptCaller()
         sources = MockSources([])
         apt_pkg = MockAptPkg(sources)
-        self.assertEqual(False, provide_with_apt("apackage", "0.2",
-                    "target", _apt_pkg=apt_pkg, _apt_caller=caller))
+        self.assertEqual(False, AptSource().get_specific_version(
+            "apackage", "0.2", "target", _apt_pkg=apt_pkg, _apt_caller=caller))
         self.assertEqual(1, apt_pkg.init_called_times)
         self.assertEqual(1, apt_pkg.get_pkg_source_records_called_times)
         self.assertEqual(1, sources.restart_called_times)
@@ -458,8 +464,8 @@
         caller = MockAptCaller()
         sources = MockSources(["0.1-1"])
         apt_pkg = MockAptPkg(sources)
-        self.assertEqual(False, provide_with_apt("apackage", "0.2",
-                    "target", _apt_pkg=apt_pkg, _apt_caller=caller))
+        self.assertEqual(False, AptSource().get_specific_version(
+            "apackage", "0.2", "target", _apt_pkg=apt_pkg, _apt_caller=caller))
         self.assertEqual(1, apt_pkg.init_called_times)
         self.assertEqual(1, apt_pkg.get_pkg_source_records_called_times)
         self.assertEqual(1, sources.restart_called_times)
@@ -471,8 +477,9 @@
         caller = MockAptCaller(work=True)
         sources = MockSources(["0.1-1", "0.2-1"])
         apt_pkg = MockAptPkg(sources)
-        self.assertEqual(True, provide_with_apt("apackage", "0.2",
-                    "target", _apt_pkg=apt_pkg, _apt_caller=caller.call))
+        self.assertEqual(True, AptSource().get_specific_version(
+            "apackage", "0.2", "target", 
+            _apt_pkg=apt_pkg, _apt_caller=caller.call))
         self.assertEqual(1, apt_pkg.init_called_times)
         self.assertEqual(1, apt_pkg.get_pkg_source_records_called_times)
         self.assertEqual(1, sources.restart_called_times)
@@ -488,8 +495,9 @@
         caller = MockAptCaller()
         sources = MockSources(["0.1-1", "0.2-1"])
         apt_pkg = MockAptPkg(sources)
-        self.assertEqual(False, provide_with_apt("apackage", "0.2",
-                    "target", _apt_pkg=apt_pkg, _apt_caller=caller.call))
+        self.assertEqual(False, AptSource().get_specific_version(
+            "apackage", "0.2", "target", 
+            _apt_pkg=apt_pkg, _apt_caller=caller.call))
         self.assertEqual(1, apt_pkg.init_called_times)
         self.assertEqual(1, apt_pkg.get_pkg_source_records_called_times)
         self.assertEqual(1, sources.restart_called_times)

=== modified file 'upstream.py'
--- a/upstream.py	2009-07-15 18:36:36 +0000
+++ b/upstream.py	2009-07-26 08:05:34 +0000
@@ -26,120 +26,271 @@
 from debian_bundle.changelog import Version
 
 from bzrlib.export import export
+from bzrlib.revisionspec import RevisionSpec
 from bzrlib.trace import info
 
 from bzrlib.plugins.builddeb.errors import MissingUpstreamTarball
 from bzrlib.plugins.builddeb.import_dsc import DistributionBranch
 from bzrlib.plugins.builddeb.repack_tarball import repack_tarball
-
-
-def get_apt_command_for_source(package, version_str):
-    return 'apt-get source -y --only-source --tar-only %s=%s' % \
-        (package, version_str)
-
-
-def call_apt_for_source(package, version_str, target_dir):
-    command = get_apt_command_for_source(package, version_str)
-    proc = subprocess.Popen(command, shell=True, cwd=target_dir)
-    proc.wait()
-    if proc.returncode != 0:
-        return False
-    return True
-
-
-def provide_with_apt(package, upstream_version, target_dir, _apt_pkg=None,
-        _apt_caller=None):
-    if _apt_pkg is None:
-        import apt_pkg
-    else:
-        apt_pkg = _apt_pkg
-    if _apt_caller is None:
-        _apt_caller = call_apt_for_source
-    apt_pkg.init()
-    sources = apt_pkg.GetPkgSrcRecords()
-    sources.Restart()
-    info("Using apt to look for the upstream tarball.")
-    while sources.Lookup(package):
-        if upstream_version \
-            == Version(sources.Version).upstream_version:
-            if _apt_caller(package, sources.Version, target_dir):
+from bzrlib.plugins.builddeb.util import (
+    get_snapshot_revision,
+    tarball_name,
+    )
+
+
+class UpstreamSource(object):
+    """A source for upstream versions (uscan, get-orig-source, etc)."""
+
+    def get_latest_version(self, package, target_dir):
+        """Fetch the source tarball for the latest available version.
+
+        :param package: Name of the package
+        :param target_dir: Directory in which to store the tarball
+        """
+        raise NotImplemented(self.get_latest_version)
+
+    def get_specific_version(self, package, version, target_dir):
+        """Fetch the source tarball for a particular version.
+
+        :param package: Name of the package
+        :param version: Version string of the version to fetch
+        :param target_dir: Directory in which to store the tarball
+        :return: Boolean indicating whether a tarball was fetched
+        """
+        raise NotImplemented(self.get_specific_version)
+
+    def _tarball_path(self, package, version, target_dir):
+        return os.path.join(target_dir, tarball_name(package, version))
+
+
+class PristineTarSource(UpstreamSource):
+    """Source that uses the pristine-tar revisions in the packaging branch."""
+
+    def __init__(self, tree, branch):
+        self.branch = branch
+        self.tree = tree
+
+    def get_specific_version(self, package, upstream_version, target_dir):
+        target_filename = self._tarball_path(package, upstream_version, 
+                                             target_dir)
+        db = DistributionBranch(self.branch, None, tree=self.tree)
+        if not db.has_upstream_version_in_packaging_branch(upstream_version):
+            return False
+        revid = db._revid_of_upstream_version_from_branch(upstream_version)
+        if not db.has_pristine_tar_delta(revid):
+            return False
+        info("Using pristine-tar to reconstruct the needed tarball.")
+        db.reconstruct_pristine_tar(revid, package, upstream_version,
+                target_filename)
+        return True
+
+
+class AptSource(UpstreamSource):
+    """Upstream source that uses apt-source."""
+
+    def get_specific_version(self, package, upstream_version, target_dir, 
+            _apt_pkg=None, _apt_caller=None):
+        if _apt_pkg is None:
+            import apt_pkg
+        else:
+            apt_pkg = _apt_pkg
+        if _apt_caller is None:
+            _apt_caller = self._run_apt_source
+        apt_pkg.init()
+        sources = apt_pkg.GetPkgSrcRecords()
+        sources.Restart()
+        info("Using apt to look for the upstream tarball.")
+        while sources.Lookup(package):
+            if upstream_version \
+                == Version(sources.Version).upstream_version:
+                if _apt_caller(package, sources.Version, target_dir):
+                    return True
+                break
+        info("apt could not find the needed tarball.")
+        return False
+
+    def _get_command(self, package, version_str):
+        return 'apt-get source -y --only-source --tar-only %s=%s' % \
+            (package, version_str)
+
+    def _run_apt_source(self, package, version_str, target_dir):
+        command = self._get_command(package, version_str)
+        proc = subprocess.Popen(command, shell=True, cwd=target_dir)
+        proc.wait()
+        if proc.returncode != 0:
+            return False
+        return True
+
+
+class UpstreamBranchSource(UpstreamSource):
+    """Upstream source that uses the upstream branch."""
+
+    def __init__(self, upstream_branch, upstream_revision=None, 
+                 fallback_revspec=None):
+        self.upstream_branch = upstream_branch
+        self.upstream_revision = upstream_revision
+        self.fallback_revspec = fallback_revspec
+
+    def _get_revision_id(self, version):
+        if self.upstream_revision is not None:
+            # Explicit revision id to use set
+            return self.upstream_revision
+        revspec = get_snapshot_revision(version)
+        if revspec is None:
+            revspec = self.fallback_revspec
+        if revspec is not None:
+            return RevisionSpec.from_string(
+                revspec).as_revision_id(self.upstream_branch)
+        return self.upstream_branch.last_revision()
+
+    def get_specific_version(self, package, version, target_dir):
+        self.upstream_branch.lock_read()
+        try:
+            revid = self._get_revision_id(version)
+            info("Exporting upstream branch revision %s to create the tarball",
+                 revid)
+            target_filename = self._tarball_path(package, version, target_dir)
+            tarball_base = "%s-%s" % (package, version)
+            rev_tree = self.upstream_branch.repository.revision_tree(revid)
+            export(rev_tree, target_filename, 'tgz', tarball_base)
+            return True
+        finally:
+            self.upstream_branch.unlock()
+
+
+class GetOrigSourceSource(UpstreamSource):
+    """Upstream source that uses the get-orig-source rule in debian/rules."""
+
+    def __init__(self, tree, larstiq):
+        self.tree = tree
+        self.larstiq = larstiq
+
+    def _get_orig_source(self, source_dir, desired_tarball_name,
+                        target_dir):
+        info("Trying to use get-orig-source to retrieve needed tarball.")
+        command = ["/usr/bin/make", "-f", "debian/rules", "get-orig-source"]
+        proc = subprocess.Popen(command, cwd=source_dir)
+        ret = proc.wait()
+        if ret != 0:
+            info("Trying to run get-orig-source rule failed")
+            return False
+        fetched_tarball = os.path.join(source_dir, desired_tarball_name)
+        if not os.path.exists(fetched_tarball):
+            info("get-orig-source did not create %s", desired_tarball_name)
+            return False
+        repack_tarball(fetched_tarball, desired_tarball_name, 
+                       target_dir=target_dir)
+        return True
+
+    def get_specific_version(self, package, version, target_dir):
+        if self.larstiq:
+            rules_name = 'rules'
+        else:
+            rules_name = 'debian/rules'
+        rules_id = self.tree.path2id(rules_name)
+        if rules_id is not None:
+            desired_tarball_name = tarball_name(package, version)
+            tmpdir = tempfile.mkdtemp(prefix="builddeb-get-orig-source-")
+            try:
+                base_export_dir = os.path.join(tmpdir, "export")
+                export_dir = base_export_dir
+                if self.larstiq:
+                    os.mkdir(export_dir)
+                    export_dir = os.path.join(export_dir, "debian")
+                export(self.tree, export_dir, format="dir")
+                return self._get_orig_source(base_export_dir,
+                        desired_tarball_name, target_dir)
+            finally:
+                shutil.rmtree(tmpdir)
+        info("No debian/rules file to try and use for a get-orig-source "
+             "rule")
+        return False
+
+
+class UScanSource(UpstreamSource):
+    """Upstream source that uses uscan."""
+
+    def __init__(self, tree, larstiq):
+        self.tree = tree
+        self.larstiq = larstiq
+
+    def _uscan(self, package, upstream_version, watch_file, target_dir):
+        info("Using uscan to look for the upstream tarball.")
+        r = os.system("uscan --upstream-version %s --force-download --rename "
+                      "--package %s --watchfile %s --check-dirname-level 0 " 
+                      "--download --repack --destdir %s --download-version %s" %
+                      (upstream_version, package, watch_file, target_dir,
+                       upstream_version))
+        if r != 0:
+            info("uscan could not find the needed tarball.")
+            return False
+        return True
+
+    def get_specific_version(self, package, version, target_dir):
+        if self.larstiq:
+            watchfile = 'watch'
+        else:
+            watchfile = 'debian/watch'
+        watch_id = self.tree.path2id(watchfile)
+        if watch_id is None:
+            info("No watch file to use to retrieve upstream tarball.")
+            return False
+        (tmp, tempfilename) = tempfile.mkstemp()
+        try:
+            tmp = os.fdopen(tmp, 'wb')
+            watch = self.tree.get_file_text(watch_id)
+            tmp.write(watch)
+        finally:
+            tmp.close()
+        try:
+            return self._uscan(package, version, tempfilename, 
+                    target_dir)
+        finally:
+          os.unlink(tempfilename)
+
+
+class SelfSplitSource(UpstreamSource):
+
+    def __init__(self, tree):
+        self.tree = tree
+
+    def _split(self, package, upstream_version, target_filename):
+        tmpdir = tempfile.mkdtemp(prefix="builddeb-get-orig-source-")
+        try:
+            export_dir = os.path.join(tmpdir,
+                    "%s-%s" % (package, upstream_version))
+            export(self.tree, export_dir, format="dir")
+            shutil.rmtree(os.path.join(export_dir, "debian"))
+            tar = tarfile.open(target_filename, "w:gz")
+            try:
+                tar.add(export_dir, "%s-%s" % (package, upstream_version))
+            finally:
+                tar.close()
+            return True
+        finally:
+            shutil.rmtree(tmpdir)
+
+    def get_specific_version(self, package, version, target_dir):
+        info("Using the current branch without the 'debian' directory "
+                "to create the tarball")
+        return self._split(package,
+                version, self._tarball_path(package, version, target_dir))
+
+
+class StackedUpstreamSource(UpstreamSource):
+    """An upstream source that checks a list of other upstream sources.
+    
+    The first source that can provide a tarball, wins. 
+    """
+
+    def __init__(self, sources):
+        self._sources = sources
+
+    def get_specific_version(self, package, version, target_dir):
+        for source in self._sources:
+            if source.get_specific_version(package, version, target_dir):
                 return True
-            break
-    info("apt could not find the needed tarball.")
-    return False
-
-
-def provide_with_uscan(package, upstream_version, watch_file, target_dir):
-    info("Using uscan to look for the upstream tarball.")
-    r = os.system("uscan --upstream-version %s --force-download --rename "
-                  "--package %s --watchfile %s --check-dirname-level 0 " 
-                  "--download --repack --destdir %s --download-version %s" %
-                  (upstream_version, package, watch_file, target_dir,
-                   upstream_version))
-    if r != 0:
-        info("uscan could not find the needed tarball.")
-        return False
-    return True
-
-
-def provide_with_pristine_tar(tree, branch, package, version,
-        target_filename):
-    db = DistributionBranch(branch, None, tree=tree)
-    if not db.has_upstream_version_in_packaging_branch(version):
-        return False
-    revid = db._revid_of_upstream_version_from_branch(version)
-    if not db.has_pristine_tar_delta(revid):
-        return False
-    info("Using pristine-tar to reconstruct the needed tarball.")
-    db.reconstruct_pristine_tar(revid, package, version, target_filename)
-    return True
-
-
-def provide_with_get_orig_source(source_dir, desired_tarball_name,
-        target_dir):
-    info("Trying to use get-orig-source to retrieve needed tarball.")
-    command = ["/usr/bin/make", "-f", "debian/rules", "get-orig-source"]
-    proc = subprocess.Popen(command, cwd=source_dir)
-    ret = proc.wait()
-    if ret != 0:
-        info("Trying to run get-orig-source rule failed")
-        return False
-    fetched_tarball = os.path.join(source_dir, desired_tarball_name)
-    if not os.path.exists(fetched_tarball):
-        info("get-orig-source did not create %s"
-                % desired_tarball_name)
-        return False
-    repack_tarball(fetched_tarball, desired_tarball_name,
-                   target_dir=target_dir)
-    return True
-
-
-def provide_from_other_branch(branch, revision, target_filename,
-        tarball_base):
-    branch.lock_read()
-    try:
-        rev_tree = branch.repository.revision_tree(revision)
-        export(rev_tree, target_filename, 'tgz', tarball_base)
-        return True
-    finally:
-        branch.unlock()
-
-
-def provide_by_split(tree, package, upstream_version, target_filename):
-    tmpdir = tempfile.mkdtemp(prefix="builddeb-get-orig-source-")
-    try:
-        export_dir = os.path.join(tmpdir,
-                "%s-%s" % (package, upstream_version))
-        export(tree, export_dir, format="dir")
-        shutil.rmtree(os.path.join(export_dir, "debian"))
-        tar = tarfile.open(target_filename, "w:gz")
-        try:
-            tar.add(export_dir, "%s-%s" % (package, upstream_version))
-        finally:
-            tar.close()
-        return True
-    finally:
-        shutil.rmtree(tmpdir)
+        return False
 
 
 class UpstreamProvider(object):
@@ -167,22 +318,23 @@
         :param allow_split: Whether the provider can provide the tarball
             by exporting the branch and removing the "debian" dir.
         """
-        self.tree = tree
-        self.branch = branch
         self.package = package
         self.version = Version(version)
         self.store_dir = store_dir
-        self.larstiq = larstiq
-        self.upstream_branch = upstream_branch
-        self.upstream_revision = upstream_revision
-        self.allow_split = allow_split
-        # for testing
-        self._apt_provider = provide_with_apt
-        self._uscan_provider = provide_with_uscan
-        self._pristine_provider = provide_with_pristine_tar
-        self._orig_source_provider = provide_with_get_orig_source
-        self._upstream_branch_provider = provide_from_other_branch
-        self._split_provider = provide_by_split
+        sources = [
+            PristineTarSource(tree, branch), 
+            AptSource(),
+            ]
+        if upstream_branch is not None:
+            sources.append(
+                UpstreamBranchSource(upstream_branch, upstream_revision))
+        sources.extend([
+            GetOrigSourceSource(tree, larstiq), 
+            UScanSource(tree, larstiq),
+            ])
+        if allow_split:
+            sources.append(SelfSplitSource(tree))
+        self.source = StackedUpstreamSource(sources)
 
     def provide(self, target_dir):
         """Provide the upstream tarball any way possible.
@@ -215,18 +367,9 @@
         if not self.already_exists_in_store():
             if not os.path.exists(self.store_dir):
                 os.makedirs(self.store_dir)
-            if self.provide_with_pristine_tar(self.store_dir):
-                pass
-            elif self.provide_with_apt(self.store_dir):
-                pass
-            elif self.provide_from_upstream_branch(self.store_dir):
-                pass
-            elif self.provide_with_get_orig_source(self.store_dir):
-                pass
-            elif self.provide_with_uscan(self.store_dir):
-                pass
-            elif self.provide_from_self_by_split(self.store_dir):
-                pass
+            self.source.get_specific_version(self.package, 
+                self.version.upstream_version,
+                target_dir)
         else:
              info("Using the upstream tarball that is present in "
                      "%s" % self.store_dir)
@@ -248,83 +391,8 @@
             return True
         return False
 
-    def provide_with_apt(self, target_dir):
-        return self._apt_provider(self.package, self.version.upstream_version,
-                target_dir)
-
-    def provide_with_uscan(self, target_dir):
-        if self.larstiq:
-            watchfile = 'watch'
-        else:
-            watchfile = 'debian/watch'
-        watch_id = self.tree.path2id(watchfile)
-        if watch_id is None:
-            info("No watch file to use to retrieve upstream tarball.")
-            return False
-        (tmp, tempfilename) = tempfile.mkstemp()
-        try:
-            tmp = os.fdopen(tmp, 'wb')
-            watch = self.tree.get_file_text(watch_id)
-            tmp.write(watch)
-        finally:
-            tmp.close()
-        try:
-            return self._uscan_provider(self.package,
-                    self.version.upstream_version, tempfilename, target_dir)
-        finally:
-          os.unlink(tempfilename)
-
-    def provide_with_pristine_tar(self, target_dir):
-        target_filename = os.path.join(target_dir, self._tarball_name())
-        return self._pristine_provider(self.tree, self.branch, self.package,
-                self.version.upstream_version, target_filename)
-
-    def provide_with_get_orig_source(self, target_dir):
-        if self.larstiq:
-            rules_name = 'rules'
-        else:
-            rules_name = 'debian/rules'
-        rules_id = self.tree.path2id(rules_name)
-        if rules_id is not None:
-            desired_tarball_name = self._tarball_name()
-            tmpdir = tempfile.mkdtemp(prefix="builddeb-get-orig-source-")
-            try:
-                base_export_dir = os.path.join(tmpdir, "export")
-                export_dir = base_export_dir
-                if self.larstiq:
-                    os.mkdir(export_dir)
-                    export_dir = os.path.join(export_dir, "debian")
-                export(self.tree, export_dir, format="dir")
-                return self._orig_source_provider(base_export_dir,
-                        desired_tarball_name, target_dir)
-            finally:
-                shutil.rmtree(tmpdir)
-        info("No debian/rules file to try and use for a get-orig-source "
-             "rule")
-        return False
-
     def _tarball_name(self):
-        return "%s_%s.orig.tar.gz" % (self.package,
-                self.version.upstream_version)
-
-    def provide_from_upstream_branch(self, target_dir):
-        if self.upstream_branch is None:
-            return False
-        assert self.upstream_revision is not None
-        info("Exporting the upstream branch to create the tarball")
-        target_filename = os.path.join(target_dir, self._tarball_name())
-        tarball_base = "%s-%s" % (self.package, self.version.upstream_version)
-        return self._upstream_branch_provider(self.upstream_branch,
-                self.upstream_revision, target_filename, tarball_base)
-
-    def provide_from_self_by_split(self, target_dir):
-        if not self.allow_split:
-            return False
-        info("Using the current branch without the 'debian' directory "
-                "to create the tarball")
-        target_filename = os.path.join(target_dir, self._tarball_name())
-        return self._split_provider(self.tree, self.package,
-                self.version.upstream_version, target_filename)
+        return tarball_name(self.package, self.version.upstream_version)
 
 
 class _MissingUpstreamProvider(UpstreamProvider):
@@ -348,6 +416,7 @@
         f.write("I am a tarball, honest\n")
         f.close()
 
+
 class _SimpleUpstreamProvider(UpstreamProvider):
     """For tests"""
 



More information about the Pkg-bazaar-commits mailing list