Package buildbot :: Package changes :: Module hgbuildbot
[frames] | no frames]

Source Code for Module buildbot.changes.hgbuildbot

  1  # hgbuildbot.py - mercurial hooks for buildbot 
  2  # 
  3  # Copyright 2007 Frederic Leroy <fredo@starox.org> 
  4  # 
  5  # This software may be used and distributed according to the terms 
  6  # of the GNU General Public License, incorporated herein by reference. 
  7   
  8  # hook extension to send change notifications to buildbot when a changeset is 
  9  # brought into the repository from elsewhere. 
 10  # 
 11  # default mode is to use mercurial branch 
 12  # 
 13  # to use, configure hgbuildbot in .hg/hgrc like this: 
 14  # 
 15  #   [hooks] 
 16  #   changegroup = python:buildbot.changes.hgbuildbot.hook 
 17  # 
 18  #   [hgbuildbot] 
 19  #   # config items go in here 
 20  # 
 21  # config items: 
 22  # 
 23  # REQUIRED: 
 24  #   master = host:port                   # host to send buildbot changes 
 25  # 
 26  # OPTIONAL: 
 27  #   branchtype = inrepo|dirname          # dirname: branch = name of directory 
 28  #                                        #          containing the repository 
 29  #                                        # 
 30  #                                        # inrepo:  branch = mercurial branch 
 31  # 
 32  #   branch = branchname                  # if set, branch is always branchname 
 33  # 
 34  #   fork = True|False                    # if mercurial should fork before  
 35  #                                        # notifying the master 
 36  # 
 37  #   strip = 3                            # number of path to strip for local  
 38  #                                        # repo path to form 'repository' 
 39  # 
 40  #   category = None                      # category property 
 41  #   project = ''                         # project this repository belong to 
 42   
 43  import os 
 44   
 45  from mercurial.i18n import gettext as _ #@UnresolvedImport 
 46  from mercurial.node import bin, hex, nullid #@UnresolvedImport 
 47  from mercurial.context import workingctx #@UnresolvedImport 
 48   
 49  # mercurial's on-demand-importing hacks interfere with the: 
 50  #from zope.interface import Interface 
 51  # that Twisted needs to do, so disable it. 
 52  try: 
 53      from mercurial import demandimport 
 54      demandimport.disable() 
 55  except ImportError: 
 56      pass 
 57   
58 -def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
59 # read config parameters 60 master = ui.config('hgbuildbot', 'master') 61 if master: 62 branchtype = ui.config('hgbuildbot', 'branchtype') 63 branch = ui.config('hgbuildbot', 'branch') 64 fork = ui.configbool('hgbuildbot', 'fork', False) 65 # notify also has this setting 66 stripcount = int(ui.config('notify','strip') or ui.config('hgbuildbot','strip',3)) 67 category = ui.config('hgbuildbot', 'category', None) 68 project = ui.config('hgbuildbot', 'project', '') 69 else: 70 ui.write("* You must add a [hgbuildbot] section to .hg/hgrc in " 71 "order to use buildbot hook\n") 72 return 73 74 if hooktype != "changegroup": 75 ui.status("hgbuildbot: hooktype %s not supported.\n" % hooktype) 76 return 77 78 if fork: 79 child_pid = os.fork() 80 if child_pid == 0: 81 #child 82 pass 83 else: 84 #parent 85 ui.status("Notifying buildbot...\n") 86 return 87 88 # only import inside the fork if forked 89 from buildbot.clients import sendchange 90 from twisted.internet import defer, reactor 91 92 if branch is None: 93 if branchtype is not None: 94 if branchtype == 'dirname': 95 branch = os.path.basename(repo.root) 96 if branchtype == 'inrepo': 97 branch = workingctx(repo).branch() 98 99 s = sendchange.Sender(master, None) 100 d = defer.Deferred() 101 reactor.callLater(0, d.callback, None) 102 # process changesets 103 def _send(res, c): 104 if not fork: 105 ui.status("rev %s sent\n" % c['revision']) 106 return s.send(c['branch'], c['revision'], c['comments'], 107 c['files'], c['username'], category=category, 108 repository=repository, project=project)
109 110 try: # first try Mercurial 1.1+ api 111 start = repo[node].rev() 112 end = len(repo) 113 except TypeError: # else fall back to old api 114 start = repo.changelog.rev(bin(node)) 115 end = repo.changelog.count() 116 117 repository = strip(repo.root, stripcount) 118 119 for rev in xrange(start, end): 120 # send changeset 121 node = repo.changelog.node(rev) 122 manifest, user, (time, timezone), files, desc, extra = repo.changelog.read(node) 123 parents = filter(lambda p: not p == nullid, repo.changelog.parents(node)) 124 if branchtype == 'inrepo': 125 branch = extra['branch'] 126 # merges don't always contain files, but at least one file is required by buildbot 127 if len(parents) > 1 and not files: 128 files = ["merge"] 129 change = { 130 'master': master, 131 'username': user, 132 'revision': hex(node), 133 'comments': desc, 134 'files': files, 135 'branch': branch 136 } 137 d.addCallback(_send, change) 138 139 d.addCallbacks(s.printSuccess, s.printFailure) 140 d.addBoth(s.stop) 141 s.run() 142 143 if fork: 144 os._exit(os.EX_OK) 145 else: 146 return 147 148 # taken from the mercurial notify extension
149 -def strip(path, count):
150 '''Strip the count first slash of the path''' 151 152 # First normalize it 153 path = '/'.join(path.split(os.sep)) 154 # and strip it part after part 155 while count > 0: 156 c = path.find('/') 157 if c == -1: 158 break 159 path = path[c + 1:] 160 count -= 1 161 return path
162