[bitbake-devel,2/2] perforce: add local path handling SRC_URI options

Submitted by Alexandru N. Onea on June 21, 2020, 5:55 p.m. | Patch ID: 173752

Details

Message ID 20200621175530.894393-2-onea.alex@gmail.com
State Master Next
Commit 436ed2ed712a54110ec68ac85c5a74c57563f6d8
Headers show

Commit Message

Alexandru N. Onea June 21, 2020, 5:55 p.m.
This patch implements three new SRC_URI options for the perforce
fetcher, namely:

* module
* destdir
* remotepath

The options are intended to provide the user more control over the
downloaded file paths. The module and remotepath options allow the user
to specify how much of the remote path should be preserved locally. The
destdir option provides a mechanism for grouping and separating
downloads in case of multiple perforce entries in SRC_URI.

The changes in this patch are backwards compatible, i.e. if none of the
introduced options is specified, the default (old) behavior is enforced.

Signed-off-by: Alexandru N. Onea <onea.alex@gmail.com>
---
 lib/bb/fetch2/perforce.py | 55 +++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/lib/bb/fetch2/perforce.py b/lib/bb/fetch2/perforce.py
index 83128cde..3237b038 100644
--- a/lib/bb/fetch2/perforce.py
+++ b/lib/bb/fetch2/perforce.py
@@ -1,6 +1,25 @@ 
 """
 BitBake 'Fetch' implementation for perforce
 
+Supported SRC_URI options are:
+
+- module
+   The top-level location to fetch while preserving the remote paths
+
+   The value of module can point to either a directory or a file. The result,
+   in both cases, is that the fetcher will preserve all file paths starting
+   from the module path. That is, the top-level directory in the module value
+   will also be the top-level directory in P4DIR.
+
+- destdir
+   An additional path element to be prefixed to the final file paths, for each
+   file in the download, helping with grouping files in case of multiple
+   SRC_URI perforce entries.
+
+- remotepath
+   If the value "keep" is given, the full depot location of each file is
+   preserved in P4DIR. This option overrides the effect of the module option.
+
 """
 
 # Copyright (C) 2003, 2004  Chris Larson
@@ -88,12 +107,31 @@  class Perforce(FetchMethod):
             logger.debug(1, 'Determined P4PORT to be: %s' % ud.host)
             if not ud.host:
                 raise FetchError('Could not determine P4PORT from P4CONFIG')
-	
+
+        # Fetcher options
+        ud.module = ud.parm.get('module')
+        ud.keepremotepath = (ud.parm.get('remotepath', '') == 'keep')
+        ud.destdir = ud.parm.get('destdir', '')
+
         if ud.path.find('/...') >= 0:
             ud.pathisdir = True
         else:
             ud.pathisdir = False
 
+        # Avoid using the "/..." syntax in SRC_URI when a module value is given
+        if ud.pathisdir and ud.module:
+            raise FetchError('SRC_URI depot path cannot not end in /... when a module value is given')
+
+        # Avoid destdir values which don't reference a single directory
+        if ud.destdir.find('/') >= 0:
+            raise FetchError('destdir cannot contain /')
+
+        # Merge the path and module into the final depot location
+        if ud.module:
+            if ud.module.find('/') == 0:
+                raise FetchError('module cannot begin with /')
+            ud.path = os.path.join(ud.path, ud.module)
+
         cleanedpath = ud.path.replace('/...', '').replace('/', '.')
         cleanedhost = ud.host.replace(':', '.')
         ud.pkgdir = os.path.join(ud.dldir, cleanedhost, cleanedpath)
@@ -125,10 +163,23 @@  class Perforce(FetchMethod):
             pathnrev = '%s' % (ud.path)
 
         if depot_filename:
-            if ud.pathisdir: # Remove leading path to obtain filename
+            if ud.keepremotepath:
+                # preserve everything (the leading // is removed below)
+                filename = depot_filename
+            elif ud.module:
+                # remove everything up to the module path
+                modulepath = ud.module.rstrip('/...')
+                filename = depot_filename[depot_filename.rfind(modulepath):]
+            elif ud.pathisdir:
+                # Remove leading (visible) path to obtain the filepath
                 filename = depot_filename[len(ud.path)-1:]
             else:
+                # Remove everything, except the filename
                 filename = depot_filename[depot_filename.rfind('/'):]
+
+            # Prepend destdir to the final file path, also remove leading //
+            filename = os.path.join(ud.destdir, filename.lstrip('/'))
+
             filename = filename[:filename.find('#')] # Remove trailing '#rev'
 
         if command == 'changes':