From 92bcc48f97de2a66d5d2f9d8e5f6ef1c75e96708 Mon Sep 17 00:00:00 2001
From: Uggla <uggla@free.fr>
Date: Sat, 27 Feb 2016 10:21:03 +0100
Subject: [PATCH] Fix installation of data_files

1- Get target prefix
2- if prefix == '/usr' --> Force configuration file location to /etc
3- else --> set file location relative to the prefix
   ex : prefix/bin, prefix/share, prefix/etc
4- Update conf file content with the template path location
5- Update script file content with version and configuration file
   location
---
 redfish-client/etc/redfish-client.conf |   2 +-
 redfish/__init__.py                    |   2 +-
 requirements.txt                       |   4 +-
 setup.cfg                              |   7 +-
 setup.py                               | 203 ++++++++++++++++++++++++-
 5 files changed, 204 insertions(+), 14 deletions(-)

diff --git a/redfish-client/etc/redfish-client.conf b/redfish-client/etc/redfish-client.conf
index 89cd47b..b00df1e 100644
--- a/redfish-client/etc/redfish-client.conf
+++ b/redfish-client/etc/redfish-client.conf
@@ -1,2 +1,2 @@
 [redfish-client]
-templates_path = /usr/share/redfish-client/templates
+templates_path = PBTEMPLATEPATH
diff --git a/redfish/__init__.py b/redfish/__init__.py
index ce09d8f..0a6657b 100644
--- a/redfish/__init__.py
+++ b/redfish/__init__.py
@@ -18,7 +18,7 @@ from redfish.main import *
 #import redfish.types
 
 try:
-    __version__ = pbr.version.VersionInfo('redfish').version_string()
+    __version__ = pbr.version.VersionInfo('redfish').release_string()
 except Exception, e:
     if "Versioning for this project requires either an sdist tarball" in e.message:
         pass
diff --git a/requirements.txt b/requirements.txt
index 6eecbba..fec375e 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,9 +2,7 @@
 # of appearance. Changing the order has an impact on the overall integration
 # process, which may cause wedges in the gate later.
 
-pbr>=0.6,!=0.7,<1.0
-#oslo.log>=1.0,<2.0
-Babel>=1.3
+pbr>=0.8
 tortilla>=0.4.1
 Jinja2>=2.7.3
 Sphinx>=1.2.3
diff --git a/setup.cfg b/setup.cfg
index 08fbfd6..3ceb164 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -27,10 +27,9 @@ packages =
 scripts =
 	redfish-client/redfish-client
 
-data_files =
-	usr/share/redfish-client/templates = redfish-client/templates/*
-	etc/ = redfish-client/etc/*
-
+[data_files_helper]
+conf = 'redfish-client/etc/redfish-client.conf', 'etc'
+templates = 'redfish-client/templates/*', 'share/redfish-client/templates'
 
 [build_sphinx]
 source-dir = doc/source
diff --git a/setup.py b/setup.py
index 7363757..ee366de 100755
--- a/setup.py
+++ b/setup.py
@@ -1,21 +1,28 @@
 #!/usr/bin/env python
-# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
+# Licensed under the Apache License, Version 2.0 (the 'License');
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
 #    http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
+# distributed under the License is distributed on an 'AS IS' BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 # implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
 # THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
+import os
+import sys
+import fileinput
+import re
+import pprint
+import distutils
+import ConfigParser
 import setuptools
+from setuptools import Distribution
+from setuptools.command.install import install
 
 # In python < 2.7.4, a lazy loading of package `pbr` will break
 # setuptools if some other modules registered functions in `atexit`.
@@ -25,6 +32,192 @@ try:
 except ImportError:
     pass
 
+
+class OnlyGetScriptPath(install):
+    '''Extend setuptools install class and replace run method to go through
+    setuptool installation and retrieve the script path
+    '''
+    def run(self):
+        # does not call install.run() by design
+        self.distribution.install_scripts = self.install_scripts
+
+
+class DataFilesHelper():
+    '''Class to help manage data files'''
+    def __init__(self):
+        '''Read setup.cfg and build the required data'''
+        self.data = {}
+        self.setupstruc = []
+        config = ConfigParser.ConfigParser()
+        config.read('setup.cfg')
+        for datafile in config.options('data_files_helper'):
+            src, dst = config.get('data_files_helper', datafile).split(',')
+            src = self.refinesrc(src)
+            dst = self.refinedst(dst)
+            self.data[datafile] = {'src': src,
+                                   'dst': dst,
+                                   'fdst': self.calculatedst(src, dst)}
+            self.update_setupstruc(src, dst)
+        try:
+            # Create an entry for scripts if available
+            src = config.get('files', 'scripts').split('\n')
+            src = [self.refinesrc(file)[0] for file in src if file]
+            self.data['script'] = {'src': src,
+                                   'dst': 'bin',
+                                   'fdst': self.calculatedst(src, 'bin')}
+        except ConfigParser.NoOptionError:
+            pass
+        pp = pprint.PrettyPrinter(indent=4)
+        pp.pprint(self.data)
+
+    def trim(self, string):
+        string = string.strip()
+        string = string.strip("'")
+        string = string.strip('"')
+        return(string)
+
+    def refinesrc(self, file):
+        '''Refine source:
+           Expend source file if needed
+
+        :param file: source files
+        :type file: string
+        :returns: source files refined
+        :rtype: list
+        '''
+        file = self.trim(file)
+        if(file.endswith('/*')):
+            return(self.getfiles(file.replace('/*', '')))
+        else:
+            return([file])
+
+    def refinedst(self, file):
+        '''Refine destination:
+           Check if destination needs an exception
+
+        :param file: destination
+        :type path: string
+        :returns: destination refined
+        :rtype: string
+        '''
+        file = self.trim(file)
+        if('etc' in file and self.getprefix() == '/usr'):
+            return('/etc')
+        else:
+            return(file)
+
+    def calculatedst(self, src, dst):
+        '''Calculate the full destination path accordind to source and
+           destination
+
+        :param src: source files
+        :type path: list
+        :param dst: destination path
+        :type path: string
+        :returns: files with full destination
+        :rtype: list
+        '''
+        destination = []
+        for file in src:
+            if(dst.startswith('/')):
+                destination.append(os.path.join(dst,
+                                   os.path.basename(file)))
+            else:
+                destination.append(os.path.join(self.getprefix(),
+                                                dst,
+                                                os.path.basename(file)))
+        return(destination)
+
+    def getfiles(self, path):
+        '''Retrieve file list within a directory
+
+        :param path: directory path
+        :type path: string
+        :returns: file list
+        :rtype: list
+        '''
+        for root, dirs, files in os.walk(path):
+            file_list = [os.path.join(root, file) for file in files]
+        return(file_list)
+
+    def getprefix(self):
+        '''Retrieve setup tool calculated prefix
+
+        :returns: prefix
+        :rtype: string
+        '''
+        dist = Distribution({'cmdclass': {'install': OnlyGetScriptPath}})
+        dist.dry_run = True  # not sure if necessary, but to be safe
+        dist.parse_config_files()
+        try:
+            dist.parse_command_line()
+        except distutils.errors.DistutilsArgError:
+            pass
+        command = dist.get_command_obj('install')
+        command.ensure_finalized()
+        command.run()
+        prefix = dist.install_scripts.replace('/bin', '')
+        return prefix
+
+    def update_setupstruc(self, src, dst):
+        '''Create/update structure for setuptools.setup()
+           like the following example.
+
+          [('etc/', ['redfish-client/etc/redfish-client.conf']),
+           ('share/redfish-client/templates',
+            ['redfish-client/templates/manager_info.template',
+             'redfish-client/templates/bla.template'])]
+        '''
+        self.setupstruc.append((dst, src))
+
+    def getsetupstruc(self):
+        '''Retrieve setup structure compatible with setuptools.setup()
+           This is only to encapsulatate setupstruc property
+
+        :returns: datafiles source and destination
+        :rtype: setuptools structure
+        '''
+        return(self.setupstruc)
+
+
+##########################################
+# Functions
+##########################################
+def replaceAll(file, searchExp, replaceExp):
+    for line in fileinput.input(file, inplace=1):
+        if searchExp in line:
+            line = line.replace(searchExp, replaceExp)
+        sys.stdout.write(line)
+
+
+def getversion():
+    with open("python_redfish.egg-info/PKG-INFO", "r") as f:
+        output = f.read()
+    s = re.search(r'\nVersion:\s+(\S+)', output)
+    return(s.group(1))
+
+##########################################
+# START
+##########################################
+
+datafiles = DataFilesHelper()
+
+# Install software
 setuptools.setup(
     setup_requires=['pbr'],
-    pbr=True)
+    pbr=True,
+    data_files=datafiles.getsetupstruc())
+
+
+if('install' in sys.argv):
+    # Update conf files
+    for file in datafiles.data['conf']['fdst']:
+        print('Update : {}'.format(file))
+        replaceAll(file, 'PBTEMPLATEPATH',
+                   os.path.dirname(datafiles.data['templates']['fdst'][0]))
+    # Update script files
+    for file in datafiles.data['script']['fdst']:
+        print('Update : {}'.format(file))
+        replaceAll(file, 'PBCONFFILE', datafiles.data['conf']['fdst'][0])
+        replaceAll(file, 'PBVER', getversion())
+