diff --git a/LICENSE b/LICENSE index 7b13d64..b755367 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2014 Ben Kurtovic +Copyright (C) 2011-2014 Ben Kurtovic Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/gitup/__init__.py b/gitup/__init__.py index 9bebff1..7482a7c 100644 --- a/gitup/__init__.py +++ b/gitup/__init__.py @@ -13,4 +13,4 @@ __license__ = "MIT License" __version__ = "0.2.dev" __email__ = "ben.kurtovic@gmail.com" -from . import script, update +from . import config, script, update diff --git a/gitup/config.py b/gitup/config.py index 72c1cbf..5571cfe 100644 --- a/gitup/config.py +++ b/gitup/config.py @@ -3,27 +3,34 @@ # Copyright (C) 2011-2014 Ben Kurtovic # See the LICENSE file for details. +from __future__ import print_function + import ConfigParser as configparser import os -from .output import out, bold, yellow +from colorama import Fore, Style __all__ = ["get_bookmarks", "add_bookmarks", "delete_bookmarks", "list_bookmarks"] -_config_filename = os.path.join(os.path.expanduser("~"), ".gitup") +CONFIG_FILENAME = os.path.join(os.path.expanduser("~"), ".gitup") + +YELLOW = Fore.YELLOW + Style.BRIGHT +RED = Fore.RED + Style.BRIGHT + +INDENT1 = " " * 3 def _load_config_file(): """Read the config file and return a SafeConfigParser() object.""" config = configparser.SafeConfigParser() # Don't lowercase option names, because we are storing paths there: config.optionxform = str - config.read(_config_filename) + config.read(CONFIG_FILENAME) return config def _save_config_file(config): - """Save config changes to the config file specified by _config_filename.""" - with open(_config_filename, "wb") as config_file: + """Save config changes to the config file specified by CONFIG_FILENAME.""" + with open(CONFIG_FILENAME, "wb") as config_file: config.write(config_file) def get_bookmarks(): @@ -40,43 +47,58 @@ def add_bookmarks(paths): if not config.has_section("bookmarks"): config.add_section("bookmarks") - out(0, yellow("Added bookmarks:")) - + added, exists = [], [] for path in paths: - path = os.path.abspath(path) # Convert relative to absolute path + path = os.path.abspath(path) if config.has_option("bookmarks", path): - out(1, "'{0}' is already bookmarked.".format(path)) + exists.append(path) else: path_name = os.path.split(path)[1] config.set("bookmarks", path, path_name) - out(1, bold(path)) - + added.append(path) _save_config_file(config) + if added: + print(YELLOW + "Added bookmarks:") + for path in added: + print(INDENT1, path) + if exists: + print(RED + "Already bookmarked:") + for path in exists: + print(INDENT1, path) + def delete_bookmarks(paths): """Remove a list of paths from the bookmark config file.""" config = _load_config_file() + deleted, notmarked = [], [] if config.has_section("bookmarks"): - out(0, yellow("Deleted bookmarks:")) for path in paths: - path = os.path.abspath(path) # Convert relative to absolute path + path = os.path.abspath(path) config_was_changed = config.remove_option("bookmarks", path) if config_was_changed: - out(1, bold(path)) + deleted.append(path) else: - out(1, "'{0}' is not bookmarked.".format(path)) + notmarked.append(path) _save_config_file(config) - else: - out(0, "There are no bookmarks to delete!") + notmarked = [os.path.abspath(path) for path in paths] + + if deleted: + print(YELLOW + "Deleted bookmarks:") + for path in deleted: + print(INDENT1, path) + if notmarked: + print(RED + "Not bookmarked:") + for path in notmarked: + print(INDENT1, path) def list_bookmarks(): """Print all of our current bookmarks.""" bookmarks = get_bookmarks() if bookmarks: - out(0, yellow("Current bookmarks:")) - for bookmark_path, bookmark_name in bookmarks: - out(1, bookmark_path) + print(YELLOW + "Current bookmarks:") + for bookmark_path, _ in bookmarks: + print(INDENT1, bookmark_path) else: - out(0, "You have no bookmarks to display.") + print("You have no bookmarks to display.") diff --git a/gitup/output.py b/gitup/output.py deleted file mode 100644 index 7b160ea..0000000 --- a/gitup/output.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2011-2014 Ben Kurtovic -# See the LICENSE file for details. - -import re - -__all__ = ["out", "bold", "red", "green", "yellow", "blue"] - -# Text formatting functions: -bold = lambda t: "\x1b[1m" + t + "\x1b[0m" -red = lambda t: "\x1b[1m\x1b[31m" + t + "\x1b[0m" -green = lambda t: "\x1b[1m\x1b[32m" + t + "\x1b[0m" -yellow = lambda t: "\x1b[1m\x1b[33m" + t + "\x1b[0m" -blue = lambda t: "\x1b[1m\x1b[34m" + t + "\x1b[0m" - -def out(indent, msg): - """Print a message at a given indentation level.""" - width = 4 # Amount to indent at each level - if indent == 0: - spacing = "\n" - else: - spacing = " " * width * indent - msg = re.sub(r"\s+", " ", msg) # Collapse multiple spaces into one - print(spacing + msg) diff --git a/gitup/script.py b/gitup/script.py index ea616cd..8105d8a 100644 --- a/gitup/script.py +++ b/gitup/script.py @@ -7,10 +7,11 @@ from __future__ import print_function import argparse +from colorama import init as color_init, Style + from . import __version__, __email__ from .config import (get_bookmarks, add_bookmarks, delete_bookmarks, list_bookmarks) -from .output import out, bold from .update import update_bookmarks, update_directories def main(): @@ -48,8 +49,11 @@ def main(): '-v', '--version', action="version", version="gitup version " + __version__) + color_init(autoreset=True) args = parser.parse_args() - print(bold("gitup") + ": the git-repo-updater") + + print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater") + print() if args.bookmarks_to_add: add_bookmarks(args.bookmarks_to_add) @@ -71,4 +75,4 @@ def run(): try: main() except KeyboardInterrupt: - out(0, "Stopped by user.") + print("Stopped by user.") diff --git a/gitup/update.py b/gitup/update.py index 480a2e9..de2d01b 100644 --- a/gitup/update.py +++ b/gitup/update.py @@ -3,21 +3,24 @@ # Copyright (C) 2011-2014 Ben Kurtovic # See the LICENSE file for details. +from __future__ import print_function + import os import shlex import subprocess -from .output import out, bold, red, green, blue +from colorama import Fore, Style __all__ = ["update_bookmarks", "update_directories"] -def _exec_shell(command): - """Execute a shell command and get the output.""" - command = shlex.split(command) - result = subprocess.check_output(command, stderr=subprocess.STDOUT) - if result: - result = result[:-1] # Strip newline if command returned anything - return result +BOLD = Style.BRIGHT +RED = Fore.RED + BOLD +GREEN = Fore.GREEN + BOLD +BLUE = Fore.BLUE + BOLD +RESET = Style.RESET_ALL + +INDENT1 = " " * 3 +INDENT2 = " " * 7 def _directory_is_git_repo(directory_path): """Check if a directory is a git repository.""" @@ -29,17 +32,25 @@ def _directory_is_git_repo(directory_path): def _update_repository(repo_path, repo_name): """Update a single git repository by pulling from the remote.""" - out(1, bold(repo_name) + ":") + def _exec_shell(command): + """Execute a shell command and get the output.""" + command = shlex.split(command) + result = subprocess.check_output(command, stderr=subprocess.STDOUT) + if result: + result = result[:-1] # Strip newline if command returned anything + return result + + print(INDENT1, BOLD + repo_name + ":") # cd into our folder so git commands target the correct repo: - os.chdir(repo_path) + os.chdir(repo_path) # TODO: remove this when using gitpython try: # Check if there is anything to pull, but don't do it yet: dry_fetch = _exec_shell("git fetch --dry-run") except subprocess.CalledProcessError: - out(2, red("Error: ") + "cannot fetch; do you have a remote " \ - "repository configured correctly?") + print(INDENT2, RED + "Error:" + RESET, "cannot fetch;", + "do you have a remote repository configured correctly?") return try: @@ -48,24 +59,27 @@ def _update_repository(repo_path, repo_name): last_commit = "never" # Couldn't get a log, so no commits if not dry_fetch: # No new changes to pull - out(2, blue("No new changes.") + - " Last commit was {0}.".format(last_commit)) + print(INDENT2, BLUE + "No new changes." + RESET, + "Last commit was {0}.".format(last_commit)) else: # Stuff has happened! - out(2, "There are new changes upstream...") + print(INDENT2, "There are new changes upstream...") status = _exec_shell("git status") if status.endswith("nothing to commit, working directory clean"): - out(2, green("Pulling new changes...")) + print(INDENT2, GREEN + "Pulling new changes...") result = _exec_shell("git pull") - out(2, "The following changes have been made since {0}:".format( - last_commit)) + if last_commit == "never": + print(INDENT2, "The following changes have been made:") + else: + print(INDENT2, "The following changes have been made since", + last_commit + ":") print(result) else: - out(2, red("Warning: ") + - "you have uncommitted changes in this repository!") - out(2, "Ignoring.") + print(INDENT2, RED + "Warning:" + RESET, + "you have uncommitted changes in this repository!") + print(INDENT2, "Ignoring.") def _update_directory(dir_path, dir_name, is_bookmark=False): """Update a particular directory. @@ -79,25 +93,24 @@ def _update_directory(dir_path, dir_name, is_bookmark=False): dir_type = "bookmark" # Where did we get this directory from? else: dir_type = "directory" - - dir_long_name = "{0} '{1}'".format(dir_type, bold(dir_path)) + dir_long_name = dir_type + ' "' + BOLD + dir_path + RESET + '"' try: os.listdir(dir_path) # Test if we can access this directory except OSError: - out(0, red("Error: ") + - "cannot enter {0}; does it exist?".format(dir_long_name)) + print(RED + "Error:" + RESET, + "cannot enter {0}; does it exist?".format(dir_long_name)) return if not os.path.isdir(dir_path): if os.path.exists(dir_path): - out(0, red("Error: ") + dir_long_name + " is not a directory!") + print(RED + "Error:" + RESET, dir_long_name, "is not a directory!") else: - out(0, red("Error: ") + dir_long_name + " does not exist!") + print(RED + "Error:" + RESET, dir_long_name, "does not exist!") return if _directory_is_git_repo(dir_path): - out(0, dir_long_name.capitalize() + " is a git repository:") + print(dir_long_name.capitalize(), "is a git repository:") _update_repository(dir_path, dir_name) else: @@ -112,10 +125,10 @@ def _update_directory(dir_path, dir_name, is_bookmark=False): num_of_repos = len(repositories) if num_of_repos == 1: - out(0, dir_long_name.capitalize() + " contains 1 git repository:") + print(dir_long_name.capitalize(), "contains 1 git repository:") else: - out(0, dir_long_name.capitalize() + - " contains {0} git repositories:".format(num_of_repos)) + print(dir_long_name.capitalize(), + "contains {0} git repositories:".format(num_of_repos)) repositories.sort() # Go alphabetically instead of randomly for repo_path, repo_name in repositories: @@ -127,8 +140,7 @@ def update_bookmarks(bookmarks): for bookmark_path, bookmark_name in bookmarks: _update_directory(bookmark_path, bookmark_name, is_bookmark=True) else: - out(0, "You don't have any bookmarks configured! " \ - "Get help with 'gitup -h'.") + print("You don't have any bookmarks configured! Get help with 'gitup -h'.") def update_directories(paths): """Update a list of directories supplied by command arguments.""" diff --git a/setup.py b/setup.py index 3d7b348..4a907ad 100644 --- a/setup.py +++ b/setup.py @@ -19,7 +19,7 @@ setup( name = "gitup", packages = find_packages(), entry_points = {"console_scripts": ["gitup = gitup.script:run"]}, - install_requires = ["GitPython >= 0.3.2.RC1"], + install_requires = ["GitPython >= 0.3.2.RC1", "colorama >= 0.2.7"], version = __version__, author = "Ben Kurtovic", author_email = "ben.kurtovic@gmail.com",