A console script that allows you to easily update multiple git repositories at once
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

update.py 4.9 KiB

10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
10 år sedan
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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, rebase=True):
  18. """Update a single git repository by fetching remotes and rebasing/merging.
  19. The specific actions depends on ...
  20. """
  21. print(INDENT1, BOLD + os.path.split(repo.working_dir)[1] + ":")
  22. ref = repo.head.ref.tracking_branch()
  23. if ref:
  24. remote = repo.remotes[ref.remote_name]
  25. # else:
  26. ###
  27. remote.fetch()
  28. if not repo.remotes:
  29. print(INDENT2, RED + "Error:" + RESET, "no remotes configured.")
  30. return
  31. try:
  32. repo = repo.remotes.origin
  33. except AttributeError:
  34. if len(repo.remotes) == 1:
  35. repo = repo.remotes[0]
  36. else:
  37. print(INDENT2, RED + "Error:" + RESET, "ambiguous remotes:",
  38. ", ".join(remote.name for remote in repo.remotes))
  39. #####################################
  40. try:
  41. # Check if there is anything to pull, but don't do it yet:
  42. dry_fetch = _exec_shell("git fetch --dry-run")
  43. except subprocess.CalledProcessError:
  44. print(INDENT2, RED + "Error:" + RESET, "cannot fetch;",
  45. "do you have a remote repository configured correctly?")
  46. return
  47. try:
  48. last_commit = _exec_shell("git log -n 1 --pretty=\"%ar\"")
  49. except subprocess.CalledProcessError:
  50. last_commit = "never" # Couldn't get a log, so no commits
  51. if not dry_fetch: # No new changes to pull
  52. print(INDENT2, BLUE + "No new changes." + RESET,
  53. "Last commit was {0}.".format(last_commit))
  54. else: # Stuff has happened!
  55. print(INDENT2, "There are new changes upstream...")
  56. status = _exec_shell("git status")
  57. if status.endswith("nothing to commit, working directory clean"):
  58. print(INDENT2, GREEN + "Pulling new changes...")
  59. result = _exec_shell("git pull")
  60. if last_commit == "never":
  61. print(INDENT2, "The following changes have been made:")
  62. else:
  63. print(INDENT2, "The following changes have been made since",
  64. last_commit + ":")
  65. print(result)
  66. else:
  67. print(INDENT2, RED + "Warning:" + RESET,
  68. "you have uncommitted changes in this repository!")
  69. print(INDENT2, "Ignoring.")
  70. def _update_subdirectories(path, long_name):
  71. """Update all subdirectories that are git repos in a given directory."""
  72. repos = []
  73. for item in os.listdir(path):
  74. try:
  75. repo = Repo(os.path.join(path, item))
  76. except (exc.InvalidGitRepositoryError, exc.NoSuchPathError):
  77. continue
  78. repos.append(repo)
  79. suffix = "ies" if len(repos) != 1 else "y"
  80. print(long_name[0].upper() + long_name[1:],
  81. "contains {0} git repositor{1}:".format(len(repos), suffix))
  82. for repo in sorted(repos, key=lambda r: os.path.split(r.working_dir)[1]):
  83. _update_repository(repo)
  84. def _update_directory(path, is_bookmark=False):
  85. """Update a particular directory.
  86. Determine whether the directory is a git repo on its own, a directory of
  87. git repositories, or something invalid. If the first, update the single
  88. repository; if the second, update all repositories contained within; if the
  89. third, print an error.
  90. """
  91. dir_type = "bookmark" if is_bookmark else "directory"
  92. long_name = dir_type + ' "' + BOLD + path + RESET + '"'
  93. try:
  94. repo = Repo(path)
  95. except exc.NoSuchPathError:
  96. print(RED + "Error:" + RESET, long_name, "doesn't exist!")
  97. except exc.InvalidGitRepositoryError:
  98. if os.path.isdir(path):
  99. _update_subdirectories(path, long_name)
  100. else:
  101. print(RED + "Error:" + RESET, long_name, "isn't a repository!")
  102. else:
  103. long_name = (dir_type.capitalize() + ' "' + BOLD + repo.working_dir +
  104. RESET + '"')
  105. print(long_name, "is a git repository:")
  106. _update_repository(repo)
  107. def update_bookmarks(bookmarks, current_only=False, rebase=False, merge=False,
  108. verbose=False):
  109. """Loop through and update all bookmarks."""
  110. if bookmarks:
  111. for path, name in bookmarks:
  112. _update_directory(path, is_bookmark=True)
  113. else:
  114. print("You don't have any bookmarks configured! Get help with 'gitup -h'.")
  115. def update_directories(paths, current_only=False, rebase=False, merge=False,
  116. verbose=False):
  117. """Update a list of directories supplied by command arguments."""
  118. for path in paths:
  119. _update_directory(os.path.abspath(path), is_bookmark=False)