rpm: support guessing spec file from git treeish
authorMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Fri, 6 Sep 2013 13:07:08 +0000 (16:07 +0300)
committerMarkus Lehtonen <markus.lehtonen@linux.intel.com>
Thu, 5 Jun 2014 11:20:07 +0000 (14:20 +0300)
Signed-off-by: Markus Lehtonen <markus.lehtonen@linux.intel.com>
gbp/rpm/__init__.py
gbp/scripts/import_orig_rpm.py
tests/test_rpm.py

index 8bbab70..7aa7ba4 100644 (file)
@@ -768,44 +768,66 @@ def parse_srpm(srpmfile):
     return srcrpm
 
 
-def guess_spec(topdir, recursive=True, preferred_name=None):
-    """Guess a spec file"""
+def guess_spec_fn(file_list, preferred_name=None):
+    """Guess spec file from a list of filenames"""
     specs = []
-    abstop = os.path.abspath(topdir)
-    for (root, dirs, files) in os.walk(abstop):
-        for f in files:
-            # Stop at the first file matching the preferred name
-            if f == preferred_name:
-                gbp.log.debug("Found a preferred spec file: %s in %s" % (f, root))
-                specs = [os.path.join(root,f)]
-                recursive = False
-                break
-            if f.endswith(".spec"):
-                gbp.log.debug("Found spec file: %s in %s" % (f, root))
-                specs.append(os.path.join(root,f))
+    for filepath in file_list:
+        filename = os.path.basename(filepath)
+        # Stop at the first file matching the preferred name
+        if filename == preferred_name:
+            gbp.log.debug("Found a preferred spec file %s" % filepath)
+            specs = [filepath]
+            break
+        if filename.endswith(".spec"):
+            gbp.log.debug("Found spec file %s" % filepath)
+            specs.append(filepath)
+    if len(specs) == 0:
+        raise NoSpecError("No spec file found.")
+    elif len(specs) > 1:
+        raise NoSpecError("Multiple spec files found (%s), don't know which "
+                          "to use." % ', '.join(specs))
+    return specs[0]
+
 
+def guess_spec(topdir, recursive=True, preferred_name=None):
+    """Guess a spec file"""
+    file_list = []
+    if not topdir:
+        topdir = '.'
+    for root, dirs, files in os.walk(topdir):
+        file_list.extend([os.path.join(root, fname) for fname in files])
         if not recursive:
             del dirs[:]
         # Skip .git dir in any case
         if '.git' in dirs:
             dirs.remove('.git')
-
-    if len(specs) == 0:
-        raise NoSpecError("No spec file found.")
-    elif len(specs) > 1:
-        filenames = [os.path.relpath(spec, abstop) for spec in specs]
-        raise NoSpecError("Multiple spec files found (%s), don't know which "
-                          "to use." % ', '.join(filenames))
-    return SpecFile(specs[0])
+    return SpecFile(os.path.abspath(guess_spec_fn(file_list, preferred_name)))
 
 
-def guess_spec_repo(repo, branch, packaging_dir):
+def guess_spec_repo(repo, treeish, topdir='', recursive=True, preferred_name=None):
     """
-    @todo: implement this
-    Try to find/parse the spec file from given branch in the git
-    repository.
+    Try to find/parse the spec file from a given git treeish.
     """
-    raise NoSpecError, "Searching spec from other branch not implemented yet"
+    topdir = topdir.rstrip('/') + ('/') if topdir else ''
+    try:
+        file_list = [nam for (mod, typ, sha, nam) in
+                    repo.list_tree(treeish, recursive, topdir) if typ == 'blob']
+    except GitRepositoryError as err:
+        raise NoSpecError("Cannot find spec file from treeish %s, Git error: %s"
+                            % (treeish, err))
+    spec_path = guess_spec_fn(file_list, preferred_name)
+    return spec_from_repo(repo, treeish, spec_path)
+
+
+def spec_from_repo(repo, treeish, spec_path):
+    """Get and parse a spec file from a give Git treeish"""
+    try:
+        spec = SpecFile(filedata=repo.show('%s:%s' % (treeish, spec_path)))
+        spec.specdir = os.path.dirname(spec_path)
+        spec.specfile = os.path.basename(spec_path)
+        return spec
+    except GitRepositoryError as err:
+        raise NoSpecError("Git error: %s" % err)
 
 
 def string_to_int(val_str):
index b208ad1..8eacfb2 100755 (executable)
@@ -58,7 +58,7 @@ def detect_name_and_version(repo, source, options):
             # we're not on the packaging-branch (but upstream, for
             # example).
             spec = guess_spec_repo(repo, options.packaging_branch,
-                                   options.packaging_dir)
+                                   options.packaging_dir, True, preferred_fn)
             sourcepackage = spec.name
         except NoSpecError:
             if options.interactive:
index 47aaf7f..69ab85b 100644 (file)
@@ -23,7 +23,9 @@ import tempfile
 from nose.tools import assert_raises
 
 from gbp.errors import GbpError
-from gbp.rpm import SrcRpmFile, SpecFile, parse_srpm, guess_spec, NoSpecError
+from gbp.rpm import (SrcRpmFile, SpecFile, parse_srpm, NoSpecError, guess_spec,
+                     guess_spec_repo, spec_from_repo)
+from gbp.git.repository import GitRepository
 
 DATA_DIR = os.path.abspath(os.path.splitext(__file__)[0] + '_data')
 SRPM_DIR = os.path.join(DATA_DIR, 'srpms')
@@ -321,6 +323,11 @@ class TestSpecFile(object):
 
 class TestUtilityFunctions(object):
     """Test utility functions of L{gbp.rpm}"""
+    def setup(self):
+        self.tmpdir = tempfile.mkdtemp(prefix='gbp_%s_' % __name__, dir='.')
+
+    def teardown(self):
+        shutil.rmtree(self.tmpdir)
 
     def test_parse_srpm(self):
         """Test parse_srpm() function"""
@@ -346,4 +353,36 @@ class TestUtilityFunctions(object):
         assert spec.specfile == 'gbp-test2.spec'
         assert spec.specdir == SPEC_DIR
 
+    def test_guess_spec_repo(self):
+        """Test guess_spec_repo() and spec_from_repo() functions"""
+        # Create dummy repository with some commits
+        repo = GitRepository.create(self.tmpdir)
+        with open(os.path.join(repo.path, 'foo.txt'), 'w') as fobj:
+            fobj.write('bar\n')
+        repo.add_files('foo.txt')
+        repo.commit_all('Add dummy file')
+        os.mkdir(os.path.join(repo.path, 'packaging'))
+        shutil.copy(os.path.join(SPEC_DIR, 'gbp-test.spec'),
+                    os.path.join(repo.path, 'packaging'))
+        repo.add_files('packaging/gbp-test.spec')
+        repo.commit_all('Add spec file')
+
+        # Spec not found
+        with assert_raises(NoSpecError):
+            guess_spec_repo(repo, 'HEAD~1', recursive=True)
+        with assert_raises(NoSpecError):
+            guess_spec_repo(repo, 'HEAD', recursive=False)
+        # Spec found
+        spec = guess_spec_repo(repo, 'HEAD', 'packaging', recursive=False)
+        spec = guess_spec_repo(repo, 'HEAD', recursive=True)
+        assert spec.specfile == 'gbp-test.spec'
+        assert spec.specdir == 'packaging'
+        assert spec.specpath == 'packaging/gbp-test.spec'
+
+        # Test spec_from_repo()
+        with assert_raises(NoSpecError):
+            spec_from_repo(repo, 'HEAD~1', 'packaging/gbp-test.spec')
+        spec = spec_from_repo(repo, 'HEAD', 'packaging/gbp-test.spec')
+        assert spec.specfile == 'gbp-test.spec'
+
 # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: