Last active
July 28, 2021 20:52
-
-
Save patkujawa-wf/e7bf49c9d72383baa1b54c573c91acc4 to your computer and use it in GitHub Desktop.
pubupgrade: Combine your dart pubspec files' information so that you can easily upgrade your pubspec.yaml to the versions in your pubspec.lock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python | |
# -*- coding: utf-8 -*- | |
from __future__ import print_function | |
import argparse | |
import sys | |
import re | |
import yaml # PyYAML | |
def merge(yamlfile, lockfile, outf=None, comment_previous_version=False, | |
include_dev=True, only_upgrade=True): | |
""" | |
""" | |
lock_data = yaml.safe_load(lockfile) | |
lock_versions_by_package_name = { | |
name: details['version'] for name, details in lock_data['packages'].items() | |
} | |
print('lock_versions_by_package_name') | |
print(lock_versions_by_package_name) | |
yaml_data = yaml.safe_load(yamlfile) | |
dep_versions_by_package_name = { | |
name: details['version'] if isinstance(details, dict) and details.get( | |
'version') else details for name, details in yaml_data['dependencies'].items() | |
} | |
print('dep_versions_by_package_name') | |
print(dep_versions_by_package_name) | |
# dev_dependencies are optional | |
if include_dev: | |
dev_dep_versions_by_package_name = { | |
name: details['version'] if isinstance(details, dict) and details.get( | |
'version') else details for name, details in yaml_data['dev_dependencies'].items() | |
} | |
print('dev_dep_versions_by_package_name') | |
print(dev_dep_versions_by_package_name) | |
dep_versions_by_package_name.update(dev_dep_versions_by_package_name) | |
def get_replacement(line, maybe_package, new_version): | |
previous_version = dep_versions_by_package_name.get(maybe_package) # type: str | |
if not previous_version: | |
return line | |
if isinstance(previous_version, dict): | |
# Likely a path dep; nothing to do | |
return line | |
if '>' in previous_version: | |
is_gte = '>=' in previous_version | |
equals_or_blank = '=' if is_gte else '' | |
if '<' in previous_version: | |
# upper_range includes the equals sign if present | |
upper_range = re.sub(r'.*?<([^ #]+)', r'\1', previous_version) | |
new_version = '>{}{} <{}'.format(equals_or_blank, new_version, upper_range) | |
else: | |
new_version = '>{}{}'.format(equals_or_blank, new_version) | |
else: | |
new_version = '^{}'.format(new_version) | |
addendum = '' | |
if previous_version != new_version and comment_previous_version: | |
addendum = ' # was {}'.format(previous_version) | |
replacement = line.replace(previous_version, new_version).replace( | |
'\n', '{}\n'.format(addendum) | |
) | |
return replacement | |
outf = outf or open('{}.updated'.format(yamlfile.name), 'w') | |
yamlfile.seek(0) | |
looking_for_version_key = False | |
maybe_package = None | |
new_version = None | |
for line in yamlfile: | |
if looking_for_version_key: | |
if 'version' in line: | |
looking_for_version_key = False | |
outf.write(get_replacement(line, maybe_package, new_version)) | |
else: | |
outf.write(line) | |
continue | |
maybe_package_and_version = line.strip().split(':') | |
maybe_package = maybe_package_and_version[0] | |
# TODO might need to strip out known keys that could be package names, e.g. 'path', 'url' | |
new_version = lock_versions_by_package_name.get(maybe_package) | |
if new_version: | |
package_and_version_on_same_line = len(maybe_package_and_version) == 2 and \ | |
maybe_package_and_version[ | |
1] # can't be empty either | |
if package_and_version_on_same_line: | |
outf.write(get_replacement(line, maybe_package, new_version)) | |
else: | |
looking_for_version_key = True | |
outf.write(line) | |
continue | |
else: | |
outf.write(line) | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser( | |
description='Copy version numbers from pubspec.lock to pubspec.yaml.' | |
) | |
parser.add_argument( | |
'yaml', type=argparse.FileType('r'), | |
help='path to pubspec.yaml file' | |
) | |
parser.add_argument( | |
'lock', type=argparse.FileType('r'), | |
help='path to pubspec.lock file' | |
) | |
parser.add_argument( | |
'--out', '-o', default=sys.stdout, type=argparse.FileType('w'), | |
help='file where the merged output should go' | |
) | |
parser.add_argument( | |
'--comment-previous-version', '-p', default=False, action='store_true', | |
help='includes the previous version as a code comment (default=false)' | |
) | |
parser.add_argument( | |
'--no-include-dev', dest='include_dev', default=False, action='store_false', | |
help='also upgrades dev dependencies (default=true)' | |
) | |
# TODO | |
# parser.add_argument( | |
# '--only-upgrade', '-u', default=True, type=bool, | |
# help='disallows downgrading deps' | |
# ) | |
args = parser.parse_args() | |
merge( | |
args.yaml, args.lock, | |
outf=args.out, | |
comment_previous_version=args.comment_previous_version, | |
include_dev=args.include_dev, | |
# args.only_upgrade, | |
) |
TIL that WP-5884 pubspec.yaml updater by toddbeckman-wf · Pull Request #1 · Workiva/pubspec_up was a thing!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example: