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.

121 rivejä
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)