From 4b168bb888b2e35ff8932a23098c48fd0c665905 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Sun, 14 Feb 2016 02:39:00 -0600 Subject: [PATCH] Use custom bookmark file format (fixes #21) --- CHANGELOG | 3 ++- gitup/config.py | 63 +++++++++++++++++++------------------------------------- gitup/migrate.py | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ gitup/script.py | 2 +- 4 files changed, 82 insertions(+), 44 deletions(-) create mode 100644 gitup/migrate.py diff --git a/CHANGELOG b/CHANGELOG index 97e5b98..83b63ea 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,8 +3,9 @@ v0.3.1 (unreleased): - Added a `--prune` flag to delete remote-tracking branches that no longer exist on their remote after fetching. - Added a '--bookmark-file' option to support multiple bookmark config files. +- Cleaned up the bookmark file format, fixing a related Windows bug. The script + will automatically migrate to the new one. - Fixed a bug related to Python 3 compatibility. -- Fixed a bug related to absolute paths in bookmarks on Windows. v0.3 (released June 7, 2015): diff --git a/gitup/config.py b/gitup/config.py index d5dc1b9..2bd8cbe 100644 --- a/gitup/config.py +++ b/gitup/config.py @@ -7,15 +7,10 @@ from __future__ import print_function import os -try: - from configparser import ConfigParser, NoSectionError - py3k = True -except ImportError: # Python 2 - from ConfigParser import SafeConfigParser as ConfigParser, NoSectionError - py3k = False - from colorama import Fore, Style +from .migrate import run_migrations + __all__ = ["get_default_config_path", "get_bookmarks", "add_bookmarks", "delete_bookmarks", "list_bookmarks"] @@ -30,61 +25,45 @@ def _ensure_dirs(path): if dirname and not os.path.exists(dirname): # Race condition, meh... os.makedirs(dirname) -def _migrate_old_config_path(): - """Migrate the old config location (~/.gitup) to the new one.""" - old_path = os.path.expanduser(os.path.join("~", ".gitup")) - if os.path.exists(old_path): - new_path = get_default_config_path() - _ensure_dirs(new_path) - os.rename(old_path, new_path) - def _load_config_file(config_path=None): """Read the config file and return a config parser object.""" - _migrate_old_config_path() - if py3k: - config = ConfigParser(delimiters='=') - else: - config = ConfigParser() - # Don't lowercase option names, because we are storing paths there: - config.optionxform = lambda opt: opt - config.read(config_path or get_default_config_path()) - return config + run_migrations() + cfg_path = config_path or get_default_config_path() + + try: + with open(cfg_path, "rb") as config_file: + return config_file.read().split("\n") + except IOError: + return [] def _save_config_file(config, config_path=None): """Save config changes to the given config file.""" - _migrate_old_config_path() + run_migrations() cfg_path = config_path or get_default_config_path() _ensure_dirs(cfg_path) - with open(cfg_path, "w") as config_file: - config.write(config_file) + + with open(cfg_path, "wb") as config_file: + config_file.write("\n".join(config)) def get_default_config_path(): """Return the default path to the configuration file.""" xdg_cfg = os.environ.get("XDG_CONFIG_HOME") or os.path.join("~", ".config") - return os.path.join(os.path.expanduser(xdg_cfg), "gitup", "config.ini") + return os.path.join(os.path.expanduser(xdg_cfg), "gitup", "bookmarks") def get_bookmarks(config_path=None): """Get a list of all bookmarks, or an empty list if there are none.""" - config = _load_config_file(config_path) - try: - return [path for path, _ in config.items("bookmarks")] - except NoSectionError: - return [] + return _load_config_file(config_path) def add_bookmarks(paths, config_path=None): """Add a list of paths as bookmarks to the config file.""" config = _load_config_file(config_path) - if not config.has_section("bookmarks"): - config.add_section("bookmarks") - added, exists = [], [] for path in paths: path = os.path.abspath(path) - if config.has_option("bookmarks", path): + if path in config: exists.append(path) else: - path_name = os.path.split(path)[1] - config.set("bookmarks", path, path_name) + config.append(path) added.append(path) _save_config_file(config, config_path) @@ -102,11 +81,11 @@ def delete_bookmarks(paths, config_path=None): config = _load_config_file(config_path) deleted, notmarked = [], [] - if config.has_section("bookmarks"): + if config: for path in paths: path = os.path.abspath(path) - config_was_changed = config.remove_option("bookmarks", path) - if config_was_changed: + if path in config: + config.remove(path) deleted.append(path) else: notmarked.append(path) diff --git a/gitup/migrate.py b/gitup/migrate.py new file mode 100644 index 0000000..388cac5 --- /dev/null +++ b/gitup/migrate.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# +# Copyright (C) 2011-2016 Ben Kurtovic +# Released under the terms of the MIT License. See LICENSE for details. + +__all__ = ["run_migrations"] + +import os + +try: + from configparser import ConfigParser, NoSectionError + PY3K = True +except ImportError: # Python 2 + from ConfigParser import SafeConfigParser as ConfigParser, NoSectionError + PY3K = False + +def _get_old_path(): + """Return the old default path to the configuration file.""" + xdg_cfg = os.environ.get("XDG_CONFIG_HOME") or os.path.join("~", ".config") + return os.path.join(os.path.expanduser(xdg_cfg), "gitup", "config.ini") + +def _migrate_old_path(): + """Migrate the old config location (~/.gitup) to the new one.""" + old_path = os.path.expanduser(os.path.join("~", ".gitup")) + if not os.path.exists(old_path): + return + + temp_path = _get_old_path() + temp_dir = os.path.dirname(temp_path) + if not os.path.exists(temp_dir): + os.makedirs(temp_dir) + os.rename(old_path, temp_path) + +def _migrate_old_format(): + """Migrate the old config file format (.INI) to our custom list format.""" + old_path = _get_old_path() + if not os.path.exists(old_path): + return + + config = ConfigParser(delimiters="=") if PY3K else ConfigParser() + config.optionxform = lambda opt: opt + config.read(old_path) + + try: + bookmarks = [path for path, _ in config.items("bookmarks")] + except NoSectionError: + bookmarks = [] + + new_path = os.path.join(os.path.split(old_path)[0], "bookmarks") + os.rename(old_path, new_path) + + with open(new_path, "wb") as handle: + handle.write("\n".join(bookmarks)) + +def run_migrations(): + """Run any necessary migrations to ensure the config file is up-to-date.""" + _migrate_old_path() + _migrate_old_format() diff --git a/gitup/script.py b/gitup/script.py index 2126142..df3e12e 100644 --- a/gitup/script.py +++ b/gitup/script.py @@ -21,7 +21,7 @@ def main(): description="Easily update multiple git repositories at once.", epilog=""" Both relative and absolute paths are accepted by all arguments. - Direct bug reports and feature requests to: + Direct bug reports and feature requests to https://github.com/earwig/git-repo-updater.""", add_help=False)