Skip to content
Permalink
Browse files
[git-webkit] Support ranges in find
https://bugs.webkit.org/show_bug.cgi?id=241806
<rdar://95601346>

Reviewed by Ryan Haddad.

* 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.commits): Use '..'' instead of '...'
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/program/find.py:
(Info.main): Support .. based range queries.
(Find): Add 'list' alias.
* Tools/Scripts/libraries/webkitscmpy/webkitscmpy/test/find_unittest.py:

Canonical link: https://commits.webkit.org/251746@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@295741 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
JonWBedard committed Jun 22, 2022
1 parent a420713 commit 4c41b3a43f1a96c1d5e0d6f3e65f762c5540dbc1
Showing 5 changed files with 141 additions and 31 deletions.
@@ -29,7 +29,7 @@ def readme():

setup(
name='webkitscmpy',
version='5.0.3',
version='5.1.0',
description='Library designed to interact with git and svn repositories.',
long_description=readme(),
classifiers=[
@@ -46,7 +46,7 @@ def _maybe_add_webkitcorepy_path():
"Please install webkitcorepy with `pip install webkitcorepy --extra-index-url <package index URL>`"
)

version = Version(5, 0, 3)
version = Version(5, 1, 0)

AutoInstall.register(Package('fasteners', Version(0, 15, 0)))
AutoInstall.register(Package('jinja2', Version(2, 11, 3)))
@@ -744,7 +744,7 @@ def commits(self, begin=None, end=None, include_log=True, include_identifier=Tru
try:
log = None
log = subprocess.Popen(
[self.executable(), 'log', '--format=fuller', '--no-decorate', '--date=unix', '{}...{}'.format(end.hash, begin.hash), '--'],
[self.executable(), 'log', '--format=fuller', '--no-decorate', '--date=unix', '{}..{}'.format(begin.hash, end.hash), '--'],
cwd=self.root_path,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
@@ -57,53 +57,72 @@ def main(cls, args, repository, reference='HEAD', **kwargs):
return 1

try:
commit = repository.find(reference, include_log=args.include_log)
except (local.Scm.Exception, ValueError) as exception:
if '..' in reference:
if '...' in reference:
sys.stderr.write("'find' sub-command only supports '..' notation\n")
return 1
references = reference.split('..')
if len(references) > 2:
sys.stderr.write('Can only include two references in a range\n')
return 1
commits = [commit for commit in repository.commits(begin=dict(argument=references[0]), end=dict(argument=references[1]))]
else:
commits = [repository.find(reference, include_log=args.include_log)]

except (local.Scm.Exception, TypeError, ValueError) as exception:
# ValueErrors and Scm exceptions usually contain enough information to be displayed
# to the user as an error
sys.stderr.write(str(exception) + '\n')
return 1

if args.verbose > 0 and not commit.message:
sys.stderr.write("Failed to find the commit message for '{}'\n".format(commit))
return 1
for commit in commits:
if args.verbose > 0 and not commit.message:
sys.stderr.write("Failed to find the commit message for '{}'\n".format(commit))
return 1

if args.json:
print(json.dumps(commit, cls=Commit.Encoder, indent=4))
print(json.dumps(commits if len(commits) > 1 else commits[0], cls=Commit.Encoder, indent=4))
return 0

if args.verbose < 0:
print('{identifier} | {hash}{revision}{title}'.format(
identifier=commit,
hash=commit.hash[:Commit.HASH_LABEL_SIZE] if commit.hash else '',
revision='{}r{}'.format(', ' if commit.hash else '', commit.revision) if commit.revision else '',
title=' | {}'.format(commit.message.splitlines()[0]) if commit.message else ''
))
for commit in commits:
print('{identifier} | {hash}{revision}{title}'.format(
identifier=commit,
hash=commit.hash[:Commit.HASH_LABEL_SIZE] if commit.hash else '',
revision='{}r{}'.format(', ' if commit.hash else '', commit.revision) if commit.revision else '',
title=' | {}'.format(commit.message.splitlines()[0]) if commit.message else ''
))
return 0

if commit.message:
print(u'Title: {}'.format(commit.message.splitlines()[0]))
try:
print(u'Author: {}'.format(commit.author))
except (UnicodeEncodeError, UnicodeDecodeError):
print('Error: Unable to print commit author name, please file a bug if seeing this locally.')
print(datetime.fromtimestamp(commit.timestamp).strftime('Date: %a %b %d %H:%M:%S %Y'))
if args.verbose > 0 or commit.revision:
print('Revision: {}'.format(commit.revision or 'N/A'))
if args.verbose > 0 or commit.hash:
print('Hash: {}'.format(commit.hash[:Commit.HASH_LABEL_SIZE] if commit.hash else 'N/A'))
print(u'Identifier: {}'.format(commit))

if args.verbose > 0:
for line in commit.message.splitlines():
print(u' {}'.format(line))
previous = False
for commit in commits:
if previous:
print('-' * 20)
previous = True
if commit.message:
print(u'Title: {}'.format(commit.message.splitlines()[0]))
try:
print(u'Author: {}'.format(commit.author))
except (UnicodeEncodeError, UnicodeDecodeError):
print('Error: Unable to print commit author name, please file a bug if seeing this locally.')
print(datetime.fromtimestamp(commit.timestamp).strftime('Date: %a %b %d %H:%M:%S %Y'))
if args.verbose > 0 or commit.revision:
print('Revision: {}'.format(commit.revision or 'N/A'))
if args.verbose > 0 or commit.hash:
print('Hash: {}'.format(commit.hash[:Commit.HASH_LABEL_SIZE] if commit.hash else 'N/A'))
print(u'Identifier: {}'.format(commit))

if args.verbose > 0:
for line in commit.message.splitlines():
print(u' {}'.format(line))

return 0


class Find(Command):
name = 'find'
help = 'Given an identifier, revision or hash, normalize and print the commit'
aliases = ['list']

@classmethod
def parser(cls, parser, loggers=None):
@@ -156,6 +156,30 @@ def test_standard(self):
'''.format(datetime.fromtimestamp(1601663000).strftime('%a %b %d %H:%M:%S %Y')),
)

def test_standard_list(self):
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(0, program.main(
args=('find', '2@main..4@main'),
path=self.path,
))
self.assertEqual(
captured.stdout.getvalue(),
'''Title: 8th commit
Author: Jonathan Bedard <jbedard@apple.com>
Date: {}
Revision: 8
Hash: bae5d1e90999
Identifier: 4@main
--------------------
Title: 4th commit
Author: Jonathan Bedard <jbedard@apple.com>
Date: {}
Revision: 4
Hash: 1abe25b443e9
Identifier: 3@main
'''.format(datetime.fromtimestamp(1601668000).strftime('%a %b %d %H:%M:%S %Y'), datetime.fromtimestamp(1601663000).strftime('%a %b %d %H:%M:%S %Y')),
)

def test_verbose(self):
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(0, program.main(
@@ -175,6 +199,39 @@ def test_verbose(self):
'''.format(datetime.fromtimestamp(1601663000).strftime('%a %b %d %H:%M:%S %Y')),
)

def test_quiet(self):
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(0, program.main(
args=('find', '3@main', '-q'),
path=self.path,
))
self.assertEqual(
captured.stdout.getvalue(),
'3@main | 1abe25b443e9, r4 | 4th commit\n',
)

def test_failed_list(self):
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(1, program.main(
args=('find', '2@main...4@main', '-q'),
path=self.path,
))
self.assertEqual(
captured.stderr.getvalue(),
"'find' sub-command only supports '..' notation\n",
)

def test_quiet_list(self):
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(0, program.main(
args=('find', '2@main..4@main', '-q'),
path=self.path,
))
self.assertEqual(
captured.stdout.getvalue(),
'4@main | bae5d1e90999, r8 | 8th commit\n3@main | 1abe25b443e9, r4 | 4th commit\n',
)

def test_json(self):
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(0, program.main(
@@ -197,6 +254,40 @@ def test_json(self):
message='4th commit\ngit-svn-id: https://svn.example.org/repository/repository/trunk@4 268f45cc-cd09-0410-ab3c-d52691b4dbfc',
))

def test_json_list(self):
self.maxDiff = None
with OutputCapture() as captured, mocks.local.Git(self.path, git_svn=True), mocks.local.Svn(), MockTime:
self.assertEqual(0, program.main(
args=('find', '2@main..4@main', '--json'),
path=self.path,
))

decoded = json.loads(captured.stdout.getvalue())
self.assertEqual(
decoded, [dict(
identifier='4@main',
hash='bae5d1e90999d4f916a8a15810ccfa43f37a2fd6',
revision=8,
author=dict(
name='Jonathan Bedard',
emails=['jbedard@apple.com'],
), timestamp=1601668000,
order=0,
branch='main',
message='8th commit\ngit-svn-id: https://svn.example.org/repository/repository/trunk@8 268f45cc-cd09-0410-ab3c-d52691b4dbfc',
), dict(
identifier='3@main',
hash='1abe25b443e985f93b90d830e4a7e3731336af4d',
revision=4,
author=dict(
name='Jonathan Bedard',
emails=['jbedard@apple.com'],
), timestamp=1601663000,
order=0,
branch='main',
message='4th commit\ngit-svn-id: https://svn.example.org/repository/repository/trunk@4 268f45cc-cd09-0410-ab3c-d52691b4dbfc',
)])

def test_tag_svn(self):
with OutputCapture() as captured, mocks.local.Git(), mocks.local.Svn(self.path), MockTime:
self.assertEqual(0, program.main(

0 comments on commit 4c41b3a

Please sign in to comment.