Changeset 648 for CMT


Ignore:
Timestamp:
Jul 9, 2013, 12:08:28 PM (11 years ago)
Author:
rybkin
Message:

See C.L. 507

Location:
CMT/HEAD
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • CMT/HEAD/ChangeLog

    r647 r648  
     12013-07-09    <rybkin@lal.in2p3.fr> 507
     2
     3        * mgr/cmt_svn_checkout.py: Use a different algorithm in the class Checkout
     4        function trunk_tag in order to optimise the performance, suggested by
     5        Wim Lavrijsen. Add --debug command line option and SVNDEBUG environment
     6        variable to facilitate debugging
     7
    182013-06-25    <rybkin@lal.in2p3.fr> 506
    29
  • CMT/HEAD/mgr/cmt_svn_checkout.py

    r605 r648  
    1515      --with_version_directory create version directory upon PATH checkout (default)
    1616      --url=URL                checkout PATH from repository URL
     17      --debug                  print lots of debugging information
    1718  -h, --help                   display this help and exit
    1819      --version                output version information and exit
     
    2324"""
    2425
    25 __version__ = '0.6.0'
    26 __date__ = 'Fri Mar 09 2012'
     26__version__ = '0.7.0'
     27__date__ = 'Tue Jul 09 2013'
    2728__author__ = 'Grigory Rybkin'
    2829
     
    4041import tempfile
    4142import re
     43
     44import logging
    4245
    4346self = 'cmt_svn_checkout.py'
     
    378381        """Attempt to determine the tag of the module's trunk.
    379382       
    380         Return the tag if its contents are the same as those of the trunk, and
    381         its last_changed_rev is greater than the trunk created_rev, None otherwise.
     383        Return the tag if its files are copied from the trunk and
     384        their last_changed_rev numbers are the same as those of the trunk files.
    382385        """
    383386        trunk = posixpath.join(module.url, self.trunk)
    384387#        trunk = posixpath.normpath(posixpath.join(module.url, self.trunk))
     388        cmd = 'svn ls -vR %s' % trunk
     389        sc, out = Utils.getstatusoutput(cmd)
     390        logger.debug('%s\n%s' % (cmd, out))
     391        if sc != 0:
     392            return None
     393        trunk_dirent = [line.split() for line in out.splitlines()]
     394        trunk_revs = dict([(line[-1], int(line[0])) for line in trunk_dirent if not line[-1].endswith(posixpath.sep)])
     395        logger.debug('%s' % trunk_revs)
     396
     397        curdir = posixpath.curdir + posixpath.sep
     398        for line in trunk_dirent:
     399            if line[-1] == curdir:
     400                class info(object): pass
     401                info.last_changed_rev = int(line[0])
     402                self.info_receiver(trunk, info, module)
     403                logger.debug('last_changed_rev: %d' % info.last_changed_rev)
     404                break
     405
     406#        cmd = 'svn info %s' % trunk
     407#         p = r'last\s+changed\s+rev:\s+(?P<rev>\d+)'
     408#         m = re.search(p, out, re.I)
     409#         if m:
     410#             class info(object): pass
     411#             info.last_changed_rev = int(m.group('rev'))
     412#             self.info_receiver(trunk, info, module)
     413# #            self.info_receiver(trunk, info, None)
     414# #             print >>sys.stderr, '%s: last_changed_rev %i' % \
     415# #                   (trunk, self.info.last_changed_rev)
     416# #            last_changed_rev = int(m.group('rev'))
     417#         else:
     418#             return None
     419
     420        tags = posixpath.join(module.url, self.tags)
     421#        tags = posixpath.normpath(posixpath.join(module.url, self.tags))
     422        cmd = 'svn ls -vR %s' % tags
     423#        cmd = 'svn ls -v %s' % tags
     424        sc, out = Utils.getstatusoutput(cmd)
     425        logger.debug('%s\n%s' % (cmd, out))
     426        if sc != 0:
     427            return None
     428        tags_dirent = [line.split() for line in out.splitlines()]
     429        tags_revs = dict()
     430        for ent in tags_dirent:
     431            try:
     432                tag, path = ent[-1].split(posixpath.sep, 1)
     433            except ValueError:
     434                continue
     435            if tag not in tags_revs:
     436                tags_revs[tag] = dict()
     437            if path and not path.endswith(posixpath.sep):
     438                # assume there are no empty directories in the tag
     439                tags_revs[tag][path] = int(ent[0])
     440        logger.debug('%s' % tags_revs)
     441
    385442        cmd = 'svn info %s' % trunk
    386443        sc, out = Utils.getstatusoutput(cmd)
     444        logger.debug('%s\n%s' % (cmd, out))
    387445        if sc != 0:
    388446            return None
    389         p = r'last\s+changed\s+rev:\s+(?P<rev>\d+)'
     447        p = r'repository\s+root:\s+(?P<root>%s://\S+)' % \
     448            ('(?:' + '|'.join(map(re.escape, client_context.schemes)) + ')')
    390449        m = re.search(p, out, re.I)
     450        logger.debug('pattern: %r' % (p))
    391451        if m:
    392             class info(object): pass
    393             info.last_changed_rev = int(m.group('rev'))
    394             self.info_receiver(trunk, info, module)
    395 #            self.info_receiver(trunk, info, None)
    396 #             print >>sys.stderr, '%s: last_changed_rev %i' % \
    397 #                   (trunk, self.info.last_changed_rev)
    398 #            last_changed_rev = int(m.group('rev'))
     452            root = m.group('root')
    399453        else:
    400454            return None
    401 
    402         tags = posixpath.join(module.url, self.tags)
    403 #        tags = posixpath.normpath(posixpath.join(module.url, self.tags))
    404         cmd = 'svn ls -v %s' % tags
     455        logger.debug('root: %s' % root)
     456        trunk_path = trunk[len(root):]
     457        tags_path = tags[len(root):]
     458        logger.debug('trunk_path: %s' % trunk_path)
     459        logger.debug('tags_path: %s' % tags_path)
     460        offset = len(trunk) - len(root) + len(posixpath.sep)
     461       
     462        # Usually, a tag is created as a server-side copy.
     463        # Sometimes, a tag is created as a copy of WC (working copy)
     464        # after commit.
     465        # Below, we try to take into account the latter case.
     466        cmd = 'svn log -v -q %s' % tags
    405467        sc, out = Utils.getstatusoutput(cmd)
     468        logger.debug('%s\n%s' % (cmd, out))
    406469        if sc != 0:
    407470            return None
    408 
    409         tags_dirent = [line.split() for line in out.splitlines()]
    410         rev_tag = dict([(int(line[0]), line[-1].rstrip(posixpath.sep)) for line in tags_dirent if line[-1].endswith(posixpath.sep)])
    411         revs = rev_tag.keys()
    412         revs.sort()
    413         revs.reverse()
    414 
    415         for rev in revs:
    416             if rev < self.info.last_changed_rev: break
    417 #            if rev < last_changed_rev: break
    418             tag = posixpath.join(tags, rev_tag[rev])
    419 #            tag = posixpath.normpath(posixpath.join(tags, rev_tag[rev]))
    420             if 0 == self.cmp(trunk, tag, client_context):
    421                 return rev_tag[rev]
     471        p = re.compile(
     472            r'^-{5,}$\s^r\d+.+$\s^Changed paths:$\s^\s+A\s+%s%s(?P<tag>[^%s]+)\s+\(from %s:\d+\)$(?P<replaced>(?:\s^\s+(?:R|A|D)\s+%s%s(?P=tag)%s(?P<path>.+)(?:\s+\(from %s%s(?P=path):\d+\))?$)*)' % (re.escape(tags_path), posixpath.sep, posixpath.sep, re.escape(trunk_path), re.escape(tags_path), posixpath.sep, posixpath.sep, re.escape(trunk_path), posixpath.sep)
     473            , re.M
     474            )
     475        tags_copied = list()
     476        tags_replaced_revs = dict()
     477        for m in p.finditer(out):
     478            logger.debug('tag: %s replaced: %r' % (m.group('tag'), m.group('replaced')))
     479            tags_copied.append(m.group('tag'))
     480            for line in m.group('replaced').strip().splitlines():
     481                l = line.split()
     482                if len(l) == 2: continue # action code D - deleted paths
     483                repl = l[3].rstrip(')')
     484                i = repl.rindex(':')
     485                path = repl[offset:i]
     486                rev = int(repl[i + 1:])
     487                logger.debug('path: %s rev: %d' % (path, rev))
     488
     489                if m.group('tag') not in tags_replaced_revs:
     490                    tags_replaced_revs[m.group('tag')] = dict()
     491                if path and not path.endswith(posixpath.sep):
     492                    # assume there are no empty directories in the tag
     493                    tags_replaced_revs[m.group('tag')][path] = rev
     494
     495        logger.debug('copied: %s' % tags_copied)
     496        logger.debug('replaced: %s' % tags_replaced_revs)
     497
     498        for t in tags_revs.keys():
     499            if t not in tags_copied:
     500                del tags_revs[t]
     501                logger.debug('%s: Not a trunk copy' % t)
     502
     503        for t in tags_replaced_revs:
     504            if t in tags_revs:
     505                tags_revs[t].update(tags_replaced_revs[t])
     506               
     507        for tag in tags_revs:
     508            logger.debug('Compare: %s -> %s' % (tag, tags_revs[tag]))
     509            if trunk_revs == tags_revs[tag]:
     510                return tag
    422511
    423512        return None
     513
     514#         tags_dirent = [line.split() for line in out.splitlines()]
     515#         rev_tag = dict([(int(line[0]), line[-1].rstrip(posixpath.sep)) for line in tags_dirent if line[-1].endswith(posixpath.sep)])
     516#         revs = rev_tag.keys()
     517#         revs.sort()
     518#         revs.reverse()
     519
     520#         for rev in revs:
     521#             logger.debug('rev: %s' % rev)
     522#             if rev < self.info.last_changed_rev: break
     523# #            if rev < last_changed_rev: break
     524#             tag = posixpath.join(tags, rev_tag[rev])
     525# #            tag = posixpath.normpath(posixpath.join(tags, rev_tag[rev]))
     526#             logger.debug('comparing: %s %s(%d)' % (trunk, tag, rev))
     527#             if 0 == self.cmp(trunk, tag, client_context):
     528#                 return rev_tag[rev]
     529
     530#         return None
    424531
    425532#         try:
     
    572679                                    "offset=", "no_config",
    573680                                    "with_version_directory",
    574                                     "without_version_directory", "url="])
     681                                    "without_version_directory", "url=", "debug"])
    575682    except getopt.error, e:
    576683        print >>sys.stderr, '%s: %s' % (self, str(e))
    577684        print >>sys.stderr, "Try '%s --help' for more information." % self
    578685        return 1
     686
     687    global logger
     688    logging.basicConfig()
     689    logger = logging.getLogger(self)
     690    logger.setLevel(logging.INFO)
     691    if os.getenv('SVNDEBUG'):
     692        logger.setLevel(logging.DEBUG)
    579693
    580694    cmt_context = CmtContext()
     
    605719        elif o in ("--url",):
    606720            checkout.url = v
     721        elif o in ("--debug",):
     722            logger.setLevel(logging.DEBUG)
    607723
    608724    if not args:
Note: See TracChangeset for help on using the changeset viewer.