Changeset 269891 in webkit
- Timestamp:
- Nov 16, 2020 7:15:47 PM (3 years ago)
- Location:
- trunk/Tools
- Files:
-
- 4 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r269887 r269891 1 2020-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 1 41 2020-11-16 Ling Ho <lingho@apple.com> 2 42 -
trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py
r269401 r269891 47 47 ) 48 48 49 version = Version(0, 3, 0)49 version = Version(0, 3, 1) 50 50 51 51 AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil')) … … 53 53 from webkitscmpy.contributor import Contributor 54 54 from webkitscmpy.commit import Commit 55 from webkitscmpy.scm_base import ScmBase 55 56 56 57 from webkitscmpy import local -
trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/scm.py
r269401 r269891 22 22 23 23 24 import logging25 24 import os 26 25 import re 27 26 import six 28 import sys29 27 30 from logging import NullHandler31 28 from webkitcorepy import run 32 from webkitscmpy import log, Commit29 from webkitscmpy import ScmBase 33 30 34 31 35 class Scm(object): 36 class Exception(RuntimeError): 37 pass 38 32 class Scm(ScmBase): 39 33 # Projects can define for themselves what constitutes a development vs a production branch, 40 34 # the following idioms seem common enough to be shared. … … 65 59 66 60 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))) 69 65 self.path = path 70 71 self.dev_branches = dev_branches or self.DEV_BRANCHES72 self.prod_branches = prod_branches or self.PROD_BRANCHES73 74 @property75 def is_svn(self):76 return False77 78 @property79 def is_git(self):80 return False81 66 82 67 @property … … 85 70 86 71 @property 87 def default_branch(self):88 raise NotImplementedError()89 90 @property91 72 def branch(self): 92 raise NotImplementedError()93 94 @property95 def branches(self):96 raise NotImplementedError()97 98 @property99 def tags(self):100 73 raise NotImplementedError() 101 74 … … 103 76 raise NotImplementedError() 104 77 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 = 0110 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 1115 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 result140 141 return self.commit(142 identifier=result.identifier - offset,143 branch=result.branch,144 )145 146 78 def checkout(self, argument): 147 79 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_branch157 if default_branch in branches:158 return default_branch159 160 # We don't have enough information to determine a branch. We will attempt to first use the branch specified161 # by the caller, then the one then checkout is currently on. If both those fail, we will pick one of the162 # other branches. We prefer production branches first, then any branch which isn't explicitly labeled a163 # dev branch. We then sort the list of candidate branches and pick the smallest164 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 = branches169 return sorted(filtered_candidates)[0]170 171 @classmethod172 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 312 312 revision = Commit._parse_revision(revision, do_assert=True) 313 313 branch = self._branch_for(revision) 314 info = self.info(cached=True, branch=branch,revision=revision)314 info = self.info(cached=True, revision=revision) 315 315 316 316 else: -
trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/scm_base.py
r269890 r269891 5 5 # are met: 6 6 # 1. Redistributions of source code must retain the above copyright 7 # 7 # notice, this list of conditions and the following disclaimer. 8 8 # 2. Redistributions in binary form must reproduce the above copyright 9 # 10 # 9 # notice, this list of conditions and the following disclaimer in the 10 # documentation and/or other materials provided with the distribution. 11 11 # 12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND13 # ANYEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED12 # 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 14 14 # 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. 23 22 24 23 import logging 25 import os26 24 import re 27 25 import six … … 29 27 30 28 from logging import NullHandler 31 from webkitcorepy import run 32 from webkitscmpy import log, Commit 29 from webkitscmpy import Commit, log 33 30 34 31 35 class Scm (object):32 class ScmBase(object): 36 33 class Exception(RuntimeError): 37 34 pass … … 42 39 PROD_BRANCHES = re.compile(r'\S+-[\d+\.]+-branch') 43 40 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): 71 42 self.dev_branches = dev_branches or self.DEV_BRANCHES 72 43 self.prod_branches = prod_branches or self.PROD_BRANCHES 44 self.path = None 73 45 74 46 @property … … 81 53 82 54 @property 83 def root_path(self):84 raise NotImplementedError()85 86 @property87 55 def default_branch(self): 88 raise NotImplementedError()89 90 @property91 def branch(self):92 56 raise NotImplementedError() 93 57 … … 100 64 raise NotImplementedError() 101 65 102 def remote(self, name=None):66 def commit(self, hash=None, revision=None, identifier=None, branch=None, tag=None): 103 67 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] 104 87 105 88 def find(self, argument): … … 144 127 ) 145 128 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_branch157 if default_branch in branches:158 return default_branch159 160 # We don't have enough information to determine a branch. We will attempt to first use the branch specified161 # by the caller, then the one then checkout is currently on. If both those fail, we will pick one of the162 # other branches. We prefer production branches first, then any branch which isn't explicitly labeled a163 # dev branch. We then sort the list of candidate branches and pick the smallest164 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 = branches169 return sorted(filtered_candidates)[0]170 171 129 @classmethod 172 130 def log(cls, message, level=logging.WARNING):
Note: See TracChangeset
for help on using the changeset viewer.