diff --git a/exact_dependencies.py b/exact_dependencies.py new file mode 100644 index 0000000..4abcde1 --- /dev/null +++ b/exact_dependencies.py @@ -0,0 +1,24 @@ +#! /usr/bin/env python +''' +Load and save exact-dependencies.json safely. + +The format of exact-dependencies is simply a dictionary of +package name and its exact version: + + { + "elm-lang/core": "4.0.5" + } +''' + +import json + +import elm_package + + +load = elm_package.load + + +# dump(package: Dict, fileobj: FileLike) -> None +def dump(package, fileobj): + to_save = elm_package.sorted_deps(package) + json.dump(to_save, fileobj, sort_keys=False, indent=4, separators=(',', ': ')) diff --git a/native_deps_sync.py b/native_deps_sync.py new file mode 100755 index 0000000..ed74cdf --- /dev/null +++ b/native_deps_sync.py @@ -0,0 +1,54 @@ +#! /usr/bin/env python +from __future__ import print_function + +import sys +import argparse + +import elm_package +import exact_dependencies + + +def sync_versions(top_level_file, spec_file, quiet=False, dry=False, note_test_deps=True): + """ first file should be the top level elm-native-package.json. + second file should be the spec level elm-native-package.json. + """ + + with open(top_level_file) as f: + top_level = exact_dependencies.load(f) + + with open(spec_file) as f: + spec = exact_dependencies.load(f) + + (messages, new_deps) = elm_package.sync_deps(top_level, spec) + spec = new_deps + + if len(messages) > 0: + print('{number} packages changed.'.format(number=len(messages))) + + if not dry: + with open(spec_file, 'w') as f: + exact_dependencies.dump(spec, f) + else: + print("No changes written.") + + if not quiet: + print('\n'.join(messages)) + else: + print('No changes needed.') + + +def main(): + + parser = argparse.ArgumentParser(description='Sync deps between a parent and a sub') + + parser.add_argument('--quiet', '-q', action='store_true', help='don\'t print anything', default=False) + parser.add_argument('--dry', '-d', action='store_true', help='only print possible changes', default=False) + parser.add_argument('top_level_file') + parser.add_argument('spec_file') + args = parser.parse_args() + + sync_versions(args.top_level_file, args.spec_file, quiet=args.quiet, dry=args.dry) + + +if __name__ == '__main__': + main() diff --git a/tests/test_native_deps_sync.py b/tests/test_native_deps_sync.py new file mode 100644 index 0000000..9c97235 --- /dev/null +++ b/tests/test_native_deps_sync.py @@ -0,0 +1,46 @@ +from collections import OrderedDict +import json + +from hypothesis import given +import hypothesis.strategies as st + +import native_deps_sync + + +top_level_deps = [ + ('NoRedInk/top-1', '1.0.0 <= v <= 1.0.0'), + ('NoRedInk/top-2', '1.0.0 <= v <= 1.0.0'), + ('NoRedInk/top-3', '1.0.0 <= v <= 1.0.0'), +] + +spec_deps = [ + ('NoRedInk/top-1', '1.0.0 <= v <= 1.0.0'), + ('NoRedInk/top-2', '1.0.0 <= v <= 1.0.0'), + ('NoRedInk/spec-1', '1.0.0 <= v <= 1.0.0'), + ('NoRedInk/spec-2', '1.0.0 <= v <= 1.0.0'), +] + + +@given(top_level_deps=st.permutations(top_level_deps), + spec_deps=st.permutations(spec_deps)) +def test_spec_order_is_preserved( + tmpdir, + top_level_deps, + spec_deps): + top_level_file = tmpdir.join('elm-native-package.json') + spec_file = tmpdir.join('spec-elm-native-package.json') + + top_level = OrderedDict(top_level_deps) + top_level_file.write(json.dumps(top_level)) + + spec = OrderedDict(spec_deps) + spec_file.write(json.dumps(spec)) + + native_deps_sync.sync_versions( + str(top_level_file), + str(spec_file), + quiet=False, + dry=False) + + new_spec = json.loads(spec_file.read(), object_pairs_hook=OrderedDict) + assert list(new_spec.keys()) == ['NoRedInk/spec-1', 'NoRedInk/spec-2', 'NoRedInk/top-1', 'NoRedInk/top-2', 'NoRedInk/top-3']