mercurial/localrepo.py
changeset 1737 2c9872a4f3fd
parent 1716 ef8cd889a78b
parent 1736 50de0887bbcd
child 1747 91c56c427171
equal deleted inserted replaced
1716:ef8cd889a78b 1737:2c9872a4f3fd
    46         try:
    46         try:
    47             self.ui.readconfig(self.join("hgrc"))
    47             self.ui.readconfig(self.join("hgrc"))
    48         except IOError:
    48         except IOError:
    49             pass
    49             pass
    50 
    50 
    51     def hook(self, name, **args):
    51     def hook(self, name, throw=False, **args):
    52         def runhook(name, cmd):
    52         def runhook(name, cmd):
    53             self.ui.note(_("running hook %s: %s\n") % (name, cmd))
    53             self.ui.note(_("running hook %s: %s\n") % (name, cmd))
    54             old = {}
    54             old = {}
    55             for k, v in args.items():
    55             for k, v in args.items():
    56                 k = k.upper()
    56                 k = k.upper()
       
    57                 old['HG_' + k] = os.environ.get(k, None)
    57                 old[k] = os.environ.get(k, None)
    58                 old[k] = os.environ.get(k, None)
    58                 os.environ[k] = v
    59                 os.environ['HG_' + k] = str(v)
    59 
    60                 os.environ[k] = str(v)
    60             # Hooks run in the repository root
    61 
    61             olddir = os.getcwd()
    62             try:
    62             os.chdir(self.root)
    63                 # Hooks run in the repository root
    63             r = os.system(cmd)
    64                 olddir = os.getcwd()
    64             os.chdir(olddir)
    65                 os.chdir(self.root)
    65 
    66                 r = os.system(cmd)
    66             for k, v in old.items():
    67             finally:
    67                 if v != None:
    68                 for k, v in old.items():
    68                     os.environ[k] = v
    69                     if v is not None:
    69                 else:
    70                         os.environ[k] = v
    70                     del os.environ[k]
    71                     else:
       
    72                         del os.environ[k]
       
    73 
       
    74                 os.chdir(olddir)
    71 
    75 
    72             if r:
    76             if r:
    73                 self.ui.warn(_("abort: %s hook failed with status %d!\n") %
    77                 desc, r = util.explain_exit(r)
    74                              (name, r))
    78                 if throw:
       
    79                     raise util.Abort(_('%s hook %s') % (name, desc))
       
    80                 self.ui.warn(_('error: %s hook %s\n') % (name, desc))
    75                 return False
    81                 return False
    76             return True
    82             return True
    77 
    83 
    78         r = True
    84         r = True
    79         for hname, cmd in self.ui.configitems("hooks"):
    85         for hname, cmd in self.ui.configitems("hooks"):
   372 
   378 
   373         if not commit and not remove and not force and p2 == nullid:
   379         if not commit and not remove and not force and p2 == nullid:
   374             self.ui.status(_("nothing changed\n"))
   380             self.ui.status(_("nothing changed\n"))
   375             return None
   381             return None
   376 
   382 
   377         if not self.hook("precommit"):
   383         xp1 = hex(p1)
   378             return None
   384         if p2 == nullid: xp2 = ''
       
   385         else: xp2 = hex(p2)
       
   386 
       
   387         self.hook("precommit", throw=True, parent1=xp1, parent2=xp2)
   379 
   388 
   380         if not wlock:
   389         if not wlock:
   381             wlock = self.wlock()
   390             wlock = self.wlock()
   382         lock = self.lock()
   391         lock = self.lock()
   383         tr = self.transaction()
   392         tr = self.transaction()
   446                 return None
   455                 return None
   447             text = edittext
   456             text = edittext
   448 
   457 
   449         user = user or self.ui.username()
   458         user = user or self.ui.username()
   450         n = self.changelog.add(mn, changed + remove, text, tr, p1, p2, user, date)
   459         n = self.changelog.add(mn, changed + remove, text, tr, p1, p2, user, date)
       
   460         self.hook('pretxncommit', throw=True, node=hex(n), parent1=xp1,
       
   461                   parent2=xp2)
   451         tr.close()
   462         tr.close()
   452 
   463 
   453         self.dirstate.setparents(n)
   464         self.dirstate.setparents(n)
   454         self.dirstate.update(new, "n")
   465         self.dirstate.update(new, "n")
   455         self.dirstate.forget(remove)
   466         self.dirstate.forget(remove)
   456 
   467 
   457         if not self.hook("commit", node=hex(n)):
   468         self.hook("commit", node=hex(n), parent1=xp1, parent2=xp2)
   458             return None
       
   459         return n
   469         return n
   460 
   470 
   461     def walk(self, node=None, files=[], match=util.always):
   471     def walk(self, node=None, files=[], match=util.always):
   462         if node:
   472         if node:
   463             fdict = dict.fromkeys(files)
   473             fdict = dict.fromkeys(files)
   934         if not fetch:
   944         if not fetch:
   935             self.ui.status(_("no changes found\n"))
   945             self.ui.status(_("no changes found\n"))
   936             return 1
   946             return 1
   937 
   947 
   938         if heads is None:
   948         if heads is None:
   939             cg = remote.changegroup(fetch)
   949             cg = remote.changegroup(fetch, 'pull')
   940         else:
   950         else:
   941             cg = remote.changegroupsubset(fetch, heads)
   951             cg = remote.changegroupsubset(fetch, heads, 'pull')
   942         return self.addchangegroup(cg)
   952         return self.addchangegroup(cg)
   943 
   953 
   944     def push(self, remote, force=False):
   954     def push(self, remote, force=False):
   945         lock = remote.lock()
   955         lock = remote.lock()
   946 
   956 
   961                 self.ui.warn(_("abort: push creates new remote branches!\n"))
   971                 self.ui.warn(_("abort: push creates new remote branches!\n"))
   962                 self.ui.status(_("(did you forget to merge?"
   972                 self.ui.status(_("(did you forget to merge?"
   963                                  " use push -f to force)\n"))
   973                                  " use push -f to force)\n"))
   964                 return 1
   974                 return 1
   965 
   975 
   966         cg = self.changegroup(update)
   976         cg = self.changegroup(update, 'push')
   967         return remote.addchangegroup(cg)
   977         return remote.addchangegroup(cg)
   968 
   978 
   969     def changegroupsubset(self, bases, heads):
   979     def changegroupsubset(self, bases, heads, source):
   970         """This function generates a changegroup consisting of all the nodes
   980         """This function generates a changegroup consisting of all the nodes
   971         that are descendents of any of the bases, and ancestors of any of
   981         that are descendents of any of the bases, and ancestors of any of
   972         the heads.
   982         the heads.
   973 
   983 
   974         It is fairly complex as determining which filenodes and which
   984         It is fairly complex as determining which filenodes and which
   975         manifest nodes need to be included for the changeset to be complete
   985         manifest nodes need to be included for the changeset to be complete
   976         is non-trivial.
   986         is non-trivial.
   977 
   987 
   978         Another wrinkle is doing the reverse, figuring out which changeset in
   988         Another wrinkle is doing the reverse, figuring out which changeset in
   979         the changegroup a particular filenode or manifestnode belongs to."""
   989         the changegroup a particular filenode or manifestnode belongs to."""
       
   990 
       
   991         self.hook('preoutgoing', throw=True, source=source)
   980 
   992 
   981         # Set up some initial variables
   993         # Set up some initial variables
   982         # Make it easy to refer to self.changelog
   994         # Make it easy to refer to self.changelog
   983         cl = self.changelog
   995         cl = self.changelog
   984         # msng is short for missing - compute the list of changesets in this
   996         # msng is short for missing - compute the list of changesets in this
  1228                     # Don't need this anymore, toss it to free memory.
  1240                     # Don't need this anymore, toss it to free memory.
  1229                     del msng_filenode_set[fname]
  1241                     del msng_filenode_set[fname]
  1230             # Signal that no more groups are left.
  1242             # Signal that no more groups are left.
  1231             yield struct.pack(">l", 0)
  1243             yield struct.pack(">l", 0)
  1232 
  1244 
       
  1245             self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source)
       
  1246 
  1233         return util.chunkbuffer(gengroup())
  1247         return util.chunkbuffer(gengroup())
  1234 
  1248 
  1235     def changegroup(self, basenodes):
  1249     def changegroup(self, basenodes, source):
  1236         """Generate a changegroup of all nodes that we have that a recipient
  1250         """Generate a changegroup of all nodes that we have that a recipient
  1237         doesn't.
  1251         doesn't.
  1238 
  1252 
  1239         This is much easier than the previous function as we can assume that
  1253         This is much easier than the previous function as we can assume that
  1240         the recipient has any changenode we aren't sending them."""
  1254         the recipient has any changenode we aren't sending them."""
       
  1255 
       
  1256         self.hook('preoutgoing', throw=True, source=source)
       
  1257 
  1241         cl = self.changelog
  1258         cl = self.changelog
  1242         nodes = cl.nodesbetween(basenodes, None)[0]
  1259         nodes = cl.nodesbetween(basenodes, None)[0]
  1243         revset = dict.fromkeys([cl.rev(n) for n in nodes])
  1260         revset = dict.fromkeys([cl.rev(n) for n in nodes])
  1244 
  1261 
  1245         def identity(x):
  1262         def identity(x):
  1287                     lookup = lookuprevlink_func(filerevlog)
  1304                     lookup = lookuprevlink_func(filerevlog)
  1288                     for chnk in filerevlog.group(nodeiter, lookup):
  1305                     for chnk in filerevlog.group(nodeiter, lookup):
  1289                         yield chnk
  1306                         yield chnk
  1290 
  1307 
  1291             yield struct.pack(">l", 0)
  1308             yield struct.pack(">l", 0)
       
  1309             self.hook('outgoing', node=hex(nodes[0]), source=source)
  1292 
  1310 
  1293         return util.chunkbuffer(gengroup())
  1311         return util.chunkbuffer(gengroup())
  1294 
  1312 
  1295     def addchangegroup(self, source):
  1313     def addchangegroup(self, source):
  1296 
  1314 
  1322         def revmap(x):
  1340         def revmap(x):
  1323             return self.changelog.rev(x)
  1341             return self.changelog.rev(x)
  1324 
  1342 
  1325         if not source:
  1343         if not source:
  1326             return
  1344             return
       
  1345 
       
  1346         self.hook('prechangegroup', throw=True)
       
  1347 
  1327         changesets = files = revisions = 0
  1348         changesets = files = revisions = 0
  1328 
  1349 
  1329         tr = self.transaction()
  1350         tr = self.transaction()
  1330 
  1351 
  1331         oldheads = len(self.changelog.heads())
  1352         oldheads = len(self.changelog.heads())
  1364 
  1385 
  1365         self.ui.status(_("added %d changesets"
  1386         self.ui.status(_("added %d changesets"
  1366                          " with %d changes to %d files%s\n")
  1387                          " with %d changes to %d files%s\n")
  1367                          % (changesets, revisions, files, heads))
  1388                          % (changesets, revisions, files, heads))
  1368 
  1389 
       
  1390         self.hook('pretxnchangegroup', throw=True,
       
  1391                   node=hex(self.changelog.node(cor+1)))
       
  1392 
  1369         tr.close()
  1393         tr.close()
  1370 
  1394 
  1371         if changesets > 0:
  1395         if changesets > 0:
  1372             if not self.hook("changegroup",
  1396             self.hook("changegroup", node=hex(self.changelog.node(cor+1)))
  1373                              node=hex(self.changelog.node(cor+1))):
       
  1374                 self.ui.warn(_("abort: changegroup hook returned failure!\n"))
       
  1375                 return 1
       
  1376 
  1397 
  1377             for i in range(cor + 1, cnr + 1):
  1398             for i in range(cor + 1, cnr + 1):
  1378                 self.hook("incoming", node=hex(self.changelog.node(i)))
  1399                 self.hook("incoming", node=hex(self.changelog.node(i)))
  1379 
       
  1380         return
       
  1381 
  1400 
  1382     def update(self, node, allow=False, force=False, choose=None,
  1401     def update(self, node, allow=False, force=False, choose=None,
  1383                moddirstate=True, forcemerge=False, wlock=None):
  1402                moddirstate=True, forcemerge=False, wlock=None):
  1384         pl = self.dirstate.parents()
  1403         pl = self.dirstate.parents()
  1385         if not force and pl[1] != nullid:
  1404         if not force and pl[1] != nullid: