Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a simple update #966

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 88 additions & 30 deletions conda_forge_tick/migrators/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -445,19 +445,14 @@ def migrate(

try:
with open(os.path.join(recipe_dir, "meta.yaml"), "r") as fp:
cmeta = CondaMetaYAML(fp.read())
old_meta_yaml = fp.read()
cmeta = CondaMetaYAML(old_meta_yaml)
except Exception as e:
attrs["new_version_errors"][version] = (
"We found a problem parsing the recipe: \n\n" + str(e)
)
return {}

# cache round-tripped yaml for testing later
s = io.StringIO()
cmeta.dump(s)
s.seek(0)
old_meta_yaml = s.read()
isuruf marked this conversation as resolved.
Show resolved Hide resolved

# if is a git url, then we error
if _recipe_has_git_url(cmeta):
logger.critical("Migrations do not work on `git_url`s!")
Expand Down Expand Up @@ -492,7 +487,69 @@ def migrate(
attrs["new_version_errors"][version] = _fmt_error_message(errors, version)
return {}

if len(list(_gen_key_selector(cmeta.meta, "source"))) > 0:
def _try_simple_update():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this a full function with inputs etc outside of here. There is a lot of logic and separate tests of it might be useful.

s = io.StringIO()
cmeta.dump(s)
s.seek(0)
new_meta_text_with_version = s.read()
try:
new_meta = parse_meta_yaml(new_meta_text_with_version)
except Exception:
msg = "the yaml couldn't be rendered easily."
return {}, msg
source = meta_yaml["source"]
if isinstance(source, collections.abc.Mapping):
sources = [source]
else:
sources = source

source_section = []
in_source = False
for line in new_meta_text_with_version.split("\n"):
if line.startswith("source:"):
in_source = True
if in_source and len(line) != 0 and line[0] not in [" ", "\t"]:
in_source = False
break
if in_source:
source_section.append(line)
if '#' in line:
return {}, "there's a selector"
if '{%' in line:
return {}, "there's complicated jinja {%"
source_section = "\n".join(source_section)

if source_section.count("url:") != len(sources):
return {}, "there are more URLs than expected"
if source_section.count(hash_type + ":") != len(sources):
return {}, "there are more hashes than expected"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These errors are not quite descriptive.

changes = {}
for source in sources:
if hash_type not in source:
return {}, "the hash type was not found"
if re.fullmatch(r"^[0-9a-fA-F]$", source[hash_type]) is not None:
return {}, "unexpected hash value"
if "url" not in source:
return {}, "a URL was not found"
new_hash = hash_url(source["url"], timeout=120, hash_type=hash_type)
old_hash = source[hash_type]
if old_hash in changes and changes[old_hash] != new_hash:
return {}, "unexpected duplicate hash"
changes[old_hash] = new_hash
return changes, ""

changes, msg = _try_simple_update()

if len(changes) > 0:
new_meta_yaml = old_meta_yaml
for old_hash, new_hash in changes.items():
new_meta_yaml = new_meta_yaml.replace(old_hash, new_hash)
with indir(recipe_dir):
with open("meta.yaml", "w") as fp:
fp.write(new_meta_yaml)
did_update = True

elif len(list(_gen_key_selector(cmeta.meta, "source"))) > 0:
did_update = True
for src_key in _gen_key_selector(cmeta.meta, "source"):
if isinstance(cmeta.meta[src_key], collections.abc.MutableSequence):
Expand All @@ -508,34 +565,35 @@ def migrate(
did_update &= _did_update
errors |= _errors

if did_update:
# if the yaml did not change, then we did not migrate actually
cmeta.jinja2_vars["version"] = old_version
s = io.StringIO()
cmeta.dump(s)
s.seek(0)
still_the_same = s.read() == old_meta_yaml
cmeta.jinja2_vars["version"] = version # put back version

if still_the_same and old_version != version:
did_update = False
beckermr marked this conversation as resolved.
Show resolved Hide resolved
errors.add(
"recipe did not appear to change even "
"though the bot said it should have"
)
logger.critical(
"Recipe did not change in version migration "
"but the code indicates an update was done!"
)
with indir(recipe_dir):
isuruf marked this conversation as resolved.
Show resolved Hide resolved
with open("meta.yaml", "w") as fp:
cmeta.dump(fp)

else:
did_update = False
errors.add("no source sections found in the recipe")

if did_update:
# if the yaml did not change, then we did not migrate actually
cmeta.jinja2_vars["version"] = old_version
s = io.StringIO()
cmeta.dump(s)
s.seek(0)
still_the_same = s.read() == old_meta_yaml
cmeta.jinja2_vars["version"] = version # put back version

if still_the_same and old_version != version:
did_update = False
errors.add(
"recipe did not appear to change even "
"though the bot said it should have"
)
logger.critical(
"Recipe did not change in version migration "
"but the code indicates an update was done!"
)

if did_update:
with indir(recipe_dir):
with open("meta.yaml", "w") as fp:
cmeta.dump(fp)
self.set_build_number("meta.yaml")

return super().migrate(recipe_dir, attrs)
Expand Down