commands.py 8.06 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 34 35
from ..sourcefiles import new_dep_solver as dep_solver
from ..util import path as path_mod
from ..fetch.svn import Svn
from ..fetch.git import Git, GitSM
from ..fetch.local import Local
36
from .action import Action
37
from ..util import shell
38

39

Tristan Gingold's avatar
Tristan Gingold committed
40
class Commands(Action):
41

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

44
    def __init__(self, *args):
Tristan Gingold's avatar
Tristan Gingold committed
45
        super(Commands, self).__init__(*args)
46
        self.git_backend = Git()
47
        self.gitsm_backend = GitSM()
48 49
        self.svn_backend = Svn()
        self.local_backend = Local()
50

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

54
        if not len([m for m in self.manifests if not m.isfetched]) == 0:
55
            raise Exception(
56
                "Fetching should be done before continuing.\n"
57
                "The following modules remains unfetched:\n"
Tristan Gingold's avatar
Tristan Gingold committed
58
                " {}".format(
59 60
                    "\n ".join([str(m) for m in self.manifests
                                if not m.isfetched])))
Tristan Gingold's avatar
Tristan Gingold committed
61

62 63
    def makefile(self):
        """Write the Makefile for the current design"""
64
        # Handle the --make option
65 66 67
        commands = self.options.__dict__.get('make')
        if commands:
            shell.set_commands_os(commands)
68 69
        # Handle --filename option.
        filename = self.options.__dict__.get('filename')
70
        self._check_all_fetched()
71 72 73 74 75 76
        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,
77
                                 filename=filename)
78

79 80 81 82 83 84 85
    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))
86
            if module.source == 'svn':
87
                result = self.svn_backend.fetch(module)
88
            elif module.source == 'git':
89
                result = self.git_backend.fetch(module)
Tristan Gingold's avatar
Tristan Gingold committed
90
            else:
91 92
                assert module.source == 'gitsm'
                result = self.gitsm_backend.fetch(module)
93
            if result is False:
94
                raise Exception("Unable to fetch module {}".format(module.url))
95
            module.parse_manifest()
96 97
            for m in module.modules:
                new_modules.extend(module.modules[m])
98 99
            return new_modules

100
        fetch_queue = [m for m in self.manifests]
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118

        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))

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

    def clean(self):
134
        """Delete the local copy of the fetched modules"""
135
        logging.info("Removing fetched modules..")
136
        remove_list = [mod_aux for mod_aux in self.manifests
137
                       if mod_aux.source in ['git', 'gitsm', 'svn']
138
                       and mod_aux.isfetched]
139 140
        remove_list.reverse()  # we will remove modules in backward order
        if len(remove_list):
141 142 143 144
            for mod_aux in remove_list:
                logging.info("... clean: " + mod_aux.url +
                             " [from: " + mod_aux.path + "]")
                mod_aux.remove_dir_from_disk()
145 146 147 148 149
        else:
            logging.info("There are no modules to be removed")
        logging.info("Modules cleaned.")

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

    def _print_comment(self, message):
        """Private method that prints a message to stdout if not terse"""
173
        if not self.options.terse:
174
            print(message)
175 176 177 178 179 180 181

    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:
182 183
                print("%s\t%s" % (
                    path_mod.relpath(file_aux.path), "file"))
184 185

    def list_modules(self):
186
        """List the modules that are contained by the pool"""
187

188
        for mod_aux in self.manifests:
189 190 191
            if not mod_aux.isfetched:
                logging.warning("Module not fetched: %s", mod_aux.url)
                self._print_comment("# MODULE UNFETCHED! -> %s" % mod_aux.url)
192
            else:
193
                self._print_comment("# MODULE START -> %s" % mod_aux.url)
194
                if mod_aux.source in ['svn', 'git', 'gitsm']:
195
                    self._print_comment("# * URL: " + mod_aux.url)
196
                if (mod_aux.source
197
                        in ['svn', 'git', 'gitsm', 'local']
198
                        and mod_aux.parent):
199 200
                    self._print_comment("# * The parent for this module is: %s"
                                        % mod_aux.parent.url)
201
                else:
202
                    self._print_comment("# * This is the root module")
203
                print("%s\t%s" % (mod_aux.path, mod_aux.source))
204
                if self.options.withfiles:
205 206 207
                    self._print_file_list(mod_aux.files)
                self._print_comment("# MODULE END -> %s" % mod_aux.url)
            self._print_comment("")