def Configure(self, config):
     self.path = config.sourcePath
     
     # os.path.abspath() call prefixes the path with a drive letter.
     # os.path.isabs() does not check for the drive letter so cannot be used as a normalization check.
     self.path = os.path.abspath(self.path)
     self.path = os.path.normpath(self.path)
     
     sectionName = "JSONObjects"
     self.jsonObjectStrings = OrderedDict(config.parser.items(sectionName))
     self.jsonObjects = OrderedDict()
     
     for p in self.jsonObjectStrings:
         try:
             if p in self._jsonObjectHooks:
                 self.jsonObjects[p] = json.loads(self.jsonObjectStrings[p], object_hook=self._jsonObjectHooks[p])
             else:
                 self.jsonObjects[p] = json.loads(self.jsonObjectStrings[p])
         except Exception as e:
             config.messagePrinter.error("The [{0}] option in the [{1}] section has an invalid JSON object!".format(p, sectionName))
             config.messagePrinter.dbg("Exception message: {0}".format(e))
             config.messagePrinter.error("Exiting.")
             sys.exit(1)
     
     
     self.projectList = OrderedDict()
     self.jsonObjects["ProjectGroupsList"]
     
     for group in self.jsonObjects["ProjectGroupsList"]:
         if config.sourcePath is not None:
             if group.pathPrefix is not None:
                 groupPathPrefix = group.pathPrefix = toPosixPath(os.path.normpath(os.path.join(config.sourcePath, group.pathPrefix)))
             else:
                 groupPathPrefix = config.sourcePath
         else:
             groupPathPrefix = None
         
         for project in group.projects:
             # Add the project reverse link back to group.
             project.groupName = group.name
             
             # Apply the group's path-prefix property to each project path.
             if groupPathPrefix is not None:
                 project.path = toPosixPath(os.path.normpath(os.path.join(groupPathPrefix, project.path)))
                 if project.includePath is not None and len(project.includePath) > 0:
                     project.includePath = toPosixPath(os.path.normpath(os.path.join(groupPathPrefix, project.includePath)))
             
             if group.pathPrefix is not None and not os.path.isdir(group.pathPrefix):
                 config.messagePrinter.error("The group \"{0}\" path-prefix \"{1}\" does not exist.".format(group.name, group.pathPrefix))
             if not os.path.isdir(project.path):
                 config.messagePrinter.error("The project \"{0}\" path \"{1}\" does not exist.".format(project.name, project.path))
             if project.includePath is not None and not os.path.isdir(project.includePath):
                 config.messagePrinter.error("The project \"{0}\" include-path \"{1}\" does not exist.".format(project.name, project.includePath))
             
             # Add the project to the dictionary
             self.projectList[project.name] = project
 def Configure(self, argv):
     self.args = argv
     self.messagePrinter = Logger()
     
     self.scriptPath, self.scriptExtension = os.path.splitext(argv[0])
     self.scriptPath, self.scriptName = os.path.split(self.scriptPath)
     
     self.argparser.parse_args(args=argv[1:], namespace=self)
     
     self.messagePrinter.isDbgEnabled = self.debugMessages
     self.messagePrinter.isInfoEnabled = self.verbose
     self.messagePrinter.isErrEnabled = not self.silenceErrors
     
     if self.scriptIni is None:
         iniPath = ''
         if self.scriptPath is not None:
             iniPath = self.scriptPath
         self.scriptIni = toPosixPath(os.path.join(iniPath, '{0}.ini'.format(self.scriptName)))
     
     self.parser = configparser.ConfigParser(allow_no_value = True) # see https://docs.python.org/2/library/configparser.html
     self.parser.optionxform = str # make case-sensitive as per https://docs.python.org/2/library/configparser.html
     
     self.isConfigured = True
     
     if os.path.exists(self.scriptIni):
         self.parser.read(self.scriptIni)
     elif os.path.exists(os.path.join(self.scriptPath, self.scriptIni)):
         self.parser.read(os.path.join(self.scriptPath, self.scriptIni))
     else:
         msg = "No configuration file found. Searched, current directory and script directory directory for {0}.".format(self.scriptIni)
         self.messagePrinter.error(msg)
         self.isConfigured = False
         
         self.databaseFilename = ':memory:'
         self.sourcePath = './'
         return
     
     try:
         if self.databaseFilename is None:
             self.databaseFilename = self.parser.get("Output", "DatabaseFilename")
     except:
         self.databaseFilename = ':memory:'
     
     try:
         if self.sourcePath is None:
             self.sourcePath = self.parser.get("Paths","SourceRoot")
             # Make the read SourceRoot path relative to the INI file's path.
             if self.isConfigured:
                 iniPath, iniFilename = os.path.split(self.scriptIni)
                 self.sourcePath = toPosixPath(os.path.normpath(os.path.join(iniPath, self.sourcePath)))
                 print('source-path: {0}'.format(self.sourcePath))
     except:
         self.sourcePath = './'
 def GetIncludeFileAbsolutePath(self, absoluteFilepath, includetext, isLocalInclude = True):
     filepath, filename = os.path.split(absoluteFilepath)
     
     localFilePath = os.path.join(filepath, includetext)
     solFilePath = os.path.join(self.solutionInfo.path, includetext)
     
     if os.path.isfile(localFilePath):
         # This is a local include file
         return os.path.abspath(localFilePath)
     elif os.path.isfile(solFilePath):
         # Solution path relative include
         return os.path.abspath(solFilePath)
     else:
         # Try one of the projects paths
         potentials = []
         for project in self.solutionInfo.projectList:
             proj = self.solutionInfo.projectList[project]
             if proj.includePath is not None:
                 projFilePath = toPosixPath(os.path.join(proj.includePath, includetext))
                 if os.path.isfile(projFilePath):
                     potentials.append(projFilePath)
         
         if len(potentials) == 1:
             return os.path.abspath(potentials[0])
         elif len(potentials) > 1:
             self.config.messagePrinter.error('include text "{0}" in {1} matches multiple files:'.format(includetext, absoluteFilepath))
             formatStr = '  {0} (selected)'
             for p in potentials:
                 self.config.messagePrinter.error(formatStr.format(p))
                 formatStr = '  {0}'
             
             return os.path.abspath(potentials[0])
         
         # Don't know where this file is...
         return None
 def GetPathRelativeToSolution(self, filepath):
     if not os.path.isabs(filepath):
         filepath = os.path.abspath(filepath)
     
     filepath = os.path.normpath(filepath)
     filepath = os.path.relpath(filepath, self.path)
     
     return toPosixPath(filepath)
 def AddFile(self, filename, project, solutionPath, exists):
     solutionPath = toPosixPath(solutionPath) # normpath doesn't normalize to posix slashes.
     
     try:
         self.cur.execute("INSERT INTO CodeFile (SolutionPath, Project, Filename) VALUES (?, ?, ?);", (solutionPath, project, filename))
     except:
         self.cur.execute("UPDATE CodeFile SET Project = ?, Filename = ? WHERE SolutionPath = ?;", (project, filename, solutionPath))
     
     return self.cur.lastrowid
 def AddProject(self, projectName, solutionPath, hierarchyLevel):
     solutionPath = toPosixPath(solutionPath) # normpath doesn't normalize to posix slashes.
     
     try:
         self.cur.execute("INSERT INTO Project (SolutionPath, Name, HierarchyLevel) VALUES (?, ?, ?);", (solutionPath, projectName, hierarchyLevel))
     except:
         self.cur.execute("UPDATE CodeFile SET Name = ?, HierarchyLevel = ? WHERE SolutionPath = ?;", (projectName, hierarchyLevel, solutionPath))
     
     return self.cur.lastrowid
 def AddInclude(self, solutionPath, includeText, includeType, includeFilename, includeProject, includeSolutionPath, lineNumber):
     solutionPath = toPosixPath(solutionPath) # normpath doesn't normalize to posix slashes.
     normIncludeText = toPosixPath(includeText) # normpath doesn't normalize to posix slashes.
     if includeSolutionPath:
         includeSolutionPath = toPosixPath(includeSolutionPath) # normpath doesn't normalize to posix slashes
     
     if normIncludeText != includeText:
         if self.errorLogger:
             self.errorLogger.write("Error, #include directive with non-posix path!" + includeText + " included in " + solutionPath + "\n")
         includeText = normIncludeText
     
     try:
         self.cur.execute("INSERT INTO IncludeDirective (CodeFileSolutionPath, IncludeText, IncludeType, IncludeFilename, IncludeProject, IncludeSolutionPath, LineNumber) VALUES (?, ?, ?, ?, ?, ?, ?);", (solutionPath, includeText, includeType, includeFilename, includeProject, includeSolutionPath, lineNumber))
     except:
         if self.messagePrinter:
             msg = "Unknown exception for: INSERT INTO IncludeDirective (CodeFileSolutionPath, IncludeText, IncludeType, IncludeFilename, IncludeProject, IncludeSolutionPath) VALUES (" + repr(solutionPath) + "," + repr(includeText) + "," + repr(includeType) + "," + repr(includeFilename) + "," + repr(includeProject) + "," + repr(includeSolutionPath) + "," + repr(lineNumber) + ");"
             self.messagePrinter.info(msg)
     
     return self.cur.lastrowid
    def GetProjectName(self, filepath):
        if not os.path.isabs(filepath):
            filepath = os.path.abspath(filepath)

        filepath = os.path.normpath(filepath)
        filepath = toPosixPath(filepath) # Standardise the slashes.
        if filepath[-1] != '/': # Ensure that the path is slash terminated otherwise we might
                                # end up including projects which start with the same name...
            filepath += '/'
            
        rv = None # Project name
        rvLen = 0 # Lenght of the matched path
        
        # Project paths are either absolute or relative to the solution path.
        for project in self.projectList:
            projectPath = self.projectList[project].path
            if not os.path.isabs(projectPath):
                projectPath = os.path.abspath(projectPath)
            
            projectPath = os.path.normpath(projectPath)
            projectPath = toPosixPath(projectPath) # Standardise the slashes.
            if projectPath[-1] != '/': # Ensure that the path is slash terminated otherwise we might
                                       # end up including projects which start with the same name...
                projectPath += '/'
            
            # Check all projects in the list and return the one with the longest matching path.
            if filepath.startswith(projectPath):
                if not rv:
                    rv = project
                    rvLen = len(projectPath)
                else:
                    if rvLen < len(projectPath):
                        rv = project
                        rvLen = len(projectPath)
        
        return rv