Exemple #1
0
def soft_config_copy(
    src: pathlib.Path,
    dest: pathlib.Path,
    dry_run: bool = True,
    keep_backup: bool = True,
) -> bool:
    """
    returns: True if it worked, False otherwise
    """
    if not src.is_file():
        utils.echo(f"{src} NOT FOUND!", color=utils.bcolors.DEBUG)
        return False

    if dest.is_file() and utils.is_symlink(dest, src):
        utils.echo(f"Already soft-linked: {dest}\n", color=utils.bcolors.DEBUG)
        return False

    if not dest.parent.is_dir():
        utils.mkdirs(dest.parent, dry_run=dry_run)

    if dest.is_file() and keep_backup:
        backup_path = dest.parent / f"{dest.name}_{utils.get_timestamp()}"
        utils.cp(src=dest, dest=backup_path, dry_run=dry_run)

    utils.soft_ln(src=src, dest=dest, dry_run=dry_run)
    return True
Exemple #2
0
def hard_config_copy(
    src: pathlib.Path,
    dest: pathlib.Path,
    dry_run: bool = True,
    keep_backup: bool = True,
) -> bool:
    """
    returns: True if it worked, False otherwise
    """
    if not src.is_file():
        utils.echo(f"{src} NOT FOUND!", color=utils.bcolors.DEBUG)
        return False

    if dest.is_file() and os.path.samefile(src, dest):
        utils.echo(f"Already hard-linked: {dest}\n", color=utils.bcolors.DEBUG)
        # resolved dest hard-link points back to the source!
        return False

    if not dest.parent.is_dir():
        utils.mkdirs(dest.parent, dry_run=dry_run)

    if dest.is_file() and keep_backup:
        backup_path = dest.parent / f"{dest.name}_{utils.get_timestamp()}"
        utils.cp(src=dest, dest=backup_path, dry_run=dry_run)

    utils.hard_ln(src=src, dest=dest, dry_run=dry_run)
    return True
Exemple #3
0
def apply_dotfiles(
    input_dotfiles: T.Set,
    dry_run: bool = True,
    homedir: T.Optional[str] = None,
    keep_backup: bool = True,
) -> None:
    if not input_dotfiles:
        utils.echo("Empty dotfile input, skipping!",
                   color=utils.bcolors.WARNING)
        utils.echo(f"Possible keys:\n{report_dotmap(DOTFILE_MAP)}",
                   color=utils.bcolors.INFO)
        return None

    if not isinstance(input_dotfiles, set):
        input_dotfiles = set(input_dotfiles)

    # Case-insensitive matching
    l_map = {k.lower(): k for k in DOTFILE_MAP}
    unkown_keys = {k for k in input_dotfiles if k.lower() not in l_map}
    known_keys = {
        l_map[k.lower()]
        for k in input_dotfiles if k.lower() in l_map
    }

    # give unkown keys the chance to expand
    expanded_keys = set()
    invalid_keys = set()
    for unmatched_key in unkown_keys:
        matched_keys = [
            known_k for l_k, known_k in l_map.items()
            if l_k.startswith(unmatched_key.lower())
        ]
        if not matched_keys:
            invalid_keys.add(unmatched_key)
        else:
            expanded_keys.update(matched_keys)

    # match_keys
    if invalid_keys:
        utils.echo(
            ["Removing invalid install keys:"] + sorted(invalid_keys),
            color=utils.bcolors.WARNING,
            sep="\n\t> ",
        )
    input_dotfiles = known_keys.union(expanded_keys)

    # Filter the dotfile map
    dotfile_map = {k: DOTFILE_MAP[k] for k in input_dotfiles}

    dotabsfilepath_map = map_dotfiles_to_paths(dotfile_map, homedir=homedir)
    for src_config_file, dest_config_file in dotabsfilepath_map.items():
        if soft_config_copy(
                src_config_file,
                dest_config_file,
                dry_run=dry_run,
                keep_backup=keep_backup,
        ):
            utils.echo(f"{src_config_file} -> {dest_config_file}",
                       color=utils.bcolors.INFO)
Exemple #4
0
def build_aptget_pkg_maps(
    pkg_keys: Optional[Sequence[str]] = None,
) -> Tuple[Dict[str, str], Dict[str, str]]:
    """
    Gets the commands for the packages with keys *pkg_keys* and returns the (*install_map*, *remove map*)
    """
    pkg_subset = (set(TRIVIAL_PGKS).union(PKG_PPAs).union(RENAMED_PKGs).union(
        MULTIPLE_PKGs))

    if pkg_keys:
        pkg_subset = pkg_subset.intersection(pkg_keys)
        lost_inputs = set(pkg_keys).difference(pkg_subset)
        if lost_inputs:
            echo(
                ([f"[{len(lost_inputs)}] UNKNOWN APT-GET pkg(s)"] + [
                    f"[{idx:> 3}] {p}"
                    for idx, p in enumerate(sorted(lost_inputs), start=1)
                ]),
                color=bcolors.WARNING,
                sep="\n\t> ",
            )

    if not pkg_subset:
        echo("No APT-GET pkgs will be installed!",
             color=bcolors.WARNING,
             sep="\n\t> ")
        return dict(), dict()

    if pkg_keys:
        echo(
            ([f"[{len(pkg_subset)}] Filtered APT-GET pkgs:"] + [
                f"[{idx:> 3}] {p}"
                for idx, p in enumerate(sorted(pkg_subset), start=1)
            ]),
            color=bcolors.DEBUG,
            sep="\n\t> ",
        )

    install_map, remove_map = dict(), dict()

    for pkg in pkg_subset:
        # Explode each name into all of the subpackages it contains
        subpkgs_to_install = MULTIPLE_PKGs.get(pkg, [pkg])

        # Get their "real-names" as opposed to our keys
        pkgs = [RENAMED_PKGs.get(p, p) for p in subpkgs_to_install]
        ppas = [PKG_PPAs.get(p, p) for p in subpkgs_to_install]

        install_map[pkg] = aptget_install(pkgs=pkgs, ppas=ppas)
        remove_map[pkg] = aptget_remove(pkgs=pkgs, ppas=ppas)

    return install_map, remove_map
Exemple #5
0
def git_pkg_vers(
    pkg_keys: Union[None, str, Sequence[str]] = None, ) -> Dict[str, str]:
    pgk_subset = set(NAME_TO_REPO_MAP)
    if pkg_keys:
        pgk_subset = pgk_subset.intersection(pkg_keys)

        lost_inputs = set(pkg_keys).difference(pgk_subset)
        if lost_inputs:
            echo(
                ([f"[{len(lost_inputs)}] UNKNOWN GIT pkg(s)"] + [
                    f"[{idx:> 3}] {p}"
                    for idx, p in enumerate(sorted(lost_inputs), start=1)
                ]),
                color=bcolors.WARNING,
                sep="\n\t> ",
            )

    if not pgk_subset:
        echo(
            "No GIT pkgs versions will be searched for!",
            color=bcolors.WARNING,
            sep="\n\t> ",
        )
        return dict()

    echo(
        ([f"[{len(pgk_subset)}] Filtered APT-GET pkgs:"] + [
            f"[{idx:> 3}] {p}"
            for idx, p in enumerate(sorted(pgk_subset), start=1)
        ]),
        color=bcolors.DEBUG,
        sep="\n\t> ",
    )

    vers = get_release_tags([NAME_TO_REPO_MAP[k] for k in pgk_subset])
    return {k: v for k, v in zip(pgk_subset, vers)}
Exemple #6
0
    parser.add_argument("-y",
                        "--yes",
                        action="store_true",
                        help="Don't ask for confirmation")

    args = parser.parse_args()
    input_dotfiles = args.dotfiles
    dry_run = args.dry
    # dry_run = True  # TODO DEBUGGING

    parser = argparse.ArgumentParser()

    input_paths = [f for f in input_dotfiles if os.path.isfile(f)]
    input_dotfiles = [f for f in input_dotfiles if f not in input_paths]

    for f in input_paths:
        # TODO DOES THIS WORK?
        with open(f, "r") as fp:
            input_dotfiles.extend(fp.readlines())

    # No inputs?
    if not input_dotfiles:
        utils.echo(f"No inputs given!", color=utils.bcolors.INFO)
        utils.echo(f"Possible keys:\n{report_dotmap(DOTFILE_MAP)}",
                   color=utils.bcolors.INFO)
        sys.exit(0)

    # Valid inputs?
    apply_dotfiles(input_dotfiles, dry_run=dry_run)
    utils.echo("\n\nDone!\n\n", color=utils.bcolors.BOLD + utils.bcolors.DEBUG)
Exemple #7
0
                        action="store_true",
                        help="More output")

    parser.add_argument("-y",
                        "--yes",
                        action="store_true",
                        help="Don't ask for confirmation")

    args = parser.parse_args()
    pkgs = args.pkgs
    args.dry = True  # TODO DEBUG MODE

    if not pkgs:
        echo(
            ["No inputs given, you can choose from these possible keys:"] +
            sorted(possible_pkg_keys),
            color=bcolors.INFO,
            sep="\n\t> ",
        )
        sys.exit(0)

    if len(pkgs) == 1 and pkgs[0].lower() == "all":
        echo("Warning, no pkgs specified... Install EVERYTHING?",
             color=bcolors.WARNING)
        confirmation = input("[Y]es/[N]o")
        if confirmation.upper()[:1] == "Y":
            pkgs = possible_pkg_keys
        elif confirmation.upper()[:1] == "N":
            echo("OK, stopping...", color=bcolors.WARNING)
            sys.exit(0)
        else:
            echo(f"Unknown selection: {confirmation}", color=bcolors.WARNING)
Exemple #8
0
def map_dotfiles_to_paths(
    dotfile_map: Dict[str, str] = None,
    dotfile_keys: Sequence[str] = None,
    homedir: Optional[str] = None,
    dotfile_dir: Union[str, pathlib.Path] = DOTFILE_DIR,
) -> Dict[str, pathlib.Path]:
    """
    Returns a mapping between each dotfile in *dotfile_map* and its destination, based on the *homedir*
    """
    if dotfile_map is None:
        dotfile_map = DOTFILE_MAP

    if dotfile_keys:
        echo(
            ["Filtering selected dotfile keys:"] + sorted(dotfile_keys),
            color=bcolors.INFO,
            sep="\n\t> ",
        )
        dotfile_map = {
            k: v
            for k, v in dotfile_map.items() if k in dotfile_keys
        }

    if not dotfile_map:
        echo("No dotfiles to map!", color=bcolors.WARNING, sep="\n\t> ")
        return dict()

    if not isinstance(dotfile_dir, pathlib.Path):
        dotfile_dir = pathlib.Path(dotfile_dir)

    # -------------------------------------------------------------------------- #
    # Clean up the dotfile map
    # -------------------------------------------------------------------------- #
    missing_fs = {k for k in dotfile_map if not (dotfile_dir / k).is_file()}

    if missing_fs:
        echo(
            ["Ignoring dotfile mappings with missing src files:"] +
            sorted(missing_fs),
            color=bcolors.WARNING,
            sep="\n\t> ",
        )
        dotfile_map = {
            k: v
            for k, v in dotfile_map.items() if k not in missing_fs
        }

    # Better logic
    if not homedir:
        homedir = os.path.expanduser("~")
        echo(f"Expanding '~' to 'hotexamples_com'\n", color=bcolors.INFO)
        dotfile_map = {
            k: pathlib.Path(v).expanduser().absolute()
            for k, v in dotfile_map.items()
        }
    elif os.path.isdir(homedir):
        echo(f"Using input home directory: hotexamples_com\n")
        dotfile_map = {
            k: pathlib.Path(v.replace("~", str(homedir))).absolute()
            for k, v in dotfile_map.items()
        }
    elif (pathlib.Path("~") / homedir).is_dir():
        homedir = pathlib.Path("~") / homedir
        echo(f"Using input home directory: hotexamples_com\n")
        dotfile_map = {
            k: pathlib.Path(v.replace("~", str(homedir))).absolute()
            for k, v in dotfile_map.items()
        }
    else:
        raise OSError(f"Invalid home directory: hotexamples_com")

    # -------------------------------------------------------------------------- #
    # Match them
    # -------------------------------------------------------------------------- #
    repo_files = {
        str(f.relative_to(dotfile_dir)): f.absolute()
        for f in dotfile_dir.rglob("*")
    }

    matched_ks = set(repo_files).intersection(dotfile_map)
    missed_ks = set(repo_files).difference(repo_files)

    if missed_ks:
        echo(
            ["files without mappings:"] + sorted(missed_ks),
            sep="\n\t> ",
            color=bcolors.WARNING,
        )

    bad_map_ks = {k for k in matched_ks if REPO_DIR in dotfile_map[k].parents}

    if bad_map_ks:
        echo(
            ["invalid dest mappings:"] + sorted(bad_map_ks),
            sep="\n\t> ",
            color=bcolors.WARNING,
        )
        matched_ks = matched_ks.difference(bad_map_ks)

    if not matched_ks:
        echo(f"No known dotfiles were found!", color=bcolors.FAIL)
        raise ValueError(f"No matched_ks found!")

    return {
        dotfile_dir / k: dotfile_map[k]
        for k in repo_files if k in matched_ks
    }