summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbitbake/bin/bitbake-setup287
-rw-r--r--bitbake/lib/bb/tests/setup.py12
2 files changed, 147 insertions, 152 deletions
diff --git a/bitbake/bin/bitbake-setup b/bitbake/bin/bitbake-setup
index 7878cd9394..e9e73a9270 100755
--- a/bitbake/bin/bitbake-setup
+++ b/bitbake/bin/bitbake-setup
@@ -32,9 +32,9 @@ logger = bb.msg.logger_create('bitbake-setup', sys.stdout)
32def cache_dir(top_dir): 32def cache_dir(top_dir):
33 return os.path.join(top_dir, '.bitbake-setup-cache') 33 return os.path.join(top_dir, '.bitbake-setup-cache')
34 34
35def init_bb_cache(settings, args): 35def init_bb_cache(top_dir, settings, args):
36 dldir = settings["default"]["dl-dir"] 36 dldir = settings["default"]["dl-dir"]
37 bb_cachedir = os.path.join(cache_dir(args.top_dir), 'bitbake-cache') 37 bb_cachedir = os.path.join(cache_dir(top_dir), 'bitbake-cache')
38 38
39 d = bb.data.init() 39 d = bb.data.init()
40 d.setVar("DL_DIR", dldir) 40 d.setVar("DL_DIR", dldir)
@@ -389,7 +389,7 @@ def choose_fragments(possibilities, parameters, non_interactive, skip_selection)
389 choices[k] = options_enumerated[option_n][1] 389 choices[k] = options_enumerated[option_n][1]
390 return choices 390 return choices
391 391
392def obtain_config(settings, args, source_overrides, d): 392def obtain_config(top_dir, settings, args, source_overrides, d):
393 if args.config: 393 if args.config:
394 config_id = args.config[0] 394 config_id = args.config[0]
395 config_parameters = args.config[1:] 395 config_parameters = args.config[1:]
@@ -407,7 +407,7 @@ def obtain_config(settings, args, source_overrides, d):
407 upstream_config = {'type':'network','uri':config_id,'name':get_config_name(config_id),'data':json.load(f)} 407 upstream_config = {'type':'network','uri':config_id,'name':get_config_name(config_id),'data':json.load(f)}
408 else: 408 else:
409 print("Looking up config {} in configuration registry".format(config_id)) 409 print("Looking up config {} in configuration registry".format(config_id))
410 registry_path = update_registry(settings["default"]["registry"], cache_dir(args.top_dir), d) 410 registry_path = update_registry(settings["default"]["registry"], cache_dir(top_dir), d)
411 registry_configs = list_registry(registry_path, with_expired=True) 411 registry_configs = list_registry(registry_path, with_expired=True)
412 if config_id not in registry_configs: 412 if config_id not in registry_configs:
413 raise Exception("Config {} not found in configuration registry, re-run 'init' without parameters to choose from available configurations.".format(config_id)) 413 raise Exception("Config {} not found in configuration registry, re-run 'init' without parameters to choose from available configurations.".format(config_id))
@@ -416,7 +416,7 @@ def obtain_config(settings, args, source_overrides, d):
416 if has_expired(expiry_date): 416 if has_expired(expiry_date):
417 print("This configuration is no longer supported after {}. Please consider changing to a supported configuration.".format(expiry_date)) 417 print("This configuration is no longer supported after {}. Please consider changing to a supported configuration.".format(expiry_date))
418 else: 418 else:
419 registry_path = update_registry(settings["default"]["registry"], cache_dir(args.top_dir), d) 419 registry_path = update_registry(settings["default"]["registry"], cache_dir(top_dir), d)
420 registry_configs = list_registry(registry_path, with_expired=True) 420 registry_configs = list_registry(registry_path, with_expired=True)
421 config_id = choose_config(registry_configs, args.non_interactive) 421 config_id = choose_config(registry_configs, args.non_interactive)
422 config_parameters = [] 422 config_parameters = []
@@ -429,7 +429,7 @@ def obtain_config(settings, args, source_overrides, d):
429 upstream_config['skip-selection'] = args.skip_selection 429 upstream_config['skip-selection'] = args.skip_selection
430 return upstream_config 430 return upstream_config
431 431
432def init_config(settings, args, d): 432def init_config(top_dir, settings, args, d):
433 stdout = sys.stdout 433 stdout = sys.stdout
434 def handle_task_progress(event, d): 434 def handle_task_progress(event, d):
435 rate = event.rate if event.rate else '' 435 rate = event.rate if event.rate else ''
@@ -437,10 +437,10 @@ def init_config(settings, args, d):
437 print("{}% {} ".format(progress, rate), file=stdout, end='\r') 437 print("{}% {} ".format(progress, rate), file=stdout, end='\r')
438 438
439 source_overrides = json.load(open(args.source_overrides)) if args.source_overrides else {'sources':{}} 439 source_overrides = json.load(open(args.source_overrides)) if args.source_overrides else {'sources':{}}
440 upstream_config = obtain_config(settings, args, source_overrides, d) 440 upstream_config = obtain_config(top_dir, settings, args, source_overrides, d)
441 print("\nRun 'bitbake-setup init --non-interactive {}' to select this configuration non-interactively.\n".format(" ".join(upstream_config['non-interactive-cmdline-options']))) 441 print("\nRun 'bitbake-setup init --non-interactive {}' to select this configuration non-interactively.\n".format(" ".join(upstream_config['non-interactive-cmdline-options'])))
442 442
443 builddir = os.path.join(os.path.abspath(args.top_dir), args.build_dir_name or "{}-{}".format(upstream_config['name']," ".join(upstream_config['non-interactive-cmdline-options'][1:]).replace(" ","-").replace("/","_"))) 443 builddir = os.path.join(os.path.abspath(top_dir), args.build_dir_name or "{}-{}".format(upstream_config['name']," ".join(upstream_config['non-interactive-cmdline-options'][1:]).replace(" ","-").replace("/","_")))
444 if os.path.exists(os.path.join(builddir, "layers")): 444 if os.path.exists(os.path.join(builddir, "layers")):
445 print("Build already initialized in {}\nUse 'bitbake-setup status' to check if it needs to be updated or 'bitbake-setup update' to perform the update.".format(builddir)) 445 print("Build already initialized in {}\nUse 'bitbake-setup status' to check if it needs to be updated or 'bitbake-setup update' to perform the update.".format(builddir))
446 return 446 return
@@ -511,7 +511,7 @@ def are_layers_changed(layers, layerdir, d):
511 511
512 return changed 512 return changed
513 513
514def build_status(settings, args, d, update=False): 514def build_status(top_dir, settings, args, d, update=False):
515 builddir = args.build_dir 515 builddir = args.build_dir
516 516
517 confdir = os.path.join(builddir, "config") 517 confdir = os.path.join(builddir, "config")
@@ -523,7 +523,7 @@ def build_status(settings, args, d, update=False):
523 args.non_interactive = True 523 args.non_interactive = True
524 args.skip_selection = current_upstream_config['skip-selection'] 524 args.skip_selection = current_upstream_config['skip-selection']
525 source_overrides = current_upstream_config["source-overrides"] 525 source_overrides = current_upstream_config["source-overrides"]
526 new_upstream_config = obtain_config(settings, args, source_overrides, d) 526 new_upstream_config = obtain_config(top_dir, settings, args, source_overrides, d)
527 527
528 write_config(new_upstream_config, confdir) 528 write_config(new_upstream_config, confdir)
529 config_diff = bb.process.run('git -C {} diff'.format(confdir))[0] 529 config_diff = bb.process.run('git -C {} diff'.format(confdir))[0]
@@ -544,8 +544,8 @@ def build_status(settings, args, d, update=False):
544 544
545 print("\nConfiguration in {} has not changed.".format(builddir)) 545 print("\nConfiguration in {} has not changed.".format(builddir))
546 546
547def build_update(settings, args, d): 547def build_update(top_dir, settings, args, d):
548 build_status(settings, args, d, update=True) 548 build_status(top_dir, settings, args, d, update=True)
549 549
550def do_fetch(fetcher, dir): 550def do_fetch(fetcher, dir):
551 # git fetcher simply dumps git output to stdout; in bitbake context that is redirected to temp/log.do_fetch 551 # git fetcher simply dumps git output to stdout; in bitbake context that is redirected to temp/log.do_fetch
@@ -595,8 +595,8 @@ def list_registry(registry_path, with_expired):
595 json_data[config_name] = {"description": config_desc} 595 json_data[config_name] = {"description": config_desc}
596 return json_data 596 return json_data
597 597
598def list_configs(settings, args, d): 598def list_configs(top_dir, settings, args, d):
599 registry_path = update_registry(settings["default"]["registry"], cache_dir(args.top_dir), d) 599 registry_path = update_registry(settings["default"]["registry"], cache_dir(top_dir), d)
600 json_data = list_registry(registry_path, args.with_expired) 600 json_data = list_registry(registry_path, args.with_expired)
601 print("\nAvailable configurations:") 601 print("\nAvailable configurations:")
602 for config_name, config_data in json_data.items(): 602 for config_name, config_data in json_data.items():
@@ -614,7 +614,7 @@ def list_configs(settings, args, d):
614 json.dump(json_data, f, sort_keys=True, indent=4) 614 json.dump(json_data, f, sort_keys=True, indent=4)
615 print("Available configurations written into {}".format(args.write_json)) 615 print("Available configurations written into {}".format(args.write_json))
616 616
617def install_buildtools(settings, args, d): 617def install_buildtools(top_dir, settings, args, d):
618 buildtools_install_dir = os.path.join(args.build_dir, 'buildtools') 618 buildtools_install_dir = os.path.join(args.build_dir, 'buildtools')
619 if os.path.exists(buildtools_install_dir): 619 if os.path.exists(buildtools_install_dir):
620 if not args.force: 620 if not args.force:
@@ -634,117 +634,113 @@ def install_buildtools(settings, args, d):
634 subprocess.check_call("{} -d {} --downloads-directory {}".format(install_buildtools, buildtools_install_dir, buildtools_download_dir), shell=True) 634 subprocess.check_call("{} -d {} --downloads-directory {}".format(install_buildtools, buildtools_install_dir, buildtools_download_dir), shell=True)
635 635
636def default_settings_path(top_dir): 636def default_settings_path(top_dir):
637 return os.path.join(top_dir, 'bitbake-setup.conf') 637 return os.path.join(top_dir, 'settings.conf')
638 638
639def write_settings(top_dir, force_replace, non_interactive=True): 639def create_settings(top_dir, non_interactive=True):
640 settings_path = default_settings_path(top_dir) 640 settings_path = default_settings_path(top_dir)
641 if not os.path.exists(settings_path) or force_replace: 641 settings = configparser.ConfigParser()
642 642 settings['default'] = {
643 settings = configparser.ConfigParser() 643 }
644 settings['default'] = { 644 os.makedirs(os.path.dirname(settings_path), exist_ok=True)
645 'registry':default_registry, 645
646 'dl-dir':os.path.join(top_dir, '.bitbake-setup-downloads'), 646 siteconfpath = os.path.join(top_dir, 'site.conf')
647 } 647 print('A new empty settings file will be created in (you can add settings to it to override defaults from the global settings file)\n {}\n'.format(settings_path))
648 os.makedirs(os.path.dirname(settings_path), exist_ok=True) 648 print('A common site.conf file will be created, please edit or replace before running builds\n {}\n'.format(siteconfpath))
649 649 if not non_interactive:
650 siteconfpath = os.path.join(top_dir, 'site.conf') 650 y_or_n = input('Bitbake-setup will be configured with the above settings in {}, (y/N): '.format(top_dir))
651 print('Configuration registry set to\n {}\n'.format(settings['default']['registry'])) 651 if y_or_n != 'y':
652 print('Bitbake-setup download cache (DL_DIR) set to\n {}\n'.format(settings['default']['dl-dir'])) 652 print("\nYou can run 'bitbake-setup install-settings' to edit them before setting up builds")
653 print('A new settings file will be created in\n {}\n'.format(settings_path)) 653 exit()
654 print('A common site.conf file will be created, please edit or replace before running builds\n {}\n'.format(siteconfpath)) 654 print()
655 if not non_interactive:
656 y_or_n = input('Bitbake-setup will be configured with the above settings in {}, (y/N): '.format(top_dir))
657 if y_or_n != 'y':
658 print("\nYou can run 'bitbake-setup install-settings' to edit them before setting up builds")
659 exit()
660 print()
661
662 if os.path.exists(settings_path):
663 backup_conf = settings_path + "-backup.{}".format(time.strftime("%Y%m%d%H%M%S"))
664 os.rename(settings_path, backup_conf)
665 print("Previous settings are in {}".format(backup_conf))
666 with open(settings_path, 'w') as settingsfile:
667 settings.write(settingsfile)
668
669 if os.path.exists(siteconfpath):
670 backup_siteconf = siteconfpath + "-backup.{}".format(time.strftime("%Y%m%d%H%M%S"))
671 os.rename(siteconfpath, backup_siteconf)
672 print("Previous settings are in {}".format(backup_siteconf))
673 with open(siteconfpath, 'w') as siteconffile:
674 siteconffile.write('# This file is intended for build host-specific bitbake settings\n')
675 655
676def load_settings(top_dir, non_interactive): 656 if os.path.exists(settings_path):
677 # This creates a new settings file if it does not yet exist 657 backup_conf = settings_path + "-backup.{}".format(time.strftime("%Y%m%d%H%M%S"))
678 write_settings(top_dir, force_replace=False, non_interactive=non_interactive) 658 os.rename(settings_path, backup_conf)
659 print("Previous settings are in {}".format(backup_conf))
660 with open(settings_path, 'w') as settingsfile:
661 settings.write(settingsfile)
662
663 if os.path.exists(siteconfpath):
664 backup_siteconf = siteconfpath + "-backup.{}".format(time.strftime("%Y%m%d%H%M%S"))
665 os.rename(siteconfpath, backup_siteconf)
666 print("Previous settings are in {}".format(backup_siteconf))
667 with open(siteconfpath, 'w') as siteconffile:
668 siteconffile.write('# This file is intended for build host-specific bitbake settings\n')
679 669
670def load_settings(top_dir, non_interactive):
680 settings_path = default_settings_path(top_dir) 671 settings_path = default_settings_path(top_dir)
672 if not os.path.exists(settings_path):
673 create_settings(top_dir, non_interactive=non_interactive)
674
681 settings = configparser.ConfigParser() 675 settings = configparser.ConfigParser()
682 print('Loading settings from\n {}\n'.format(settings_path)) 676 print('Loading settings from\n {}\n'.format(settings_path))
683 settings.read_file(open(settings_path)) 677 settings.read_file(open(settings_path))
684 return settings 678 return settings
685 679
686def global_settings_path(args): 680def global_settings_path(args):
687 return os.path.abspath(args.global_settings) if args.global_settings else os.path.join(os.path.expanduser('~'), '.config', 'bitbake-setup', 'config') 681 return os.path.abspath(args.global_settings) if args.global_settings else os.path.join(os.path.expanduser('~'), '.config', 'bitbake-setup', 'settings.conf')
688 682
689def write_global_settings(settings_path, force_replace, non_interactive=True): 683def create_global_settings(settings_path, non_interactive=True):
690 if not os.path.exists(settings_path) or force_replace: 684 settings = configparser.ConfigParser()
691 685 settings['default'] = {
692 settings = configparser.ConfigParser() 686 'top-dir-prefix':os.path.expanduser('~'),
693 settings['default'] = { 687 'top-dir-name':'bitbake-builds',
694 'top-dir-prefix':os.path.expanduser('~'), 688 'registry':default_registry,
695 'top-dir-name':'bitbake-builds' 689 'dl-dir':os.path.join(os.path.expanduser('~'), '.cache', 'bitbake-setup', 'downloads'),
696 } 690 }
697 os.makedirs(os.path.dirname(settings_path), exist_ok=True) 691 os.makedirs(os.path.dirname(settings_path), exist_ok=True)
698 print('Configuring global settings in\n {}\n'.format(settings_path)) 692 print('Configuring global settings in\n {}\n'.format(settings_path))
699 print('Top directory prefix (where all top level directories are created) set to\n {}\n'.format(settings['default']['top-dir-prefix'])) 693 print('Top directory prefix (where all top level directories are created) set to\n {}\n'.format(settings['default']['top-dir-prefix']))
700 print('Top directory name (this is added to the top directory prefix to form a top directory where builds are set up) set to\n {}\n'.format(settings['default']['top-dir-name'])) 694 print('Top directory name (this is added to the top directory prefix to form a top directory where builds are set up) set to\n {}\n'.format(settings['default']['top-dir-name']))
701 if not non_interactive: 695 print('Configuration registry set to\n {}\n'.format(settings['default']['registry']))
702 y_or_n = input('Write out the global settings as specified above (y/N)? ') 696 print('Bitbake-setup download cache (DL_DIR) set to\n {}\n'.format(settings['default']['dl-dir']))
703 if y_or_n != 'y': 697 if not non_interactive:
704 print("\nYou can run 'bitbake-setup install-global-settings' to edit them before setting up builds") 698 y_or_n = input('Write out the global settings as specified above (y/N)? ')
705 exit() 699 if y_or_n != 'y':
706 print() 700 print("\nYou can run 'bitbake-setup install-global-settings' to edit them before setting up builds")
707 701 exit()
708 if os.path.exists(settings_path): 702 print()
709 backup_conf = settings_path + "-backup.{}".format(time.strftime("%Y%m%d%H%M%S")) 703
710 os.rename(settings_path, backup_conf) 704 if os.path.exists(settings_path):
711 print("Previous global settings are in {}".format(backup_conf)) 705 backup_conf = settings_path + "-backup.{}".format(time.strftime("%Y%m%d%H%M%S"))
712 with open(settings_path, 'w') as settingsfile: 706 os.rename(settings_path, backup_conf)
713 settings.write(settingsfile) 707 print("Previous global settings are in {}".format(backup_conf))
708 with open(settings_path, 'w') as settingsfile:
709 settings.write(settingsfile)
714 710
715def load_global_settings(settings_path, non_interactive): 711def load_global_settings(settings_path, non_interactive):
716 # This creates a new settings file if it does not yet exist 712 if not os.path.exists(settings_path):
717 write_global_settings(settings_path, force_replace=False, non_interactive=non_interactive) 713 create_global_settings(settings_path, non_interactive=non_interactive)
718 714
719 settings = configparser.ConfigParser() 715 settings = configparser.ConfigParser()
720 print('Loading global settings from\n {}\n'.format(settings_path)) 716 print('Loading global settings from\n {}\n'.format(settings_path))
721 settings.read_file(open(settings_path)) 717 settings.read_file(open(settings_path))
722 return settings 718 return settings
723 719
724def change_settings(top_dir, new_settings): 720def change_setting(settings_path, settings, args):
725 settings = load_settings(top_dir, non_interactive=True) 721 if args.section and args.key and args.value:
726 for section, section_settings in new_settings.items(): 722 settings[args.section][args.key] = args.value
727 for setting, value in section_settings.items(): 723 print("Setting '{}' in section '{}' is changed to '{}'".format(args.key, args.section, args.value))
728 settings[section][setting] = value 724 if args.unset:
729 print("Setting '{}' in section '{}' is changed to '{}'".format(setting, section, value)) 725 section = args.unset[0]
726 setting = args.unset[1]
727 if section in settings.keys() and setting in settings[section].keys():
728 del settings[section][setting]
729 print("Setting '{} in section '{}' is removed".format(setting, section))
730 730
731 settings_path = default_settings_path(top_dir)
732 with open(settings_path, 'w') as settingsfile: 731 with open(settings_path, 'w') as settingsfile:
733 settings.write(settingsfile) 732 settings.write(settingsfile)
734 print("New settings written to {}".format(settings_path)) 733 print("New settings written to {}".format(settings_path))
735 return settings
736 734
737def change_global_settings(settings_path, new_settings): 735def setting_global(args):
738 settings = load_global_settings(settings_path, non_interactive=True) 736 settings = load_global_settings(global_settings_path(args), args.non_interactive)
739 for section, section_settings in new_settings.items(): 737 settings_path = global_settings_path(args)
740 for setting, value in section_settings.items(): 738 change_setting(settings_path, settings, args)
741 settings[section][setting] = value
742 print("Setting '{}' in section '{}' is changed to '{}'".format(setting, section, value))
743 739
744 with open(settings_path, 'w') as settingsfile: 740def setting(top_dir, args):
745 settings.write(settingsfile) 741 settings = load_settings(top_dir, args.non_interactive)
746 print("New global settings written to {}".format(settings_path)) 742 settings_path = default_settings_path(top_dir)
747 return settings 743 change_setting(settings_path, settings, args)
748 744
749def get_build_dir_via_bbpath(): 745def get_build_dir_via_bbpath():
750 bbpath = os.environ.get('BBPATH') 746 bbpath = os.environ.get('BBPATH')
@@ -755,7 +751,7 @@ def get_build_dir_via_bbpath():
755 return build_dir 751 return build_dir
756 return None 752 return None
757 753
758def get_top_dir(args, global_settings): 754def get_top_dir(args, settings):
759 build_dir_via_bbpath = get_build_dir_via_bbpath() 755 build_dir_via_bbpath = get_build_dir_via_bbpath()
760 if build_dir_via_bbpath: 756 if build_dir_via_bbpath:
761 top_dir = os.path.dirname(build_dir_via_bbpath) 757 top_dir = os.path.dirname(build_dir_via_bbpath)
@@ -763,20 +759,25 @@ def get_top_dir(args, global_settings):
763 return top_dir 759 return top_dir
764 760
765 if hasattr(args, 'build_dir'): 761 if hasattr(args, 'build_dir'):
766 # commands without --top-dir-prefix/name arguments (status, update) still need to know where
767 # the top dir is, but it should be auto-deduced as parent of args.build_dir
768 top_dir = os.path.dirname(os.path.normpath(args.build_dir)) 762 top_dir = os.path.dirname(os.path.normpath(args.build_dir))
769 return top_dir 763 return top_dir
770 764
771 top_dir_prefix = args.top_dir_prefix if args.top_dir_prefix else global_settings['default']['top-dir-prefix'] 765 top_dir_prefix = settings['default']['top-dir-prefix']
772 top_dir_name = args.top_dir_name if args.top_dir_name else global_settings['default']['top-dir-name'] 766 top_dir_name = settings['default']['top-dir-name']
773 return os.path.join(top_dir_prefix, top_dir_name) 767 return os.path.join(top_dir_prefix, top_dir_name)
774 768
775def main(): 769def merge_settings(global_settings, local_settings, cmdline_settings):
776 def add_top_dir_arg(parser): 770 all_settings = global_settings
777 parser.add_argument('--top-dir-prefix', help='Top level directory prefix. This is where all top level directories are created.') 771 for section, section_settings in local_settings.items():
778 parser.add_argument('--top-dir-name', help='Top level directory name. Together with the top directory prefix this forms a top directory where builds are set up and downloaded configurations and layers are cached for reproducibility and offline builds.') 772 for setting, value in section_settings.items():
773 all_settings[section][setting] = value
774
775 for (section, setting, value) in cmdline_settings:
776 all_settings[section][setting] = value
777
778 return all_settings
779 779
780def main():
780 def add_build_dir_arg(parser): 781 def add_build_dir_arg(parser):
781 build_dir = get_build_dir_via_bbpath() 782 build_dir = get_build_dir_via_bbpath()
782 if build_dir: 783 if build_dir:
@@ -792,18 +793,17 @@ def main():
792 parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true') 793 parser.add_argument('-q', '--quiet', help='Print only errors', action='store_true')
793 parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR') 794 parser.add_argument('--color', choices=['auto', 'always', 'never'], default='auto', help='Colorize output (where %(metavar)s is %(choices)s)', metavar='COLOR')
794 parser.add_argument('--no-network', action='store_true', help='Do not check whether configuration repositories and layer repositories have been updated; use only the local cache.') 795 parser.add_argument('--no-network', action='store_true', help='Do not check whether configuration repositories and layer repositories have been updated; use only the local cache.')
795 parser.add_argument('--global-settings', action='store', help='Path to the global settings file where defaults for top directory prefix and name can be specified') 796 parser.add_argument('--global-settings', action='store', help='Path to the global settings file.')
797 parser.add_argument('--setting', default=[], action='append', nargs=3, help='Modify a setting (for this bitbake-setup invocation only), for example "--setting default top-dir-prefix /path/to/top/dir".')
796 798
797 subparsers = parser.add_subparsers() 799 subparsers = parser.add_subparsers()
798 800
799 parser_list = subparsers.add_parser('list', help='List available configurations') 801 parser_list = subparsers.add_parser('list', help='List available configurations')
800 add_top_dir_arg(parser_list)
801 parser_list.add_argument('--with-expired', action='store_true', help='List also configurations that are no longer supported due to reaching their end-of-life dates.') 802 parser_list.add_argument('--with-expired', action='store_true', help='List also configurations that are no longer supported due to reaching their end-of-life dates.')
802 parser_list.add_argument('--write-json', action='store', help='Write available configurations into a json file so they can be programmatically processed.') 803 parser_list.add_argument('--write-json', action='store', help='Write available configurations into a json file so they can be programmatically processed.')
803 parser_list.set_defaults(func=list_configs) 804 parser_list.set_defaults(func=list_configs)
804 805
805 parser_init = subparsers.add_parser('init', help='Select a configuration and initialize a build from it') 806 parser_init = subparsers.add_parser('init', help='Select a configuration and initialize a build from it')
806 add_top_dir_arg(parser_init)
807 parser_init.add_argument('config', nargs='*', help="path/URL/id to a configuration file (use 'list' command to get available ids), followed by configuration options. Bitbake-setup will ask to choose from available choices if command line doesn't completely specify them.") 807 parser_init.add_argument('config', nargs='*', help="path/URL/id to a configuration file (use 'list' command to get available ids), followed by configuration options. Bitbake-setup will ask to choose from available choices if command line doesn't completely specify them.")
808 parser_init.add_argument('--non-interactive', action='store_true', help='Do not ask to interactively choose from available options; if bitbake-setup cannot make a decision it will stop with a failure.') 808 parser_init.add_argument('--non-interactive', action='store_true', help='Do not ask to interactively choose from available options; if bitbake-setup cannot make a decision it will stop with a failure.')
809 parser_init.add_argument('--source-overrides', action='store', help='Override sources information (repositories/revisions) with values from a local json file.') 809 parser_init.add_argument('--source-overrides', action='store', help='Override sources information (repositories/revisions) with values from a local json file.')
@@ -824,25 +824,16 @@ def main():
824 parser_install_buildtools.add_argument('--force', action='store_true', help='Force a reinstall of buildtools over the previous installation.') 824 parser_install_buildtools.add_argument('--force', action='store_true', help='Force a reinstall of buildtools over the previous installation.')
825 parser_install_buildtools.set_defaults(func=install_buildtools) 825 parser_install_buildtools.set_defaults(func=install_buildtools)
826 826
827 parser_install_settings = subparsers.add_parser('install-settings', help='Write a settings file with default values into the top level directory (contains the location of build configuration registry, downloads directory and other settings specific to a top directory)') 827 parser_install_global_settings = subparsers.add_parser('install-global-settings', help='Write a global settings file with default values')
828 add_top_dir_arg(parser_install_settings) 828 parser_install_global_settings.set_defaults(func=create_global_settings)
829 parser_install_settings.set_defaults(func=write_settings)
830
831 parser_install_global_settings = subparsers.add_parser('install-global-settings', help='Write a global settings file with default values (contains the default prefix and name of the top directory)')
832 parser_install_global_settings.set_defaults(func=write_global_settings)
833
834 parser_change_setting = subparsers.add_parser('change-setting', help='Change a setting in the settings file')
835 add_top_dir_arg(parser_change_setting)
836 parser_change_setting.add_argument('section', help="Section in a settings file, typically 'default'")
837 parser_change_setting.add_argument('key', help="Name of the setting")
838 parser_change_setting.add_argument('value', help="Value of the setting")
839 parser_change_setting.set_defaults(func=change_settings)
840 829
841 parser_change_global_setting = subparsers.add_parser('change-global-setting', help='Change a setting in the global settings file') 830 parser_setting = subparsers.add_parser('setting', help='Set or unset a setting in a setting file (e.g. the default prefix and name of the top directory, the location of build configuration registry, downloads directory and other settings specific to a top directory)')
842 parser_change_global_setting.add_argument('section', help="Section in a global settings file, typically 'default'") 831 parser_setting.add_argument('section', nargs='?', help="Section in a settings file, typically 'default'")
843 parser_change_global_setting.add_argument('key', help="Name of the setting") 832 parser_setting.add_argument('key', nargs='?', help="Name of the setting")
844 parser_change_global_setting.add_argument('value', help="Value of the setting") 833 parser_setting.add_argument('value', nargs='?', help="Value of the setting")
845 parser_change_global_setting.set_defaults(func=change_global_settings) 834 parser_setting.add_argument('--global', action='store_true', help="Modify the setting in a global settings file, rather than one specific to a top directory")
835 parser_setting.add_argument('--unset', nargs=2, help="Unset a setting, e.g. 'bitbake-setup setting --unset default registry' would revert to the registry setting in a global settings file")
836 parser_setting.set_defaults(func=setting)
846 837
847 args = parser.parse_args() 838 args = parser.parse_args()
848 839
@@ -859,11 +850,8 @@ def main():
859 level=logger.getEffectiveLevel()) 850 level=logger.getEffectiveLevel())
860 851
861 if 'func' in args: 852 if 'func' in args:
862 if args.func == write_global_settings: 853 if args.func == create_global_settings:
863 write_global_settings(global_settings_path(args), force_replace=True) 854 create_global_settings(global_settings_path(args))
864 return
865 elif args.func == change_global_settings:
866 change_global_settings(global_settings_path(args), {args.section:{args.key:args.value}})
867 return 855 return
868 856
869 if hasattr(args, 'build_dir'): 857 if hasattr(args, 'build_dir'):
@@ -874,19 +862,24 @@ def main():
874 if not hasattr(args, 'non_interactive'): 862 if not hasattr(args, 'non_interactive'):
875 args.non_interactive = True 863 args.non_interactive = True
876 864
865 if args.func == setting and vars(args)['global']:
866 setting_global(args)
867 return
868
877 global_settings = load_global_settings(global_settings_path(args), args.non_interactive) 869 global_settings = load_global_settings(global_settings_path(args), args.non_interactive)
878 args.top_dir = get_top_dir(args, global_settings) 870 top_dir = get_top_dir(args, merge_settings(global_settings, {}, args.setting))
879 871
880 print('Bitbake-setup is using {} as top directory (can be changed with --top-dir-prefix/name arguments or by setting them in {}).\n'.format(args.top_dir, global_settings_path(args))) 872 if args.func == setting:
881 if args.func == write_settings: 873 setting(top_dir, args)
882 write_settings(args.top_dir, force_replace=True) 874 return
883 elif args.func == change_settings: 875
884 change_settings(args.top_dir, {args.section:{args.key:args.value}}) 876 print('Bitbake-setup is using {} as top directory (can be changed by setting top dir prefix and name in {}).\n'.format(top_dir, global_settings_path(args)))
885 else: 877
886 settings = load_settings(args.top_dir, args.non_interactive) 878 settings = load_settings(top_dir, args.non_interactive)
887 d = init_bb_cache(settings, args) 879 settings = merge_settings(global_settings, settings, args.setting)
888 args.func(settings, args, d) 880 d = init_bb_cache(top_dir, settings, args)
889 save_bb_cache() 881 args.func(top_dir, settings, args, d)
882 save_bb_cache()
890 else: 883 else:
891 from argparse import Namespace 884 from argparse import Namespace
892 parser.print_help() 885 parser.print_help()
diff --git a/bitbake/lib/bb/tests/setup.py b/bitbake/lib/bb/tests/setup.py
index 495d1da203..22edda40e4 100644
--- a/bitbake/lib/bb/tests/setup.py
+++ b/bitbake/lib/bb/tests/setup.py
@@ -235,16 +235,18 @@ print("BBPATH is {{}}".format(os.environ["BBPATH"]))
235 out = self.runbbsetup("install-global-settings") 235 out = self.runbbsetup("install-global-settings")
236 settings_path = "{}/global-config".format(self.tempdir) 236 settings_path = "{}/global-config".format(self.tempdir)
237 self.assertIn(settings_path, out[0]) 237 self.assertIn(settings_path, out[0])
238 out = self.runbbsetup("change-global-setting default top-dir-prefix {}".format(self.tempdir)) 238 out = self.runbbsetup("setting --global default top-dir-prefix {}".format(self.tempdir))
239 self.assertIn("Setting 'top-dir-prefix' in section 'default' is changed to", out[0]) 239 self.assertIn("Setting 'top-dir-prefix' in section 'default' is changed to", out[0])
240 self.assertIn("New global settings written to".format(settings_path), out[0]) 240 self.assertIn("New settings written to".format(settings_path), out[0])
241 out = self.runbbsetup("setting --global default dl-dir {}".format(os.path.join(self.tempdir, 'downloads')))
242 self.assertIn("Setting 'dl-dir' in section 'default' is changed to", out[0])
243 self.assertIn("New settings written to".format(settings_path), out[0])
241 244
242 # check that writing settings works and then adjust them to point to 245 # check that writing settings works and then adjust them to point to
243 # test registry repo 246 # test registry repo
244 out = self.runbbsetup("install-settings") 247 out = self.runbbsetup("setting default registry 'git://{};protocol=file;branch=master;rev=master'".format(self.registrypath))
245 settings_path = "{}/bitbake-builds/bitbake-setup.conf".format(self.tempdir) 248 settings_path = "{}/bitbake-builds/settings.conf".format(self.tempdir)
246 self.assertIn(settings_path, out[0]) 249 self.assertIn(settings_path, out[0])
247 out = self.runbbsetup("change-setting default registry 'git://{};protocol=file;branch=master;rev=master'".format(self.registrypath))
248 self.assertIn("Setting 'registry' in section 'default' is changed to", out[0]) 250 self.assertIn("Setting 'registry' in section 'default' is changed to", out[0])
249 self.assertIn("New settings written to".format(settings_path), out[0]) 251 self.assertIn("New settings written to".format(settings_path), out[0])
250 252