A console script that allows you to easily update multiple git repositories at once
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

script.py 5.6 KiB

9 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  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. import argparse
  7. import os
  8. import platform
  9. import sys
  10. from colorama import init as color_init, Fore, Style
  11. from . import __version__
  12. from .config import (get_default_config_path, get_bookmarks, add_bookmarks,
  13. delete_bookmarks, list_bookmarks, clean_bookmarks)
  14. from .update import update_bookmarks, update_directories, run_command
  15. def _decode(path):
  16. """Decode the given string using the system's filesystem encoding."""
  17. if sys.version_info.major > 2:
  18. return path
  19. return path.decode(sys.getfilesystemencoding())
  20. def main():
  21. """Parse arguments and then call the appropriate function(s)."""
  22. parser = argparse.ArgumentParser(
  23. description="Easily update multiple git repositories at once.",
  24. epilog="""
  25. Both relative and absolute paths are accepted by all arguments.
  26. Direct bug reports and feature requests to
  27. https://github.com/earwig/git-repo-updater.""",
  28. add_help=False)
  29. group_u = parser.add_argument_group("updating repositories")
  30. group_b = parser.add_argument_group("bookmarking")
  31. group_a = parser.add_argument_group("advanced")
  32. group_m = parser.add_argument_group("miscellaneous")
  33. group_u.add_argument(
  34. 'directories_to_update', nargs="*", metavar="path", type=_decode,
  35. help="""update this repository, or all repositories it contains
  36. (if not a repo directly)""")
  37. group_u.add_argument(
  38. '-u', '--update', action="store_true", help="""update all bookmarks
  39. (default behavior when called without arguments)""")
  40. group_u.add_argument(
  41. '-t', '--depth', dest="max_depth", metavar="n", type=int, default=3,
  42. help="""max recursion depth when searching for repos in subdirectories
  43. (default: 3; use 0 for no recursion, or -1 for unlimited)""")
  44. group_u.add_argument(
  45. '-c', '--current-only', action="store_true", help="""only fetch the
  46. remote tracked by the current branch instead of all remotes""")
  47. group_u.add_argument(
  48. '-f', '--fetch-only', action="store_true",
  49. help="only fetch remotes, don't try to fast-forward any branches")
  50. group_u.add_argument(
  51. '-p', '--prune', action="store_true", help="""after fetching, delete
  52. remote-tracking branches that no longer exist on their remote""")
  53. group_b.add_argument(
  54. '-a', '--add', dest="bookmarks_to_add", nargs="+", metavar="path",
  55. type=_decode, help="add directory(s) as bookmarks")
  56. group_b.add_argument(
  57. '-d', '--delete', dest="bookmarks_to_del", nargs="+", metavar="path",
  58. type=_decode,
  59. help="delete bookmark(s) (leaves actual directories alone)")
  60. group_b.add_argument(
  61. '-l', '--list', dest="list_bookmarks", action="store_true",
  62. help="list current bookmarks")
  63. group_b.add_argument(
  64. '-n', '--clean', '--cleanup', dest="clean_bookmarks",
  65. action="store_true", help="delete any bookmarks that don't exist")
  66. group_b.add_argument(
  67. '-b', '--bookmark-file', nargs="?", metavar="path", type=_decode,
  68. help="use a specific bookmark config file (default: {0})".format(
  69. get_default_config_path()))
  70. group_a.add_argument(
  71. '-e', '--exec', '--batch', dest="command", metavar="command",
  72. help="run a shell command on all repos")
  73. group_m.add_argument(
  74. '-h', '--help', action="help", help="show this help message and exit")
  75. group_m.add_argument(
  76. '-v', '--version', action="version",
  77. version="gitup {0} (Python {1})".format(
  78. __version__, platform.python_version()))
  79. # TODO: deprecated arguments, for removal in v1.0:
  80. parser.add_argument(
  81. '-m', '--merge', action="store_true", help=argparse.SUPPRESS)
  82. parser.add_argument(
  83. '-r', '--rebase', action="store_true", help=argparse.SUPPRESS)
  84. color_init(autoreset=True)
  85. args = parser.parse_args()
  86. print(Style.BRIGHT + "gitup" + Style.RESET_ALL + ": the git-repo-updater")
  87. print()
  88. # TODO: remove in v1.0
  89. if args.merge or args.rebase:
  90. print(Style.BRIGHT + Fore.YELLOW + "Warning:", "--merge and --rebase "
  91. "are deprecated. Branches are only updated if they\ntrack an "
  92. "upstream branch and can be safely fast-forwarded. Use "
  93. "--fetch-only to\navoid updating any branches.\n")
  94. if args.bookmark_file:
  95. args.bookmark_file = os.path.expanduser(args.bookmark_file)
  96. acted = False
  97. if args.bookmarks_to_add:
  98. add_bookmarks(args.bookmarks_to_add, args.bookmark_file)
  99. acted = True
  100. if args.bookmarks_to_del:
  101. delete_bookmarks(args.bookmarks_to_del, args.bookmark_file)
  102. acted = True
  103. if args.list_bookmarks:
  104. list_bookmarks(args.bookmark_file)
  105. acted = True
  106. if args.clean_bookmarks:
  107. clean_bookmarks(args.bookmark_file)
  108. acted = True
  109. if args.command:
  110. if args.directories_to_update:
  111. run_command(args.directories_to_update, args)
  112. if args.update or not args.directories_to_update:
  113. run_command(get_bookmarks(args.bookmark_file), args)
  114. else:
  115. if args.directories_to_update:
  116. update_directories(args.directories_to_update, args)
  117. acted = True
  118. if args.update or not acted:
  119. update_bookmarks(get_bookmarks(args.bookmark_file), args)
  120. def run():
  121. """Thin wrapper for main() that catches KeyboardInterrupts."""
  122. try:
  123. main()
  124. except KeyboardInterrupt:
  125. print("Stopped by user.")