A console script that allows you to easily update multiple git repositories at once
Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

121 wiersze
4.3 KiB

  1. # -*- coding: utf-8 -*-
  2. #
  3. # Copyright (C) 2011-2014 Ben Kurtovic <ben.kurtovic@gmail.com>
  4. # See the LICENSE file for details.
  5. from __future__ import print_function
  6. import os
  7. from colorama import Fore, Style
  8. from git import Repo, exc
  9. __all__ = ["update_bookmarks", "update_directories"]
  10. BOLD = Style.BRIGHT
  11. RED = Fore.RED + BOLD
  12. GREEN = Fore.GREEN + BOLD
  13. BLUE = Fore.BLUE + BOLD
  14. RESET = Style.RESET_ALL
  15. INDENT1 = " " * 3
  16. INDENT2 = " " * 7
  17. def _update_repository(repo, repo_name):
  18. """Update a single git repository by pulling from the remote."""
  19. print(INDENT1, BOLD + repo_name + ":")
  20. try:
  21. # Check if there is anything to pull, but don't do it yet:
  22. dry_fetch = _exec_shell("git fetch --dry-run")
  23. except subprocess.CalledProcessError:
  24. print(INDENT2, RED + "Error:" + RESET, "cannot fetch;",
  25. "do you have a remote repository configured correctly?")
  26. return
  27. try:
  28. last_commit = _exec_shell("git log -n 1 --pretty=\"%ar\"")
  29. except subprocess.CalledProcessError:
  30. last_commit = "never" # Couldn't get a log, so no commits
  31. if not dry_fetch: # No new changes to pull
  32. print(INDENT2, BLUE + "No new changes." + RESET,
  33. "Last commit was {0}.".format(last_commit))
  34. else: # Stuff has happened!
  35. print(INDENT2, "There are new changes upstream...")
  36. status = _exec_shell("git status")
  37. if status.endswith("nothing to commit, working directory clean"):
  38. print(INDENT2, GREEN + "Pulling new changes...")
  39. result = _exec_shell("git pull")
  40. if last_commit == "never":
  41. print(INDENT2, "The following changes have been made:")
  42. else:
  43. print(INDENT2, "The following changes have been made since",
  44. last_commit + ":")
  45. print(result)
  46. else:
  47. print(INDENT2, RED + "Warning:" + RESET,
  48. "you have uncommitted changes in this repository!")
  49. print(INDENT2, "Ignoring.")
  50. def _update_subdirectories(dir_path, dir_name, dir_long_name):
  51. """Update all subdirectories that are git repos in a given directory."""
  52. repos = []
  53. for item in os.listdir(dir_path):
  54. try:
  55. repo = Repo(os.path.join(dir_path, item))
  56. except (exc.InvalidGitRepositoryError, exc.NoSuchPathError):
  57. continue
  58. repos.append((repo, os.path.join(dir_name, item)))
  59. if len(repos) == 1:
  60. print(dir_long_name.capitalize(), "contains 1 git repository:")
  61. else:
  62. print(dir_long_name.capitalize(),
  63. "contains {0} git repositories:".format(len(repos)))
  64. for repo_path, repo_name in sorted(repos):
  65. _update_repository(repo_path, repo_name)
  66. def _update_directory(dir_path, dir_name, is_bookmark=False):
  67. """Update a particular directory.
  68. Determine whether the directory is a git repo on its own, a directory of
  69. git repositories, or something invalid. If the first, update the single
  70. repository; if the second, update all repositories contained within; if the
  71. third, print an error.
  72. """
  73. dir_type = "bookmark" if is_bookmark else "directory"
  74. dir_long_name = dir_type + ' "' + BOLD + dir_path + RESET + '"'
  75. try:
  76. repo = Repo(dir_path)
  77. except exc.NoSuchPathError:
  78. print(RED + "Error:" + RESET, dir_long_name, "doesn't exist!")
  79. except exc.InvalidGitRepositoryError:
  80. if os.path.isdir(dir_path):
  81. _update_subdirectories(dir_path, dir_name, dir_long_name)
  82. else:
  83. print(RED + "Error:" + RESET, dir_long_name, "isn't a repository!")
  84. else:
  85. print(dir_long_name.capitalize(), "is a git repository:")
  86. _update_repository(repo, dir_name)
  87. def update_bookmarks(bookmarks):
  88. """Loop through and update all bookmarks."""
  89. if bookmarks:
  90. for bookmark_path, bookmark_name in bookmarks:
  91. _update_directory(bookmark_path, bookmark_name, is_bookmark=True)
  92. else:
  93. print("You don't have any bookmarks configured! Get help with 'gitup -h'.")
  94. def update_directories(paths):
  95. """Update a list of directories supplied by command arguments."""
  96. for path in paths:
  97. path = os.path.abspath(path) # Convert relative to absolute path
  98. path_name = os.path.split(path)[1] # Dir name ("x" in /path/to/x/)
  99. _update_directory(path, path_name, is_bookmark=False)