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

Source Code for Module buildbot.changes.hgbuildbot

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Portions Copyright Buildbot Team Members 
 15  # Portions Copyright 2007 Frederic Leroy <fredo@starox.org> 
 16   
 17  # hook extension to send change notifications to buildbot when a changeset is 
 18  # brought into the repository from elsewhere. 
 19  # 
 20  # default mode is to use mercurial branch 
 21  # 
 22  # to use, configure hgbuildbot in .hg/hgrc like this: 
 23  # 
 24  #   [hooks] 
 25  #   changegroup = python:buildbot.changes.hgbuildbot.hook 
 26  # 
 27  #   [hgbuildbot] 
 28  #   # config items go in here 
 29  # 
 30  # config items: 
 31  # 
 32  # REQUIRED: 
 33  #   master = host:port                   # host to send buildbot changes 
 34  # 
 35  # OPTIONAL: 
 36  #   branchtype = inrepo|dirname          # dirname: branch = name of directory 
 37  #                                        #          containing the repository 
 38  #                                        # 
 39  #                                        # inrepo:  branch = mercurial branch 
 40  # 
 41  #   branch = branchname                  # if set, branch is always branchname 
 42  # 
 43  #   fork = True|False                    # if mercurial should fork before  
 44  #                                        # notifying the master 
 45  # 
 46  #   strip = 3                            # number of path to strip for local  
 47  #                                        # repo path to form 'repository' 
 48  # 
 49  #   category = None                      # category property 
 50  #   project = ''                         # project this repository belong to 
 51  # 
 52  #   auth = user:passwd                   # How to authenticate, defaults to 
 53  #                                        # change:changepw, which is also 
 54  #                                        # the default of PBChangeSource. 
 55   
 56  import os 
 57   
 58  from mercurial.node import bin, hex, nullid #@UnresolvedImport 
 59  from mercurial.context import workingctx #@UnresolvedImport 
 60   
 61  # mercurial's on-demand-importing hacks interfere with the: 
 62  #from zope.interface import Interface 
 63  # that Twisted needs to do, so disable it. 
 64  try: 
 65      from mercurial import demandimport 
 66      demandimport.disable() 
 67  except ImportError: 
 68      pass 
 69   
 70  # In Mercurial post-1.7, some strings might be stored as a 
 71  # encoding.localstr class. encoding.fromlocal will translate 
 72  # those back to UTF-8 strings. 
 73  try: 
 74      from mercurial.encoding import fromlocal 
 75      _hush_pyflakes = [fromlocal] 
 76      del _hush_pyflakes 
 77  except ImportError: 
78 - def fromlocal(s):
79 return s
80
81 -def hook(ui, repo, hooktype, node=None, source=None, **kwargs):
82 # read config parameters 83 master = ui.config('hgbuildbot', 'master') 84 if master: 85 branchtype = ui.config('hgbuildbot', 'branchtype') 86 branch = ui.config('hgbuildbot', 'branch') 87 fork = ui.configbool('hgbuildbot', 'fork', False) 88 # notify also has this setting 89 stripcount = int(ui.config('notify','strip') or ui.config('hgbuildbot','strip',3)) 90 category = ui.config('hgbuildbot', 'category', None) 91 project = ui.config('hgbuildbot', 'project', '') 92 auth = ui.config('hgbuildbot', 'auth', None) 93 else: 94 ui.write("* You must add a [hgbuildbot] section to .hg/hgrc in " 95 "order to use buildbot hook\n") 96 return 97 98 if hooktype != "changegroup": 99 ui.status("hgbuildbot: hooktype %s not supported.\n" % hooktype) 100 return 101 102 if fork: 103 child_pid = os.fork() 104 if child_pid == 0: 105 #child 106 pass 107 else: 108 #parent 109 ui.status("Notifying buildbot...\n") 110 return 111 112 # only import inside the fork if forked 113 from buildbot.clients import sendchange 114 from twisted.internet import defer, reactor 115 116 if branch is None: 117 if branchtype is not None: 118 if branchtype == 'dirname': 119 branch = os.path.basename(repo.root) 120 if branchtype == 'inrepo': 121 branch = workingctx(repo).branch() 122 123 if not auth: 124 auth = 'change:changepw' 125 auth = auth.split(':', 1) 126 127 s = sendchange.Sender(master, auth=auth) 128 d = defer.Deferred() 129 reactor.callLater(0, d.callback, None) 130 # process changesets 131 def _send(res, c): 132 if not fork: 133 ui.status("rev %s sent\n" % c['revision']) 134 return s.send(c['branch'], c['revision'], c['comments'], 135 c['files'], c['username'], category=category, 136 repository=repository, project=project)
137 138 try: # first try Mercurial 1.1+ api 139 start = repo[node].rev() 140 end = len(repo) 141 except TypeError: # else fall back to old api 142 start = repo.changelog.rev(bin(node)) 143 end = repo.changelog.count() 144 145 repository = strip(repo.root, stripcount) 146 147 for rev in xrange(start, end): 148 # send changeset 149 node = repo.changelog.node(rev) 150 manifest, user, (time, timezone), files, desc, extra = repo.changelog.read(node) 151 parents = filter(lambda p: not p == nullid, repo.changelog.parents(node)) 152 if branchtype == 'inrepo': 153 branch = extra['branch'] 154 # merges don't always contain files, but at least one file is required by buildbot 155 if len(parents) > 1 and not files: 156 files = ["merge"] 157 if branch: 158 branch = fromlocal(branch) 159 change = { 160 'master': master, 161 'username': fromlocal(user), 162 'revision': hex(node), 163 'comments': fromlocal(desc), 164 'files': files, 165 'branch': branch 166 } 167 d.addCallback(_send, change) 168 169 def _printSuccess(res): 170 ui.status(s.getSuccessString(res) + '\n') 171 172 def _printFailure(why): 173 ui.warn(s.getFailureString(why) + '\n') 174 175 d.addCallbacks(_printSuccess, _printFailure) 176 d.addBoth(lambda _ : reactor.stop()) 177 reactor.run() 178 179 if fork: 180 os._exit(os.EX_OK) 181 else: 182 return 183 184 # taken from the mercurial notify extension
185 -def strip(path, count):
186 '''Strip the count first slash of the path''' 187 188 # First normalize it 189 path = '/'.join(path.split(os.sep)) 190 # and strip it part after part 191 while count > 0: 192 c = path.find('/') 193 if c == -1: 194 break 195 path = path[c + 1:] 196 count -= 1 197 return path
198