# Path: bento/utils/utils.py
# def subst_vars (s, local_vars):
#     """Perform shell/Perl-style variable substitution.
# 
#     Every occurrence of '$' followed by a name is considered a variable, and
#     variable is substituted by the value found in the `local_vars' dictionary.
#     Raise ValueError for any variables not found in `local_vars'.
# 
#     '$' may be escaped by using '$$'
# 
#     Parameters
#     ----------
#     s: str
#         variable to substitute
#     local_vars: dict
#         dict of variables
#     """
#     # Resolve variable substitution within the local_vars dict
#     local_vars = _simple_subst_vars(local_vars, local_vars)
# 
#     def _subst (match):
#         named = match.group("named")
#         if named is not None:
#             if named in local_vars:
#                 return str(local_vars[named])
#             else:
#                 raise ValueError("Invalid variable '%s'" % named)
#         if match.group("escaped") is not None:
#             return _DELIM
#         raise ValueError("This should not happen")
# 
#     def _do_subst(v):
#         pattern_s = r"""
#         %(delim)s(?:
#             (?P<escaped>%(delim)s) |
#             (?P<named>%(id)s)
#         )""" % {"delim": r"\%s" % _DELIM, "id": _IDPATTERN}
#         pattern = re.compile(pattern_s, re.VERBOSE)
#         return pattern.sub(_subst, v)
# 
#     try:
#         return _do_subst(s)
#     except KeyError:
#         raise ValueError("invalid variable '$%s'" % ex_stack())
# 
# def same_content(f1, f2):
#     """Return true if files in f1 and f2 has the same content."""
#     fid1 = open(f1, "rb")
#     try:
#         fid2 = open(f2, "rb")
#         try:
#             return md5(fid1.read()).digest() == md5(fid2.read()).digest()
#         finally:
#             fid2.close()
#     finally:
#         fid1.close()
# 
# def fix_kw(kw):
#     """Make sure the given dictionary may be used as a kw dict independently on
#     the python version and encoding of kw's keys."""
#     return dict([(str(k), v) for k, v in kw.items()])
# 
# def explode_path(path):
#     """Split a path into its components.
# 
#     If the path is absolute, the first value of the returned list will be '/',
#     or the drive letter for platforms where it is applicable.
# 
#     Example
#     -------
#     >>> explode_path("/Users/joe")
#     ["/", "Users", "joe"]
#     """
#     ret = []
#     d, p = op.splitdrive(path)
# 
#     while p:
#         head, tail = op.split(p)
#         if head == p:
#             ret.append(head)
#             break
#         if tail:
#             ret.append(tail)
#         p = head
#     if d:
#         ret.append(d)
#     return ret[::-1]
# 
# Path: bento/core/pkg_objects.py
# class Executable(object):
#     @classmethod
#     def from_parse_dict(cls, d):
#         return cls(**d)
# 
#     @classmethod
#     def from_representation(cls, s):
#         if not "=" in s:
#             raise ValueError("s should be of the form name=module:function")
#         name, value = [j.strip() for j in s.split("=")]
#         if not ":" in value:
#             raise ValueError(
#                 "string representation should be of the form module:function, not %s"
#                 % value)
#         module, function = value.split(":", 1)
#         return cls(name, module, function)
# 
#     def __init__(self, name, module, function):
#         # FIXME: check that module is a module name ?
#         self.name = name
#         self.module = module
#         self.function = function
# 
#     # FIXME: this function should not really be here...
#     def representation(self):
#         return ":".join([self.module, self.function])
# 
#     # FIXME: this function should not really be here...
#     def full_representation(self):
#         return "%s = %s" % (self.name, self.representation())
# 
#     def __repr__(self):
#         return repr({"name": self.name, "module": self.module, "function": self.function})


import os
import sys
import copy
import warnings
import bento.compat.api as compat
import bento.utils.path
from bento.compat.api import json
from bento.core.node \
    import \
        find_root
from bento.core.platforms \
    import \
        get_scheme
from bento.utils.utils import subst_vars, same_content, fix_kw, explode_path
from bento.core.pkg_objects \
    import \
        Executable
        """Same as resolve_paths, but prefix every path with $destdir."""
        return self._resolve_paths(src_root_node, use_destdir=True)

    def resolve_paths(self, src_root_node):
        return self._resolve_paths(src_root_node, use_destdir=False)

    def _resolve_paths(self, src_root_node, use_destdir):
        variables = copy.copy(self._path_variables)
        variables.update(self._variables)
        variables['_srcrootdir'] = src_root_node.abspath()

        root = find_root(src_root_node)

        def _prefix_destdir(path):
            destdir = subst_vars("$destdir", variables)
            if path:
                tail = explode_path(path)[1:]
                if not tail:
                    raise ValueError("Invalid target directory in section %r "
                                     "(not absolute: %r)" % (name, path))
                return os.path.join(destdir, os.path.join(*tail))
            else:
                raise ValueError("Invalid target directory in section "
                                 "%r: %r" % (name, path))

        node_sections = {}
        for category in self.file_sections:
            node_sections[category] = {}
            for name, section in self.file_sections[category].items():
                srcdir = subst_vars(section.source_dir, variables)

# Path: bento/utils/utils.py
# def subst_vars (s, local_vars):
#     """Perform shell/Perl-style variable substitution.
# 
#     Every occurrence of '$' followed by a name is considered a variable, and
#     variable is substituted by the value found in the `local_vars' dictionary.
#     Raise ValueError for any variables not found in `local_vars'.
# 
#     '$' may be escaped by using '$$'
# 
#     Parameters
#     ----------
#     s: str
#         variable to substitute
#     local_vars: dict
#         dict of variables
#     """
#     # Resolve variable substitution within the local_vars dict
#     local_vars = _simple_subst_vars(local_vars, local_vars)
# 
#     def _subst (match):
#         named = match.group("named")
#         if named is not None:
#             if named in local_vars:
#                 return str(local_vars[named])
#             else:
#                 raise ValueError("Invalid variable '%s'" % named)
#         if match.group("escaped") is not None:
#             return _DELIM
#         raise ValueError("This should not happen")
# 
#     def _do_subst(v):
#         pattern_s = r"""
#         %(delim)s(?:
#             (?P<escaped>%(delim)s) |
#             (?P<named>%(id)s)
#         )""" % {"delim": r"\%s" % _DELIM, "id": _IDPATTERN}
#         pattern = re.compile(pattern_s, re.VERBOSE)
#         return pattern.sub(_subst, v)
# 
#     try:
#         return _do_subst(s)
#     except KeyError:
#         raise ValueError("invalid variable '$%s'" % ex_stack())
# 
# def same_content(f1, f2):
#     """Return true if files in f1 and f2 has the same content."""
#     fid1 = open(f1, "rb")
#     try:
#         fid2 = open(f2, "rb")
#         try:
#             return md5(fid1.read()).digest() == md5(fid2.read()).digest()
#         finally:
#             fid2.close()
#     finally:
#         fid1.close()
# 
# def fix_kw(kw):
#     """Make sure the given dictionary may be used as a kw dict independently on
#     the python version and encoding of kw's keys."""
#     return dict([(str(k), v) for k, v in kw.items()])
# 
# def explode_path(path):
#     """Split a path into its components.
# 
#     If the path is absolute, the first value of the returned list will be '/',
#     or the drive letter for platforms where it is applicable.
# 
#     Example
#     -------
#     >>> explode_path("/Users/joe")
#     ["/", "Users", "joe"]
#     """
#     ret = []
#     d, p = op.splitdrive(path)
# 
#     while p:
#         head, tail = op.split(p)
#         if head == p:
#             ret.append(head)
#             break
#         if tail:
#             ret.append(tail)
#         p = head
#     if d:
#         ret.append(d)
#     return ret[::-1]
# 
# Path: bento/core/pkg_objects.py
# class Executable(object):
#     @classmethod
#     def from_parse_dict(cls, d):
#         return cls(**d)
# 
#     @classmethod
#     def from_representation(cls, s):
#         if not "=" in s:
#             raise ValueError("s should be of the form name=module:function")
#         name, value = [j.strip() for j in s.split("=")]
#         if not ":" in value:
#             raise ValueError(
#                 "string representation should be of the form module:function, not %s"
#                 % value)
#         module, function = value.split(":", 1)
#         return cls(name, module, function)
# 
#     def __init__(self, name, module, function):
#         # FIXME: check that module is a module name ?
#         self.name = name
#         self.module = module
#         self.function = function
# 
#     # FIXME: this function should not really be here...
#     def representation(self):
#         return ":".join([self.module, self.function])
# 
#     # FIXME: this function should not really be here...
#     def full_representation(self):
#         return "%s = %s" % (self.name, self.representation())
# 
#     def __repr__(self):
#         return repr({"name": self.name, "module": self.module, "function": self.function})


# Path: bento/installed_package_description.py
import os
import sys
import copy
import warnings
import bento.compat.api as compat
import bento.utils.path
from bento.compat.api import json
from bento.core.node \
    import \
        find_root
from bento.core.platforms \
    import \
        get_scheme
from bento.utils.utils import subst_vars, same_content, fix_kw, explode_path
from bento.core.pkg_objects \
    import \
        Executable

        """Same as resolve_paths, but prefix every path with $destdir."""
        return self._resolve_paths(src_root_node, use_destdir=True)

    def resolve_paths(self, src_root_node):
        return self._resolve_paths(src_root_node, use_destdir=False)

    def _resolve_paths(self, src_root_node, use_destdir):
        variables = copy.copy(self._path_variables)
        variables.update(self._variables)
        variables['_srcrootdir'] = src_root_node.abspath()

        root = find_root(src_root_node)

        def _prefix_destdir(path):
            destdir = subst_vars("$destdir", variables)
            if path:
                tail = explode_path(path)[1:]
                if not tail:
                    raise ValueError("Invalid target directory in section %r "
                                     "(not absolute: %r)" % (name, path))
                return os.path.join(destdir, os.path.join(*tail))
            else:
                raise ValueError("Invalid target directory in section "
                                 "%r: %r" % (name, path))

        node_sections = {}
        for category in self.file_sections:
            node_sections[category] = {}
            for name, section in self.file_sections[category].items():
                srcdir = subst_vars(section.source_dir, variables)

                target = subst_vars(section.target_dir, variables)