core.py 8.43 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2013 CERN
# Author: Pawel Szostek (pawel.szostek@cern.ch)
#
# This file is part of Hdlmake.
#
# Hdlmake is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Hdlmake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Hdlmake.  If not, see <http://www.gnu.org/licenses/>.

22 23
"""This module provides the core actions to the pool"""

24 25
from __future__ import absolute_import
from __future__ import print_function
26 27
import logging
import os
28
import sys
29
import os.path
30 31 32 33

import hdlmake.fetch as fetch
import hdlmake.new_dep_solver as dep_solver
from hdlmake.util import path as path_mod
34 35
from hdlmake.fetch import Svn, Git, GitSM, Local
from hdlmake.fetch import SVN, GIT, GITSM, LOCAL
36
from .action import Action
37

38

39
class ActionCore(Action):
40

41
    """Class that contains the methods for core actions"""
42

43
    def __init__(self, *args):
44
        super(ActionCore, self).__init__(*args)
45
        self.git_backend = Git()
46
        self.gitsm_backend = GitSM()
47 48
        self.svn_backend = Svn()
        self.local_backend = Local()
49

50
    def _check_all_fetched(self):
51 52 53 54
        """Check if every module in the pool is fetched"""

        if not len([m for m in self if not m.isfetched]) == 0:
            logging.error(
55
                "Fetching should be done before continuing.\n"
56 57
                "The following modules remains unfetched:\n"
                "%s",
58
                "\n".join([str(m) for m in self if not m.isfetched]))
59
            quit(1)
60 61
    def makefile(self):
        """Write the Makefile for the current design"""
62
        self._check_all_fetched()
63 64 65 66 67 68 69
        self.build_file_set()
        self.solve_file_set()
        combined_fileset = self.parseable_fileset
        combined_fileset.add(self.privative_fileset)
        self.tool.write_makefile(self.config,
                                 combined_fileset,
                                 filename=self.options.filename)
70

71 72 73 74 75 76 77
    def _fetch_all(self):
        """Fetch all the modules declared in the design"""

        def _fetch_module(module):
            """Fetch the given module from the remote origin"""
            new_modules = []
            logging.debug("Fetching module: %s", str(module))
78 79 80 81
            if module.source is SVN:
                result = self.svn_backend.fetch(module)
            elif module.source is GIT:
                result = self.git_backend.fetch(module)
82 83
            elif module.source is GITSM:
                result = self.gitsm_backend.fetch(module)
84 85
            elif module.source is LOCAL:
                result = self.local_backend.fetch(module)
86 87 88 89 90 91 92
            if result is False:
                logging.error("Unable to fetch module %s", str(module.url))
                sys.exit("Exiting")
            module.parse_manifest()
            new_modules.extend(module.local)
            new_modules.extend(module.svn)
            new_modules.extend(module.git)
93
            new_modules.extend(module.gitsm)
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
            return new_modules

        fetch_queue = [m for m in self]

        while len(fetch_queue) > 0:
            cur_mod = fetch_queue.pop()
            new_modules = []
            if cur_mod.isfetched:
                new_modules = cur_mod.submodules()
            else:
                new_modules = _fetch_module(cur_mod)
            for mod in new_modules:
                if not mod.isfetched:
                    logging.debug("Appended to fetch queue: "
                                  + str(mod.url))
                    self._add(mod)
                    fetch_queue.append(mod)
                else:
                    logging.debug("NOT appended to fetch queue: "
                                  + str(mod.url))

115
    def fetch(self):
116
        """Fetch the missing required modules from their remote origin"""
117
        logging.info("Fetching needed modules.")
118
        for mod in self:
119
            if mod.isfetched and not mod.manifest_dict == None:
120 121
                if 'fetch_pre_cmd' in mod.manifest_dict:
                    os.system(mod.manifest_dict.get("fetch_pre_cmd", ''))
122
        self._fetch_all()
123
        for mod in self:
124
            if mod.isfetched and not mod.manifest_dict == None:
125 126
                if 'fetch_post_cmd' in mod.manifest_dict:
                    os.system(mod.manifest_dict.get("fetch_post_cmd", ''))
127 128 129
        logging.info("All modules fetched.")

    def clean(self):
130
        """Delete the local copy of the fetched modules"""
131
        logging.info("Removing fetched modules..")
132
        remove_list = [mod_aux for mod_aux in self
133
                       if mod_aux.source in [fetch.GIT, fetch.GITSM, fetch.SVN]
134
                       and mod_aux.isfetched]
135 136
        remove_list.reverse()  # we will remove modules in backward order
        if len(remove_list):
137 138 139 140
            for mod_aux in remove_list:
                logging.info("... clean: " + mod_aux.url +
                             " [from: " + mod_aux.path + "]")
                mod_aux.remove_dir_from_disk()
141 142 143 144 145
        else:
            logging.info("There are no modules to be removed")
        logging.info("Modules cleaned.")

    def list_files(self):
146 147 148 149 150 151
        """List the files added to the design across the pool hierarchy"""
        unfetched_modules = [mod_aux for mod_aux in self
                             if not mod_aux.isfetched]
        for mod_aux in unfetched_modules:
            logging.warning(
                "List incomplete, module %s has not been fetched!", mod_aux)
152 153
        if self.options.top != None:
            self.top_entity = self.options.top
154 155 156 157
        self.build_file_set()
        self.solve_file_set()
        file_list = dep_solver.make_dependency_sorted_list(
            self.parseable_fileset)
158
        files_str = [file_aux.path for file_aux in file_list]
159
        if self.options.reverse is True:
160
            files_str.reverse()
161
        if self.options.delimiter is None:
162 163
            delimiter = "\n"
        else:
164
            delimiter = self.options.delimiter
165
        print(delimiter.join(files_str))
166 167 168

    def _print_comment(self, message):
        """Private method that prints a message to stdout if not terse"""
169
        if not self.options.terse:
170
            print(message)
171 172 173 174 175 176 177

    def _print_file_list(self, file_list):
        """Print file list to standard out"""
        if not len(file_list):
            self._print_comment("# * This module has no files")
        else:
            for file_aux in file_list:
178 179
                print("%s\t%s" % (
                    path_mod.relpath(file_aux.path), "file"))
180 181

    def list_modules(self):
182
        """List the modules that are contained by the pool"""
183 184

        def _convert_to_source_name(source_code):
185
            """Private function that returns a string with the source type"""
186 187
            if source_code == fetch.GIT:
                return "git"
188 189
            elif source_code == fetch.GITSM:
                return "gitsm"
190 191 192 193
            elif source_code == fetch.SVN:
                return "svn"
            elif source_code == fetch.LOCAL:
                return "local"
194 195 196 197 198

        for mod_aux in self:
            if not mod_aux.isfetched:
                logging.warning("Module not fetched: %s", mod_aux.url)
                self._print_comment("# MODULE UNFETCHED! -> %s" % mod_aux.url)
199
            else:
200
                self._print_comment("# MODULE START -> %s" % mod_aux.url)
201
                if mod_aux.source in [fetch.SVN, fetch.GIT, fetch.GITSM]:
202
                    self._print_comment("# * URL: " + mod_aux.url)
203 204 205
                if (mod_aux.source
                        in [fetch.SVN, fetch.GIT, fetch.GITSM, fetch.LOCAL]
                        and mod_aux.parent):
206 207
                    self._print_comment("# * The parent for this module is: %s"
                                        % mod_aux.parent.url)
208
                else:
209
                    self._print_comment("# * This is the root module")
210
                print("%s\t%s" % (mod_aux.path,
211
                                  _convert_to_source_name(mod_aux.source)))
212
                if self.options.withfiles:
213 214 215
                    self._print_file_list(mod_aux.files)
                self._print_comment("# MODULE END -> %s" % mod_aux.url)
            self._print_comment("")