def check_for_notmuch_database(email_archive_folder): notmuch_database_folder = email_archive_folder / Path( "_Maildirs/.notmuch/xapian") if not os.path.isdir(notmuch_database_folder): eprint( '''Error: notmuch has not created the xapian database yet. Run \"mail_update [email protected] --update\" first. Exiting.''' ) sys.exit(1)
def create_root_device( ctx, devices: Tuple[Path, ...], partition_table: str, filesystem: str, force: bool, raid: str, raid_group_size: int, verbose: int, verbose_inf: bool, pool_name: str, ): devices = tuple([Path(_device) for _device in devices]) eprint("installing gentoo on root devices:", ' '.join([_device.as_posix() for _device in devices]), '(' + partition_table + ')', '(' + filesystem + ')', '(', pool_name, ')') for _device in devices: if not _device.name.startswith('nvme'): assert not _device.name[-1].isdigit() assert path_is_block_special(_device) assert not block_special_path_is_mounted( _device, verbose=verbose, ) if len(devices) == 1: assert raid == 'disk' else: assert raid != 'disk' if not force: warn( devices, verbose=verbose, ) if pool_name: ctx.invoke( write_sysfs_partition, devices=devices, force=True, filesystem=filesystem, raid=raid, pool_name=pool_name, raid_group_size=raid_group_size, ) else: ctx.invoke( write_sysfs_partition, devices=devices, force=True, filesystem=filesystem, raid=raid, raid_group_size=raid_group_size, )
def check_noupdate_list( *, gpgmda_config_folder: Path, email_address: str, verbose: bool, debug: bool, ): noupdate_list = open(gpgmda_config_folder / Path(".noupdate"), 'r').readlines() # todo move config to ~/.gpgmda for item in noupdate_list: if email_address in item: eprint(email_address + " is listed in .noupdate, exiting") sys.exit(1)
def install(ctx, *, root_devices: Tuple[Path, ...], vm: str, vm_ram: int, boot_device: Path, boot_device_partition_table: str, root_device_partition_table: str, boot_filesystem: str, root_filesystem: str, stdlib: str, arch: str, raid: str, raid_group_size: int, march: str, hostname: str, newpasswd: str, ip: str, ip_gateway: str, mesa_use_enable: list[str], mesa_use_disable: list[str], proxy: str, force: bool, encrypt: bool, pinebook_overlay: bool, kernel: str, multilib: bool, minimal: bool, verbose: int, verbose_inf: bool, skip_to_chroot: bool, ): assert isinstance(root_devices, tuple) boot_device = Path(boot_device) root_devices = tuple([Path(_device) for _device in root_devices]) assert isinstance(root_devices, tuple) assert hostname.lower() == hostname assert '_' not in hostname mount_path = Path("/mnt/gentoo") mount_path_boot = mount_path / Path('boot') mount_path_boot_efi = mount_path_boot / Path('efi') if not skip_to_chroot: distfiles_dir = Path('/var/db/repos/gentoo/distfiles') os.makedirs(distfiles_dir, exist_ok=True) if not os.path.isdir('/var/db/repos/gentoo/sys-kernel'): eprint("run emerge --sync first") sys.exit(1) if encrypt: eprint("encryption not yet supported") #sys.exit(1) if stdlib == 'uclibc': eprint("uclibc fails with efi grub because efivar fails to compile. See Note.") sys.exit(1) os.makedirs(mount_path, exist_ok=True) assert Path('/usr/bin/ischroot').exists() eprint("using C library:", stdlib) eprint("hostname:", hostname) if root_filesystem == '9p': assert vm if vm: assert vm_ram assert root_filesystem == "9p" assert not root_devices assert not boot_device assert not boot_filesystem guests_root = Path('/guests') / Path(vm) guest_path = guests_root / Path(hostname) guest_path_chroot = guests_root / Path(hostname + "-chroot") os.makedirs(guest_path, exist_ok=True) os.makedirs(guest_path_chroot, exist_ok=True) mount_path = guest_path else: assert boot_device assert root_devices if boot_device: assert boot_device_partition_table assert boot_filesystem if root_devices: assert root_device_partition_table if len(root_devices) > 1: assert root_filesystem == 'zfs' elif len(root_devices) == 1: if root_filesystem == 'zfs': assert raid == 'disk' if root_filesystem == 'zfs': assert root_device_partition_table == 'gpt' if root_filesystem == 'zfs' or boot_filesystem == 'zfs': input("note zfs boot/root is not working, many fixes will be needed, press enter to break things") safety_check_devices(boot_device=boot_device, root_devices=root_devices, verbose=verbose, boot_device_partition_table=boot_device_partition_table, boot_filesystem=boot_filesystem, root_device_partition_table=root_device_partition_table, root_filesystem=root_filesystem, force=force,) if boot_device and root_devices and not vm: if boot_device == root_devices[0]: assert boot_filesystem == root_filesystem assert boot_device_partition_table == root_device_partition_table if boot_filesystem == 'zfs': assert False # untested #ctx.invoke(destroy_block_devices_head_and_tail, # devices=root_devices, # force=True, # no_backup=True, # size=(1024 * 1024 * 128), # note=False, # verbose=verbose, # ) ## if this is zfs, it will make a gpt table, / and EFI partition #ctx.invoke(create_root_device, # devices=root_devices, # exclusive=True, # filesystem=root_filesystem, # partition_table=root_device_partition_table, # force=True, # raid=raid, # raid_group_size=raid_group_size, # pool_name=hostname,) #create_boot_device(ctx, # device=boot_device, # partition_table='none', # filesystem=boot_filesystem, # force=True, # verbose=verbose, # ) # dont want to delete the gpt that zfs made #boot_mount_command = False #root_mount_command = False elif boot_filesystem == 'ext4': ctx.invoke(destroy_block_device_head_and_tail, device=boot_device, force=True,) create_boot_device(ctx, device=boot_device, partition_table=boot_device_partition_table, filesystem=boot_filesystem, force=True, verbose=verbose, ) # writes gurb_bios from 48s to 1023s then writes EFI partition from 1024s to 205824s (100M efi) (nope, too big for fat16) ctx.invoke(create_root_device, devices=root_devices, filesystem=root_filesystem, partition_table=root_device_partition_table, force=True, raid=raid, raid_group_size=raid_group_size, pool_name=hostname,) root_partition_path = add_partition_number_to_device(device=root_devices[0], partition_number="3", verbose=verbose,) root_mount_command = "mount " + root_partition_path.as_posix() + " " + str(mount_path) boot_mount_command = False else: # unknown case assert False else: assert False # not tested #eprint("differing root and boot devices: (exclusive) root_devices[0]:", root_devices[0], "boot_device:", boot_device) #create_boot_device(ctx, # device=boot_device, # partition_table=boot_device_partition_table, # filesystem=boot_filesystem, # force=True, # verbose=verbose, # ) #ctx.invoke(write_boot_partition, # device=boot_device, # force=True, # verbose=verbose, # ) #ctx.invoke(create_root_device, # devices=root_devices, # exclusive=True, # filesystem=root_filesystem, # partition_table=root_device_partition_table, # force=True, # raid=raid,) #if root_filesystem == 'zfs': # assert False # root_mount_command = False #elif root_filesystem == 'ext4': # root_partition_path = add_partition_number_to_device(device=root_devices[0], partition_number="1") # root_mount_command = "mount " + root_partition_path.as_posix() + " " + mount_path.as_posix() #boot_partition_path = add_partition_number_to_device(device=boot_device, partition_number="3") #boot_mount_command = "mount " + boot_partition_path.as_posix() + " " + mount_path_boot.as_posix() if root_mount_command: run_command(root_mount_command, verbose=verbose,) assert path_is_mounted(mount_path, verbose=verbose,) os.makedirs(mount_path_boot, exist_ok=True) if boot_mount_command: run_command(boot_mount_command, verbose=verbose,) assert path_is_mounted(mount_path_boot, verbose=verbose,) else: assert not path_is_mounted(mount_path_boot, verbose=verbose,) if boot_device: os.makedirs(mount_path_boot_efi, exist_ok=True) if boot_filesystem == 'zfs': efi_partition_path = add_partition_number_to_device(device=boot_device, partition_number="9", verbose=verbose,) efi_mount_command = "mount " + efi_partition_path.as_posix() + " " + mount_path_boot_efi.as_posix() else: efi_partition_path = add_partition_number_to_device(device=boot_device, partition_number="2", verbose=verbose,) efi_mount_command = "mount " + efi_partition_path.as_posix() + " " + mount_path_boot_efi.as_posix() if boot_device: run_command(efi_mount_command, verbose=verbose,) assert path_is_mounted(mount_path_boot_efi, verbose=verbose,) extract_stage3(stdlib=stdlib, multilib=multilib, arch=arch, destination=mount_path, expect_mounted_destination=True, vm=vm, vm_ram=vm_ram, verbose=verbose, ) # skip_to_chroot lands here if not boot_device: assert False #boot_device = "False" # fixme skip_to_rsync = False if skip_to_chroot: skip_to_rsync = True ctx.invoke(chroot_gentoo, mount_path=mount_path, stdlib=stdlib, boot_device=boot_device, hostname=hostname, march=march, arch=arch, root_filesystem=root_filesystem, newpasswd=newpasswd, kernel=kernel, ip=ip, ip_gateway=ip_gateway, vm=vm, mesa_use_enable=mesa_use_enable, mesa_use_disable=mesa_use_disable, pinebook_overlay=pinebook_overlay, ipython=False, skip_to_rsync=skip_to_rsync, verbose=verbose, )
def write_sysfs_partition( ctx, devices: Tuple[Path, ...], filesystem: str, force: bool, exclusive: bool, raid: str, raid_group_size: int, pool_name: str, verbose: int, verbose_inf: bool, ): tty, verbose = tv( ctx=ctx, verbose=verbose, verbose_inf=verbose_inf, ) devices = tuple([Path(_device) for _device in devices]) ic('creating sysfs partition on:', devices) if filesystem == 'zfs': assert pool_name for device in devices: if not device.name.startswith('nvme'): assert not device.name[-1].isdigit() assert path_is_block_special(device) assert not block_special_path_is_mounted( device, verbose=verbose, ) if not force: warn( devices, verbose=verbose, ) if filesystem in ['ext4', 'fat32']: assert len(devices) == 1 if exclusive: #destroy_block_device_head_and_tail(device=device, force=True) #these are done in create_root_device #write_gpt(device) partition_number = '1' start = "0%" end = "100%" else: partition_number = '3' start = "100MiB" end = "100%" run_command("parted -a optimal " + devices[0].as_posix() + " --script -- mkpart primary " + filesystem + ' ' + start + ' ' + end, verbose=verbose) run_command( "parted " + devices[0].as_posix() + " --script -- name " + partition_number + " rootfs", verbose=verbose, ) time.sleep(1) sysfs_partition_path = add_partition_number_to_device( device=devices[0], partition_number=partition_number, verbose=verbose, ) if filesystem == 'ext4': ext4_command = sh.Command('mkfs.ext4') ext4_command(sysfs_partition_path.as_posix(), _out=sys.stdout, _err=sys.stderr) elif filesystem == 'fat32': mkfs_vfat_command = sh.Command('mkfs.vfat', sysfs_partition_path.as_posix()) mkfs_vfat_command(_out=sys.stdout, _err=sys.stderr) else: eprint("unknown filesystem:", filesystem) sys.exit(1) elif filesystem == 'zfs': assert exclusive assert False ctx.invoke( write_zfs_root_filesystem_on_devices, ctx=ctx, devices=devices, mount_point=None, force=True, raid=raid, raid_group_size=raid_group_size, pool_name=pool_name, verbose=verbose, ) else: eprint("unknown filesystem:", filesystem) sys.exit(1)
def run_notmuch( *, mode, email_address, email_archive_folder, gpgmaildir, query, notmuch_config_file, notmuch_config_folder, ): ic() yesall = False if mode == "update_notmuch_db": current_env = os.environ.copy() current_env["NOTMUCH_CONFIG"] = notmuch_config_file notmuch_new_command = [ "notmuch", "--config=" + notmuch_config_file.as_posix(), "new" ] ic(notmuch_new_command) notmuch_p = subprocess.Popen(notmuch_new_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False, env=current_env) ic(notmuch_p.args) notmuch_p_output = notmuch_p.communicate() ic('notmuch_p_output:') ic(notmuch_p_output) ic('len(notmuch_p_output[0]):', len(notmuch_p_output[0])) ic('notmuch_p_output[0]:') for line in notmuch_p_output[0].split(b'\n'): ic(line.decode('utf-8')) ic('notmuch_p_output[1]:') for line in notmuch_p_output[1].decode('utf8').split('\n'): #line = line.decode('utf-8') ic(line) if "Note: Ignoring non-mail file:" in line: non_mail_file = Path(line.split(" ")[-1]) ic('found file that gmime does not like:', non_mail_file) random_id = Path(non_mail_file.as_posix()[-40:]) ic(random_id) #maildir_subfolder = Path(non_mail_file.parent.parent) maildir_subfolder = Path(non_mail_file.parent).name ic(maildir_subfolder) assert maildir_subfolder in ['new', '.sent'] encrypted_file = Path(gpgmaildir) / Path( maildir_subfolder) / Path(random_id) ic(encrypted_file) ic('head -c 500:') command = "head -c 500 " + non_mail_file.as_posix() os.system(command) with open(non_mail_file, 'rb') as fh: data = fh.read() if data == b'metastable': ic('metastable test message... fixme') if not yesall: #ic('running vi') #command = "vi " + non_mail_file #os.system(command) delete_message_answer = \ input("Would you like to move this message locally to the ~/.gpgmda/non-mail folder and delete it on the server? (yes/no/skipall/yesall): ") if delete_message_answer.lower() == "yesall": yesall = True if delete_message_answer.lower() == "skipall": break else: delete_message_answer = 'yes' if delete_message_answer.lower() == "yes": non_mail_path = Path('~/.gpgmda/non-mail').expanduser() os.makedirs(non_mail_path, exist_ok=True) ic('Processing files for local move and delete:') ic(non_mail_file) sh.mv(non_mail_file, non_mail_path) ic(encrypted_file) sh.mv(encrypted_file, non_mail_path) if maildir_subfolder == ".sent": target_file = Path( "/home/sentuser/gpgMaildir/new/") / random_id command = "ssh [email protected] rm -v " + target_file.as_posix( ) ic(command) os.system(command) elif maildir_subfolder == "new": target_file = Path( "/home/user/gpgMaildir/new/") / random_id command = "ssh [email protected] rm -v " + target_file.as_posix( ) # todo use ~/.gpgmda/config ic(command) os.system(command) else: eprint("unknown maildir_subfolder:", maildir_subfolder.as_posix(), "exiting") sys.exit(1) ic(notmuch_p.returncode) if notmuch_p.returncode != 0: eprint("notmuch new did not return 0, exiting") sys.exit(1) elif mode == "query_notmuch": check_for_notmuch_database(email_archive_folder=email_archive_folder) command = "NOTMUCH_CONFIG=" + notmuch_config_file.as_posix( ) + " notmuch " + query ic(command) return_code = os.system(command) if return_code != 0: eprint("\"notmuch " + query + "\" returned nonzero, exiting") sys.exit(1) elif mode == "query_afew": check_for_notmuch_database(email_archive_folder=email_archive_folder) command = "afew" + " --notmuch-config=" + notmuch_config_file.as_posix( ) + " " + query ic(command) return_code = os.system(command) if return_code != 0: eprint("\"notmuch " + query + "\" returned nonzero, exiting") sys.exit(1) elif mode == "query_address_db": check_for_notmuch_database(email_archive_folder=email_archive_folder) command = "XDG_CONFIG_HOME=" + \ notmuch_config_folder.as_posix() + \ " NOTMUCH_CONFIG=" + \ notmuch_config_file.as_posix() + " " + \ "nottoomuch-addresses.sh " + \ query return_code = os.system(command) if return_code != 0: eprint("\"nottoomuch-addresses.sh\" returned nonzero, exiting") sys.exit(1) elif mode == "build_address_db": check_for_notmuch_database(email_archive_folder=email_archive_folder) command = "XDG_CONFIG_HOME=" + \ notmuch_config_folder.as_posix() + \ " NOTMUCH_CONFIG=" + \ notmuch_config_file.as_posix() + \ " " + \ "nottoomuch-addresses.sh --update --rebuild" return_code = os.system(command) if return_code != 0: eprint("\"nottoomuch-addresses.sh\" returned nonzero, exiting") sys.exit(1) elif mode == "update_address_db": check_for_notmuch_database(email_archive_folder=email_archive_folder) command = "XDG_CONFIG_HOME=" + \ notmuch_config_folder.as_posix() + \ " NOTMUCH_CONFIG=" + \ notmuch_config_file.as_posix() + " " + \ "nottoomuch-addresses.sh --update" return_code = os.system(command) if return_code != 0: eprint("\"nottoomuch-addresses.sh\" returned nonzero, exiting") sys.exit(1) else: ic('invalid', mode, 'exiting.') sys.exit(1)
def gpgmaildir_to_maildir( *, email_address: str, gpgMaildir_archive_folder: Path, gpgmaildir: Path, maildir: Path, verbose: bool, debug: bool, ): # todo add locking ic() assert isinstance(maildir, Path) assert isinstance(gpgmaildir, Path) assert isinstance(gpgMaildir_archive_folder, Path) iterator = None ic('gpgmda_to_maildir using:', gpgMaildir_archive_folder) ic('Checking for default-recipient in ~/.gnupg/gpg.conf') command = "grep \"^default-recipient\" ~/.gnupg/gpg.conf" grep_exit_code = os.system(command) if grep_exit_code != 0: eprint( "error: default-recipient is not defined in ~/.gnupg/gpg.conf. Exiting." ) sys.exit(1) rsync_last_new_mail_file = '/dev/shm/.gpgmda_rsync_last_new_mail_' + email_address ic('checking to see if', rsync_last_new_mail_file, 'exists and is greater than 0 bytes') rsync_files_transferred = 0 if path_exists(rsync_last_new_mail_file): with open(rsync_last_new_mail_file, 'r') as fh: for line in fh.readlines(): if 'Number of regular files transferred:' in line: ic(line) rsync_files_transferred = int(line.split(':')[1].strip()) ic(rsync_files_transferred) break if rsync_files_transferred == 0: ic('rsync transferred 0 files, skipping decrypt') else: rsync_list = parse_rsync_log_to_list( email_address=email_address, gpgMaildir_archive_folder=gpgMaildir_archive_folder) ic(rsync_list) iterator = rsync_list skip_hashes = [] else: ic(rsync_last_new_mail_file, 'does not exist or is 0 bytes') ic('checking if the message counts in the maildir and the gpgmaildir match' ) maildir_counts_dict = get_maildir_file_counts( gpgmaildir=gpgmaildir, maildir=maildir, verbose=verbose, debug=debug, ) ic(maildir_counts_dict) maildir_file_count = maildir_counts_dict['files_in_maildir'] gpgmaildir_file_count = maildir_counts_dict['files_in_gpgmaildir'] ##if gpgmaildir_file_count > maildir_file_count: # not a good check. #if gpgmaildir_file_count != maildir_file_count: # not a good check. # ic('files_in_gpgmaildir != files_in_maildir:', gpgmaildir_file_count, '!=', maildir_file_count) # ic('locating un-decrypted files') # files_in_gpgmaildir = [dent.pathlib for dent in files(gpgmaildir, verbose=verbose, debug=debug,)] # assert isinstance(files_in_gpgmaildir[0], Path) # files_in_maildir = [dent.pathlib for dent in files(maildir, verbose=verbose, debug=debug,)] # ic(len(files_in_gpgmaildir)) # ic(len(files_in_maildir)) # ic(len(files_in_gpgmaildir) - len(files_in_maildir)) # ic('building hash lists') # #hashes_in_gpgmaildir = [path.name.split('.')[-1] for path in files_in_gpgmaildir] # hashes_in_maildir = [path.name.split('.')[-1] for path in files_in_maildir] # ic(len(hashes_in_maildir)) # skip_hashes = hashes_in_maildir # iterator = files_in_gpgmaildir if iterator: # used in 2 places above decrypt_list_of_messages( message_list=iterator, skip_hashes=skip_hashes, email_address=email_address, maildir=maildir, verbose=verbose, debug=debug, )
def new(ctx, language: str, repo_url: str, group: str, branch: str, rename: Optional[str], templates: Optional[tuple[Path]], apps_folder: str, gentoo_overlay_repo: str, github_user: str, license: str, owner: str, owner_email: str, description: str, local: bool, use_existing_repo: bool, verbose: int, verbose_inf: bool, hg: bool, ): not_root() tty, verbose = tv(ctx=ctx, verbose=verbose, verbose_inf=verbose_inf, ) apps_folder = Path(apps_folder) ic(apps_folder) if templates: templates = [t.resolve() for t in templates] if repo_url.endswith('.git'): repo_url = repo_url[:-4] assert '/' not in group assert ':' not in group assert group in portage_categories() assert repo_url.startswith('https://') template_repo_url: Optional[str] = None if not repo_url.startswith('https://github.com/{}/'.format(github_user)): template_repo_url = repo_url _app_name, _app_user, _app_module_name, _app_path = parse_url(repo_url, apps_folder=apps_folder, verbose=verbose, ) if rename: _app_name = rename repo_url = 'https://github.com/{github_user}/{app_name}'.format(github_user=github_user, app_name=_app_name) del _app_name, _app_user, _app_module_name, _app_path else: template_repo_url = None app_name, app_user, app_module_name, app_path = parse_url(repo_url, apps_folder=apps_folder, verbose=verbose, ) ic(app_name) ic(app_user) assert app_user == github_user assert '_' not in app_path.name if language == 'sh': language = 'bash' if language == 'python': ext = '.py' elif language == 'bash': ext = '.sh' elif language == 'zig': ext = '.zig' assert group == 'dev-zig' elif language == 'c': ext = '.c' else: raise ValueError('unsupported language: ' + language) if template_repo_url: clone_repo(repo_url=repo_url, template_repo_url=template_repo_url, apps_folder=apps_folder, hg=hg, branch=branch, app_path=app_path, app_group=group, local=local, verbose=verbose, ) if ((not app_path.exists()) or use_existing_repo): if not use_existing_repo: create_repo(hg=hg, app_path=app_path, app_module_name=app_module_name, verbose=verbose, ) else: assert app_path.is_dir() assert Path(app_path / Path('.git')).exists() with chdir(app_path): os.makedirs(app_module_name, exist_ok=True) if not template_repo_url: with chdir(app_path): if language == 'python': write_setup_py(use_existing_repo=use_existing_repo, app_module_name=app_module_name, app_name=app_name, owner=owner, owner_email=owner_email, description=description, license=license, repo_url=repo_url,) gitignore_template = generate_gitignore_template() if use_existing_repo: with open('.gitignore', 'a') as fh: fh.write(gitignore_template) else: with open('.gitignore', 'x') as fh: fh.write(gitignore_template) if not Path('url.sh').exists(): write_url_sh(repo_url, verbose=verbose,) if language == 'python': os.system("fastep") with chdir(app_path / app_module_name): app_template = generate_app_template(package_name=app_module_name, language=language, append_files=templates, verbose=ctx.obj['verbose'], ) with open(app_module_name + ext, 'x') as fh: fh.write(app_template) if language == 'python': init_template = generate_init_template(package_name=app_module_name) with open("__init__.py", 'x') as fh: fh.write(init_template) sh.touch('py.typed') with chdir(app_path): sh.git.add('--all') sh.git.commit('-m', 'autocomit') with chdir(app_path): with open(".edit_config", 'x') as fh: fh.write(generate_edit_config(package_name=app_name, package_group=group, local=local)) remote_add_origin(hg=hg, app_path=app_path, local=local, app_name=app_name, verbose=verbose, ) else: eprint("Not creating new app, {} already exists.".format(app_path)) ebuild_path = Path(gentoo_overlay_repo) / Path(group) / Path(app_name) if not ebuild_path.exists(): enable_python = False if Path(app_path / Path('setup.py')).exists(): enable_python = True os.makedirs(ebuild_path, exist_ok=False) ebuild_name = app_name + "-9999.ebuild" enable_dobin = False if language in ['bash']: enable_dobin = True with chdir(ebuild_path): with open(ebuild_name, 'w') as fh: fh.write(generate_ebuild_template(app_name=app_name, description=description, enable_python=enable_python, enable_dobin=enable_dobin, homepage=repo_url, app_path=app_path,)) sh.git.add(ebuild_name) sh.ebuild(ebuild_name, 'manifest') sh.git.add('*') os.system("git commit -m 'newapp {}'".format(app_name)) os.system("git push") os.system("sudo emaint sync -A") accept_keyword = "={}/{}-9999 **\n".format(group, app_name) accept_keywords = Path("/etc/portage/package.accept_keywords") / Path(group) / Path(app_name) accept_keywords.parent.mkdir(exist_ok=True) write_line_to_file(path=accept_keywords, line=accept_keyword, unique=True, make_new_if_necessary=True, verbose=verbose, ) sh.ln('-s', ebuild_path / ebuild_name, app_path / ebuild_name) sh.git.diff('--exit-code') # need to commit any pending ebuild changes here, but that's the wront git message, and it fails if it's unhanged sh.git.commit('-m', 'initial commit', _ok_code=[0, 1]) else: eprint('Not creating new ebuild, {} already exists.'.format(ebuild_path)) ic(app_path) ic(app_module_name) main_py_path = app_path / Path(app_module_name) / Path(app_module_name + ext) ic(main_py_path) os.system("edittool edit " + main_py_path.as_posix())