Title: [289077] trunk
Revision
289077
Author
jbed...@apple.com
Date
2022-02-03 13:47:06 -0800 (Thu, 03 Feb 2022)

Log Message

[git-webkit] Configure default branch management
https://bugs.webkit.org/show_bug.cgi?id=235378
<rdar://problem/87989533>

Reviewed by Dewei Zhu.

* Tools/Scripts/libraries/webkitcorepy/setup.py: Bump version.
* Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Ditto.
* Tools/Scripts/libraries/webkitcorepy/webkitcorepy/decorators.py:
(hybridmethod.__get__): Forward certain attributes, namely those used by Memoize.
* Tools/Scripts/libraries/webkitscmpy/setup.py: Bump version.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py:
(Git):
(Git.config): Add project config to fall back on.
(Git.url): Move memoize to config.
(Git.checkout): Clear Git.config, since that owns memoization.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py:
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py:
(PullRequest.parser): Add --overwrite and --append flags.
(PullRequest.create_commit): Either amend an existing commit or create a new one,
depending on the repository settings and arguments passed.
(PullRequest.main): Only keep track of branch history if the user explicitly requests
it or we're using an overwrite workflow with a user owned fork. If repository settings
indicate such branches should never be created, return an error if the user attempts to do so.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py:
(Setup.git): Add project config to repository config, prompt the user about their prefered
history retention strategy if the project is using an overwrite workflow.
(Setup.parser): Use the project's default merge behavior.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py:
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py:
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/setup_unittest.py:

Canonical link: https://commits.webkit.org/246783@main

Modified Paths

Added Paths

Diff

Modified: trunk/ChangeLog (289076 => 289077)


--- trunk/ChangeLog	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/ChangeLog	2022-02-03 21:47:06 UTC (rev 289077)
@@ -1,3 +1,13 @@
+2022-01-24  Jonathan Bedard  <jbed...@apple.com>
+
+        [git-webkit] Configure default branch management 
+        https://bugs.webkit.org/show_bug.cgi?id=235378
+        <rdar://problem/87989533>
+
+        Reviewed by Dewei Zhu.
+
+        * metadata/project_config: Added.
+
 2022-02-03  Carlos Garcia Campos  <cgar...@igalia.com>
 
         Unreviewed. Update OptionsGTK.cmake and NEWS for 2.35.2 release

Modified: trunk/Tools/ChangeLog (289076 => 289077)


--- trunk/Tools/ChangeLog	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/ChangeLog	2022-02-03 21:47:06 UTC (rev 289077)
@@ -1,3 +1,38 @@
+2022-02-03  Jonathan Bedard  <jbed...@apple.com>
+
+        [git-webkit] Configure default branch management 
+        https://bugs.webkit.org/show_bug.cgi?id=235378
+        <rdar://problem/87989533>
+
+        Reviewed by Dewei Zhu.
+
+        * Scripts/libraries/webkitcorepy/setup.py: Bump version.
+        * Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py: Ditto.
+        * Scripts/libraries/webkitcorepy/webkitcorepy/decorators.py:
+        (hybridmethod.__get__): Forward certain attributes, namely those used by Memoize.
+        * Scripts/libraries/webkitscmpy/setup.py: Bump version.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py: Ditto.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py:
+        (Git):
+        (Git.config): Add project config to fall back on.
+        (Git.url): Move memoize to config.
+        (Git.checkout): Clear Git.config, since that owns memoization.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py:
+        * Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py:
+        (PullRequest.parser): Add --overwrite and --append flags.
+        (PullRequest.create_commit): Either amend an existing commit or create a new one,
+        depending on the repository settings and arguments passed.
+        (PullRequest.main): Only keep track of branch history if the user explicitly requests
+        it or we're using an overwrite workflow with a user owned fork. If repository settings
+        indicate such branches should never be created, return an error if the user attempts to do so.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py:
+        (Setup.git): Add project config to repository config, prompt the user about their prefered
+        history retention strategy if the project is using an overwrite workflow.
+        (Setup.parser): Use the project's default merge behavior.
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py:
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py:
+        * Scripts/libraries/webkitscmpy/webkitscmpy/test/setup_unittest.py:
+
 2022-02-03  Fujii Hironori  <hironori.fu...@sony.com>
 
         REGRESSION(r288878) webkitpy.layout_tests.controllers.layout_test_finder_legacy_unittest.LayoutTestFinderTests tests are failing with Windows Python

Modified: trunk/Tools/Scripts/libraries/webkitcorepy/setup.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitcorepy/setup.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/setup.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -30,7 +30,7 @@
 
 setup(
     name='webkitcorepy',
-    version='0.12.8',
+    version='0.12.9',
     description='Library containing various Python support classes and functions.',
     long_description=readme(),
     classifiers=[

Modified: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/__init__.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -44,7 +44,7 @@
 from webkitcorepy.editor import Editor
 from webkitcorepy.file_lock import FileLock
 
-version = Version(0, 12, 8)
+version = Version(0, 12, 9)
 
 from webkitcorepy.autoinstall import Package, AutoInstall
 if sys.version_info > (3, 0):

Modified: trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/decorators.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/decorators.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitcorepy/webkitcorepy/decorators.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -80,5 +80,8 @@
         wrapper.__doc__ = self.function.__doc__
         wrapper.__func__ = wrapper.im_func = self.function
         wrapper.__self__ = wrapper.im_self = context
+        for attribute in ['clear']:
+            if getattr(self.function, attribute, None):
+                setattr(wrapper, attribute, getattr(self.function, attribute))
 
         return wrapper

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/setup.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/setup.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/setup.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -29,7 +29,7 @@
 
 setup(
     name='webkitscmpy',
-    version='3.1.7',
+    version='3.2.0',
     description='Library designed to interact with git and svn repositories.',
     long_description=readme(),
     classifiers=[

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/__init__.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -46,7 +46,7 @@
         "Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
     )
 
-version = Version(3, 1, 7)
+version = Version(3, 2, 0)
 
 AutoInstall.register(Package('fasteners', Version(0, 15, 0)))
 AutoInstall.register(Package('jinja2', Version(2, 11, 3)))

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/contributor.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/contributor.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/contributor.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -93,13 +93,13 @@
         def save(self, file):
             alias_to_name = defaultdict(list)
             for alias, contributor in self.items():
-                if alias in contributor.emails or alias == contributor.name:
+                if not contributor or alias in contributor.emails or alias == contributor.name:
                     continue
                 alias_to_name[contributor.name].append(alias)
 
             contributors = []
             for alias, contributor in self.items():
-                if alias != contributor.name:
+                if not contributor or alias != contributor.name:
                     continue
                 contributors.append(Contributor.Encoder().default(contributor))
                 contributors[-1]['aliases'] = alias_to_name[contributor.name]

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/local/git.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -1,4 +1,4 @@
-# Copyright (C) 2020, 2021 Apple Inc. All rights reserved.
+# Copyright (C) 2020-2022 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -300,6 +300,13 @@
     HTTP_REMOTE = re.compile(r'(?P<protocol>https?)://(?P<host>[^\/]+)/(?P<path>.+).git')
     REMOTE_BRANCH = re.compile(r'remotes\/(?P<remote>[^\/]+)\/(?P<branch>.+)')
     USER_REMOTE = re.compile(r'(?P<username>[^:/]+):(?P<branch>.+)')
+    PROJECT_CONFIG_PATH = os.path.join('metadata', 'project_config')
+    PROJECT_CONFIG_OPTIONS = {
+        'pull.rebase': ['true', 'false'],
+        'webkitscmpy.pull-request': ['overwrite', 'append'],
+        'webkitscmpy.history': ['when-user-owned', 'disabled', 'always', 'never'],
+    }
+    CONFIG_LOCATIONS = ['global', 'repository', 'project']
 
     @classmethod
     @decorators.Memoize()
@@ -311,14 +318,25 @@
         return run([cls.executable(), 'rev-parse', '--show-toplevel'], cwd=path, capture_output=True).returncode == 0
 
     @decorators.hybridmethod
-    def config(context):
+    @decorators.Memoize()
+    def config(context, location=None):
         args = [context.executable(), 'config', '-l']
         kwargs = dict(capture_output=True, encoding='utf-8')
+        if location and location not in context.CONFIG_LOCATIONS:
+            raise TypeError("'{}' is not a valid git config location".format(location))
 
-        if isinstance(context, type):
+        if isinstance(context, type) and location in ['repository', 'project']:
+            raise TypeError("Cannot find '{}' git config without local checkout".format(location))
+
+        if isinstance(context, type) or location == 'global':
             args += ['--global']
         else:
             kwargs['cwd'] = context.root_path
+            if location == 'project':
+                # Without a project config, use the library defaults
+                if not os.path.isfile(os.path.join(context.root_path, context.PROJECT_CONFIG_PATH)):
+                    return {key: values[0] for key, values in context.PROJECT_CONFIG_OPTIONS.items()}
+                args += ['--file', context.PROJECT_CONFIG_PATH]
 
         command = run(args, **kwargs)
         if command.returncode:
@@ -332,6 +350,22 @@
         for line in command.stdout.splitlines():
             parts = line.split('=')
             result[parts[0]] = '='.join(parts[1:])
+
+        # When no location argument is provided, combine the project config and the repository config
+        if not isinstance(context, type) and not location:
+            default_config_values = context.config(location='project')
+        else:
+            default_config_values = {key: values[0] for key, values in Git.PROJECT_CONFIG_OPTIONS.items()}
+
+        for key, value in default_config_values.items():
+            if not result.get(key):
+                result[key] = value
+            elif not Git.PROJECT_CONFIG_OPTIONS.get(key):
+                continue
+            elif result.get(key) not in Git.PROJECT_CONFIG_OPTIONS[key]:
+                sys.stderr.write("'{}' is not a valid value for '{}', using '{}' instead\n".format(result[key], key, value))
+                result[key] = value
+
         return result
 
     def __init__(self, path, dev_branches=None, prod_branches=None, contributors=None, id=None, cached=sys.version_info > (3, 0)):
@@ -422,9 +456,8 @@
             raise self.Exception('Failed to retrieve tag list for {}'.format(self.root_path))
         return tags.stdout.splitlines()
 
-    @decorators.Memoize()
-    def url(self, name=None):
-        return self.config().get('remote.{}.url'.format(name or 'origin'))
+    def url(self, name=None, cached=None):
+        return self.config(cached=cached).get('remote.{}.url'.format(name or 'origin'))
 
     @decorators.Memoize()
     def remote(self, name=None):
@@ -840,7 +873,7 @@
                 ).returncode:
                     sys.stderr.write("Failed to add remote '{}' as '{}'\n".format(rmt, username))
                     return None
-                self.url.clear()
+                self.config.clear()
             branch = match.group('branch')
             rc = run(
                 [self.executable(), 'checkout'] + ['-B', branch, '{}/{}'.format(username, branch)] + log_arg,

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/mocks/local/git.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -399,6 +399,16 @@
                         stdout='\n'.join(['{}={}'.format(key, value) for key, value in self.config().items()])
                     ),
             ), mocks.Subprocess.Route(
+                self.executable, 'config', '-l', '--file', re.compile(r'.+'),
+                cwd=self.path,
+                generator=lambda *args, **kwargs:
+                    mocks.ProcessCompletion(
+                        returncode=0,
+                        stdout='\n'.join([
+                            '{}={}'.format(key, value) for key, value in self.config(path=os.path.join(self.path, args[4])).items()
+                        ])
+                    ),
+            ), mocks.Subprocess.Route(
                 self.executable, 'config', '-l', '--global',
                 generator=lambda *args, **kwargs:
                     mocks.ProcessCompletion(
@@ -533,7 +543,8 @@
                 found = self.find(split[0])
                 difference = int(split[1])
                 if difference < found.identifier:
-                    return self.commits[found.branch][found.identifier - difference - 1]
+                    difference += self.commits[found.branch][0].identifier
+                    return self.commits[found.branch][found.identifier - difference]
                 difference -= found.identifier
                 if found.branch_point and difference < found.branch_point:
                     return self.commits[self.default_branch][found.branch_point - difference - 1]
@@ -763,7 +774,7 @@
                     end = commit.hash
 
     @decorators.hybridmethod
-    def config(context):
+    def config(context, path=None):
         if isinstance(context, type):
             return {
                 'user.name': 'Tim Apple',
@@ -773,7 +784,10 @@
 
         top = None
         result = Git.config()
-        with open(os.path.join(context.path, '.git', 'config'), 'r') as configfile:
+        path = path or os.path.join(context.path, '.git', 'config')
+        if not os.path.isfile(path):
+            return result
+        with open(path, 'r') as configfile:
             for line in configfile.readlines():
                 match = context.RE_MULTI_TOP.match(line)
                 if match:

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/pull_request.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -56,6 +56,16 @@
             help='Do not prompt the user for defaults, always use (or do not use) them',
         )
         parser.add_argument(
+            '--overwrite', '--amend', action='', const='overwrite',
+            dest='technique', default=None,
+            help='When creating a pull request, overwrite the existing commit by default',
+        )
+        parser.add_argument(
+            '--append', action='', const='append',
+            dest='technique', default=None,
+            help='When creating a pull request, append a new commit on the existing branch by default',
+        )
+        parser.add_argument(
             '--with-history', '--no-history',
             dest='history', default=None,
             help='Create numbered branches to track the history of a change',
@@ -83,11 +93,12 @@
             return 0
 
         # Otherwise, we need to create a commit
+        will_amend = has_commit and args.technique == 'overwrite'
         if not modified:
             sys.stderr.write('No modified files\n')
             return 1
-        log.info('Amending commit...' if has_commit else 'Creating commit...')
-        if run([repository.executable(), 'commit', '--date=now'] + (['--amend'] if has_commit else []), cwd=repository.root_path).returncode:
+        log.info('Amending commit...' if will_amend else 'Creating commit...')
+        if run([repository.executable(), 'commit', '--date=now'] + (['--amend'] if will_amend else []), cwd=repository.root_path).returncode:
             sys.stderr.write('Failed to generate commit\n')
             return 1
 
@@ -107,6 +118,18 @@
             sys.stderr.write("Can only '{}' on a native Git repository\n".format(cls.name))
             return 1
 
+        if not args.technique:
+            args.technique = repository.config()['webkitscmpy.pull-request']
+        if args.history is None:
+            args.history = dict(
+                always=True,
+                disabled=False,
+                never=False,
+            ).get(repository.config()['webkitscmpy.history'])
+        if args.history and repository.config()['webkitscmpy.history'] == 'never':
+            sys.stderr.write('History retention was requested, but repository configuration forbids it\n')
+            return 1
+
         if not repository.DEV_BRANCHES.match(repository.branch):
             if Branch.main(args, repository, why="'{}' is not a pull request branch".format(repository.branch), **kwargs):
                 sys.stderr.write("Abandoning pushing pull-request because '{}' could not be created\n".format(args.issue))
@@ -140,7 +163,7 @@
             sys.stderr.write("your checkout may not have permission to push to '{}'\n".format(repository.url(name=target)))
             return 1
 
-        if args.history or (target != 'origin' and args.history is None):
+        if args.history or (target != 'origin' and args.history is None and args.technique == 'overwrite'):
             regex = re.compile(r'^{}-(?P<count>\d+)$'.format(repository.branch))
             count = max([
                 int(regex.match(branch).group('count')) if regex.match(branch) else 0 for branch in

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/setup.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -118,6 +118,16 @@
         else:
             log.info("Set git user name to '{}' for this repository".format(name))
 
+        if os.path.isfile(os.path.join(repository.path, local.Git.PROJECT_CONFIG_PATH)):
+            log.info('Adding project git config to repository config...')
+            result += run(
+                [local.Git.executable(), 'config', 'include.path', os.path.join('..', local.Git.PROJECT_CONFIG_PATH)],
+                capture_output=True, cwd=repository.root_path,
+            ).returncode
+            log.info('Added project git config to repository config!')
+        else:
+            log.info('No project git config found, continuing')
+
         log.info('Setting better Objective-C diffing behavior for this repository...')
         result += run(
             [local.Git.executable(), 'config', 'diff.objcpp.xfuncname', '^[-+@a-zA-Z_].*$'],
@@ -139,6 +149,8 @@
                     capture_output=True, cwd=repository.root_path,
                 ).returncode
 
+        if args.merge is None:
+            args.merge = repository.config(location='project')['pull.rebase'] == 'false'
         log.info('Using {} merge strategy for this repository'.format('merge commits as a' if args.merge else 'a rebase'))
         if run(
             [local.Git.executable(), 'config', 'pull.rebase', 'false' if args.merge else 'true'],
@@ -147,6 +159,25 @@
             sys.stderr.write('Failed to use {} as the merge strategy for this repository\n'.format('merge commits' if args.merge else 'rebase'))
             result += 1
 
+        if repository.config(location='project')['webkitscmpy.history'] == 'never':
+            pr_history = 'never'
+        elif repository.config(location='project')['webkitscmpy.pull-request'] != 'overwrite':
+            pr_history = None
+        elif args.defaults:
+            pr_history = repository.config(location='project')['webkitscmpy.history']
+        else:
+            pr_history = Terminal.choose(
+                'Would you like to create new branches to retain history when you overwrite\na pull request branch?',
+                default=repository.config(location='project')['webkitscmpy.history'],
+                options=repository.PROJECT_CONFIG_OPTIONS['webkitscmpy.history'],
+            )
+        if pr_history and run(
+            [local.Git.executable(), 'config', 'webkitscmpy.history', pr_history],
+            capture_output=True, cwd=repository.root_path,
+        ).returncode:
+            sys.stderr.write("Failed to set '{}' as the default history management approach\n".format(pr_history))
+            result += 1
+
         if hooks:
             for hook in os.listdir(hooks):
                 source_path = os.path.join(hooks, hook)
@@ -264,7 +295,7 @@
             help='Do not prompt the user for defaults, always use (or do not use) them',
         )
         parser.add_argument(
-            '--merge', '--no-merge', action="" default=False,
+            '--merge', '--no-merge', action="" default=None,
             help='Use a merge-commit workflow instead of a rebase workflow',
         )
 

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/git_unittest.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -1,4 +1,4 @@
-# Copyright (C) 2020, 2021 Apple Inc. All rights reserved.
+# Copyright (C) 2020-2022 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -402,6 +402,7 @@
             self.assertEqual(repo.config()['remote.origin.url'], 'g...@example.org:/mock/repository')
             self.assertEqual(repo.config()['svn-remote.svn.url'], 'https://svn.example.org/repository/webkit')
             self.assertEqual(repo.config()['svn-remote.svn.fetch'], 'trunk:refs/remotes/origin/main')
+            self.assertEqual(repo.config()['webkitscmpy.history'], 'when-user-owned')
 
     def test_global_config(self):
         with mocks.local.Git(self.path, git_svn=True), OutputCapture():
@@ -408,6 +409,19 @@
             self.assertEqual(local.Git.config()['user.name'], 'Tim Apple')
             self.assertEqual(local.Git.config()['sendemail.transferencoding'], 'base64')
 
+    def test_project_config(self):
+        with mocks.local.Git(self.path, git_svn=True):
+            project_config = os.path.join(self.path, local.Git.PROJECT_CONFIG_PATH)
+            os.mkdir(os.path.dirname(project_config))
+            with open(project_config, 'w') as f:
+                f.write('[webkitscmpy]\n')
+                f.write('    history = never\n')
+                f.write('    test = example\n')
+
+            repo = local.Git(self.path)
+            self.assertEqual(repo.config()['webkitscmpy.history'], 'never')
+            self.assertEqual(repo.config()['webkitscmpy.test'], 'example')
+
     def test_modified(self):
         with mocks.local.Git(self.path) as mrepo, OutputCapture():
             repo = local.Git(self.path)

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/pull_request_unittest.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -382,6 +382,43 @@
             ],
         )
 
+    def test_github_append(self):
+        with mocks.remote.GitHub() as remote, mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
+            with OutputCapture():
+                repo.staged['added.txt'] = 'added'
+                self.assertEqual(0, program.main(
+                    args=('pull-request', '-i', 'pr-branch'),
+                    path=self.path,
+                ))
+
+            with OutputCapture(level=logging.INFO) as captured:
+                repo.staged['modified.txt'] = 'diff'
+                self.assertEqual(0, program.main(
+                    args=('pull-request', '-v', '--no-history', '--append'),
+                    path=self.path,
+                ))
+
+        self.assertEqual(
+            captured.stdout.getvalue(),
+            "Updated 'PR 1 | [Testing] Creating commits'!\n"
+            "https://github.example.com/WebKit/WebKit/pull/1\n",
+        )
+        self.assertEqual(captured.stderr.getvalue(), '')
+        log = captured.root.log.getvalue().splitlines()
+        self.assertEqual(
+            [line for line in log if 'Mock process' not in line], [
+                "Creating commit...",
+                '    Found 1 commit...',
+                '    Found 2 commits...',
+                "Rebasing 'eng/pr-branch' on 'main'...",
+                "Rebased 'eng/pr-branch' on 'main!'",
+                '    Found 1 commit...',
+                '    Found 2 commits...',
+                "Pushing 'eng/pr-branch' to 'fork'...",
+                "Updating pull-request for 'eng/pr-branch'...",
+            ],
+        )
+
     def test_github_reopen(self):
         with mocks.remote.GitHub() as remote, mocks.local.Git(self.path, remote='https://{}'.format(remote.remote)) as repo, mocks.local.Svn():
             with OutputCapture():
@@ -493,6 +530,45 @@
             ],
         )
 
+    def test_bitbucket_append(self):
+        with mocks.remote.BitBucket() as remote, mocks.local.Git(self.path, remote='ssh://git@{}/{}/{}.git'.format(
+            remote.hosts[0], remote.project.split('/')[1], remote.project.split('/')[3],
+        )) as repo, mocks.local.Svn():
+            with OutputCapture():
+                repo.staged['added.txt'] = 'added'
+                self.assertEqual(0, program.main(
+                    args=('pull-request', '-i', 'pr-branch'),
+                    path=self.path,
+                ))
+
+            with OutputCapture(level=logging.INFO) as captured:
+                repo.staged['modified.txt'] = 'diff'
+                self.assertEqual(0, program.main(
+                    args=('pull-request', '-v', '--append'),
+                    path=self.path,
+                ))
+
+        self.assertEqual(
+            captured.stdout.getvalue(),
+            "Updated 'PR 1 | [Testing] Creating commits'!\n"
+            "https://bitbucket.example.com/projects/WEBKIT/repos/webkit/pull-requests/1/overview\n"
+        )
+        self.assertEqual(captured.stderr.getvalue(), '')
+        log = captured.root.log.getvalue().splitlines()
+        self.assertEqual(
+            [line for line in log if 'Mock process' not in line], [
+                "Creating commit...",
+                '    Found 1 commit...',
+                '    Found 2 commits...',
+                "Rebasing 'eng/pr-branch' on 'main'...",
+                "Rebased 'eng/pr-branch' on 'main!'",
+                '    Found 1 commit...',
+                '    Found 2 commits...',
+                "Pushing 'eng/pr-branch' to 'origin'...",
+                "Updating pull-request for 'eng/pr-branch'...",
+            ],
+        )
+
     def test_bitbucket_reopen(self):
         with mocks.remote.BitBucket() as remote, mocks.local.Git(self.path, remote='ssh://git@{}/{}/{}.git'.format(
             remote.hosts[0], remote.project.split('/')[1], remote.project.split('/')[3],

Modified: trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/setup_unittest.py (289076 => 289077)


--- trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/setup_unittest.py	2022-02-03 21:42:21 UTC (rev 289076)
+++ trunk/Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/setup_unittest.py	2022-02-03 21:47:06 UTC (rev 289077)
@@ -88,6 +88,7 @@
 Set git user email to 'tap...@webkit.org' for this repository
 Setting git user name for {repository}...
 Set git user name to 'Tim Apple' for this repository
+No project git config found, continuing
 Setting better Objective-C diffing behavior for this repository...
 Set better Objective-C diffing behavior for this repository!
 Using a rebase merge strategy for this repository
@@ -99,7 +100,7 @@
     def test_github_checkout(self):
         self.maxDiff = None
         with OutputCapture(level=logging.INFO) as captured, mocks.remote.GitHub() as remote, \
-            MockTerminal.input('n', 'commit...@webkit.org', 'n', 'Committer', 'n', '1', 'y', 'y'), \
+            MockTerminal.input('n', 'commit...@webkit.org', 'n', 'Committer', 'n', 'overwrite', 'disabled', '1', 'y', 'y'), \
             mocks.local.Git(self.path, remote='https://{}.git'.format(remote.remote)) as repo, \
             wkmocks.Environment(EMAIL_ADDRESS=''):
 
@@ -124,6 +125,8 @@
 Set 'Tim Apple' as the git user name for this repository ([Yes]/No): 
 Enter git user name for this repository: 
 Auto-color status, diff, and branch for this repository? ([Yes]/No): 
+Would you like to create new branches to retain history when you overwrite
+a pull request branch? ([when-user-owned]/disabled/always/never): 
 Pick a commit message editor for this repository:
     {}
 : 
@@ -143,6 +146,7 @@
 Set git user email to 'commit...@webkit.org' for this repository
 Setting git user name for {repository}...
 Set git user name to 'Committer' for this repository
+No project git config found, continuing
 Setting better Objective-C diffing behavior for this repository...
 Set better Objective-C diffing behavior for this repository!
 Using a rebase merge strategy for this repository

Added: trunk/metadata/project_config (0 => 289077)


--- trunk/metadata/project_config	                        (rev 0)
+++ trunk/metadata/project_config	2022-02-03 21:47:06 UTC (rev 289077)
@@ -0,0 +1,5 @@
+[pull]
+        rebase = true
+[webkitscmpy]
+        pull-request = append
+        history = disabled
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to