Changeset 269891 in webkit


Ignore:
Timestamp:
Nov 16, 2020 7:15:47 PM (3 years ago)
Author:
Jonathan Bedard
Message:

[webkitscmpy] Generalize parts of local.Scm class
https://bugs.webkit.org/show_bug.cgi?id=218935
<rdar://problem/71395688>

Rubber-stamped by Aakash Jain.

  • Scripts/libraries/webkitscmpy/webkitscmpy/init.py: Bump version.
  • Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py:

(Scm):
(Scm.Exception): Moved to ScmBase.
(Scm.init): Move branches logic to ScmBase.
(Scm.is_svn): Moved to ScmBase.
(Scm.is_git): Ditto.
(Scm.default_branch): Ditto.
(Scm.branches): Ditto.
(Scm.tags): Ditto.
(Scm.find): Ditto.
(Scm.commit): Ditto.
(Scm.prioritize_branches): Ditto.
(Scm.log): Ditto.

  • Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py:

(Svn.commit): Passing branch to self.info is redundant.

  • Scripts/libraries/webkitscmpy/webkitscmpy/mocks/init.py:
  • Scripts/libraries/webkitscmpy/webkitscmpy/scm_base.py: Added.

(ScmBase): Base class for all local and remote Scm objects.
(ScmBase.Exception): Moved from local.Scm.
(ScmBase.init): Ditto.
(ScmBase.is_svn): Ditto.
(ScmBase.is_git): Ditto.
(ScmBase.default_branch): Ditto.
(ScmBase.branches): Ditto.
(ScmBase.tags): Ditto.
(ScmBase.commit): Ditto.
(ScmBase.prioritize_branches): Ditto.
(ScmBase.find): Ditto.
(ScmBase.log): Ditto.

  • Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py:
Location:
trunk/Tools
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r269887 r269891  
     12020-11-16  Jonathan Bedard  <jbedard@apple.com>
     2
     3        [webkitscmpy] Generalize parts of local.Scm class
     4        https://bugs.webkit.org/show_bug.cgi?id=218935
     5        <rdar://problem/71395688>
     6
     7        Rubber-stamped by Aakash Jain.
     8
     9        * Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Bump version.
     10        * Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py:
     11        (Scm):
     12        (Scm.Exception): Moved to ScmBase.
     13        (Scm.__init__): Move branches logic to ScmBase.
     14        (Scm.is_svn): Moved to ScmBase.
     15        (Scm.is_git): Ditto.
     16        (Scm.default_branch): Ditto.
     17        (Scm.branches): Ditto.
     18        (Scm.tags): Ditto.
     19        (Scm.find): Ditto.
     20        (Scm.commit): Ditto.
     21        (Scm.prioritize_branches): Ditto.
     22        (Scm.log): Ditto.
     23        * Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py:
     24        (Svn.commit): Passing branch to self.info is redundant.
     25        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/__init__.py:
     26        * Scripts/libraries/webkitscmpy/webkitscmpy/scm_base.py: Added.
     27        (ScmBase): Base class for all local and remote Scm objects.
     28        (ScmBase.Exception): Moved from local.Scm.
     29        (ScmBase.__init__): Ditto.
     30        (ScmBase.is_svn): Ditto.
     31        (ScmBase.is_git): Ditto.
     32        (ScmBase.default_branch): Ditto.
     33        (ScmBase.branches): Ditto.
     34        (ScmBase.tags): Ditto.
     35        (ScmBase.commit): Ditto.
     36        (ScmBase.prioritize_branches): Ditto.
     37        (ScmBase.find): Ditto.
     38        (ScmBase.log): Ditto.
     39        * Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py:
     40
    1412020-11-16  Ling Ho  <lingho@apple.com>
    242
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py

    r269401 r269891  
    4747    )
    4848
    49 version = Version(0, 3, 0)
     49version = Version(0, 3, 1)
    5050
    5151AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil'))
     
    5353from webkitscmpy.contributor import Contributor
    5454from webkitscmpy.commit import Commit
     55from webkitscmpy.scm_base import ScmBase
    5556
    5657from webkitscmpy import local
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py

    r269401 r269891  
    2222
    2323
    24 import logging
    2524import os
    2625import re
    2726import six
    28 import sys
    2927
    30 from logging import NullHandler
    3128from webkitcorepy import run
    32 from webkitscmpy import log, Commit
     29from webkitscmpy import ScmBase
    3330
    3431
    35 class Scm(object):
    36     class Exception(RuntimeError):
    37         pass
    38 
     32class Scm(ScmBase):
    3933    # Projects can define for themselves what constitutes a development vs a production branch,
    4034    # the following idioms seem common enough to be shared.
     
    6559
    6660    def __init__(self, path, dev_branches=None, prod_branches=None):
    67         if not isinstance(path, str):
    68             raise ValueError('')
     61        super(Scm, self).__init__(dev_branches=dev_branches, prod_branches=prod_branches)
     62
     63        if not isinstance(path, six.string_types):
     64            raise ValueError("Expected 'path' to be a string type, not '{}'".format(type(path)))
    6965        self.path = path
    70 
    71         self.dev_branches = dev_branches or self.DEV_BRANCHES
    72         self.prod_branches = prod_branches or self.PROD_BRANCHES
    73 
    74     @property
    75     def is_svn(self):
    76         return False
    77 
    78     @property
    79     def is_git(self):
    80         return False
    8166
    8267    @property
     
    8570
    8671    @property
    87     def default_branch(self):
    88         raise NotImplementedError()
    89 
    90     @property
    9172    def branch(self):
    92         raise NotImplementedError()
    93 
    94     @property
    95     def branches(self):
    96         raise NotImplementedError()
    97 
    98     @property
    99     def tags(self):
    10073        raise NotImplementedError()
    10174
     
    10376        raise NotImplementedError()
    10477
    105     def find(self, argument):
    106         if not isinstance(argument, six.string_types):
    107             raise ValueError("Expected 'argument' to be a string, not '{}'".format(type(argument)))
    108 
    109         offset = 0
    110         if '~' in argument:
    111             for s in argument.split('~')[1:]:
    112                 if s and not s.isdigit():
    113                     raise ValueError("'{}' is not a valid argument to Scm.find()".format(argument))
    114                 offset += int(s) if s else 1
    115             argument = argument.split('~')[0]
    116 
    117         if argument == 'HEAD':
    118             result = self.commit()
    119 
    120         elif argument in self.branches:
    121             result = self.commit(branch=argument)
    122 
    123         elif argument in self.tags:
    124             result = self.commit(tag=argument)
    125 
    126         else:
    127             if offset:
    128                 raise ValueError("'~' offsets are not supported for revisions and identifiers")
    129 
    130             parsed_commit = Commit.parse(argument)
    131             return self.commit(
    132                 hash=parsed_commit.hash,
    133                 revision=parsed_commit.revision,
    134                 identifier=parsed_commit.identifier,
    135                 branch=parsed_commit.branch,
    136             )
    137 
    138         if not offset:
    139             return result
    140 
    141         return self.commit(
    142             identifier=result.identifier - offset,
    143             branch=result.branch,
    144         )
    145 
    14678    def checkout(self, argument):
    14779        raise NotImplementedError()
    148 
    149     def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None):
    150         raise NotImplementedError()
    151 
    152     def prioritize_branches(self, branches):
    153         if len(branches) == 1:
    154             return branches[0]
    155 
    156         default_branch = self.default_branch
    157         if default_branch in branches:
    158             return default_branch
    159 
    160         # We don't have enough information to determine a branch. We will attempt to first use the branch specified
    161         # by the caller, then the one then checkout is currently on. If both those fail, we will pick one of the
    162         # other branches. We prefer production branches first, then any branch which isn't explicitly labeled a
    163         # dev branch. We then sort the list of candidate branches and pick the smallest
    164         filtered_candidates = [candidate for candidate in branches if self.prod_branches.match(candidate)]
    165         if not filtered_candidates:
    166             filtered_candidates = [candidate for candidate in branches if not self.dev_branches.match(candidate)]
    167         if not filtered_candidates:
    168             filtered_candidates = branches
    169         return sorted(filtered_candidates)[0]
    170 
    171     @classmethod
    172     def log(cls, message, level=logging.WARNING):
    173         if not log.handlers or all([isinstance(handle, NullHandler) for handle in log.handlers]):
    174             sys.stderr.write(message + '\n')
    175         else:
    176             log.log(level, message)
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/svn.py

    r269401 r269891  
    312312            revision = Commit._parse_revision(revision, do_assert=True)
    313313            branch = self._branch_for(revision)
    314             info = self.info(cached=True, branch=branch, revision=revision)
     314            info = self.info(cached=True, revision=revision)
    315315
    316316        else:
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/scm_base.py

    r269890 r269891  
    55# are met:
    66# 1.  Redistributions of source code must retain the above copyright
    7 #     notice, this list of conditions and the following disclaimer.
     7#    notice, this list of conditions and the following disclaimer.
    88# 2.  Redistributions in binary form must reproduce the above copyright
    9 #     notice, this list of conditions and the following disclaimer in the
    10 #     documentation and/or other materials provided with the distribution.
     9#    notice, this list of conditions and the following disclaimer in the
     10#    documentation and/or other materials provided with the distribution.
    1111#
    12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND
    13 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     13# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
    1414# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
    15 # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
    16 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
    17 # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
    18 # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
    19 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
    20 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    21 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    22 
     15# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     16# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     17# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     18# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     19# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     20# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     21# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2322
    2423import logging
    25 import os
    2624import re
    2725import six
     
    2927
    3028from logging import NullHandler
    31 from webkitcorepy import run
    32 from webkitscmpy import log, Commit
     29from webkitscmpy import Commit, log
    3330
    3431
    35 class Scm(object):
     32class ScmBase(object):
    3633    class Exception(RuntimeError):
    3734        pass
     
    4239    PROD_BRANCHES = re.compile(r'\S+-[\d+\.]+-branch')
    4340
    44     @classmethod
    45     def executable(cls, program):
    46         for candidate in ['/usr/bin', '/usr/bin/local']:
    47             candidate = os.path.join(candidate, program)
    48             if os.path.exists(candidate):
    49                 return candidate
    50 
    51         which = run(['/usr/bin/which', program], capture_output=True, encoding='utf-8')
    52         if not which.returncode:
    53             return os.path.realpath(which.stdout.rstrip())
    54         raise OSError("Cannot find '{}' program".format(program))
    55 
    56     @classmethod
    57     def from_path(cls, path):
    58         from webkitscmpy import local
    59 
    60         if local.Git.is_checkout(path):
    61             return local.Git(path)
    62         if local.Svn.is_checkout(path):
    63             return local.Svn(path)
    64         raise OSError("'{}' is not a known SCM type".format(path))
    65 
    66     def __init__(self, path, dev_branches=None, prod_branches=None):
    67         if not isinstance(path, str):
    68             raise ValueError('')
    69         self.path = path
    70 
     41    def __init__(self, dev_branches=None, prod_branches=None):
    7142        self.dev_branches = dev_branches or self.DEV_BRANCHES
    7243        self.prod_branches = prod_branches or self.PROD_BRANCHES
     44        self.path = None
    7345
    7446    @property
     
    8153
    8254    @property
    83     def root_path(self):
    84         raise NotImplementedError()
    85 
    86     @property
    8755    def default_branch(self):
    88         raise NotImplementedError()
    89 
    90     @property
    91     def branch(self):
    9256        raise NotImplementedError()
    9357
     
    10064        raise NotImplementedError()
    10165
    102     def remote(self, name=None):
     66    def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None):
    10367        raise NotImplementedError()
     68
     69    def prioritize_branches(self, branches):
     70        if len(branches) == 1:
     71            return branches[0]
     72
     73        default_branch = self.default_branch
     74        if default_branch in branches:
     75            return default_branch
     76
     77        # We don't have enough information to determine a branch. We will attempt to first use the branch specified
     78        # by the caller, then the one then checkout is currently on. If both those fail, we will pick one of the
     79        # other branches. We prefer production branches first, then any branch which isn't explicitly labeled a
     80        # dev branch. We then sort the list of candidate branches and pick the smallest
     81        filtered_candidates = [candidate for candidate in branches if self.prod_branches.match(candidate)]
     82        if not filtered_candidates:
     83            filtered_candidates = [candidate for candidate in branches if not self.dev_branches.match(candidate)]
     84        if not filtered_candidates:
     85            filtered_candidates = branches
     86        return sorted(filtered_candidates)[0]
    10487
    10588    def find(self, argument):
     
    144127        )
    145128
    146     def checkout(self, argument):
    147         raise NotImplementedError()
    148 
    149     def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None):
    150         raise NotImplementedError()
    151 
    152     def prioritize_branches(self, branches):
    153         if len(branches) == 1:
    154             return branches[0]
    155 
    156         default_branch = self.default_branch
    157         if default_branch in branches:
    158             return default_branch
    159 
    160         # We don't have enough information to determine a branch. We will attempt to first use the branch specified
    161         # by the caller, then the one then checkout is currently on. If both those fail, we will pick one of the
    162         # other branches. We prefer production branches first, then any branch which isn't explicitly labeled a
    163         # dev branch. We then sort the list of candidate branches and pick the smallest
    164         filtered_candidates = [candidate for candidate in branches if self.prod_branches.match(candidate)]
    165         if not filtered_candidates:
    166             filtered_candidates = [candidate for candidate in branches if not self.dev_branches.match(candidate)]
    167         if not filtered_candidates:
    168             filtered_candidates = branches
    169         return sorted(filtered_candidates)[0]
    170 
    171129    @classmethod
    172130    def log(cls, message, level=logging.WARNING):
Note: See TracChangeset for help on using the changeset viewer.