pull.py 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. # vim: set fileencoding=utf-8 :
  2. #
  3. # (C) 2009,2013 Guido Guenther <agx@sigxcpu.org>
  4. # This program is free software; you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation; either version 2 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with this program; if not, please see
  16. # <http://www.gnu.org/licenses/>
  17. #
  18. # heavily inspired by dom-safe-pull which is © 2009 Stéphane Glondu <steph@glondu.net>
  19. #
  20. """Pull remote changes and fast forward debian, upstream and pristine-tar branch"""
  21. from six.moves import configparser
  22. import sys
  23. import os
  24. import os.path
  25. from gbp.command_wrappers import (Command, CommandExecFailed)
  26. from gbp.config import (GbpOptionParser, GbpOptionGroup)
  27. from gbp.errors import GbpError
  28. from gbp.git import GitRepositoryError
  29. from gbp.deb.git import DebianGitRepository
  30. import gbp.log
  31. def fast_forward_branch(branch, repo, options):
  32. """
  33. update branch to its remote branch, fail on non fast forward updates
  34. unless --force is given
  35. @return: branch updated or already up to date
  36. @rtype: boolean
  37. """
  38. update = False
  39. remote = repo.get_merge_branch(branch)
  40. if not remote:
  41. gbp.log.warn("No branch tracking '%s' found - skipping." % branch)
  42. return False
  43. can_fast_forward, up_to_date = repo.is_fast_forward(branch, remote)
  44. if up_to_date: # Great, we're done
  45. gbp.log.info("Branch '%s' is already up to date." % branch)
  46. return True
  47. if can_fast_forward:
  48. update = True
  49. else:
  50. if options.force:
  51. gbp.log.info("Non-fast forwarding '%s' due to --force" % branch)
  52. update = True
  53. else:
  54. gbp.log.warn("Skipping non-fast forward of '%s' - use --force" % branch)
  55. if update:
  56. gbp.log.info("Updating '%s'" % branch)
  57. if repo.branch == branch:
  58. repo.merge(remote)
  59. else:
  60. sha1 = repo.rev_parse(remote)
  61. repo.update_ref("refs/heads/%s" % branch, sha1,
  62. msg="gbp: forward %s to %s" % (branch, remote))
  63. return update
  64. def build_parser(name):
  65. try:
  66. parser = GbpOptionParser(command=os.path.basename(name), prefix='',
  67. usage='%prog [options] - safely update a repository from remote')
  68. except configparser.ParsingError as err:
  69. gbp.log.err(err)
  70. return None
  71. branch_group = GbpOptionGroup(parser, "branch options", "branch update and layout options")
  72. parser.add_option_group(branch_group)
  73. branch_group.add_boolean_config_file_option(option_name="ignore-branch", dest="ignore_branch")
  74. branch_group.add_option("--force", action="store_true", dest="force", default=False,
  75. help="force a branch update even if it can't be fast forwarded")
  76. branch_group.add_option("--redo-pq", action="store_true", dest="redo_pq", default=False,
  77. help="redo the patch queue branch after a pull. Warning: this drops the old patch-queue branch")
  78. branch_group.add_config_file_option(option_name="upstream-branch", dest="upstream_branch")
  79. branch_group.add_config_file_option(option_name="debian-branch", dest="debian_branch")
  80. branch_group.add_boolean_config_file_option(option_name="pristine-tar", dest="pristine_tar")
  81. branch_group.add_option("--depth", action="store", dest="depth", default=0,
  82. help="git history depth (for deepening shallow clones)")
  83. parser.add_option("-v", "--verbose", action="store_true", dest="verbose", default=False,
  84. help="verbose command execution")
  85. parser.add_config_file_option(option_name="color", dest="color", type='tristate')
  86. parser.add_config_file_option(option_name="color-scheme",
  87. dest="color_scheme")
  88. return parser
  89. def parse_args(argv):
  90. parser = build_parser(argv[0])
  91. if not parser:
  92. return None, None
  93. return parser.parse_args(argv)
  94. def main(argv):
  95. retval = 0
  96. current = None
  97. (options, args) = parse_args(argv)
  98. if not options:
  99. return 1
  100. gbp.log.setup(options.color, options.verbose, options.color_scheme)
  101. try:
  102. repo = DebianGitRepository(os.path.curdir)
  103. except GitRepositoryError:
  104. gbp.log.err("%s is not a git repository" % (os.path.abspath('.')))
  105. return 1
  106. try:
  107. branches = []
  108. try:
  109. current = repo.get_branch()
  110. except GitRepositoryError:
  111. # Not being on any branch is o.k. with --git-ignore-branch
  112. if options.ignore_branch:
  113. current = repo.head
  114. gbp.log.info("Found detached head at '%s'" % current)
  115. else:
  116. raise
  117. for branch in [options.debian_branch, options.upstream_branch]:
  118. if repo.has_branch(branch):
  119. branches += [branch]
  120. if repo.has_pristine_tar_branch() and options.pristine_tar:
  121. branches += [repo.pristine_tar_branch]
  122. (ret, out) = repo.is_clean()
  123. if not ret:
  124. gbp.log.err("You have uncommitted changes in your source tree:")
  125. gbp.log.err(out)
  126. raise GbpError
  127. repo.fetch(depth=options.depth)
  128. repo.fetch(depth=options.depth, tags=True)
  129. for branch in branches:
  130. if not fast_forward_branch(branch, repo, options):
  131. retval = 2
  132. if options.redo_pq:
  133. repo.set_branch(options.debian_branch)
  134. Command("gbp-pq")(["drop"])
  135. Command("gbp-pq")(["import"])
  136. repo.set_branch(current)
  137. except CommandExecFailed:
  138. retval = 1
  139. except (GbpError, GitRepositoryError) as err:
  140. if str(err):
  141. gbp.log.err(err)
  142. retval = 1
  143. return retval
  144. if __name__ == '__main__':
  145. sys.exit(main(sys.argv))
  146. # vim:et:ts=4:sw=4:et:sts=4:ai:set list listchars=tab\:»·,trail\:·: