Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package obs-scm-bridge for openSUSE:Factory 
checked in at 2025-05-26 18:34:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/obs-scm-bridge (Old)
 and      /work/SRC/openSUSE:Factory/.obs-scm-bridge.new.2732 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "obs-scm-bridge"

Mon May 26 18:34:25 2025 rev:19 rq:1279572 version:0.7.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/obs-scm-bridge/obs-scm-bridge.changes    
2025-05-13 20:08:35.902718292 +0200
+++ /work/SRC/openSUSE:Factory/.obs-scm-bridge.new.2732/obs-scm-bridge.changes  
2025-05-26 18:36:08.828964436 +0200
@@ -1,0 +2,8 @@
+Fri May 23 14:30:39 UTC 2025 - Adrian Schröter <adr...@suse.de>
+
+- 0.7.0
+  * supporting _manifest file as successor of _subdirs
+  * record configured branch of submodules in package scmsync url
+  * stay on the configured branch of a submodule on checkout
+
+-------------------------------------------------------------------

Old:
----
  obs-scm-bridge-0.6.3.obscpio

New:
----
  obs-scm-bridge-0.7.0.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ obs-scm-bridge.spec ++++++
--- /var/tmp/diff_new_pack.sSfnvH/_old  2025-05-26 18:36:09.689000690 +0200
+++ /var/tmp/diff_new_pack.sSfnvH/_new  2025-05-26 18:36:09.693000859 +0200
@@ -22,7 +22,7 @@
 %define build_pkg_name build
 %endif
 Name:           obs-scm-bridge
-Version:        0.6.3
+Version:        0.7.0
 Release:        0
 Summary:        A help service to work with git repositories in OBS
 License:        GPL-2.0-or-later

++++++ _service ++++++
--- /var/tmp/diff_new_pack.sSfnvH/_old  2025-05-26 18:36:09.721002039 +0200
+++ /var/tmp/diff_new_pack.sSfnvH/_new  2025-05-26 18:36:09.725002208 +0200
@@ -2,8 +2,8 @@
   <service name="obs_scm" mode="manual">
     <param name="url">https://github.com/openSUSE/obs-scm-bridge</param>
     <param name="scm">git</param>
-    <param name="revision">0.6.3</param>
-    <param name="version">0.6.3</param>
+    <param name="revision">0.7.0</param>
+    <param name="version">0.7.0</param>
   </service>
   <service mode="manual" name="set_version" />
 

++++++ obs-scm-bridge-0.6.3.obscpio -> obs-scm-bridge-0.7.0.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/obs-scm-bridge-0.6.3/README.md 
new/obs-scm-bridge-0.7.0/README.md
--- old/obs-scm-bridge-0.6.3/README.md  2025-05-13 14:39:58.000000000 +0200
+++ new/obs-scm-bridge-0.7.0/README.md  2025-05-23 13:03:23.000000000 +0200
@@ -66,6 +66,9 @@
 
  * noobsinfo=1 do not write a `_scmsync.obsinfo` file
 
+ * trackingbranch=BRANCH may be used to clone the branch instead of a revision.
+                         information is taken from .gitmodules if available.
+
 Special directives for entire projects
 ======================================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/obs-scm-bridge-0.6.3/obs_scm_bridge 
new/obs-scm-bridge-0.7.0/obs_scm_bridge
--- old/obs-scm-bridge-0.6.3/obs_scm_bridge     2025-05-13 14:39:58.000000000 
+0200
+++ new/obs-scm-bridge-0.7.0/obs_scm_bridge     2025-05-23 13:03:23.000000000 
+0200
@@ -30,6 +30,7 @@
 credentials_config = "/etc/obs/services/scm-bridge/credentials"
 export_debian_orig_from_git = '/usr/lib/build/export_debian_orig_from_git'
 pack_directories = False
+follow_tracking_branch = False
 get_assets = False
 shallow_clone = True
 create_obsinfo = False
@@ -50,6 +51,7 @@
     shallow_clone = False
     create_obsinfo = False
     rewrite_url_to_ssh = True
+    follow_tracking_branch = True
 os.environ['LANG'] = "C"
 
 class ObsGit(object):
@@ -60,6 +62,7 @@
         self.outdir   = outdir
         self.clonedir = None
         self.revision = None
+        self.trackingbranch = None
         self.subdir   = None
         self.projectscmsync = projectscmsync
         self.keep_meta = False
@@ -77,6 +80,8 @@
         self.add_noobsinfo = False
         #: git submodule config, if present
         self.gsmconfig: Optional[configparser.ConfigParser] = None
+        self.gsmpath = {}
+        self.gsmrevisions = {}
 
         query = urllib.parse.parse_qs(self.url[4], keep_blank_values=True)
         if "subdir" in query:
@@ -109,6 +114,10 @@
             self.create_obsinfo = False
             del query['noobsinfo']
             self.url[4] = urllib.parse.urlencode(query, doseq=True)
+        if 'trackingbranch' in query:
+            self.trackingbranch = query['trackingbranch'][0]
+            del query['trackingbranch']
+            self.url[4] = urllib.parse.urlencode(query, doseq=True)
         if self.url[5]:
             self.revision = self.url[5]
             self.url[5] = ''
@@ -234,12 +243,12 @@
 
     def verify_branch(self, branch:str) -> None:
         if branch.startswith('-'):
-            self.die(f"illegel branch/commit '{branch}'")
+            self.die(f"illegal branch/commit '{branch}'")
             sys.exit(1)
 
     def verify_subdir(self, subdir:str) -> None:
         if subdir.startswith('-'):
-            self.die(f"illegel sub-directory '{subdir}'")
+            self.die(f"illegal sub-directory '{subdir}'")
 
     def verify_scmurl(self, scmurl:str) -> None:
         if testcase_mode and scmurl.startswith('file://'):
@@ -296,28 +305,42 @@
         self.verify_scmurl(self.scmtoolurl)
         if self.revision:
             self.verify_branch(self.revision)
+        if self.trackingbranch:
+            self.verify_branch(self.trackingbranch)
         if self.subdir:
             self.verify_subdir(self.subdir)
+        branch = self.revision
+        reset_to_commit = None
         if self.revision and re.match(r"^[0-9a-fA-F]{40,}$", self.revision):
-            self.do_clone_commit(outdir, include_submodules=include_submodules)
-            return
+            if follow_tracking_branch:
+                branch = self.trackingbranch
+                reset_to_commit = self.revision
+            else:
+                self.do_clone_commit(outdir, 
include_submodules=include_submodules)
+                return
         cmd = [ 'git', 'clone', self.scmtoolurl, outdir ]
         if include_submodules:
             if self.subdir:
                cmd += [ "--recurse-submodules=" + self.subdir ]
             else:
                cmd += [ '--recurse-submodules' ]
-        if self.shallow_clone:
+        if self.shallow_clone and not reset_to_commit:
             cmd += [ '--depth', '1' ]
         if self.subdir:
-            cmd += [ '--filter=blob:none', '--no-checkout' ]
-        if self.revision:
+            cmd += [ '--filter=blob:none' ]
+        if self.subdir or reset_to_commit:
+            cmd += [ '--no-checkout' ]
+        if branch:
             cmd.insert(2, '-b')
-            cmd.insert(3, self.revision)
+            cmd.insert(3, branch)
         env = {"GIT_LFS_SKIP_SMUDGE": "1", **os.environ} if self.no_lfs else 
None
         self.run_cmd(cmd, fatal="git clone", env=env)
+        if reset_to_commit:
+            cmd = [ 'git', '-C', outdir, 'reset', '--soft', reset_to_commit ]
+            self.run_cmd(cmd, fatal="git reset", env=env)
         if self.subdir:
             self.do_set_sparse_checkout(outdir)
+        if self.subdir or reset_to_commit:
             self.do_checkout(outdir, 'HEAD', 
include_submodules=include_submodules)
 
     # the _scmsync.obsinfo file might become obsolete again when we store 
entire
@@ -537,17 +560,36 @@
                 revisions[lstree[3]] = lstree[2]
         return revisions
 
-    def process_package_submodule(self, gsmsection: configparser.SectionProxy, 
name: str, revision: str) -> None:
+    def process_package_submodule(self, name: str, subdir: str) -> None:
         if not self._REGEXP.match(name):
             logging.warn("submodule name contains invalid char: %s", name)
             return
 
-        path = gsmsection['path']
+        section = self.gsmpath[subdir + name]
+        if not section:
+            logging.warn("submodule not configured for %s", subdir + name)
+            return
+        gsmsection = self.gsmconfig[section]
+
         urlstr = gsmsection['url']
+        if not urlstr:
+            self.die(f"url not defined for submodule {section}")
+
+        revisions = self.gsmrevisions.get(subdir)
+        if not revisions:
+            revisions = self.gsmrevisions[subdir] = 
self.list_submodule_revisions(subdir)
+
+        revision = revisions.get(gsmsection['path'])
+        if not revision:
+            self.die(f"could not determine revision of submodule for 
{gsmsection['path']}")
 
         # write xml file and register the module
         url = list(urllib.parse.urlparse(urlstr))
         url[5] = revision
+        if 'branch' in gsmsection:
+            query = urllib.parse.parse_qs(url[4], keep_blank_values=True);
+            query['trackingbranch'] = [gsmsection['branch']]
+            url[4] = urllib.parse.urlencode(query, doseq=True)
         if self.arch:
             query = urllib.parse.parse_qs(url[4], keep_blank_values=True);
             query['arch'] = self.arch
@@ -609,6 +651,22 @@
             return
         self.write_package_xml_local_link(name, target)
 
+    def parse_gsmconfig(self):
+        self.gsmconfig = configparser.ConfigParser()
+        self.gsmconfig.read(self.clonedir + '/.gitmodules')
+        gsmpath = {}
+        for section in self.gsmconfig.sections():
+            gsmconfig = self.gsmconfig[section]
+            if not 'path' in gsmconfig:
+                logging.warn("path not defined for git submodule " + section)
+                continue
+            path = gsmconfig['path']
+            if path in gsmpath:
+                logging.warn("multiple definitions of %s path in git submodule 
config", path)
+                continue
+            gsmpath[path] = section
+        self.gsmpath = gsmpath
+
     def generate_project_files(self) -> None:
         clonedir = tempfile.mkdtemp(prefix="obs-scm-bridge")
         self.clonedir = clonedir
@@ -622,37 +680,46 @@
         os.chdir(self.outdir)
         subdir = self.subdir + '/' if self.subdir else ''
         if os.path.isfile(clonedir + '/.gitmodules'):
-            self.gsmconfig = configparser.ConfigParser()
-            self.gsmconfig.read(clonedir + '/.gitmodules')
+            self.parse_gsmconfig()
         self.generate_package_xml_files_of_directory(subdir)
         shutil.rmtree(clonedir)
         self.clonedir = None
 
-    def generate_package_xml_files_of_directory_submodules(self, subdir) -> 
None:
-        revisions = None
-        for section in self.gsmconfig.sections():
-            gsmconfig = self.gsmconfig[section]
-            if not 'path' in gsmconfig:
-                logging.warn("path not defined for git submodule " + section)
-                continue
-            name = gsmconfig['path']
-            if subdir:
-                if not name.startswith(subdir):
-                     continue
-                name = name.removeprefix(subdir)
-            if '/' in name:
-                continue
-            if name in self.processed:
-                continue                # already handled
-            if not 'url' in gsmconfig:
-                self.die(f"url not defined for submodule {section}")
-            if not revisions:
-                revisions = self.list_submodule_revisions(subdir)
-            revision = revisions.get(gsmconfig['path'], None)
-            if not revision:
-                self.die("could not determine revision of submodule for 
{gsmconfig['path']}")
-            self.process_package_submodule(gsmconfig, name, revision)
-            self.processed[name] = True
+    def read_project_manifest(self, filename):
+        packages = None
+        subdirectories = []
+        manifest_yml = None
+        with open(filename) as stream:
+            manifest_yml = yaml.safe_load(stream)
+        if 'packages' in manifest_yml:
+            packages = []
+        if manifest_yml.get('packages'):
+            for name in manifest_yml['packages']:
+                if not name or name.startswith('.') or name.startswith('/'):
+                    logging.warn("illegal packages entry '%s'", name)
+                    continue
+                if '/' in name or '*' in name: # for now
+                    logging.warn("packages entry with '/' or '*' not 
implemented yet")
+                    continue
+                packages.append(name)
+        if manifest_yml.get('subdirectories'):
+            for newsubdir in manifest_yml['subdirectories']:
+                if newsubdir:
+                    subdirectories.append(newsubdir)
+        return packages, subdirectories
+
+    def read_project_subdirs(self, filename):
+        packages = None
+        subdirectories = []
+        subdir_yml = None
+        with open(filename) as stream:
+            subdir_yml = yaml.safe_load(stream)
+        for newsubdir in subdir_yml['subdirs']:
+            if newsubdir:
+                subdirectories.append(newsubdir)
+        if 'toplevel' not in subdir_yml or subdir_yml['toplevel'] != 'include':
+            packages = []
+        return packages, subdirectories
 
     def generate_package_xml_files_of_directory(self, subdir) -> None:
         if subdir:
@@ -665,28 +732,27 @@
             shutil.move(directory + '/_config', '.')
             self.processed['_config'] = True
 
-        if os.path.isfile(directory + '/_subdirs'):
-            subdir_yml = None
-            with open(directory + '/_subdirs') as stream:
-                subdir_yml = yaml.safe_load(stream)
-            for newsubdir in subdir_yml['subdirs']:
-                if not newsubdir:
-                    continue
-                if (subdir + newsubdir + '/') in self.processed:
-                    continue
-                self.processed[subdir + newsubdir + '/'] = True
-                self.generate_package_xml_files_of_directory(subdir + 
newsubdir + '/')
-            if 'toplevel' not in subdir_yml or subdir_yml['toplevel'] != 
'include':
-                return
+        packages = None
+        subdirectories = []
 
-        # process all submodules in this directory
-        if self.gsmconfig:
-            self.generate_package_xml_files_of_directory_submodules(subdir)
+        if os.path.isfile(directory + '/_manifest'):
+            (packages, subdirectories) = self.read_project_manifest(directory 
+ '/_manifest')
+        elif os.path.isfile(directory + '/_subdirs'):
+            (packages, subdirectories) = self.read_project_subdirs(directory + 
'/_subdirs')
+
+        # handle all subdirectories
+        for newsubdir in subdirectories:
+            if (subdir + newsubdir + '/') in self.processed:
+                continue
+            self.processed[subdir + newsubdir + '/'] = True
+            self.generate_package_xml_files_of_directory(subdir + newsubdir + 
'/')
+
+        if packages is None:
+            logging.debug("walk via %s", directory)
+            packages = sorted(os.listdir(directory))
 
         # handle plain files and directories
-        logging.debug("walk via %s", directory)
-        listing = sorted(os.listdir(directory))
-        for name in listing:
+        for name in packages:
             if name in self.processed:
                 continue                # already handled
             fname = directory + '/' + name
@@ -697,7 +763,7 @@
             elif os.path.islink(fname):
                 target = os.readlink(fname).rstrip('/') # this is no recursive 
lookup, but is there a usecase?
                 if not target or '/' in target or target.startswith('.'):
-                    logging.warn("only local links are supported, skipping: " 
+ name)
+                    logging.warn("only local links are supported, skipping: %s 
-> %s", name, target)
                     continue
                 if not os.path.isdir(directory + '/' + target):
                     logging.debug("skipping dangling symlink %s -> %s", name, 
target)
@@ -707,7 +773,10 @@
             elif os.path.isdir(fname):
                 if (subdir + name + '/') in self.processed:
                     continue            # already handled in _subdir loop
-                self.process_package_subdirectory(name, subdir)
+                if (subdir + name) in self.gsmpath:
+                    self.process_package_submodule(name, subdir)
+                else:
+                    self.process_package_subdirectory(name, subdir)
                 self.processed[name] = True
 
 if __name__ == '__main__':

++++++ obs-scm-bridge.obsinfo ++++++
--- /var/tmp/diff_new_pack.sSfnvH/_old  2025-05-26 18:36:09.881008785 +0200
+++ /var/tmp/diff_new_pack.sSfnvH/_new  2025-05-26 18:36:09.889009122 +0200
@@ -1,5 +1,5 @@
 name: obs-scm-bridge
-version: 0.6.3
-mtime: 1747139998
-commit: f51c5818e939ae854b41f66d7cd38ddccc4a6791
+version: 0.7.0
+mtime: 1747998203
+commit: 0a33be1d0808ab7e3a358a31fd2541fa3b128cbb
 

Reply via email to