# Path: alibuild_helpers/build.py
# def storeHashes(package, specs, isDevelPkg, considerRelocation):
#   """Calculate various hashes for package, and store them in specs[package].
# 
#   Assumes that all dependencies of the package already have a definitive hash.
#   """
#   spec = specs[package]
# 
#   if "remote_revision_hash" in spec and "local_revision_hash" in spec:
#     # We've already calculated these hashes before, so no need to do it again.
#     # This also works around a bug, where after the first hash calculation,
#     # some attributes of spec are changed (e.g. append_path and prepend_path
#     # entries are turned from strings into lists), which changes the hash on
#     # subsequent calculations.
#     return
# 
#   # For now, all the hashers share data -- they'll be split below.
#   h_all = Hasher()
# 
#   if spec.get("force_rebuild", False):
#     h_all(str(time.time()))
# 
#   def hash_data_for_key(key):
#     if sys.version_info[0] < 3 and key in spec and isinstance(spec[key], OrderedDict):
#       # Python 2: use YAML dict order to prevent changing hashes
#       return str(yaml.safe_load(yamlDump(spec[x])))
#     else:
#       return str(spec.get(x, "none"))
# 
#   for x in ("recipe", "version", "package"):
#     h_all(hash_data_for_key(x))
# 
#   # commit_hash could be a commit hash (if we're not building a tag, but
#   # instead e.g. a branch or particular commit specified by its hash), or it
#   # could be a tag name (if we're building a tag). We want to calculate the
#   # hash for both cases, so that if we build some commit, we want to be able to
#   # reuse tarballs from other builds of the same commit, even if it was
#   # referred to differently in the other build.
#   debug("Base git ref is %s", spec["commit_hash"])
#   h_default = h_all.copy()
#   h_default(spec["commit_hash"])
#   try:
#     # If spec["commit_hash"] is a tag, get the actual git commit hash.
#     real_commit_hash = spec["git_refs"]["refs/tags/" + spec["commit_hash"]]
#   except KeyError:
#     # If it's not a tag, assume it's an actual commit hash.
#     real_commit_hash = spec["commit_hash"]
#   # Get any other git tags that refer to the same commit. We do not consider
#   # branches, as their heads move, and that will cause problems.
#   debug("Real commit hash is %s, storing alternative", real_commit_hash)
#   h_real_commit = h_all.copy()
#   h_real_commit(real_commit_hash)
#   h_alternatives = [(spec.get("tag", "0"), spec["commit_hash"], h_default),
#                     (spec.get("tag", "0"), real_commit_hash, h_real_commit)]
#   for ref, git_hash in spec.get("git_refs", {}).items():
#     if ref.startswith("refs/tags/") and git_hash == real_commit_hash:
#       tag_name = ref[len("refs/tags/"):]
#       debug("Tag %s also points to %s, storing alternative",
#             tag_name, real_commit_hash)
#       hasher = h_all.copy()
#       hasher(tag_name)
#       h_alternatives.append((tag_name, git_hash, hasher))
# 
#   # Now that we've split the hasher with the real commit hash off from the ones
#   # with a tag name, h_all has to add the data to all of them separately.
#   def h_all(data):  # pylint: disable=function-redefined
#     for _, _, hasher in h_alternatives:
#       hasher(data)
# 
#   for x in ("env", "append_path", "prepend_path"):
#     h_all(hash_data_for_key(x))
# 
#   for tag, commit_hash, hasher in h_alternatives:
#     # If the commit hash is a real hash, and not a tag, we can safely assume
#     # that's unique, and therefore we can avoid putting the repository or the
#     # name of the branch in the hash.
#     if commit_hash == tag:
#       hasher(spec.get("source", "none"))
#       if "source" in spec:
#         hasher(tag)
# 
#   dh = Hasher()
#   for dep in spec.get("requires", []):
#     # At this point, our dependencies have a single hash, local or remote.
#     hash_and_devel_hash = specs[dep]["hash"] + specs[dep].get("devel_hash", "")
#     h_all(hash_and_devel_hash)
#     dh(hash_and_devel_hash)
# 
#   if isDevelPkg and "incremental_recipe" in spec:
#     h_all(spec["incremental_recipe"])
#     ih = Hasher()
#     ih(spec["incremental_recipe"])
#     spec["incremental_hash"] = ih.hexdigest()
#   elif isDevelPkg:
#     h_all(spec.get("devel_hash"))
# 
#   if considerRelocation and "relocate_paths" in spec:
#     h_all("relocate:"+" ".join(sorted(spec["relocate_paths"])))
# 
#   spec["deps_hash"] = dh.hexdigest()
#   spec["remote_revision_hash"] = h_default.hexdigest()
#   # Store hypothetical hashes of this spec if we were building it using other
#   # tags that refer to the same commit that we're actually building. These are
#   # later used when fetching from the remote store. The "primary" hash should
#   # be the first in the list, so it's checked first by the remote stores.
#   spec["remote_hashes"] = [spec["remote_revision_hash"]] + \
#     list({h.hexdigest() for _, _, h in h_alternatives} - {spec["remote_revision_hash"]})
#   # The local hash must differ from the remote hash to avoid conflicts where
#   # the remote has a package with the same hash as an existing local revision.
#   h_all("local")
#   spec["local_revision_hash"] = h_default.hexdigest()
#   spec["local_hashes"] = [spec["local_revision_hash"]] + \
#     list({h.hexdigest() for _, _, h, in h_alternatives} - {spec["local_revision_hash"]})


import codecs
import os.path
import re
import unittest
    from collections import OrderedDict
    from ordereddict import OrderedDict
from alibuild_helpers.build import storeHashes

try:
except ImportError:


LOGFILE = "build.log"

# Path: alibuild_helpers/build.py
# def storeHashes(package, specs, isDevelPkg, considerRelocation):
#   """Calculate various hashes for package, and store them in specs[package].
# 
#   Assumes that all dependencies of the package already have a definitive hash.
#   """
#   spec = specs[package]
# 
#   if "remote_revision_hash" in spec and "local_revision_hash" in spec:
#     # We've already calculated these hashes before, so no need to do it again.
#     # This also works around a bug, where after the first hash calculation,
#     # some attributes of spec are changed (e.g. append_path and prepend_path
#     # entries are turned from strings into lists), which changes the hash on
#     # subsequent calculations.
#     return
# 
#   # For now, all the hashers share data -- they'll be split below.
#   h_all = Hasher()
# 
#   if spec.get("force_rebuild", False):
#     h_all(str(time.time()))
# 
#   def hash_data_for_key(key):
#     if sys.version_info[0] < 3 and key in spec and isinstance(spec[key], OrderedDict):
#       # Python 2: use YAML dict order to prevent changing hashes
#       return str(yaml.safe_load(yamlDump(spec[x])))
#     else:
#       return str(spec.get(x, "none"))
# 
#   for x in ("recipe", "version", "package"):
#     h_all(hash_data_for_key(x))
# 
#   # commit_hash could be a commit hash (if we're not building a tag, but
#   # instead e.g. a branch or particular commit specified by its hash), or it
#   # could be a tag name (if we're building a tag). We want to calculate the
#   # hash for both cases, so that if we build some commit, we want to be able to
#   # reuse tarballs from other builds of the same commit, even if it was
#   # referred to differently in the other build.
#   debug("Base git ref is %s", spec["commit_hash"])
#   h_default = h_all.copy()
#   h_default(spec["commit_hash"])
#   try:
#     # If spec["commit_hash"] is a tag, get the actual git commit hash.
#     real_commit_hash = spec["git_refs"]["refs/tags/" + spec["commit_hash"]]
#   except KeyError:
#     # If it's not a tag, assume it's an actual commit hash.
#     real_commit_hash = spec["commit_hash"]
#   # Get any other git tags that refer to the same commit. We do not consider
#   # branches, as their heads move, and that will cause problems.
#   debug("Real commit hash is %s, storing alternative", real_commit_hash)
#   h_real_commit = h_all.copy()
#   h_real_commit(real_commit_hash)
#   h_alternatives = [(spec.get("tag", "0"), spec["commit_hash"], h_default),
#                     (spec.get("tag", "0"), real_commit_hash, h_real_commit)]
#   for ref, git_hash in spec.get("git_refs", {}).items():
#     if ref.startswith("refs/tags/") and git_hash == real_commit_hash:
#       tag_name = ref[len("refs/tags/"):]
#       debug("Tag %s also points to %s, storing alternative",
#             tag_name, real_commit_hash)
#       hasher = h_all.copy()
#       hasher(tag_name)
#       h_alternatives.append((tag_name, git_hash, hasher))
# 
#   # Now that we've split the hasher with the real commit hash off from the ones
#   # with a tag name, h_all has to add the data to all of them separately.
#   def h_all(data):  # pylint: disable=function-redefined
#     for _, _, hasher in h_alternatives:
#       hasher(data)
# 
#   for x in ("env", "append_path", "prepend_path"):
#     h_all(hash_data_for_key(x))
# 
#   for tag, commit_hash, hasher in h_alternatives:
#     # If the commit hash is a real hash, and not a tag, we can safely assume
#     # that's unique, and therefore we can avoid putting the repository or the
#     # name of the branch in the hash.
#     if commit_hash == tag:
#       hasher(spec.get("source", "none"))
#       if "source" in spec:
#         hasher(tag)
# 
#   dh = Hasher()
#   for dep in spec.get("requires", []):
#     # At this point, our dependencies have a single hash, local or remote.
#     hash_and_devel_hash = specs[dep]["hash"] + specs[dep].get("devel_hash", "")
#     h_all(hash_and_devel_hash)
#     dh(hash_and_devel_hash)
# 
#   if isDevelPkg and "incremental_recipe" in spec:
#     h_all(spec["incremental_recipe"])
#     ih = Hasher()
#     ih(spec["incremental_recipe"])
#     spec["incremental_hash"] = ih.hexdigest()
#   elif isDevelPkg:
#     h_all(spec.get("devel_hash"))
# 
#   if considerRelocation and "relocate_paths" in spec:
#     h_all("relocate:"+" ".join(sorted(spec["relocate_paths"])))
# 
#   spec["deps_hash"] = dh.hexdigest()
#   spec["remote_revision_hash"] = h_default.hexdigest()
#   # Store hypothetical hashes of this spec if we were building it using other
#   # tags that refer to the same commit that we're actually building. These are
#   # later used when fetching from the remote store. The "primary" hash should
#   # be the first in the list, so it's checked first by the remote stores.
#   spec["remote_hashes"] = [spec["remote_revision_hash"]] + \
#     list({h.hexdigest() for _, _, h in h_alternatives} - {spec["remote_revision_hash"]})
#   # The local hash must differ from the remote hash to avoid conflicts where
#   # the remote has a package with the same hash as an existing local revision.
#   h_all("local")
#   spec["local_revision_hash"] = h_default.hexdigest()
#   spec["local_hashes"] = [spec["local_revision_hash"]] + \
#     list({h.hexdigest() for _, _, h, in h_alternatives} - {spec["local_revision_hash"]})


# Path: tests/test_hashing.py
import codecs
import os.path
import re
import unittest
    from collections import OrderedDict
    from ordereddict import OrderedDict
from alibuild_helpers.build import storeHashes


try:
except ImportError:


LOGFILE = "build.log"

SPEC_RE = re.compile(r"spec = (OrderedDict\(\[\('package', '([^']+)'.*\)\]\))")