from .base_moduleinfo import BaseModuleInfoError, BaseModuleInfo
-__version__ = '0.1.0'
+__version__ = '0.2.0'
LOG = logging.getLogger(__name__)
default_repo_type = 'forge'
valid_repo_types = ('forge', 'git', 'svn', 'tarball', 'local')
+ re_mod_pf_line = re.compile(r'\s*mod\s+\'([^\']+)\'\s*,\s*(\S+.*)\s*$', re.IGNORECASE)
+ re_pf_line_version = re.compile(r"^\s*'([^']+)'")
+ re_def_token = re.compile(r'^\s*(?:,\s*)?([^,]+)(?:\s*,|$)')
+ re_empty = re.compile(r'^\s*(?:,\s*)?$')
+ re_key_val_pair = re.compile(r'^\s*:?([a-z]+)\s*=>\s*[\'"]([^\'"]+)[\'"]\s*$', re.IGNORECASE)
+ re_key_val_pair_unquoted = re.compile(r'^\s*:?([a-z]+)\s*=>\s*(\S+)\s*$', re.IGNORECASE)
+ re_v_at_start = re.compile(r"^v", re.IGNORECASE)
+
+ re_newline = re.compile(r'(?:\r\n?|\n\r?)+')
+
# -------------------------------------------------------------------------
def __init__(
self, appname=None, verbose=0, version=__version__, base_dir=None,
initialized=None, name=None, vendor=None, full_name=None,
repo_type=None, repo=None, ref=None, use_control_branch=False,
- forge_version=None, default_branch=None):
+ forge_version=None, default_branch=None, exclude_spec=False,
+ install_path=None):
self._repo_type = self.default_repo_type
self._repo = None
self._use_control_branch = False
self._forge_version = None
self._default_branch = None
+ self._exclude_spec = False
+ self._install_path = None
super(ModuleInfo, self).__init__(
appname=appname, verbose=verbose, version=version, base_dir=base_dir,
self.use_control_branch = use_control_branch
self.forge_version = forge_version
self.default_branch = default_branch
+ self.exclude_spec = exclude_spec
+ self.install_path = install_path
if initialized:
self.initialized = True
def use_control_branch(self, value):
self._use_control_branch = to_bool(value)
+ # -------------------------------------------------------------------------
+ @property
+ def exclude_spec(self):
+ """Should the 'spec' subdirectory excluded on checkiung out?"""
+ return self._exclude_spec
+
+ @exclude_spec.setter
+ def exclude_spec(self, value):
+ self._exclude_spec = to_bool(value)
+
+ # -------------------------------------------------------------------------
+ @property
+ def install_path(self):
+ """Installing the module in a different directory than the module name."""
+ return self._install_path
+
+ @install_path.setter
+ def install_path(self, value):
+ if value is None:
+ self._install_path = None
+ return
+ self._install_path = to_str(value)
+
# -------------------------------------------------------------------------
@property
def default_branch(self):
- """The The default branch name of the repository, if the branch name
+ """The default branch name of the repository, if the branch name
of the control branch does not exists."""
return self._default_branch
res = super(ModuleInfo, self).as_dict(short=short)
- res['repo_type'] = self.repo_type
- res['repo'] = self.repo
+ res['default_branch'] = self.default_branch
+ res['exclude_spec'] = self.exclude_spec
+ res['forge_version'] = self.forge_version
+ res['install_path'] = self.install_path
res['ref'] = self.ref
+ res['repo'] = self.repo
+ res['repo_type'] = self.repo_type
res['use_control_branch'] = self.use_control_branch
- res['forge_version'] = self.forge_version
- res['default_branch'] = self.default_branch
return res
res = super(ModuleInfo, self).to_data()
- res['repo_type'] = self.repo_type
- res['repo'] = self.repo
+ res['default_branch'] = self.default_branch
+ res['exclude_spec'] = self.exclude_spec
+ res['forge_version'] = self.forge_version
+ res['install_path'] = self.install_path
res['ref'] = self.ref
+ res['repo'] = self.repo
+ res['repo_type'] = self.repo_type
res['use_control_branch'] = self.use_control_branch
- res['forge_version'] = self.forge_version
- res['default_branch'] = self.default_branch
return res
module_info.forge_version = self.forge_version
if self.default_branch:
module_info.repo_type = self.default_branch
+ if self.exclude_spec:
+ module_info.exclude_spec = self.exclude_spec
+ if self.install_path:
+ module_info.install_path = self.install_path
module_info.initialized = self.initialized
return module_info
if 'default_branch' in data:
module_info.default_branch = data['default_branch']
+ if 'exclude_spec' in data:
+ module_info.exclude_spec = data['exclude_spec']
+
+ if 'install_path' in data:
+ module_info.install_path = data['install_path']
+
+ return module_info
+
+ # -------------------------------------------------------------------------
+ @classmethod
+ def get_module_definitions(cls, mod_def, verbose=0):
+
+ if verbose > 3:
+ LOG.debug("Analyzing definitions from:\n{}".format(mod_def))
+ tokens = []
+ defs = {}
+
+ rest = mod_def
+ while not cls.re_empty.search(rest):
+ if verbose > 4:
+ LOG.debug("Current def rest: {!r}.".format(rest))
+
+ match = cls.re_def_token.search(rest)
+ if match:
+ token = match.group(1)
+ rest = cls.re_def_token.sub('', rest)
+ tokens.append(token)
+ continue
+
+ match = cls.re_key_val_pair_unquoted.search(rest)
+ if match:
+ token = match.group(1)
+ rest = cls.re_key_val_pair_unquoted.sub('', rest)
+ token = match.group(1)
+ continue
+
+ LOG.warn(_("Could not analyze definitions in {!r}.").format(rest))
+ break
+
+ if verbose > 4:
+ LOG.debug("Got def tokens:\n{}".format(pp(tokens)))
+
+ for token in tokens:
+ match = cls.re_key_val_pair.match(token)
+ if match:
+ key = match.group(1)
+ val = match.group(2)
+ defs[key] = val
+ else:
+ LOG.warn(_("Could not analyze definition token {!r}.").format(token))
+
+ if verbose > 4:
+ LOG.debug("Got definitions:\n{}".format(pp(defs)))
+
+ return defs
+
+ # -------------------------------------------------------------------------
+ @classmethod
+ def init_from_puppetfile_line(cls, line, env, appname=None, verbose=0, base_dir=None):
+
+ # Removing all newlines
+ mline = self.re_newline.sub(' ', line)
+
+ match = cls.re_mod_pf_line.search(mline)
+ if not match:
+ if verbose > 2:
+ LOG.debug("Line {!r} is not a module definition line.".format(line))
+ return None
+
+ fullname_orig = match.group(1)
+ mod_def = match.group(2)
+ module_info = None
+
+ try:
+ module_info = cls(
+ appname=appname, verbose=verbose, base_dir=base_dir,
+ full_name=fullname_orig,
+ )
+ except ModuleInfoError as e:
+ LOG.warn("{c}: {e}".format(c=e.__class__.__name__, e=e))
+ return None
+
+ match = cls.re_pf_line_version.search(mod_def)
+ if match:
+ module_info.repo_type = 'forge'
+ module_info.forge_version = match.group(1)
+ else:
+ definitions = cls.get_module_definitions(mod_def, verbose=verbose)
+
+ if 'type' in definitions:
+ module_info.repo_type = definitions['type']
+
+ if 'git' in definitions:
+ module_info.repo = definitions['git']
+ module_info.repo_type = 'git'
+
+ if 'svn' in definitions:
+ module_info.repo = definitions['svn']
+ module_info.repo_type = 'svn'
+
+ if 'local' in definitions:
+ if definitions['local']
+
+ if 'source' in definitions:
+ module_info.repo = definitions['source']
+
+ if 'tag' in definitions:
+ module_info.ref = definitions['tag']
+
+ if 'ref' in definitions:
+ module_info.ref = definitions['ref']
+
+ if 'branch' in definitions:
+ branch = definitions['branch']
+ if branch == ':control_branch':
+ module_info.use_control_branch = True
+ else:
+ module_info.ref = branch
+
+ if 'commit' in definitions:
+ module_info.ref = definitions['commit'}
+
+ if 'version' in definitions:
+ module_info.ref = definitions['version']
+
+ if 'default_branch' in definitions:
+ module_info.default_branch = definitions['default_branch']
+
+ if 'exclude_spec' in definitions:
+ module_info.exclude_spec = to_bool(definitions['exclude_spec'])
+
+ if 'install_path' in definitions:
+ module_info.install_path = definitions['install_path']
+
+
+ module_info.initialized = True
+
+ if verbose > 3:
+ LOG.debug("Initialized {c} object:\n{s}".format(
+ c=module_info.__class__.__name__, s=pp(module_info.as_dict())))
+
return module_info