Commit 0f1addcb authored by Gavin Mak's avatar Gavin Mak Committed by LUCI CQ

Reland "Remove old DepotToolsOwners implementation"

This is a reland of commit 10dbd7ba

Original change's description:
> Remove old DepotToolsOwners implementation
>
> code-owners should have been enabled for most hosts that depot_tools
> supports by now. Remove our own implementation and rely on code-owners.
>
> Change-Id: Iaf0d3db65b2e5063b67d42b92188c4ec51d2cd9a
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3783475
> Reviewed-by: Aravind Vasudevan <aravindvasudev@google.com>
> Reviewed-by: Joanna Wang <jojwang@chromium.org>
> Commit-Queue: Gavin Mak <gavinmak@google.com>

Change-Id: Ic87f34411bb38b91fcf49adb07601ae10244e828
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3881043Reviewed-by: 's avatarJosip Sokcevic <sokcevic@google.com>
Commit-Queue: Gavin Mak <gavinmak@google.com>
Reviewed-by: 's avatarJoanna Wang <jojwang@chromium.org>
parent 07d6e698
......@@ -1023,8 +1023,6 @@ class Changelist(object):
remote, remote_branch = self.GetRemoteBranch()
branch = GetTargetRef(remote, remote_branch, None)
self._owners_client = owners_client.GetCodeOwnersClient(
root=settings.GetRoot(),
upstream=self.GetCommonAncestorWithUpstream(),
host=self.GetGerritHost(),
project=self.GetGerritProject(),
branch=branch)
......
This diff is collapsed.
......@@ -2,15 +2,11 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import itertools
import os
import random
import threading
import gerrit_util
import git_common
import owners as owners_db
import scm
class OwnersClient(object):
......@@ -117,47 +113,6 @@ class OwnersClient(object):
return selected
class DepotToolsClient(OwnersClient):
"""Implement OwnersClient using owners.py Database."""
def __init__(self, root, branch, fopen=open, os_path=os.path):
super(DepotToolsClient, self).__init__()
self._root = root
self._branch = branch
self._fopen = fopen
self._os_path = os_path
self._db = None
self._db_lock = threading.Lock()
def _ensure_db(self):
if self._db is not None:
return
self._db = owners_db.Database(self._root, self._fopen, self._os_path)
self._db.override_files = self._GetOriginalOwnersFiles()
def _GetOriginalOwnersFiles(self):
return {
f: scm.GIT.GetOldContents(self._root, f, self._branch).splitlines()
for _, f in scm.GIT.CaptureStatus(self._root, self._branch)
if os.path.basename(f) == 'OWNERS'
}
def ListOwners(self, path):
# all_possible_owners is not thread safe.
with self._db_lock:
self._ensure_db()
# all_possible_owners returns a dict {owner: [(path, distance)]}. We want
# to return a list of owners sorted by increasing distance.
distance_by_owner = self._db.all_possible_owners([path], None)
# We add a small random number to the distance, so that owners at the
# same distance are returned in random order to avoid overloading those
# who would appear first.
return sorted(
distance_by_owner,
key=lambda o: distance_by_owner[o][0][1] + random.random())
class GerritClient(OwnersClient):
"""Implement OwnersClient using OWNERS REST API."""
def __init__(self, host, project, branch):
......@@ -217,11 +172,14 @@ class GerritClient(OwnersClient):
pool.imap_unordered(lambda p: (p, self.ListBestOwners(p)), paths))
def GetCodeOwnersClient(root, upstream, host, project, branch):
def GetCodeOwnersClient(host, project, branch):
"""Get a new OwnersClient.
Defaults to GerritClient, and falls back to DepotToolsClient if code-owners
plugin is not available."""
Uses GerritClient and raises an exception if code-owners plugin is not
available."""
if gerrit_util.IsCodeOwnersEnabledOnHost(host):
return GerritClient(host, project, branch)
return DepotToolsClient(root, upstream)
raise Exception(
'code-owners plugin is not enabled. Ask your host admin to enable it '
'on %s. Read more about code-owners at '
'https://gerrit.googlesource.com/plugins/code-owners.' % host)
......@@ -1264,21 +1264,13 @@ def CheckOwnersDirMetadataExclusive(input_api, output_api):
def CheckOwnersFormat(input_api, output_api):
if input_api.gerrit and input_api.gerrit.IsCodeOwnersEnabledOnRepo():
return []
affected_files = {
f.LocalPath()
for f in input_api.change.AffectedFiles()
if 'OWNERS' in f.LocalPath() and f.Action() != 'D'
}
if not affected_files:
return []
try:
owners_db = input_api.owners_db
owners_db.override_files = {}
owners_db.load_data_needed_for(affected_files)
return []
except Exception as e:
return [output_api.PresubmitError(
'Error parsing OWNERS files:\n%s' % e)]
return [
output_api.PresubmitError(
'code-owners is not enabled. Ask your host enable it on your gerrit '
'host. Read more about code-owners at '
'https://gerrit.googlesource.com/plugins/code-owners.')
]
def CheckOwners(
......@@ -1293,58 +1285,12 @@ def CheckOwners(
if input_api.gerrit and input_api.gerrit.IsCodeOwnersEnabledOnRepo():
return []
affected_files = {f.LocalPath() for f in
input_api.change.AffectedFiles(
file_filter=source_file_filter)}
owner_email, reviewers = GetCodereviewOwnerAndReviewers(
input_api, approval_needed=input_api.is_committing)
owner_email = owner_email or input_api.change.author_email
approval_status = input_api.owners_client.GetFilesApprovalStatus(
affected_files, reviewers.union([owner_email]), [])
missing_files = [
f for f in affected_files
if approval_status[f] != input_api.owners_client.APPROVED]
affects_owners = any('OWNERS' in name for name in missing_files)
if input_api.is_committing:
if input_api.tbr and not affects_owners:
return [output_api.PresubmitNotifyResult(
'--tbr was specified, skipping OWNERS check')]
needed = 'LGTM from an OWNER'
output_fn = output_api.PresubmitError
if input_api.change.issue:
if input_api.dry_run:
output_fn = lambda text: output_api.PresubmitNotifyResult(
'This is a dry run, but these failures would be reported on ' +
'commit:\n' + text)
else:
return [output_api.PresubmitError(
'OWNERS check failed: this CL has no Gerrit change number, '
'so we can\'t check it for approvals.')]
else:
needed = 'OWNER reviewers'
output_fn = output_api.PresubmitNotifyResult
if missing_files:
output_list = [
output_fn('Missing %s for these files:\n %s' %
(needed, '\n '.join(sorted(missing_files))))]
if input_api.tbr and affects_owners:
output_list.append(output_fn('TBR for OWNERS files are ignored.'))
if not input_api.is_committing:
suggested_owners = input_api.owners_client.SuggestOwners(
missing_files, exclude=[owner_email])
output_list.append(output_fn('Suggested OWNERS: ' +
'(Use "git-cl owners" to interactively select owners.)\n %s' %
('\n '.join(suggested_owners))))
return output_list
if (input_api.is_committing and not reviewers and
not input_api.gerrit.IsBotCommitApproved(input_api.change.issue)):
return [output_fn('Missing LGTM from someone other than %s' % owner_email)]
return []
return [
output_api.PresubmitError(
'code-owners is not enabled. Ask your host enable it on your gerrit '
'host. Read more about code-owners at '
'https://gerrit.googlesource.com/plugins/code-owners.')
]
def GetCodereviewOwnerAndReviewers(
......
......@@ -44,7 +44,6 @@ import gclient_paths # Exposed through the API
import gclient_utils
import git_footers
import gerrit_util
import owners as owners_db
import owners_client
import owners_finder
import presubmit_canned_checks
......@@ -678,15 +677,11 @@ class InputApi(object):
if self.gerrit and not 'PRESUBMIT_SKIP_NETWORK' in self.environ:
try:
self.owners_client = owners_client.GetCodeOwnersClient(
root=change.RepositoryRoot(),
upstream=change.UpstreamBranch(),
host=self.gerrit.host,
project=self.gerrit.project,
branch=self.gerrit.branch)
except Exception as e:
print('Failed to set owners_client - %s' % str(e))
self.owners_db = owners_db.Database(
change.RepositoryRoot(), fopen=open, os_path=self.os_path)
self.owners_finder = owners_finder.OwnersFinder
self.verbose = verbose
self.Command = CommandData
......
......@@ -27,41 +27,6 @@ dave = 'dave@example.com'
emily = 'emily@example.com'
class DepotToolsClientTest(unittest.TestCase):
def setUp(self):
self.repo = filesystem_mock.MockFileSystem(files={
'/OWNERS': '\n'.join([
'per-file approved.cc=approver@example.com',
'per-file reviewed.h=reviewer@example.com',
'missing@example.com',
]),
'/approved.cc': '',
'/reviewed.h': '',
'/bar/insufficient_reviewers.py': '',
'/bar/everyone/OWNERS': '*',
'/bar/everyone/foo.txt': '',
})
self.root = '/'
self.fopen = self.repo.open_for_reading
self.addCleanup(mock.patch.stopall)
self.client = owners_client.DepotToolsClient(
'/', 'branch', self.fopen, self.repo)
@mock.patch('scm.GIT.CaptureStatus')
@mock.patch('scm.GIT.GetOldContents')
def testListOwners(self, mockGetOldContents, mockCaptureStatus):
mockGetOldContents.side_effect = lambda r, f, _b: self.repo.files[r + f]
mockCaptureStatus.return_value = [
('M', 'bar/everyone/foo.txt'),
('M', 'OWNERS'),
]
self.assertEqual(
['*', 'missing@example.com'],
self.client.ListOwners('bar/everyone/foo.txt'))
mockCaptureStatus.assert_called_once_with('/', 'branch')
class GerritClientTest(unittest.TestCase):
def setUp(self):
self.client = owners_client.GerritClient('host', 'project', 'branch')
......@@ -293,17 +258,16 @@ class GetCodeOwnersClientTest(unittest.TestCase):
mock.patch('gerrit_util.IsCodeOwnersEnabledOnHost').start()
self.addCleanup(mock.patch.stopall)
def testGetCodeOwnersClient_GerritClient(self):
def testGetCodeOwnersClient_CodeOwnersEnabled(self):
gerrit_util.IsCodeOwnersEnabledOnHost.return_value = True
self.assertIsInstance(
owners_client.GetCodeOwnersClient('', '', 'host', 'project', 'branch'),
owners_client.GetCodeOwnersClient('host', 'project', 'branch'),
owners_client.GerritClient)
def testGetCodeOwnersClient_DepotToolsClient(self):
def testGetCodeOwnersClient_CodeOwnersDisabled(self):
gerrit_util.IsCodeOwnersEnabledOnHost.return_value = False
self.assertIsInstance(
owners_client.GetCodeOwnersClient('root', 'branch', '', '', ''),
owners_client.DepotToolsClient)
with self.assertRaises(Exception):
owners_client.GetCodeOwnersClient('', '', '')
if __name__ == '__main__':
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment