Commit 7677e5cc authored by Edward Lesmes's avatar Edward Lesmes Committed by LUCI CQ

git-cl: Mock GetChangeDetail on tests.

Mock GetChangeDetail instead of using self.calls to make the code
easier to change.

Bug: 1051631
Change-Id: I77361caccaf694644839825d890343864267688f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/2062716
Commit-Queue: Edward Lesmes <ehmaldonado@chromium.org>
Reviewed-by: 's avatarAnthony Polito <apolito@google.com>
parent 6693d092
...@@ -1420,8 +1420,6 @@ class Changelist(object): ...@@ -1420,8 +1420,6 @@ class Changelist(object):
self.description = description self.description = description
self.has_description = True self.has_description = True
def RunHook(self, committing, may_prompt, verbose, change, parallel): def RunHook(self, committing, may_prompt, verbose, change, parallel):
"""Calls sys.exit() if the hook fails; returns a HookResults otherwise.""" """Calls sys.exit() if the hook fails; returns a HookResults otherwise."""
try: try:
...@@ -1693,11 +1691,6 @@ class Changelist(object): ...@@ -1693,11 +1691,6 @@ class Changelist(object):
if not self.GetIssue(): if not self.GetIssue():
return return
# Warm change details cache now to avoid RPCs later, reducing latency for
# developers.
self._GetChangeDetail(
['DETAILED_ACCOUNTS', 'CURRENT_REVISION', 'CURRENT_COMMIT', 'LABELS'])
status = self._GetChangeDetail()['status'] status = self._GetChangeDetail()['status']
if status in ('MERGED', 'ABANDONED'): if status in ('MERGED', 'ABANDONED'):
DieWithError('Change %s has been %s, new uploads are not allowed' % DieWithError('Change %s has been %s, new uploads are not allowed' %
...@@ -1912,49 +1905,38 @@ class Changelist(object): ...@@ -1912,49 +1905,38 @@ class Changelist(object):
self._GetGerritHost(), self._GerritChangeIdentifier(), self._GetGerritHost(), self._GerritChangeIdentifier(),
wait_for_merge=wait_for_merge) wait_for_merge=wait_for_merge)
def _GetChangeDetail(self, options=None, no_cache=False): def _GetChangeDetail(self, options=None):
"""Returns details of associated Gerrit change and caching results. """Returns details of associated Gerrit change and caching results."""
If fresh data is needed, set no_cache=True which will clear cache and
thus new data will be fetched from Gerrit.
"""
options = options or [] options = options or []
assert self.GetIssue(), 'issue is required to query Gerrit' assert self.GetIssue(), 'issue is required to query Gerrit'
# Optimization to avoid multiple RPCs: # Optimization to avoid multiple RPCs:
if (('CURRENT_REVISION' in options or 'ALL_REVISIONS' in options) and if 'CURRENT_REVISION' in options or 'ALL_REVISIONS' in options:
'CURRENT_COMMIT' not in options):
options.append('CURRENT_COMMIT') options.append('CURRENT_COMMIT')
# Normalize issue and options for consistent keys in cache. # Normalize issue and options for consistent keys in cache.
cache_key = str(self.GetIssue()) cache_key = str(self.GetIssue())
options = [o.upper() for o in options] options_set = frozenset(o.upper() for o in options)
# Check in cache first unless no_cache is True. for cached_options_set, data in self._detail_cache.get(cache_key, []):
if no_cache: # Assumption: data fetched before with extra options is suitable
self._detail_cache.pop(cache_key, None) # for return for a smaller set of options.
else: # For example, if we cached data for
options_set = frozenset(options) # options=[CURRENT_REVISION, DETAILED_FOOTERS]
for cached_options_set, data in self._detail_cache.get(cache_key, []): # and request is for options=[CURRENT_REVISION],
# Assumption: data fetched before with extra options is suitable # THEN we can return prior cached data.
# for return for a smaller set of options. if options_set.issubset(cached_options_set):
# For example, if we cached data for return data
# options=[CURRENT_REVISION, DETAILED_FOOTERS]
# and request is for options=[CURRENT_REVISION],
# THEN we can return prior cached data.
if options_set.issubset(cached_options_set):
return data
try: try:
data = gerrit_util.GetChangeDetail( data = gerrit_util.GetChangeDetail(
self._GetGerritHost(), self._GerritChangeIdentifier(), options) self._GetGerritHost(), self._GerritChangeIdentifier(), options_set)
except gerrit_util.GerritError as e: except gerrit_util.GerritError as e:
if e.http_status == 404: if e.http_status == 404:
raise GerritChangeNotExists(self.GetIssue(), self.GetCodereviewServer()) raise GerritChangeNotExists(self.GetIssue(), self.GetCodereviewServer())
raise raise
self._detail_cache.setdefault(cache_key, []).append( self._detail_cache.setdefault(cache_key, []).append((options_set, data))
(frozenset(options), data))
return data return data
def _GetChangeCommit(self): def _GetChangeCommit(self):
...@@ -4363,9 +4345,16 @@ def CMDupload(parser, args): ...@@ -4363,9 +4345,16 @@ def CMDupload(parser, args):
settings.GetIsGerrit() settings.GetIsGerrit()
cl = Changelist() cl = Changelist()
# Warm change details cache now to avoid RPCs later, reducing latency for
# developers.
if cl.GetIssue():
cl._GetChangeDetail(
['DETAILED_ACCOUNTS', 'CURRENT_REVISION', 'CURRENT_COMMIT', 'LABELS'])
if options.retry_failed and not cl.GetIssue(): if options.retry_failed and not cl.GetIssue():
print('No previous patchsets, so --retry-failed has no effect.') print('No previous patchsets, so --retry-failed has no effect.')
options.retry_failed = False options.retry_failed = False
# cl.GetMostRecentPatchset uses cached information, and can return the last # cl.GetMostRecentPatchset uses cached information, and can return the last
# patchset before upload. Calling it here makes it clear that it's the # patchset before upload. Calling it here makes it clear that it's the
# last patchset before upload. Note that GetMostRecentPatchset will fail # last patchset before upload. Note that GetMostRecentPatchset will fail
......
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