Changeset 270038 in webkit


Ignore:
Timestamp:
Nov 19, 2020 10:49:36 AM (3 years ago)
Author:
Jonathan Bedard
Message:

[webkitscmpy] Support remote Subversion repository
https://bugs.webkit.org/show_bug.cgi?id=218827
<rdar://problem/71304485>

Rubber-stamped by Aakash Jain.

It is possible to interact with a Subversion repository without the svn command. This is useful
for services hosted in environments where installing binaries is burdensome, or in cases where
tools are running without a checkout.

  • Scripts/libraries/webkitcorepy/webkitcorepy/init.py: Bump version, add dependencies.
  • Scripts/libraries/webkitscmpy/webkitscmpy/mocks/init.py:
  • Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote: Added.
  • Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/init.py: Added.
  • Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/svn.py: Added.

(Svn): Interact with a remote Subversion repository without using the svn command.
(Svn.is_webserver): Check if the provided url matches the pattern for a Subversion server.
(Svn.init):
(Svn.is_svn):
(Svn._latest): Return the latest revision.
(Svn.info): Return the bits of the svn info command that are used in code.
(Svn.default_branch):
(Svn.list):
(Svn.branches): List all branches.
(Svn.tags): List all tags.
(Svn._cache_path): Return path to json cache.
(Svn._cache_lock): Filesystem lock used to prevent contention over the json cache, this
is particularly important during testing.
(Svn._cache_revisions): Cache the identifier/revision mapping.
(Svn._branch_for): Given a commit, determine which branch that commit is on.
(Svn._commit_count): Determine the amount of commits on a branch since branching.
(Svn.commit): Return a commit object given a revision, branch, identifier or tag.

  • Scripts/libraries/webkitscmpy/webkitscmpy/remote: Added.
  • Scripts/libraries/webkitscmpy/webkitscmpy/remote/init.py: Added.
  • Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py: Added.

(Scm):
(Scm.from_url): Given a URL, attempt to determine what kind of remote API is available.
(Scm.init):

  • Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/svn.py: Added.

(Svn): Mock requests needed to interact with a remote Subversion repository.
(Svn.latest): Return the most recent commit on any branch.
(Svn.branches): Return branches at some revision.
(Svn.tags): Return tags at some revision.
(Svn.range): Give a start and end revision, along with a tag or branch,
return all commits in that range.
(Svn.request): Handle a small subset of requests to a Subversion server.

  • Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py:

(TestLocalSvn): Moved from TestSvn.
(TestRemoteSvn): Added.
(TestSvn): Moved to TestLocalSvn.

Location:
trunk/Tools
Files:
4 added
4 edited
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/Tools/ChangeLog

    r270035 r270038  
     12020-11-19  Jonathan Bedard  <jbedard@apple.com>
     2
     3        [webkitscmpy] Support remote Subversion repository
     4        https://bugs.webkit.org/show_bug.cgi?id=218827
     5        <rdar://problem/71304485>
     6
     7        Rubber-stamped by Aakash Jain.
     8
     9        It is possible to interact with a Subversion repository without the svn command. This is useful
     10        for services hosted in environments where installing binaries is burdensome, or in cases where
     11        tools are running without a checkout.
     12
     13        * Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Bump version, add dependencies.
     14        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/__init__.py:
     15        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote: Added.
     16        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/__init__.py: Added.
     17        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/svn.py: Added.
     18        (Svn): Interact with a remote Subversion repository without using the svn command.
     19        (Svn.is_webserver): Check if the provided url matches the pattern for a Subversion server.
     20        (Svn.__init__):
     21        (Svn.is_svn):
     22        (Svn._latest): Return the latest revision.
     23        (Svn.info): Return the bits of the `svn info` command that are used in code.
     24        (Svn.default_branch):
     25        (Svn.list):
     26        (Svn.branches): List all branches.
     27        (Svn.tags): List all tags.
     28        (Svn._cache_path): Return path to json cache.
     29        (Svn._cache_lock): Filesystem lock used to prevent contention over the json cache, this
     30        is particularly important during testing.
     31        (Svn._cache_revisions): Cache the identifier/revision mapping.
     32        (Svn._branch_for): Given a commit, determine which branch that commit is on.
     33        (Svn._commit_count): Determine the amount of commits on a branch since branching.
     34        (Svn.commit): Return a commit object given a revision, branch, identifier or tag.
     35        * Scripts/libraries/webkitscmpy/webkitscmpy/remote: Added.
     36        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/__init__.py: Added.
     37        * Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py: Added.
     38        (Scm):
     39        (Scm.from_url): Given a URL, attempt to determine what kind of remote API is available.
     40        (Scm.__init__):
     41        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/svn.py: Added.
     42        (Svn): Mock requests needed to interact with a remote Subversion repository.
     43        (Svn.latest): Return the most recent commit on any branch.
     44        (Svn.branches): Return branches at some revision.
     45        (Svn.tags): Return tags at some revision.
     46        (Svn.range): Give a start and end revision, along with a tag or branch,
     47        return all commits in that range.
     48        (Svn.request): Handle a small subset of requests to a Subversion server.
     49        * Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py:
     50        (TestLocalSvn): Moved from TestSvn.
     51        (TestRemoteSvn): Added.
     52        (TestSvn): Moved to TestLocalSvn.
     53
    1542020-11-19  Per Arne Vollan  <pvollan@apple.com>
    255
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py

    r270004 r270038  
    4747    )
    4848
    49 version = Version(0, 3, 2)
     49version = Version(0, 4, 0)
    5050
    5151AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil'))
     52AutoInstall.register(Package('fasteners', Version(0, 15, 0)))
     53AutoInstall.register(Package('monotonic', Version(1, 5)))
     54AutoInstall.register(Package('xmltodict', Version(0, 12, 0)))
    5255
    5356from webkitscmpy.contributor import Contributor
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/__init__.py

    r266628 r270038  
    22
    33from webkitscmpy.mocks import local
     4from webkitscmpy.mocks import remote
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/remote/__init__.py

    r270037 r270038  
    2121# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2222
    23 import logging
    24 import os
    25 import sys
    26 
    27 log = logging.getLogger('webkitscmpy')
    28 
    29 
    30 def _maybe_add_webkitcorepy_path():
    31     # Hopefully we're beside webkitcorepy, otherwise webkitcorepy will need to be installed.
    32     libraries_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
    33     webkitcorepy_path = os.path.join(libraries_path, 'webkitcorepy')
    34     if os.path.isdir(webkitcorepy_path) and os.path.isdir(os.path.join(webkitcorepy_path, 'webkitcorepy')) and webkitcorepy_path not in sys.path:
    35         sys.path.insert(0, webkitcorepy_path)
    36 
    37 
    38 _maybe_add_webkitcorepy_path()
    39 
    40 try:
    41     from webkitcorepy import AutoInstall, Package, Version
    42 except ImportError:
    43     raise ImportError(
    44         "'webkitcorepy' could not be found on your Python path.\n" +
    45         "You are not running from a WebKit checkout.\n" +
    46         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
    47     )
    48 
    49 version = Version(0, 3, 2)
    50 
    51 AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil'))
    52 
    53 from webkitscmpy.contributor import Contributor
    54 from webkitscmpy.commit import Commit
    55 from webkitscmpy.scm_base import ScmBase
    56 
    57 from webkitscmpy import local
    58 from webkitscmpy import mocks
    59 
    60 name = 'webkitscmpy'
     23from webkitscmpy.mocks.remote.svn import Svn
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/__init__.py

    r270037 r270038  
    2121# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2222
    23 import logging
    24 import os
    25 import sys
    26 
    27 log = logging.getLogger('webkitscmpy')
    28 
    29 
    30 def _maybe_add_webkitcorepy_path():
    31     # Hopefully we're beside webkitcorepy, otherwise webkitcorepy will need to be installed.
    32     libraries_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
    33     webkitcorepy_path = os.path.join(libraries_path, 'webkitcorepy')
    34     if os.path.isdir(webkitcorepy_path) and os.path.isdir(os.path.join(webkitcorepy_path, 'webkitcorepy')) and webkitcorepy_path not in sys.path:
    35         sys.path.insert(0, webkitcorepy_path)
    36 
    37 
    38 _maybe_add_webkitcorepy_path()
    39 
    40 try:
    41     from webkitcorepy import AutoInstall, Package, Version
    42 except ImportError:
    43     raise ImportError(
    44         "'webkitcorepy' could not be found on your Python path.\n" +
    45         "You are not running from a WebKit checkout.\n" +
    46         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
    47     )
    48 
    49 version = Version(0, 3, 2)
    50 
    51 AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil'))
    52 
    53 from webkitscmpy.contributor import Contributor
    54 from webkitscmpy.commit import Commit
    55 from webkitscmpy.scm_base import ScmBase
    56 
    57 from webkitscmpy import local
    58 from webkitscmpy import mocks
    59 
    60 name = 'webkitscmpy'
     23from webkitscmpy.remote.scm import Scm
     24from webkitscmpy.remote.svn import Svn
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/remote/scm.py

    r270037 r270038  
    2121# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2222
    23 import logging
    24 import os
    25 import sys
     23import six
    2624
    27 log = logging.getLogger('webkitscmpy')
     25from webkitscmpy.scm_base import ScmBase
    2826
    2927
    30 def _maybe_add_webkitcorepy_path():
    31     # Hopefully we're beside webkitcorepy, otherwise webkitcorepy will need to be installed.
    32     libraries_path = os.path.dirname(os.path.dirname(os.path.abspath(os.path.dirname(__file__))))
    33     webkitcorepy_path = os.path.join(libraries_path, 'webkitcorepy')
    34     if os.path.isdir(webkitcorepy_path) and os.path.isdir(os.path.join(webkitcorepy_path, 'webkitcorepy')) and webkitcorepy_path not in sys.path:
    35         sys.path.insert(0, webkitcorepy_path)
     28class Scm(ScmBase):
     29    @classmethod
     30    def from_url(cls, url):
     31        from webkitscmpy import remote
    3632
     33        if remote.Svn.is_webserver(url):
     34            return remote.Svn(url)
     35        raise OSError("'{}' is not a known SCM server".format(url))
    3736
    38 _maybe_add_webkitcorepy_path()
     37    def __init__(self, url, dev_branches=None, prod_branches=None):
     38        super(Scm, self).__init__(dev_branches=dev_branches, prod_branches=prod_branches)
    3939
    40 try:
    41     from webkitcorepy import AutoInstall, Package, Version
    42 except ImportError:
    43     raise ImportError(
    44         "'webkitcorepy' could not be found on your Python path.\n" +
    45         "You are not running from a WebKit checkout.\n" +
    46         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
    47     )
    48 
    49 version = Version(0, 3, 2)
    50 
    51 AutoInstall.register(Package('dateutil', Version(2, 8, 1), pypi_name='python-dateutil'))
    52 
    53 from webkitscmpy.contributor import Contributor
    54 from webkitscmpy.commit import Commit
    55 from webkitscmpy.scm_base import ScmBase
    56 
    57 from webkitscmpy import local
    58 from webkitscmpy import mocks
    59 
    60 name = 'webkitscmpy'
     40        if not isinstance(url, six.string_types):
     41            raise ValueError("Expected 'url' to be a string type, not '{}'".format(type(url)))
     42        self.url = url
  • trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/svn_unittest.py

    r269401 r270038  
    2828from datetime import datetime
    2929from webkitcorepy import OutputCapture
    30 from webkitscmpy import local, mocks
    31 
    32 
    33 class TestSvn(unittest.TestCase):
     30from webkitscmpy import local, mocks, remote
     31
     32
     33class TestLocalSvn(unittest.TestCase):
    3434    path = '/mock/repository'
    3535
     
    218218            self.assertEqual(9, repository.checkout('tag-1').revision)
    219219            self.assertEqual(9, repository.commit().revision)
     220
     221
     222class TestRemoteSvn(unittest.TestCase):
     223    remote = 'https://svn.webkit.org/repository/webkit'
     224
     225    def test_detection(self):
     226        self.assertEqual(remote.Svn.is_webserver('https://svn.webkit.org/repository/webkit'), True)
     227        self.assertEqual(remote.Svn.is_webserver('http://svn.webkit.org/repository/webkit'), True)
     228        self.assertEqual(remote.Svn.is_webserver('https://github.com/WebKit/webkit'), False)
     229
     230    def test_branches(self):
     231        with mocks.remote.Svn():
     232            self.assertEqual(
     233                remote.Svn(self.remote).branches,
     234                ['trunk', 'branch-a', 'branch-b'],
     235            )
     236
     237    def test_tags(self):
     238        with mocks.remote.Svn():
     239            self.assertEqual(
     240                remote.Svn(self.remote).tags,
     241                ['tag-1', 'tag-2'],
     242            )
     243
     244    def test_scm_type(self):
     245        self.assertTrue(remote.Svn(self.remote).is_svn)
     246        self.assertFalse(remote.Svn(self.remote).is_git)
     247
     248    def test_info(self):
     249        with mocks.remote.Svn():
     250            self.assertDictEqual({
     251                'Last Changed Author': 'jbedard@apple.com',
     252                'Last Changed Date': '2020-10-02 11:58:20',
     253                'Last Changed Rev': '6',
     254                'Revision': 10,
     255            }, remote.Svn(self.remote).info())
     256
     257    def test_commit_revision(self):
     258        with mocks.remote.Svn():
     259            self.assertEqual('1@trunk', str(remote.Svn(self.remote).commit(revision=1)))
     260            self.assertEqual('2@trunk', str(remote.Svn(self.remote).commit(revision=2)))
     261            self.assertEqual('2.1@branch-a', str(remote.Svn(self.remote).commit(revision=3)))
     262            self.assertEqual('3@trunk', str(remote.Svn(self.remote).commit(revision=4)))
     263            self.assertEqual('2.2@branch-b', str(remote.Svn(self.remote).commit(revision=5)))
     264            self.assertEqual('4@trunk', str(remote.Svn(self.remote).commit(revision=6)))
     265            self.assertEqual('2.2@branch-a', str(remote.Svn(self.remote).commit(revision=7)))
     266            self.assertEqual('2.3@branch-b', str(remote.Svn(self.remote).commit(revision=8)))
     267
     268            # Out-of-bounds commit
     269            with self.assertRaises(remote.Svn.Exception):
     270                self.assertEqual(None, remote.Svn(self.remote).commit(revision=11))
     271
     272    def test_commit_from_branch(self):
     273        with mocks.remote.Svn():
     274            self.assertEqual('4@trunk', str(remote.Svn(self.remote).commit(branch='trunk')))
     275            self.assertEqual('2.2@branch-a', str(remote.Svn(self.remote).commit(branch='branch-a')))
     276            self.assertEqual('2.3@branch-b', str(remote.Svn(self.remote).commit(branch='branch-b')))
     277
     278    def test_identifier(self):
     279        with mocks.remote.Svn():
     280            self.assertEqual(1, remote.Svn(self.remote).commit(identifier='1@trunk').revision)
     281            self.assertEqual(2, remote.Svn(self.remote).commit(identifier='2@trunk').revision)
     282            self.assertEqual(3, remote.Svn(self.remote).commit(identifier='2.1@branch-a').revision)
     283            self.assertEqual(4, remote.Svn(self.remote).commit(identifier='3@trunk').revision)
     284            self.assertEqual(5, remote.Svn(self.remote).commit(identifier='2.2@branch-b').revision)
     285            self.assertEqual(6, remote.Svn(self.remote).commit(identifier='4@trunk').revision)
     286            self.assertEqual(7, remote.Svn(self.remote).commit(identifier='2.2@branch-a').revision)
     287            self.assertEqual(8, remote.Svn(self.remote).commit(identifier='2.3@branch-b').revision)
     288
     289    def test_non_cannonical_identifiers(self):
     290        with mocks.remote.Svn():
     291            self.assertEqual('2@trunk', str(remote.Svn(self.remote).commit(identifier='0@branch-a')))
     292            self.assertEqual('1@trunk', str(remote.Svn(self.remote).commit(identifier='-1@branch-a')))
     293
     294            self.assertEqual('2@trunk', str(remote.Svn(self.remote).commit(identifier='0@branch-b')))
     295            self.assertEqual('1@trunk', str(remote.Svn(self.remote).commit(identifier='-1@branch-b')))
     296
     297    def test_tag(self):
     298        with mocks.remote.Svn():
     299            self.assertEqual(9, remote.Svn(self.remote).commit(tag='tag-1').revision)
     300
     301    def test_tag_previous(self):
     302        with mocks.remote.Svn():
     303            self.assertEqual(7, remote.Svn(self.remote).commit(identifier='2.2@tags/tag-1').revision)
Note: See TracChangeset for help on using the changeset viewer.