A console script that allows you to easily update multiple git repositories at once

145 行
4.5 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2011-2018 Ben Kurtovic <ben.kurtovic@gmail.com>
  4. # Released under the terms of the MIT License. See LICENSE for details.
  5. from __future__ import print_function
  6. from glob import glob
  7. import os
  8. from colorama import Fore, Style
  9. from gitup.migrate import run_migrations
  10. __all__ = ["get_default_config_path", "get_bookmarks", "add_bookmarks",
  11. "delete_bookmarks", "list_bookmarks", "clean_bookmarks"]
  12. YELLOW = Fore.YELLOW + Style.BRIGHT
  13. RED = Fore.RED + Style.BRIGHT
  14. INDENT1 = " " * 3
  15. def _ensure_dirs(path):
  16. """Ensure the directories within the given pathname exist."""
  17. dirname = os.path.dirname(path)
  18. if dirname and not os.path.exists(dirname): # Race condition, meh...
  19. os.makedirs(dirname)
  20. def _load_config_file(config_path=None):
  21. """Read the config file and return a list of bookmarks."""
  22. run_migrations()
  23. cfg_path = config_path or get_default_config_path()
  24. try:
  25. with open(cfg_path, "rb") as config_file:
  26. paths = config_file.read().split(b"\n")
  27. except IOError:
  28. return []
  29. paths = [path.decode("utf8").strip() for path in paths]
  30. return [path for path in paths if path]
  31. def _save_config_file(bookmarks, config_path=None):
  32. """Save the bookmarks list to the given config file."""
  33. run_migrations()
  34. cfg_path = config_path or get_default_config_path()
  35. _ensure_dirs(cfg_path)
  36. dump = b"\n".join(path.encode("utf8") for path in bookmarks)
  37. with open(cfg_path, "wb") as config_file:
  38. config_file.write(dump)
  39. def _normalize_path(path):
  40. """Normalize the given path."""
  41. if path.startswith("~"):
  42. return os.path.normcase(os.path.normpath(path))
  43. return os.path.normcase(os.path.abspath(path))
  44. def get_default_config_path():
  45. """Return the default path to the configuration file."""
  46. xdg_cfg = os.environ.get("XDG_CONFIG_HOME") or os.path.join("~", ".config")
  47. return os.path.join(os.path.expanduser(xdg_cfg), "gitup", "bookmarks")
  48. def get_bookmarks(config_path=None):
  49. """Get a list of all bookmarks, or an empty list if there are none."""
  50. return _load_config_file(config_path)
  51. def add_bookmarks(paths, config_path=None):
  52. """Add a list of paths as bookmarks to the config file."""
  53. config = _load_config_file(config_path)
  54. paths = [_normalize_path(path) for path in paths]
  55. added, exists = [], []
  56. for path in paths:
  57. if path in config:
  58. exists.append(path)
  59. else:
  60. config.append(path)
  61. added.append(path)
  62. _save_config_file(config, config_path)
  63. if added:
  64. print(YELLOW + "Added bookmarks:")
  65. for path in added:
  66. print(INDENT1, path)
  67. if exists:
  68. print(RED + "Already bookmarked:")
  69. for path in exists:
  70. print(INDENT1, path)
  71. def delete_bookmarks(paths, config_path=None):
  72. """Remove a list of paths from the bookmark config file."""
  73. config = _load_config_file(config_path)
  74. paths = [_normalize_path(path) for path in paths]
  75. deleted, notmarked = [], []
  76. if config:
  77. for path in paths:
  78. if path in config:
  79. config.remove(path)
  80. deleted.append(path)
  81. else:
  82. notmarked.append(path)
  83. _save_config_file(config, config_path)
  84. else:
  85. notmarked = paths
  86. if deleted:
  87. print(YELLOW + "Deleted bookmarks:")
  88. for path in deleted:
  89. print(INDENT1, path)
  90. if notmarked:
  91. print(RED + "Not bookmarked:")
  92. for path in notmarked:
  93. print(INDENT1, path)
  94. def list_bookmarks(config_path=None):
  95. """Print all of our current bookmarks."""
  96. bookmarks = _load_config_file(config_path)
  97. if bookmarks:
  98. print(YELLOW + "Current bookmarks:")
  99. for bookmark_path in bookmarks:
  100. print(INDENT1, bookmark_path)
  101. else:
  102. print("You have no bookmarks to display.")
  103. def clean_bookmarks(config_path=None):
  104. """Delete any bookmarks that don't exist."""
  105. bookmarks = _load_config_file(config_path)
  106. if not bookmarks:
  107. print("You have no bookmarks to clean up.")
  108. return
  109. delete = [path for path in bookmarks
  110. if not (os.path.isdir(path) or glob(os.path.expanduser(path)))]
  111. if not delete:
  112. print("All of your bookmarks are valid.")
  113. return
  114. bookmarks = [path for path in bookmarks if path not in delete]
  115. _save_config_file(bookmarks, config_path)
  116. print(YELLOW + "Deleted bookmarks:")
  117. for path in delete:
  118. print(INDENT1, path)